php-src/ext/gd/gd.c
Stig Bakken 257de2bade First commit of re-structuring phase one. We have started using automake in
sub-directories and started to move extension code into ext/<name>.  For now,
I have moved the "standard" extension (which is quite a mix of everything
right now) and the GD extension into their own subdirs in ext/.
The configure script now also runs configure in the libzend directory
automatically and makes sure php4 and libzend use the same config.cache file.
To avoid running configure in libzend, use the --no-recursion option.
"make" in php4 also builds libzend now.
The Apache module doesn't compile right now, but a fix for that is
coming up.
1999-04-17 00:37:12 +00:00

1787 lines
43 KiB
C

/*
+----------------------------------------------------------------------+
| PHP HTML Embedded Scripting Language Version 3.0 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-1999 PHP Development Team (See Credits file) |
+----------------------------------------------------------------------+
| This program is free software; you can redistribute it and/or modify |
| it under the terms of one of the following licenses: |
| |
| A) the GNU General Public License as published by the Free Software |
| Foundation; either version 2 of the License, or (at your option) |
| any later version. |
| |
| B) the PHP License as published by the PHP Development Team and |
| included in the distribution in the file: LICENSE |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of both licenses referred to here. |
| If you did not, or have any questions about PHP licensing, please |
| contact core@php.net. |
+----------------------------------------------------------------------+
| Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
| Stig Bakken <ssb@guardian.no> |
| Jim Winstead <jimw@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
/* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center,
Cold Spring Harbor Labs. */
/* Note that there is no code from the gd package in this file */
#ifdef THREAD_SAFE
# include "tls.h"
#endif
#include "php.h"
#include "functions/head.h"
#include <math.h>
#include "php3_gd.h"
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#if WIN32|WINNT
# include <io.h>
# include <fcntl.h>
#endif
#if HAVE_LIBGD
#include <gd.h>
#include <gdfontt.h> /* 1 Tiny font */
#include <gdfonts.h> /* 2 Small font */
#include <gdfontmb.h> /* 3 Medium bold font */
#include <gdfontl.h> /* 4 Large font */
#include <gdfontg.h> /* 5 Giant font */
#if HAVE_LIBTTF
# if PHP_31
# include "gdttf.h"
# else
# include "functions/gdttf.h"
# endif
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#if HAVE_LIBTTF
static void php3_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int);
#endif
#ifdef THREAD_SAFE
DWORD GDlibTls;
static int numthreads=0;
void *gdlib_mutex=NULL;
typedef struct gdlib_global_struct{
int le_gd;
int le_gd_font;
} gdlib_global_struct;
# define GD_GLOBAL(a) gdlib_globals->a
# define GD_TLS_VARS gdlib_global_struct *gdlib_globals = TlsGetValue(GDlibTls);
#else
# define GD_GLOBAL(a) a
# define GD_TLS_VARS
int le_gd;
int le_gd_font;
#endif
function_entry gd_functions[] = {
{"imagearc", php3_imagearc, NULL},
{"imagechar", php3_imagechar, NULL},
{"imagecharup", php3_imagecharup, NULL},
{"imagecolorallocate", php3_imagecolorallocate, NULL},
{"imagecolorat", php3_imagecolorat, NULL},
{"imagecolorclosest", php3_imagecolorclosest, NULL},
{"imagecolordeallocate", php3_imagecolordeallocate, NULL},
{"imagecolorresolve", php3_imagecolorresolve, NULL},
{"imagecolorexact", php3_imagecolorexact, NULL},
{"imagecolorset", php3_imagecolorset, NULL},
{"imagecolortransparent", php3_imagecolortransparent, NULL},
{"imagecolorstotal", php3_imagecolorstotal, NULL},
{"imagecolorsforindex", php3_imagecolorsforindex, NULL},
{"imagecopy", php3_imagecopy, NULL},
{"imagecopyresized", php3_imagecopyresized, NULL},
{"imagecreate", php3_imagecreate, NULL},
{"imagecreatefromgif", php3_imagecreatefromgif, NULL},
{"imagedestroy", php3_imagedestroy, NULL},
{"imagefill", php3_imagefill, NULL},
{"imagefilledpolygon", php3_imagefilledpolygon, NULL},
{"imagefilledrectangle", php3_imagefilledrectangle, NULL},
{"imagefilltoborder", php3_imagefilltoborder, NULL},
{"imagefontwidth", php3_imagefontwidth, NULL},
{"imagefontheight", php3_imagefontheight, NULL},
{"imagegif", php3_imagegif, NULL},
{"imageinterlace", php3_imageinterlace, NULL},
{"imageline", php3_imageline, NULL},
{"imageloadfont", php3_imageloadfont, NULL},
{"imagepolygon", php3_imagepolygon, NULL},
{"imagerectangle", php3_imagerectangle, NULL},
{"imagesetpixel", php3_imagesetpixel, NULL},
{"imagestring", php3_imagestring, NULL},
{"imagestringup", php3_imagestringup, NULL},
{"imagesx", php3_imagesxfn, NULL},
{"imagesy", php3_imagesyfn, NULL},
{"imagedashedline", php3_imagedashedline, NULL},
#if HAVE_LIBTTF
{"imagettfbbox", php3_imagettfbbox, NULL},
{"imagettftext", php3_imagettftext, NULL},
#endif
{NULL, NULL, NULL}
};
php3_module_entry gd_module_entry = {
"gd", gd_functions, php3_minit_gd, php3_mend_gd, NULL, NULL, php3_info_gd, STANDARD_MODULE_PROPERTIES
};
#if COMPILE_DL
# if PHP_31
# include "../phpdl.h"
# else
# include "dl/phpdl.h"
# endif
DLEXPORT php3_module_entry *get_module(void) { return &gd_module_entry; }
#endif
#define PolyMaxPoints 256
int php3_minit_gd(INIT_FUNC_ARGS)
{
#if defined(THREAD_SAFE)
gdlib_global_struct *gdlib_globals;
PHP3_MUTEX_ALLOC(gdlib_mutex);
PHP3_MUTEX_LOCK(gdlib_mutex);
numthreads++;
if (numthreads==1){
if (!PHP3_TLS_PROC_STARTUP(GDlibTls)){
PHP3_MUTEX_UNLOCK(gdlib_mutex);
PHP3_MUTEX_FREE(gdlib_mutex);
return FAILURE;
}
}
PHP3_MUTEX_UNLOCK(gdlib_mutex);
if(!PHP3_TLS_THREAD_INIT(GDlibTls,gdlib_globals,gdlib_global_struct)){
PHP3_MUTEX_FREE(gdlib_mutex);
return FAILURE;
}
#endif
GD_GLOBAL(le_gd) = register_list_destructors(gdImageDestroy, NULL);
GD_GLOBAL(le_gd_font) = register_list_destructors(php3_free_gd_font, NULL);
return SUCCESS;
}
void php3_info_gd(void) {
/* need to use a PHPAPI function here because it is external module in windows */
#if HAVE_LIBGD13
php3_printf("Version 1.3");
#else
php3_printf("Version 1.2");
#endif
#if HAVE_LIBTTF
php3_printf(" with FreeType support");
#endif
}
int php3_mend_gd(void){
GD_TLS_VARS;
#ifdef THREAD_SAFE
PHP3_TLS_THREAD_FREE(gdlib_globals);
PHP3_MUTEX_LOCK(gdlib_mutex);
numthreads--;
if (numthreads<1) {
PHP3_TLS_PROC_SHUTDOWN(GDlibTls);
PHP3_MUTEX_UNLOCK(gdlib_mutex);
PHP3_MUTEX_FREE(gdlib_mutex);
return SUCCESS;
}
PHP3_MUTEX_UNLOCK(gdlib_mutex);
#endif
return SUCCESS;
}
/********************************************************************/
/* gdImageColorResolve is a replacement for the old fragment: */
/* */
/* if ((color=gdImageColorExact(im,R,G,B)) < 0) */
/* if ((color=gdImageColorAllocate(im,R,G,B)) < 0) */
/* color=gdImageColorClosest(im,R,G,B); */
/* */
/* in a single function */
int
gdImageColorResolve(gdImagePtr im, int r, int g, int b)
{
int c;
int ct = -1;
int op = -1;
long rd, gd, bd, dist;
long mindist = 3*255*255; /* init to max poss dist */
for (c = 0; c < im->colorsTotal; c++) {
if (im->open[c]) {
op = c; /* Save open slot */
continue; /* Color not in use */
}
rd = (long)(im->red [c] - r);
gd = (long)(im->green[c] - g);
bd = (long)(im->blue [c] - b);
dist = rd * rd + gd * gd + bd * bd;
if (dist < mindist) {
if (dist == 0) {
return c; /* Return exact match color */
}
mindist = dist;
ct = c;
}
}
/* no exact match. We now know closest, but first try to allocate exact */
if (op == -1) {
op = im->colorsTotal;
if (op == gdMaxColors) { /* No room for more colors */
return ct; /* Return closest available color */
}
im->colorsTotal++;
}
im->red [op] = r;
im->green[op] = g;
im->blue [op] = b;
im->open [op] = 0;
return op; /* Return newly allocated color */
}
void php3_free_gd_font(gdFontPtr fp)
{
if (fp->data) {
efree(fp->data);
}
efree(fp);
}
/* {{{ proto int imageloadfont(string filename)
Load a new font */
void php3_imageloadfont(INTERNAL_FUNCTION_PARAMETERS) {
pval *file;
int hdr_size = sizeof(gdFont) - sizeof(char *);
int ind, body_size, n=0, b;
gdFontPtr font;
FILE *fp;
int issock=0, socketd=0;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string(file);
#if WIN32|WINNT
fp = fopen(file->value.str.val, "rb");
#else
fp = php3_fopen_wrapper(file->value.str.val, "r", IGNORE_PATH|IGNORE_URL_WIN, &issock, &socketd);
#endif
if (fp == NULL) {
php3_error(E_WARNING, "ImageFontLoad: unable to open file");
RETURN_FALSE;
}
/* Only supports a architecture-dependent binary dump format
* at the moment.
* The file format is like this on machines with 32-byte integers:
*
* byte 0-3: (int) number of characters in the font
* byte 4-7: (int) value of first character in the font (often 32, space)
* byte 8-11: (int) pixel width of each character
* byte 12-15: (int) pixel height of each character
* bytes 16-: (char) array with character data, one byte per pixel
* in each character, for a total of
* (nchars*width*height) bytes.
*/
font = (gdFontPtr)emalloc(sizeof(gdFont));
b = 0;
while (b < hdr_size && (n = fread(&font[b], 1, hdr_size - b, fp)))
b += n;
if (!n) {
fclose(fp);
efree(font);
if (feof(fp)) {
php3_error(E_WARNING, "ImageFontLoad: end of file while reading header");
} else {
php3_error(E_WARNING, "ImageFontLoad: error while reading header");
}
RETURN_FALSE;
}
body_size = font->w * font->h * font->nchars;
font->data = emalloc(body_size);
b = 0;
while (b < body_size && (n = fread(&font->data[b], 1, body_size - b, fp)))
b += n;
if (!n) {
fclose(fp);
efree(font->data);
efree(font);
if (feof(fp)) {
php3_error(E_WARNING, "ImageFontLoad: end of file while reading body");
} else {
php3_error(E_WARNING, "ImageFontLoad: error while reading body");
}
RETURN_FALSE;
}
fclose(fp);
/* Adding 5 to the font index so we will never have font indices
* that overlap with the old fonts (with indices 1-5). The first
* list index given out is always 1.
*/
ind = 5 + php3_list_insert(font, GD_GLOBAL(le_gd_font));
RETURN_LONG(ind);
}
/* }}} */
/* {{{ proto int imagecreate(int x_size, int y_size)
Create a new image */
void php3_imagecreate(INTERNAL_FUNCTION_PARAMETERS) {
pval *x_size, *y_size;
int ind;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &x_size, &y_size) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(x_size);
convert_to_long(y_size);
im = gdImageCreate(x_size->value.lval, y_size->value.lval);
ind = php3_list_insert(im, GD_GLOBAL(le_gd));
RETURN_LONG(ind);
}
/* }}} */
/* {{{ proto int imagecreatefromgif(string filename)
Create a new image from file or URL */
void php3_imagecreatefromgif (INTERNAL_FUNCTION_PARAMETERS) {
pval *file;
int ind;
gdImagePtr im;
char *fn=NULL;
FILE *fp;
int issock=0, socketd=0;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string(file);
fn = file->value.str.val;
#if WIN32|WINNT
fp = fopen(file->value.str.val, "rb");
#else
fp = php3_fopen_wrapper(file->value.str.val, "r", IGNORE_PATH|IGNORE_URL_WIN, &issock, &socketd);
#endif
if (!fp) {
php3_strip_url_passwd(fn);
php3_error(E_WARNING,
"ImageCreateFromGif: Unable to open %s for reading", fn);
RETURN_FALSE;
}
im = gdImageCreateFromGif (fp);
fflush(fp);
fclose(fp);
ind = php3_list_insert(im, GD_GLOBAL(le_gd));
RETURN_LONG(ind);
}
/* }}} */
/* {{{ proto int imagedestroy(int im)
Destroy an image */
void php3_imagedestroy(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &imgind) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
php3_list_delete(imgind->value.lval);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagecolorallocate(int im, int red, int green, int blue)
Allocate a color for an image */
void php3_imagecolorallocate(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *red, *green, *blue;
int ind, ind_type;
int col;
int r, g, b;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &imgind, &red,
&green, &blue) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(red);
convert_to_long(green);
convert_to_long(blue);
ind = imgind->value.lval;
r = red->value.lval;
g = green->value.lval;
b = blue->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorAllocate: Unable to find image pointer");
RETURN_FALSE;
}
col = gdImageColorAllocate(im, r, g, b);
RETURN_LONG(col);
}
/* }}} */
/* im, x, y */
/* {{{ proto int imagecolorat(int im, int x, int y)
Get the index of the color of a pixel */
void php3_imagecolorat(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *x, *y;
int ind, ind_type;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &imgind, &x, &y) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(x);
convert_to_long(y);
ind = imgind->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorAt: Unable to find image pointer");
RETURN_FALSE;
}
if (gdImageBoundsSafe(im, x->value.lval, y->value.lval)) {
#if HAVE_LIBGD13
RETURN_LONG(im->pixels[y->value.lval][x->value.lval]);
#else
RETURN_LONG(im->pixels[x->value.lval][y->value.lval]);
#endif
}
else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto int imagecolorclosest(int im, int red, int green, int blue)
Get the index of the closest color to the specified color */
void php3_imagecolorclosest(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *red, *green, *blue;
int ind, ind_type;
int col;
int r, g, b;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &imgind, &red,
&green, &blue) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(red);
convert_to_long(green);
convert_to_long(blue);
ind = imgind->value.lval;
r = red->value.lval;
g = green->value.lval;
b = blue->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorClosest: Unable to find image pointer");
RETURN_FALSE;
}
col = gdImageColorClosest(im, r, g, b);
RETURN_LONG(col);
}
/* }}} */
/* {{{ proto int imagecolordeallocate(int im, int index)
De-allocate a color for an image */
void php3_imagecolordeallocate(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *index;
int ind, ind_type, col;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &imgind, &index) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(index);
ind = imgind->value.lval;
col = index->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorDeallocate: Unable to find image pointer");
RETURN_FALSE;
}
if (col >= 0 && col < gdImageColorsTotal(im)) {
gdImageColorDeallocate(im, col);
RETURN_TRUE;
}
else {
php3_error(E_WARNING, "Color index out of range");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto int imagecolorresolve(int im, int red, int green, int blue)
Get the index of the specified color or its closest possible alternative */
void php3_imagecolorresolve(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *red, *green, *blue;
int ind, ind_type;
int col;
int r, g, b;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &imgind, &red,
&green, &blue) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(red);
convert_to_long(green);
convert_to_long(blue);
ind = imgind->value.lval;
r = red->value.lval;
g = green->value.lval;
b = blue->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorResolve: Unable to find image pointer");
RETURN_FALSE;
}
col = gdImageColorResolve(im, r, g, b);
RETURN_LONG(col);
}
/* }}} */
/* {{{ proto int imagecolorexact(int im, int red, int green, int blue)
Get the index of the specified color */
void php3_imagecolorexact(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *red, *green, *blue;
int ind, ind_type;
int col;
int r, g, b;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &imgind, &red,
&green, &blue) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(red);
convert_to_long(green);
convert_to_long(blue);
ind = imgind->value.lval;
r = red->value.lval;
g = green->value.lval;
b = blue->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorExact: Unable to find image pointer");
RETURN_FALSE;
}
col = gdImageColorExact(im, r, g, b);
RETURN_LONG(col);
}
/* }}} */
/* {{{ proto int imagecolorset(int im, int col, int red, int green, int blue)
Set the color for the specified palette index */
void php3_imagecolorset(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *color, *red, *green, *blue;
int ind, ind_type;
int col;
int r, g, b;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 5 || getParameters(ht, 5, &imgind, &color, &red, &green, &blue) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(color);
convert_to_long(red);
convert_to_long(green);
convert_to_long(blue);
ind = imgind->value.lval;
col = color->value.lval;
r = red->value.lval;
g = green->value.lval;
b = blue->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorSet: Unable to find image pointer");
RETURN_FALSE;
}
if (col >= 0 && col < gdImageColorsTotal(im)) {
im->red[col] = r;
im->green[col] = g;
im->blue[col] = b;
}
else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto array imagecolorsforindex(int im, int col)
Get the colors for an index */
void php3_imagecolorsforindex(INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *index;
int col, ind, ind_type;
gdImagePtr im;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &imgind, &index) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
convert_to_long(index);
ind = imgind->value.lval;
col = index->value.lval;
im = php3_list_find(ind, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageColorsForIndex: Unable to find image pointer");
RETURN_FALSE;
}
if (col >= 0 && col < gdImageColorsTotal(im)) {
if (array_init(return_value) == FAILURE) {
RETURN_FALSE;
}
add_assoc_long(return_value,"red",im->red[col]);
add_assoc_long(return_value,"green",im->green[col]);
add_assoc_long(return_value,"blue",im->blue[col]);
}
else {
php3_error(E_WARNING, "Color index out of range");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto int imagegif(int im, string filename)
Output image to browser or file */
void php3_imagegif (INTERNAL_FUNCTION_PARAMETERS) {
pval *imgind, *file;
gdImagePtr im;
char *fn=NULL;
FILE *fp;
int argc;
int ind_type;
int output=1;
GD_TLS_VARS;
argc = ARG_COUNT(ht);
if (argc < 1 || argc > 2 || getParameters(ht, argc, &imgind, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(imgind);
if (argc == 2) {
convert_to_string(file);
fn = file->value.str.val;
if (!fn || fn == empty_string || _php3_check_open_basedir(fn)) {
php3_error(E_WARNING, "ImageGif: Invalid filename");
RETURN_FALSE;
}
}
im = php3_list_find(imgind->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "ImageGif: unable to find image pointer");
RETURN_FALSE;
}
if (argc == 2) {
fp = fopen(fn, "wb");
if (!fp) {
php3_error(E_WARNING, "ImageGif: unable to open %s for writing", fn);
RETURN_FALSE;
}
gdImageGif (im,fp);
fflush(fp);
fclose(fp);
}
else {
int b;
FILE *tmp;
char buf[4096];
tmp = tmpfile();
if (tmp == NULL) {
php3_error(E_WARNING, "Unable to open temporary file");
RETURN_FALSE;
}
output = php3_header();
if (output) {
gdImageGif (im, tmp);
fseek(tmp, 0, SEEK_SET);
#if APACHE && defined(CHARSET_EBCDIC)
/* This is a binary file already: avoid EBCDIC->ASCII conversion */
ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
#endif
while ((b = fread(buf, 1, sizeof(buf), tmp)) > 0) {
php3_write(buf, b);
}
}
fclose(tmp);
/* the temporary file is automatically deleted */
}
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagesetpixel(int im, int x, int y, int col)
Set a single pixel */
void php3_imagesetpixel(INTERNAL_FUNCTION_PARAMETERS) {
pval *imarg, *xarg, *yarg, *colarg;
gdImagePtr im;
int col, y, x;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 ||
getParameters(ht, 4, &imarg, &xarg, &yarg, &colarg) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(imarg);
convert_to_long(xarg);
convert_to_long(yarg);
convert_to_long(colarg);
col = colarg->value.lval;
y = yarg->value.lval;
x = xarg->value.lval;
im = php3_list_find(imarg->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageSetPixel(im,x,y,col);
RETURN_TRUE;
}
/* }}} */
/* im, x1, y1, x2, y2, col */
/* {{{ proto int imageline(int im, int x1, int y1, int x2, int y2, int col)
Draw a line */
void php3_imageline(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *COL, *X1, *Y1, *X2, *Y2;
gdImagePtr im;
int col, y2, x2, y1, x1;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 6 ||
getParameters(ht, 6, &IM, &X1, &Y1, &X2, &Y2, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X1);
convert_to_long(Y1);
convert_to_long(X2);
convert_to_long(Y2);
convert_to_long(COL);
x1 = X1->value.lval;
y1 = Y1->value.lval;
x2 = X2->value.lval;
y2 = Y2->value.lval;
col = COL->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageLine(im,x1,y1,x2,y2,col);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagedashedline(int im, int x1, int y1, int x2, int y2, int col)
Draw a dashed line */
void php3_imagedashedline(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *COL, *X1, *Y1, *X2, *Y2;
gdImagePtr im;
int col, y2, x2, y1, x1;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 6 || getParameters(ht, 6, &IM, &X1, &Y1, &X2, &Y2, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X1);
convert_to_long(Y1);
convert_to_long(X2);
convert_to_long(Y2);
convert_to_long(COL);
x1 = X1->value.lval;
y1 = Y1->value.lval;
x2 = X2->value.lval;
y2 = Y2->value.lval;
col = COL->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageDashedLine(im,x1,y1,x2,y2,col);
RETURN_TRUE;
}
/* }}} */
/* im, x1, y1, x2, y2, col */
/* {{{ proto int imagerectangle(int im, int x1, int y1, int x2, int y2, int col)
Draw a rectangle */
void php3_imagerectangle(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *COL, *X1, *Y1, *X2, *Y2;
gdImagePtr im;
int col, y2, x2, y1, x1;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 6 ||
getParameters(ht, 6, &IM, &X1, &Y1, &X2, &Y2, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X1);
convert_to_long(Y1);
convert_to_long(X2);
convert_to_long(Y2);
convert_to_long(COL);
x1 = X1->value.lval;
y1 = Y1->value.lval;
x2 = X2->value.lval;
y2 = Y2->value.lval;
col = COL->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageRectangle(im,x1,y1,x2,y2,col);
RETURN_TRUE;
}
/* }}} */
/* im, x1, y1, x2, y2, col */
/* {{{ proto int imagefilledrectangle(int im, int x1, int y1, int x2, int y2, int col)
Draw a filled rectangle */
void php3_imagefilledrectangle(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *COL, *X1, *Y1, *X2, *Y2;
gdImagePtr im;
int col, y2, x2, y1, x1;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 6 ||
getParameters(ht, 6, &IM, &X1, &Y1, &X2, &Y2, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X1);
convert_to_long(Y1);
convert_to_long(X2);
convert_to_long(Y2);
convert_to_long(COL);
x1 = X1->value.lval;
y1 = Y1->value.lval;
x2 = X2->value.lval;
y2 = Y2->value.lval;
col = COL->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageFilledRectangle(im,x1,y1,x2,y2,col);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagearc(int im, int cx, int cy, int w, int h, int s, int e, int col)
Draw a partial ellipse */
void php3_imagearc(INTERNAL_FUNCTION_PARAMETERS) {
pval *COL, *E, *ST, *H, *W, *CY, *CX, *IM;
gdImagePtr im;
int col, e, st, h, w, cy, cx;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 8 ||
getParameters(ht, 8, &IM, &CX, &CY, &W, &H, &ST, &E, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(CX);
convert_to_long(CY);
convert_to_long(W);
convert_to_long(H);
convert_to_long(ST);
convert_to_long(E);
convert_to_long(COL);
col = COL->value.lval;
e = E->value.lval;
st = ST->value.lval;
h = H->value.lval;
w = W->value.lval;
cy = CY->value.lval;
cx = CX->value.lval;
if (e < 0) {
e %= 360;
}
if (st < 0) {
st %= 360;
}
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageArc(im,cx,cy,w,h,st,e,col);
RETURN_TRUE;
}
/* }}} */
/* im, x, y, border, col */
/* {{{ proto int imagefilltoborder(int im, int x, int y, int border, int col)
Flood fill to specific color */
void php3_imagefilltoborder(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *X, *Y, *BORDER, *COL;
gdImagePtr im;
int col, border, y, x;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 5 ||
getParameters(ht, 5, &IM, &X, &Y, &BORDER, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X);
convert_to_long(Y);
convert_to_long(BORDER);
convert_to_long(COL);
col = COL->value.lval;
border = BORDER->value.lval;
y = Y->value.lval;
x = X->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageFillToBorder(im,x,y,border,col);
RETURN_TRUE;
}
/* }}} */
/* im, x, y, col */
/* {{{ proto int imagefill(int im, int x, int y, int col)
Flood fill */
void php3_imagefill(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *X, *Y, *COL;
gdImagePtr im;
int col, y, x;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 ||
getParameters(ht, 4, &IM, &X, &Y, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(X);
convert_to_long(Y);
convert_to_long(COL);
col = COL->value.lval;
y = Y->value.lval;
x = X->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageFill(im,x,y,col);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagecolorstotal(int im)
Find out the number of colors in an image's palette */
void php3_imagecolorstotal(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM;
gdImagePtr im;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &IM) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
RETURN_LONG(gdImageColorsTotal(im));
}
/* }}} */
/* im, col */
/* {{{ proto int imagecolortransparent(int im [, int col])
Define a color as transparent */
void php3_imagecolortransparent(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *COL = NULL;
gdImagePtr im;
int col;
int ind_type;
GD_TLS_VARS;
switch(ARG_COUNT(ht)) {
case 1:
if (getParameters(ht, 1, &IM) == FAILURE) {
WRONG_PARAM_COUNT;
}
break;
case 2:
if (getParameters(ht, 2, &IM, &COL) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(COL);
break;
default:
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
if (COL != NULL) {
col = COL->value.lval;
gdImageColorTransparent(im,col);
}
col = gdImageGetTransparent(im);
RETURN_LONG(col);
}
/* }}} */
/* im, interlace */
/* {{{ proto int imageinterlace(int im [, int interlace])
Enable or disable interlace */
void php3_imageinterlace(INTERNAL_FUNCTION_PARAMETERS) {
pval *IM, *INT = NULL;
gdImagePtr im;
int interlace;
int ind_type;
GD_TLS_VARS;
switch(ARG_COUNT(ht)) {
case 1:
if (getParameters(ht, 1, &IM) == FAILURE) {
WRONG_PARAM_COUNT;
}
break;
case 2:
if (getParameters(ht, 2, &IM, &INT) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(INT);
break;
default:
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
if (INT != NULL) {
interlace = INT->value.lval;
gdImageInterlace(im,interlace);
}
interlace = gdImageGetInterlaced(im);
RETURN_LONG(interlace);
}
/* }}} */
/* arg = 0 normal polygon
arg = 1 filled polygon */
/* im, points, num_points, col */
static void _php3_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) {
pval *IM, *POINTS, *NPOINTS, *COL, *var;
gdImagePtr im;
gdPoint points[PolyMaxPoints];
int npoints, col, nelem, i;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 4 ||
getParameters(ht, 4, &IM, &POINTS, &NPOINTS, &COL) == FAILURE)
{
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(NPOINTS);
convert_to_long(COL);
npoints = NPOINTS->value.lval;
col = COL->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
if (POINTS->type != IS_ARRAY) {
php3_error(E_WARNING, "2nd argument to imagepolygon not an array");
RETURN_FALSE;
}
/*
** we shouldn't need this check, should we? **
if (!ParameterPassedByReference(ht, 2)) {
php3_error(E_WARNING, "2nd argument to imagepolygon not passed by reference");
RETURN_FALSE;
}
*/
nelem = _php3_hash_num_elements(POINTS->value.ht);
if (nelem < 6) {
php3_error(E_WARNING,
"you must have at least 3 points in your array");
RETURN_FALSE;
}
if (nelem < npoints * 2) {
php3_error(E_WARNING,
"trying to use %d points in array with only %d points",
npoints, nelem/2);
RETURN_FALSE;
}
if (npoints > PolyMaxPoints) {
php3_error(E_WARNING, "maximum %d points", PolyMaxPoints);
RETURN_FALSE;
}
for (i = 0; i < npoints; i++) {
if (_php3_hash_index_find(POINTS->value.ht, (i * 2), (void **)&var) == SUCCESS) {
convert_to_long(var);
points[i].x = var->value.lval;
}
if (_php3_hash_index_find(POINTS->value.ht, (i * 2) + 1, (void **)&var) == SUCCESS) {
convert_to_long(var);
points[i].y = var->value.lval;
}
}
if (filled) {
gdImageFilledPolygon(im, points, npoints, col);
}
else {
gdImagePolygon(im, points, npoints, col);
}
RETURN_TRUE;
}
/* {{{ proto int imagepolygon(int im, array point, int num_points, int col)
Draw a polygon */
void php3_imagepolygon(INTERNAL_FUNCTION_PARAMETERS)
{
_php3_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ proto int imagefilledpolygon(int im, array point, int num_points, int col)
Draw a filled polygon */
void php3_imagefilledpolygon(INTERNAL_FUNCTION_PARAMETERS)
{
_php3_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
static gdFontPtr _php3_find_gd_font(int size)
{
gdFontPtr font;
int ind_type;
GD_TLS_VARS;
switch (size) {
case 1:
font = gdFontTiny;
break;
case 2:
font = gdFontSmall;
break;
case 3:
font = gdFontMediumBold;
break;
case 4:
font = gdFontLarge;
break;
case 5:
font = gdFontGiant;
break;
default:
font = php3_list_find(size - 5, &ind_type);
if (!font || ind_type != GD_GLOBAL(le_gd_font)) {
if (size < 1) {
font = gdFontTiny;
} else {
font = gdFontGiant;
}
}
break;
}
return font;
}
/*
* arg = 0 ImageFontWidth
* arg = 1 ImageFontHeight
*/
static void _php3_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
{
pval *SIZE;
gdFontPtr font;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &SIZE) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(SIZE);
font = _php3_find_gd_font(SIZE->value.lval);
RETURN_LONG(arg ? font->h : font->w);
}
/* {{{ proto int imagefontwidth(int font)
Get font width */
void php3_imagefontwidth(INTERNAL_FUNCTION_PARAMETERS)
{
_php3_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ proto int imagefontheight(int font)
Get font height */
void php3_imagefontheight(INTERNAL_FUNCTION_PARAMETERS)
{
_php3_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
/* workaround for a bug in gd 1.2 */
void _php3_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c,
int color)
{
int cx, cy, px, py, fline;
cx = 0;
cy = 0;
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
return;
}
fline = (c - f->offset) * f->h * f->w;
for (py = y; (py > (y - f->w)); py--) {
for (px = x; (px < (x + f->h)); px++) {
if (f->data[fline + cy * f->w + cx]) {
gdImageSetPixel(im, px, py, color);
}
cy++;
}
cy = 0;
cx++;
}
}
/*
* arg = 0 ImageChar
* arg = 1 ImageCharUp
* arg = 2 ImageString
* arg = 3 ImageStringUp
*/
static void _php3_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) {
pval *IM, *SIZE, *X, *Y, *C, *COL;
gdImagePtr im;
int ch = 0, col, x, y, size, i, l = 0;
unsigned char *string = NULL;
int ind_type;
gdFontPtr font;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 6 ||
getParameters(ht, 6, &IM, &SIZE, &X, &Y, &C, &COL) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(IM);
convert_to_long(SIZE);
convert_to_long(X);
convert_to_long(Y);
convert_to_string(C);
convert_to_long(COL);
col = COL->value.lval;
if (mode < 2) {
ch = (int)((unsigned char)*(C->value.str.val));
} else {
string = (unsigned char *) estrndup(C->value.str.val,C->value.str.len);
l = strlen(string);
}
y = Y->value.lval;
x = X->value.lval;
size = SIZE->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
if (string) {
efree(string);
}
RETURN_FALSE;
}
font = _php3_find_gd_font(size);
switch(mode) {
case 0:
gdImageChar(im, font, x, y, ch, col);
break;
case 1:
_php3_gdimagecharup(im, font, x, y, ch, col);
break;
case 2:
for (i = 0; (i < l); i++) {
gdImageChar(im, font, x, y, (int)((unsigned char)string[i]),
col);
x += font->w;
}
break;
case 3: {
for (i = 0; (i < l); i++) {
/* _php3_gdimagecharup(im, font, x, y, (int)string[i], col); */
gdImageCharUp(im, font, x, y, (int)string[i], col);
y -= font->w;
}
break;
}
}
if (string) {
efree(string);
}
RETURN_TRUE;
}
/* {{{ proto int imagechar(int im, int font, int x, int y, string c, int col)
Draw a character */
void php3_imagechar(INTERNAL_FUNCTION_PARAMETERS) {
_php3_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
/* {{{ proto int imagecharup(int im, int font, int x, int y, string c, int col)
Draw a character rotated 90 degrees counter-clockwise */
void php3_imagecharup(INTERNAL_FUNCTION_PARAMETERS) {
_php3_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
/* }}} */
/* {{{ proto int imagestring(int im, int font, int x, int y, string str, int col)
Draw a string horizontally */
void php3_imagestring(INTERNAL_FUNCTION_PARAMETERS) {
_php3_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
}
/* }}} */
/* {{{ proto int imagestringup(int im, int font, int x, int y, string str, int col)
Draw a string vertically - rotated 90 degrees counter-clockwise */
void php3_imagestringup(INTERNAL_FUNCTION_PARAMETERS) {
_php3_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
}
/* }}} */
/* {{{ proto int imagecopy(int dst_im, int src_im, int dstX, int dstY, int srcX, int srcY, int srcW, int srcH)
Copy part of an image */
void php3_imagecopy(INTERNAL_FUNCTION_PARAMETERS)
{
pval *SIM, *DIM, *SX, *SY, *SW, *SH, *DX, *DY;
gdImagePtr im_dst;
gdImagePtr im_src;
int srcH, srcW, srcY, srcX, dstY, dstX;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 8 ||
getParameters(ht, 8, &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH)
== FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(SIM);
convert_to_long(DIM);
convert_to_long(SX);
convert_to_long(SY);
convert_to_long(SW);
convert_to_long(SH);
convert_to_long(DX);
convert_to_long(DY);
srcX = SX->value.lval;
srcY = SY->value.lval;
srcH = SH->value.lval;
srcW = SW->value.lval;
dstX = DX->value.lval;
dstY = DY->value.lval;
im_src = php3_list_find(SIM->value.lval, &ind_type);
if (!im_src || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
im_dst = php3_list_find(DIM->value.lval, &ind_type);
if (!im_dst || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageCopy(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagecopyresized(int dst_im, int src_im, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH);
Copy and resize part of an image */
void php3_imagecopyresized(INTERNAL_FUNCTION_PARAMETERS)
{
pval *SIM, *DIM, *SX, *SY, *SW, *SH, *DX, *DY, *DW, *DH;
gdImagePtr im_dst;
gdImagePtr im_src;
int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 10 ||
getParameters(ht, 10, &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH,
&SW, &SH) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long(SIM);
convert_to_long(DIM);
convert_to_long(SX);
convert_to_long(SY);
convert_to_long(SW);
convert_to_long(SH);
convert_to_long(DX);
convert_to_long(DY);
convert_to_long(DW);
convert_to_long(DH);
srcX = SX->value.lval;
srcY = SY->value.lval;
srcH = SH->value.lval;
srcW = SW->value.lval;
dstX = DX->value.lval;
dstY = DY->value.lval;
dstH = DH->value.lval;
dstW = DW->value.lval;
im_src = php3_list_find(SIM->value.lval, &ind_type);
if (!im_src || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
im_dst = php3_list_find(DIM->value.lval, &ind_type);
if (!im_dst || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH,
srcW, srcH);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int imagesx(int im)
Get image width */
void php3_imagesxfn(INTERNAL_FUNCTION_PARAMETERS)
{
pval *IM;
gdImagePtr im;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &IM) == FAILURE) {
WRONG_PARAM_COUNT;
}
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
RETURN_LONG(gdImageSX(im));
}
/* }}} */
/* {{{ proto int imagesy(int im)
Get image height */
void php3_imagesyfn(INTERNAL_FUNCTION_PARAMETERS)
{
pval *IM;
gdImagePtr im;
int ind_type;
GD_TLS_VARS;
if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &IM) == FAILURE) {
WRONG_PARAM_COUNT;
}
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
RETURN_LONG(gdImageSY(im));
}
/* }}} */
#if HAVE_LIBTTF
#define TTFTEXT_DRAW 0
#define TTFTEXT_BBOX 1
/* {{{ proto array imagettfbbox(int size, int angle, string font_file, string text)
Give the bounding box of a text using TrueType fonts */
void php3_imagettfbbox(INTERNAL_FUNCTION_PARAMETERS)
{
php3_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX);
}
/* }}} */
/* {{{ proto array imagettftext(int im, int size, int angle, int x, int y, int col, string font_file, string text)
Write text to the image using a TrueType font */
void php3_imagettftext(INTERNAL_FUNCTION_PARAMETERS)
{
php3_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW);
}
/* }}} */
static
void php3_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
pval *IM, *PTSIZE, *ANGLE, *X, *Y, *C, *FONTNAME, *COL;
gdImagePtr im;
int col, x, y, l=0, i;
int brect[8];
double ptsize, angle;
unsigned char *string = NULL, *fontname = NULL;
int ind_type;
char *error;
GD_TLS_VARS;
if (mode == TTFTEXT_BBOX) {
if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &PTSIZE, &ANGLE, &FONTNAME, &C) == FAILURE) {
WRONG_PARAM_COUNT;
}
} else {
if (ARG_COUNT(ht) != 8 || getParameters(ht, 8, &IM, &PTSIZE, &ANGLE, &X, &Y, &COL, &FONTNAME, &C) == FAILURE) {
WRONG_PARAM_COUNT;
}
}
convert_to_double(PTSIZE);
convert_to_double(ANGLE);
convert_to_string(FONTNAME);
convert_to_string(C);
if (mode == TTFTEXT_BBOX) {
im = NULL;
col = x = y = -1;
} else {
convert_to_long(X);
convert_to_long(Y);
convert_to_long(IM);
convert_to_long(COL);
col = COL->value.lval;
y = Y->value.lval;
x = X->value.lval;
im = php3_list_find(IM->value.lval, &ind_type);
if (!im || ind_type != GD_GLOBAL(le_gd)) {
php3_error(E_WARNING, "Unable to find image pointer");
RETURN_FALSE;
}
}
ptsize = PTSIZE->value.dval;
angle = ANGLE->value.dval * (M_PI/180); /* convert to radians */
string = (unsigned char *) C->value.str.val;
l = strlen(string);
fontname = (unsigned char *) FONTNAME->value.str.val;
error = gdttf(im, brect, col, fontname, ptsize, angle, x, y, string);
if (error) {
php3_error(E_WARNING, error);
RETURN_FALSE;
}
if (array_init(return_value) == FAILURE) {
RETURN_FALSE;
}
/* return array with the text's bounding box */
for (i = 0; i < 8; i++) {
add_next_index_long(return_value, brect[i]);
}
}
#endif
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/