diff -urN php-4.4.8.org/ext/gd/config.m4 php-4.4.8/ext/gd/config.m4 --- php-4.4.8.org/ext/gd/config.m4 2007-03-10 14:06:37.000000000 +0100 +++ php-4.4.8/ext/gd/config.m4 2008-01-22 22:38:05.833815388 +0100 @@ -259,12 +259,13 @@ PHP_CHECK_LIBRARY(gd, gdCacheCreate, [AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_FONTCACHESHUTDOWN,1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdFreeFontCache, [AC_DEFINE(HAVE_GD_FREEFONTCACHE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFontCacheMutexSetup, [AC_DEFINE(HAVE_GD_FONTMUTEX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx, [AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) ]) dnl dnl Main GD configure -dnl +dnl if test "$PHP_GD" = "yes"; then GD_MODULE_TYPE=builtin @@ -310,6 +311,7 @@ AC_DEFINE(HAVE_GD_GIF_CREATE, 1, [ ]) AC_DEFINE(HAVE_GD_IMAGEELLIPSE, 1, [ ]) AC_DEFINE(HAVE_GD_FONTCACHESHUTDOWN,1, [ ]) + AC_DEFINE(HAVE_GD_FONTMUTEX, 1, [ ]) AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ]) AC_DEFINE(HAVE_GD_GIF_CTX, 1, [ ]) diff -urN php-4.4.8.org/ext/gd/gd.c php-4.4.8/ext/gd/gd.c --- php-4.4.8.org/ext/gd/gd.c 2007-12-31 08:22:47.000000000 +0100 +++ php-4.4.8/ext/gd/gd.c 2008-01-22 22:38:05.837148890 +0100 @@ -29,7 +29,13 @@ #include "config.h" #endif +#ifdef HAVE_GD_PNG +/* needs to be first */ +#include +#endif + #include "php.h" +#include "php_ini.h" #include "ext/standard/head.h" #include #include "SAPI.h" @@ -46,6 +52,9 @@ #ifdef PHP_WIN32 # include # include +#include +#include +#include #endif #if HAVE_LIBGD @@ -64,10 +73,20 @@ #include /* 3 Medium bold font */ #include /* 4 Large font */ #include /* 5 Giant font */ +#if HAVE_GD_BUNDLED #ifdef HAVE_GD_WBMP #include "libgd/wbmp.h" #endif +#endif #ifdef ENABLE_GD_TTF +# ifdef HAVE_LIBFREETYPE +# include +# include FT_FREETYPE_H +# else +# ifdef HAVE_LIBTTF +# include +# endif +# endif # include "gdttf.h" #endif @@ -112,6 +131,40 @@ #define gdNewDynamicCtxEx(len, data, val) gdNewDynamicCtx(len, data) #endif +/* Section Filters Declarations */ +/* IMPORTANT NOTE FOR NEW FILTER + * Do not forget to update: + * IMAGE_FILTER_MAX: define the last filter index + * IMAGE_FILTER_MAX_ARGS: define the biggest amout of arguments + * image_filter array in PHP_FUNCTION(imagefilter) + * */ +#if HAVE_GD_BUNDLED +#define IMAGE_FILTER_NEGATE 0 +#define IMAGE_FILTER_GRAYSCALE 1 +#define IMAGE_FILTER_BRIGHTNESS 2 +#define IMAGE_FILTER_CONTRAST 3 +#define IMAGE_FILTER_COLORIZE 4 +#define IMAGE_FILTER_EDGEDETECT 5 +#define IMAGE_FILTER_EMBOSS 6 +#define IMAGE_FILTER_GAUSSIAN_BLUR 7 +#define IMAGE_FILTER_SELECTIVE_BLUR 8 +#define IMAGE_FILTER_MEAN_REMOVAL 9 +#define IMAGE_FILTER_SMOOTH 10 +#define IMAGE_FILTER_MAX 10 +#define IMAGE_FILTER_MAX_ARGS 5 +static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS); +static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS); +#endif +/* End Section filters declarations */ static gdImagePtr _php_image_create_from_string (zval **Data, char *tn, gdImagePtr (*ioctx_func_p)() TSRMLS_DC); static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()); static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()); @@ -121,7 +174,7 @@ /* {{{ gd_functions[] */ -function_entry gd_functions[] = { +zend_function_entry gd_functions[] = { PHP_FE(gd_info, NULL) PHP_FE(imagearc, NULL) PHP_FE(imageellipse, NULL) @@ -167,6 +220,11 @@ PHP_FE(imagecopyresampled, NULL) #endif +#ifdef PHP_WIN32 + PHP_FE(imagegrabwindow, NULL) + PHP_FE(imagegrabscreen, NULL) +#endif + #ifdef HAVE_GD_BUNDLED PHP_FE(imagerotate, NULL) PHP_FE(imageantialias, NULL) @@ -277,6 +335,12 @@ #if HAVE_GD_BUNDLED PHP_FE(imagelayereffect, NULL) PHP_FE(imagecolormatch, NULL) + PHP_FE(imagexbm, NULL) +#endif +/* gd filters */ +#ifdef HAVE_GD_BUNDLED + PHP_FE(imagefilter, NULL) + PHP_FE(imageconvolution, NULL) #endif {NULL, NULL, NULL} @@ -288,9 +352,13 @@ "gd", gd_functions, PHP_MINIT(gd), +#if HAVE_LIBT1 || HAVE_GD_FONTMUTEX PHP_MSHUTDOWN(gd), +#else + NULL, +#endif NULL, -#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE) +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_LIBFREETYPE && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE)) PHP_RSHUTDOWN(gd), #else NULL, @@ -304,6 +372,12 @@ ZEND_GET_MODULE(gd) #endif +/* {{{ PHP_INI_BEGIN */ +PHP_INI_BEGIN() + PHP_INI_ENTRY("gd.jpeg_ignore_warning", "0", PHP_INI_ALL, NULL) +PHP_INI_END() +/* }}} */ + /* {{{ php_free_gd_image */ static void php_free_gd_image(zend_rsrc_list_entry *rsrc TSRMLS_DC) @@ -326,15 +400,21 @@ } /* }}} */ + /* {{{ PHP_MSHUTDOWN_FUNCTION */ +#if HAVE_LIBT1 || HAVE_GD_FONTMUTEX PHP_MSHUTDOWN_FUNCTION(gd) { #if HAVE_LIBT1 T1_CloseLib(); #endif +#if HAVE_GD_FONTMUTEX && HAVE_LIBFREETYPE + gdFontCacheMutexShutdown(); +#endif return SUCCESS; } +#endif /* }}} */ @@ -344,6 +424,10 @@ { le_gd = zend_register_list_destructors_ex(php_free_gd_image, NULL, "gd", module_number); le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number); + +#if HAVE_GD_FONTMUTEX && HAVE_LIBFREETYPE + gdFontCacheMutexSetup(); +#endif #if HAVE_LIBT1 T1_SetBitmapPad(8); T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE); @@ -352,6 +436,8 @@ le_ps_enc = zend_register_list_destructors_ex(php_free_ps_enc, NULL, "gd PS encoding", module_number); #endif + REGISTER_INI_ENTRIES(); + REGISTER_LONG_CONSTANT("IMG_GIF", 1, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_JPG", 2, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_JPEG", 2, CONST_CS | CONST_PERSISTENT); @@ -387,16 +473,58 @@ REGISTER_LONG_CONSTANT("IMG_EFFECT_NORMAL", gdEffectNormal, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_EFFECT_OVERLAY", gdEffectOverlay, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("GD_BUNDLED", 1, CONST_CS | CONST_PERSISTENT); + + /* Section Filters */ + REGISTER_LONG_CONSTANT("IMG_FILTER_NEGATE", IMAGE_FILTER_NEGATE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_GRAYSCALE", IMAGE_FILTER_GRAYSCALE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_BRIGHTNESS", IMAGE_FILTER_BRIGHTNESS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_CONTRAST", IMAGE_FILTER_CONTRAST, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_COLORIZE", IMAGE_FILTER_COLORIZE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_EDGEDETECT", IMAGE_FILTER_EDGEDETECT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_GAUSSIAN_BLUR", IMAGE_FILTER_GAUSSIAN_BLUR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_SELECTIVE_BLUR", IMAGE_FILTER_SELECTIVE_BLUR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_EMBOSS", IMAGE_FILTER_EMBOSS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_MEAN_REMOVAL", IMAGE_FILTER_MEAN_REMOVAL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_FILTER_SMOOTH", IMAGE_FILTER_SMOOTH, CONST_CS | CONST_PERSISTENT); + /* End Section Filters */ #else REGISTER_LONG_CONSTANT("GD_BUNDLED", 0, CONST_CS | CONST_PERSISTENT); #endif + +#ifdef GD_VERSION_STRING + REGISTER_STRING_CONSTANT("GD_VERSION", GD_VERSION_STRING, CONST_CS | CONST_PERSISTENT); +#endif + +#if defined(GD_MAJOR_VERSION) && defined(GD_MINOR_VERSION) && defined(GD_RELEASE_VERSION) && defined(GD_EXTRA_VERSION) + REGISTER_LONG_CONSTANT("GD_MAJOR_VERSION", GD_MAJOR_VERSION, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("GD_MINOR_VERSION", GD_MINOR_VERSION, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("GD_RELEASE_VERSION", GD_RELEASE_VERSION, CONST_CS | CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("GD_EXTRA_VERSION", GD_EXTRA_VERSION, CONST_CS | CONST_PERSISTENT); +#endif + + +#ifdef HAVE_GD_PNG + +/* + * cannot include #include "png.h" + * /usr/include/pngconf.h:310:2: error: #error png.h already includes setjmp.h with some additional fixup. + * as error, use the values for now... + */ + REGISTER_LONG_CONSTANT("PNG_NO_FILTER", 0x00, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_FILTER_NONE", 0x08, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_FILTER_SUB", 0x10, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_FILTER_UP", 0x20, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_FILTER_AVG", 0x40, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_FILTER_PAETH", 0x80, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PNG_ALL_FILTERS", 0x08 | 0x10 | 0x20 | 0x40 | 0x80, CONST_CS | CONST_PERSISTENT); +#endif return SUCCESS; } /* }}} */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ -#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE) +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT && (HAVE_LIBFREETYPE && (HAVE_GD_FONTCACHESHUTDOWN || HAVE_GD_FREEFONTCACHE)) PHP_RSHUTDOWN_FUNCTION(gd) { #if HAVE_GD_FONTCACHESHUTDOWN @@ -410,7 +538,7 @@ /* }}} */ #if HAVE_GD_BUNDLED -#define PHP_GD_VERSION_STRING "bundled (2.0.28 compatible)" +#define PHP_GD_VERSION_STRING "bundled (2.0.34 compatible)" #elif HAVE_LIBGD20 #define PHP_GD_VERSION_STRING "2.0 or higher" #elif HAVE_GDIMAGECOLORRESOLVE @@ -436,8 +564,24 @@ php_info_print_table_row(2, "FreeType Support", "enabled"); #if HAVE_LIBFREETYPE php_info_print_table_row(2, "FreeType Linkage", "with freetype"); + { + char tmp[256]; +#ifdef FREETYPE_PATCH + snprintf(tmp, sizeof(tmp), "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH); +#elif defined(FREETYPE_MAJOR) + snprintf(tmp, sizeof(tmp), "%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR); +#else + snprintf(tmp, sizeof(tmp), "1.x"); +#endif + php_info_print_table_row(2, "FreeType Version", tmp); + } #elif HAVE_LIBTTF php_info_print_table_row(2, "FreeType Linkage", "with TTF library"); + { + char tmp[256]; + snprintf(tmp, sizeof(tmp), "%d.%d", TT_FREETYPE_MAJOR, TT_FREETYPE_MINOR); + php_info_print_table_row(2, "FreeType Version", tmp); + } #else php_info_print_table_row(2, "FreeType Linkage", "with unknown library"); #endif @@ -464,6 +608,9 @@ #ifdef HAVE_GD_WBMP php_info_print_table_row(2, "WBMP Support", "enabled"); #endif +#if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED) + php_info_print_table_row(2, "XPM Support", "enabled"); +#endif #ifdef HAVE_GD_XBM php_info_print_table_row(2, "XBM Support", "enabled"); #endif @@ -530,6 +677,11 @@ #else add_assoc_bool(return_value, "WBMP Support", 0); #endif +#if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED) + add_assoc_bool(return_value, "XPM Support", 1); +#else + add_assoc_bool(return_value, "XPM Support", 0); +#endif #ifdef HAVE_GD_XBM add_assoc_bool(return_value, "XBM Support", 1); #else @@ -548,6 +700,7 @@ { return le_gd; } +/* }}} */ #ifndef HAVE_GDIMAGECOLORRESOLVE @@ -763,13 +916,19 @@ convert_to_long_ex(x_size); convert_to_long_ex(y_size); - if (Z_LVAL_PP(x_size) <= 0 || Z_LVAL_PP(y_size) <= 0) { + if (Z_LVAL_PP(x_size) <= 0 || Z_LVAL_PP(y_size) <= 0 || + Z_LVAL_PP(x_size) >= INT_MAX || Z_LVAL_PP(y_size) >= INT_MAX + ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid image dimensions"); RETURN_FALSE; } im = gdImageCreateTrueColor(Z_LVAL_PP(x_size), Z_LVAL_PP(y_size)); + if (!im) { + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, im, le_gd); } /* }}} */ @@ -836,15 +995,19 @@ result = gdImageColorMatch(im1, im2); switch (result) { case -1: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Image1 must be TrueColor" ); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image1 must be TrueColor" ); RETURN_FALSE; break; case -2: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Image2 must be Palette" ); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image2 must be Palette" ); RETURN_FALSE; break; case -3: - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Image1 and Image2 must be the same size" ); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image1 and Image2 must be the same size" ); + RETURN_FALSE; + break; + case -4: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Image2 must have at least one color" ); RETURN_FALSE; break; } @@ -977,6 +1140,7 @@ RETURN_TRUE; } +/* }}} */ #endif #if HAVE_GD_BUNDLED @@ -1008,6 +1172,7 @@ zval *IM; long red, green, blue, alpha; gdImagePtr im; + int ct = (-1); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zllll", &IM, &red, &green, &blue, &alpha) == FAILURE) { RETURN_FALSE; @@ -1015,7 +1180,12 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); - RETURN_LONG(gdImageColorAllocateAlpha(im, red, green, blue, alpha)); + ct = gdImageColorAllocateAlpha(im, red, green, blue, alpha); + if (ct < 0) { + RETURN_FALSE; + } + + RETURN_LONG((long)ct); } /* }}} */ @@ -1125,28 +1295,173 @@ /* }}} */ #endif +#ifdef PHP_WIN32 +/* {{{ proto resource imagegrabwindow(int window_handle [, int client_area]) + Grab a window or its client area using a windows handle (HWND property in COM instance) */ +PHP_FUNCTION(imagegrabwindow) +{ + HWND window; + long client_area = 0; + RECT rc = {0}; + RECT rc_win = {0}; + int Width, Height; + HDC hdc; + HDC memDC; + HBITMAP memBM; + HBITMAP hOld; + HINSTANCE handle; + long lwindow_handle; + typedef BOOL (WINAPI *tPrintWindow)(HWND, HDC,UINT); + tPrintWindow pPrintWindow = 0; + gdImagePtr im; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &lwindow_handle, &client_area) == FAILURE) { + RETURN_FALSE; + } + + window = (HWND) lwindow_handle; + + if (!IsWindow(window)) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid window handle"); + RETURN_FALSE; + } + + hdc = GetDC(0); + + if (client_area) { + GetClientRect(window, &rc); + Width = rc.right; + Height = rc.bottom; + } else { + GetWindowRect(window, &rc); + Width = rc.right - rc.left; + Height = rc.bottom - rc.top; + } + + Width = (Width/4)*4; + + memDC = CreateCompatibleDC(hdc); + memBM = CreateCompatibleBitmap(hdc, Width, Height); + hOld = (HBITMAP) SelectObject (memDC, memBM); + + + handle = LoadLibrary("User32.dll"); + if ( handle == 0 ) { + goto clean; + } + pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow"); + + if ( pPrintWindow ) { + pPrintWindow(window, memDC, (UINT) client_area); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows API too old"); + RETURN_FALSE; + goto clean; + } + + FreeLibrary(handle); + + im = gdImageCreateTrueColor(Width, Height); + if (im) { + int x,y; + for (y=0; y <= Height; y++) { + for (x=0; x <= Width; x++) { + int c = GetPixel(memDC, x,y); + gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c))); + } + } + } + +clean: + SelectObject(memDC,hOld); + DeleteObject(memBM); + DeleteDC(memDC); + ReleaseDC( 0, hdc ); + + if (!im) { + RETURN_FALSE; + } else { + ZEND_REGISTER_RESOURCE(return_value, im, le_gd); + } +} +/* }}} */ + +/* {{{ proto resource imagegrabscreen() + Grab a screenshot */ +PHP_FUNCTION(imagegrabscreen) +{ + HWND window = GetDesktopWindow(); + RECT rc = {0}; + int Width, Height; + HDC hdc; + HDC memDC; + HBITMAP memBM; + HBITMAP hOld; + HINSTANCE handle; + long lwindow_handle; + typedef BOOL (WINAPI *tPrintWindow)(HWND, HDC,UINT); + tPrintWindow pPrintWindow = 0; + gdImagePtr im; + hdc = GetDC(0); + + if (!hdc) { + RETURN_FALSE; + } + + GetWindowRect(window, &rc); + Width = rc.right - rc.left; + Height = rc.bottom - rc.top; + + Width = (Width/4)*4; + + memDC = CreateCompatibleDC(hdc); + memBM = CreateCompatibleBitmap(hdc, Width, Height); + hOld = (HBITMAP) SelectObject (memDC, memBM); + BitBlt( memDC, 0, 0, Width, Height , hdc, rc.left, rc.top , SRCCOPY ); + + im = gdImageCreateTrueColor(Width, Height); + if (im) { + int x,y; + for (y=0; y <= Height; y++) { + for (x=0; x <= Width; x++) { + int c = GetPixel(memDC, x,y); + gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c))); + } + } + } + + SelectObject(memDC,hOld); + DeleteObject(memBM); + DeleteDC(memDC); + ReleaseDC( 0, hdc ); + + if (!im) { + RETURN_FALSE; + } else { + ZEND_REGISTER_RESOURCE(return_value, im, le_gd); + } +} +/* }}} */ +#endif /* PHP_WIN32 */ + #ifdef HAVE_GD_BUNDLED -/* {{{ proto resource imagerotate(resource src_im, float angle, int bgdcolor) +/* {{{ proto resource imagerotate(resource src_im, float angle, int bgdcolor [, int ignoretransparent]) Rotate an image using a custom angle */ PHP_FUNCTION(imagerotate) { - zval **SIM, **ANGLE, **BGDCOLOR; + zval *SIM; gdImagePtr im_dst, im_src; double degrees; long color; + long ignoretransparent = 0; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &SIM, &ANGLE, &BGDCOLOR) == FAILURE) { - ZEND_WRONG_PARAM_COUNT(); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rdl|l", &SIM, °rees, &color, &ignoretransparent) == FAILURE) { + RETURN_FALSE; } - ZEND_FETCH_RESOURCE(im_src, gdImagePtr, SIM, -1, "Image", le_gd); - - convert_to_long_ex(BGDCOLOR); - color = Z_LVAL_PP(BGDCOLOR); + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); - convert_to_double_ex(ANGLE); - degrees = Z_DVAL_PP(ANGLE); - im_dst = gdImageRotate(im_src, degrees, color); + im_dst = gdImageRotate(im_src, degrees, color, ignoretransparent); if (im_dst != NULL) { ZEND_REGISTER_RESOURCE(return_value, im_dst, le_gd); @@ -1215,13 +1530,19 @@ convert_to_long_ex(x_size); convert_to_long_ex(y_size); - if (Z_LVAL_PP(x_size) <= 0 || Z_LVAL_PP(y_size) <= 0) { + if (Z_LVAL_PP(x_size) <= 0 || Z_LVAL_PP(y_size) <= 0 || + Z_LVAL_PP(x_size) >= INT_MAX || Z_LVAL_PP(y_size) >= INT_MAX + ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid image dimensions"); RETURN_FALSE; } im = gdImageCreate(Z_LVAL_PP(x_size), Z_LVAL_PP(y_size)); + if (!im) { + RETURN_FALSE; + } + ZEND_REGISTER_RESOURCE(return_value, im, le_gd); } /* }}} */ @@ -1323,6 +1644,11 @@ im = (*ioctx_func_p)(io_ctx); if (!im) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passed data is not in '%s' format", tn); +#if HAVE_LIBGD204 + io_ctx->gd_free(io_ctx); +#else + io_ctx->free(io_ctx); +#endif return NULL; } @@ -1350,6 +1676,11 @@ } convert_to_string_ex(data); + if (Z_STRLEN_PP(data) < 8) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string or invalid image"); + RETURN_FALSE; + } + memcpy(sig, Z_STRVAL_PP(data), 8); imtype = _php_image_type(sig); @@ -1401,7 +1732,7 @@ break; default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is not in a recognized format."); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is not in a recognized format"); RETURN_FALSE; } @@ -1425,6 +1756,9 @@ php_stream *stream; FILE * fp = NULL; int argc=ZEND_NUM_ARGS(); +#ifdef HAVE_GD_JPG + long ignore_warning; +#endif if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 5) || (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) || @@ -1436,6 +1770,10 @@ if (argc == 5 && image_type == PHP_GDIMG_TYPE_GD2PART) { multi_convert_to_long_ex(4, srcx, srcy, width, height); + if (Z_LVAL_PP(width) < 1 || Z_LVAL_PP(height) < 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Zero width or height not allowed"); + RETURN_FALSE; + } } fn = Z_STRVAL_PP(file); @@ -1471,6 +1809,7 @@ io_ctx = gdNewDynamicCtxEx(buff_size, buff, 0); if (!io_ctx) { + pefree(buff, 1); php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot allocate GD IO context"); goto out_err; } @@ -1485,7 +1824,7 @@ #else io_ctx->free(io_ctx); #endif - + pefree(buff, 1); #endif } else { @@ -1505,6 +1844,18 @@ im = gdImageCreateFromXpm(fn); break; #endif + +#ifdef HAVE_GD_JPG + case PHP_GDIMG_TYPE_JPG: + ignore_warning = INI_INT("gd.jpeg_ignore_warning"); +#ifdef HAVE_GD_BUNDLED + im = gdImageCreateFromJpeg(fp, ignore_warning); +#else + im = gdImageCreateFromJpeg(fp); +#endif + break; +#endif + default: im = (*func_p)(fp); break; @@ -1685,6 +2036,14 @@ (*func_p)(im, fp); break; #endif +#ifdef HAVE_GD_GD2 + case PHP_GDIMG_TYPE_GD2: + if (q == -1) { + q = 128; + } + (*func_p)(im, fp, q, t); + break; +#endif default: if (q == -1) { q = 128; @@ -1737,6 +2096,14 @@ (*func_p)(im, tmp); break; #endif +#ifdef HAVE_GD_GD2 + case PHP_GDIMG_TYPE_GD2: + if (q == -1) { + q = 128; + } + (*func_p)(im, tmp, q, t); + break; +#endif default: (*func_p)(im, tmp); break; @@ -1762,6 +2129,16 @@ } /* }}} */ +/* {{{ proto int imagexbm(int im, string filename [, int foreground]) + Output XBM image to browser or file */ +#if HAVE_GD_BUNDLED +PHP_FUNCTION(imagexbm) +{ + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx); +} +#endif +/* }}} */ + #ifdef HAVE_GD_GIF_CREATE /* {{{ proto bool imagegif(resource im [, string filename]) Output GIF image to browser or file */ @@ -1782,7 +2159,7 @@ PHP_FUNCTION(imagepng) { #ifdef USE_GD_IOCTX - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtx); + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx); #else _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePng); #endif @@ -1862,6 +2239,7 @@ { zval **IM, **red, **green, **blue; gdImagePtr im; + int ct = (-1); if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -1872,8 +2250,11 @@ convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - - RETURN_LONG(gdImageColorAllocate(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); + ct = gdImageColorAllocate(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue)); + if (ct < 0) { + RETURN_FALSE; + } + RETURN_LONG(ct); } /* }}} */ @@ -2508,7 +2889,7 @@ static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) { zval **IM, **POINTS, **NPOINTS, **COL; - pval **var = NULL; + zval **var = NULL; gdImagePtr im; gdPointPtr points; int npoints, col, nelem, i; @@ -2716,7 +3097,7 @@ ch = (int)((unsigned char)*(Z_STRVAL_PP(C))); } else { str = (unsigned char *) estrndup(Z_STRVAL_PP(C), Z_STRLEN_PP(C)); - l = strlen(str); + l = strlen((char *)str); } y = Z_LVAL_PP(Y); @@ -3083,7 +3464,7 @@ { char tmp_font_path[MAXPATHLEN]; - if (VCWD_REALPATH(fontname, tmp_font_path)) { + if (VCWD_REALPATH((char *)fontname, tmp_font_path)) { fontname = (unsigned char *) fontname; } else { fontname = NULL; @@ -3093,16 +3474,18 @@ fontname = (unsigned char *) fontname; #endif + PHP_GD_CHECK_OPEN_BASEDIR((char *)fontname, "Invalid font filename"); + #ifdef USE_GD_IMGSTRTTF # if HAVE_GD_STRINGFTEX if (extended) { - error = gdImageStringFTEx(im, brect, col, fontname, ptsize, angle, x, y, str, &strex); + error = gdImageStringFTEx(im, brect, col, (char *)fontname, ptsize, angle, x, y, (char *)str, &strex); } else # endif # if HAVE_GD_STRINGFT - error = gdImageStringFT(im, brect, col, fontname, ptsize, angle, x, y, str); + error = gdImageStringFT(im, brect, col, (char *)fontname, ptsize, angle, x, y, (char *)str); # elif HAVE_GD_STRINGTTF error = gdImageStringTTF(im, brect, col, fontname, ptsize, angle, x, y, str); # endif @@ -3155,6 +3538,9 @@ { zval **file; int f_ind, *font; +#ifdef PHP_WIN32 + struct stat st; +#endif if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &file) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -3162,24 +3548,18 @@ convert_to_string_ex(file); +#ifdef PHP_WIN32 + if (VCWD_STAT(Z_STRVAL_PP(file), &st) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Font file not found (%s)", Z_STRVAL_PP(file)); + RETURN_FALSE; + } +#endif + f_ind = T1_AddFont(Z_STRVAL_PP(file)); if (f_ind < 0) { - switch (f_ind) { - case -1: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't find the font file"); - RETURN_FALSE; - break; - case -2: - case -3: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memory allocation fault in t1lib"); - RETURN_FALSE; - break; - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "An unknown error occurred in t1lib"); - RETURN_FALSE; - break; - } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "T1Lib Error (%i): %s", f_ind, T1_StrError(f_ind)); + RETURN_FALSE; } if (T1_LoadFont(f_ind)) { @@ -3317,6 +3697,11 @@ T1_DeleteAllSizes(*f_ind); + if (Z_DVAL_PP(ext) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second parameter %F out of range (must be > 0)", Z_DVAL_PP(ext)); + RETURN_FALSE; + } + if (T1_ExtendFont(*f_ind, Z_DVAL_PP(ext)) != 0) { RETURN_FALSE; } @@ -3348,7 +3733,7 @@ } /* }}} */ -/* {{{ proto array imagepstext(resource image, string text, resource font, int size, int xcoord, int ycoord [, int space, int tightness, float angle, int antialias]) +/* {{{ proto array imagepstext(resource image, string text, resource font, int size, int foreground, int background, int xcoord, int ycoord [, int space, int tightness, float angle, int antialias]) Rasterize a string over an image */ PHP_FUNCTION(imagepstext) { @@ -3371,11 +3756,6 @@ T1_TMATRIX *transform = NULL; char *str; int str_len; - int argc = ZEND_NUM_ARGS(); - - if (argc != 8 && argc != 12) { - ZEND_WRONG_PARAM_COUNT(); - } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrlllll|lldl", &img, &str, &str_len, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) { return; @@ -3455,7 +3835,7 @@ if (!str_path) { if (T1_errno) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "libt1 returned error %d", T1_errno); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "T1Lib Error: %s", T1_StrError(T1_errno)); } RETURN_FALSE; } @@ -3476,7 +3856,7 @@ str_img = T1_AASetString(*f_ind, str, str_len, space, T1_KERNING, size, transform); } if (T1_errno) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "libt1 returned error %d", T1_errno); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "T1Lib Error: %s", T1_StrError(T1_errno)); RETURN_FALSE; } @@ -3719,7 +4099,10 @@ int int_threshold; int x, y; float x_ratio, y_ratio; - +#ifdef HAVE_GD_JPG + long ignore_warning; +#endif + if (argc != 5 || zend_get_parameters_ex(argc, &f_org, &f_dest, &height, &width, &threshold) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } @@ -3775,7 +4158,12 @@ #ifdef HAVE_GD_JPG case PHP_GDIMG_TYPE_JPG: + ignore_warning = INI_INT("gd.jpeg_ignore_warning"); +#ifdef HAVE_GD_BUNDLED + im_org = gdImageCreateFromJpeg(org, ignore_warning); +#else im_org = gdImageCreateFromJpeg(org); +#endif if (im_org == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' Not a valid JPEG file", fn_dest); RETURN_FALSE; @@ -3886,7 +4274,282 @@ /* }}} */ #endif /* HAVE_GD_WBMP */ +#endif /* HAVE_LIBGD */ + +/* Section Filters */ #ifdef HAVE_GD_BUNDLED + +#define PHP_GD_SINGLE_RES \ + zval **SIM; \ + gdImagePtr im_src; \ + if (zend_get_parameters_ex(1, &SIM) == FAILURE) { \ + RETURN_FALSE; \ + } \ + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, SIM, -1, "Image", le_gd); \ + if (im_src == NULL) { \ + RETURN_FALSE; \ + } + +static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageNegate(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageGrayScale(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *SIM; + gdImagePtr im_src; + long brightness, tmp; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll", &SIM, &tmp, &brightness) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); + + if (im_src == NULL) { + RETURN_FALSE; + } + + if (gdImageBrightness(im_src, (int)brightness) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *SIM; + gdImagePtr im_src; + long contrast, tmp; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &SIM, &tmp, &contrast) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); + + if (im_src == NULL) { + RETURN_FALSE; + } + + if (gdImageContrast(im_src, (int)contrast) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *SIM; + gdImagePtr im_src; + long r,g,b,tmp; + long a = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllll|l", &SIM, &tmp, &r, &g, &b, &a) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); + + if (im_src == NULL) { + RETURN_FALSE; + } + + if (gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageEdgeDetectQuick(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageEmboss(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageGaussianBlur(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageSelectiveBlur(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS) +{ + PHP_GD_SINGLE_RES + + if (gdImageMeanRemoval(im_src) == 1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS) +{ + zval *SIM; + long tmp; + gdImagePtr im_src; + double weight; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rld", &SIM, &tmp, &weight) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); + + if (im_src == NULL) { + RETURN_FALSE; + } + + if (gdImageSmooth(im_src, (float)weight)==1) { + RETURN_TRUE; + } + + RETURN_FALSE; +} + +/* {{{ proto bool imagefilter(resource src_im, int filtertype, [args] ) + Applies Filter an image using a custom angle */ +PHP_FUNCTION(imagefilter) +{ + zval *tmp; + + typedef void (*image_filter)(INTERNAL_FUNCTION_PARAMETERS); + long filtertype; + image_filter filters[] = + { + php_image_filter_negate , + php_image_filter_grayscale, + php_image_filter_brightness, + php_image_filter_contrast, + php_image_filter_colorize, + php_image_filter_edgedetect, + php_image_filter_emboss, + php_image_filter_gaussian_blur, + php_image_filter_selective_blur, + php_image_filter_mean_removal, + php_image_filter_smooth + }; + + if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 6) { + WRONG_PARAM_COUNT; + } else if (zend_parse_parameters(2 TSRMLS_CC, "rl", &tmp, &filtertype) == FAILURE) { + return; + } + + if (filtertype >= 0 && filtertype <= IMAGE_FILTER_MAX) { + filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU); + } +} +/* }}} */ + +/* {{{ proto resource imageconvolution(resource src_im, array matrix3x3, double div, double offset) + Apply a 3x3 convolution matrix, using coefficient div and offset */ +PHP_FUNCTION(imageconvolution) +{ + zval *SIM, *hash_matrix; + zval **var = NULL, **var2 = NULL; + gdImagePtr im_src = NULL; + double div, offset; + int nelem, i, j, res; + float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "radd", &SIM, &hash_matrix, &div, &offset) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im_src, gdImagePtr, &SIM, -1, "Image", le_gd); + + nelem = zend_hash_num_elements(Z_ARRVAL_P(hash_matrix)); + if (nelem != 3) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must have 3x3 array"); + RETURN_FALSE; + } + + for (i=0; i<3; i++) { + if (zend_hash_index_find(Z_ARRVAL_P(hash_matrix), (i), (void **) &var) == SUCCESS && Z_TYPE_PP(var) == IS_ARRAY) { + if (Z_TYPE_PP(var) != IS_ARRAY || zend_hash_num_elements(Z_ARRVAL_PP(var)) != 3 ) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must have 3x3 array"); + RETURN_FALSE; + } + + for (j=0; j<3; j++) { + if (zend_hash_index_find(Z_ARRVAL_PP(var), (j), (void **) &var2) == SUCCESS) { + SEPARATE_ZVAL(var2); + convert_to_double(*var2); + matrix[i][j] = Z_DVAL_PP(var2); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must have a 3x3 matrix"); + RETURN_FALSE; + } + } + } + } + res = gdImageConvolution(im_src, matrix, div, offset); + + if (res) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* End section: Filters */ + /* {{{ proto bool imageantialias(resource im, bool on) Should antialiased functions used or not*/ PHP_FUNCTION(imageantialias) @@ -3908,8 +4571,6 @@ /* }}} */ #endif -#endif /* HAVE_LIBGD */ - /* * Local variables: * tab-width: 4 diff -urN php-4.4.8.org/ext/gd/gdcache.c php-4.4.8/ext/gd/gdcache.c --- php-4.4.8.org/ext/gd/gdcache.c 2005-01-09 22:05:31.000000000 +0100 +++ php-4.4.8/ext/gd/gdcache.c 2008-01-22 22:38:05.863816915 +0100 @@ -59,9 +59,9 @@ int size, gdCacheTestFn_t gdCacheTest, gdCacheFetchFn_t gdCacheFetch, - gdCacheReleaseFn_t gdCacheRelease ) + gdCacheReleaseFn_t gdCacheRelease ) { - gdCache_head_t *head; + gdCache_head_t *head; head = (gdCache_head_t *)pemalloc(sizeof(gdCache_head_t), 1); head->mru = NULL; diff -urN php-4.4.8.org/ext/gd/gd_ctx.c php-4.4.8/ext/gd/gd_ctx.c --- php-4.4.8.org/ext/gd/gd_ctx.c 2007-12-31 08:22:47.000000000 +0100 +++ php-4.4.8/ext/gd/gd_ctx.c 2008-01-22 22:38:05.863816915 +0100 @@ -15,11 +15,13 @@ | Authors: Stanislav Malyshev | +----------------------------------------------------------------------+ */ -#include "php_gd.h" +/* $Id$ */ + +#include "php_gd.h" #define CTX_PUTC(c,ctx) ctx->putC(ctx, c) - + static void _php_image_output_putc(struct gdIOCtx *ctx, int c) { /* without the following downcast, the write will fail @@ -43,20 +45,29 @@ efree(ctx); } } - -static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) + +/* {{{ _php_image_output_ctx */ +static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { - zval **imgind, **file, **quality; + zval **imgind, **file, **quality, **basefilter; gdImagePtr im; char *fn = NULL; FILE *fp = NULL; int argc = ZEND_NUM_ARGS(); int q = -1, i; + int f = -1; gdIOCtx *ctx; - /* The quality parameter for Wbmp stands for the threshold when called from image2wbmp() */ - - if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind, &file, &quality) == FAILURE) + /* The third (quality) parameter for Wbmp stands for the threshold when called from image2wbmp(). + * The third (quality) parameter for Wbmp and Xbm stands for the foreground color index when called + * from imagey(). + */ + + if (argc < 2 && image_type == PHP_GDIMG_TYPE_XBM) { + WRONG_PARAM_COUNT; + } + + if (argc < 1 || argc > 4 || zend_get_parameters_ex(argc, &imgind, &file, &quality, &basefilter) == FAILURE) { WRONG_PARAM_COUNT; } @@ -64,20 +75,27 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, imgind, -1, "Image", phpi_get_le_gd()); if (argc > 1) { - convert_to_string_ex(file); + if (argc >= 2 && Z_TYPE_PP(file) != IS_NULL) { + convert_to_string_ex(file); + } fn = Z_STRVAL_PP(file); - if (argc == 3) { + if (argc >= 3) { convert_to_long_ex(quality); - q = Z_LVAL_PP(quality); + q = Z_LVAL_PP(quality);/* or colorindex for foreground of BW images (defaults to black) */ + if (argc == 4) { + convert_to_long_ex(basefilter); + f = Z_LVAL_PP(basefilter); + } } } - if ((argc == 2) || (argc > 2 && Z_STRLEN_PP(file))) { + if (argc > 1 && (Z_TYPE_PP(file) != IS_NULL && ((argc == 2) || (argc > 2 && Z_STRLEN_PP(file))))) { + PHP_GD_CHECK_OPEN_BASEDIR(fn, "Invalid filename"); fp = VCWD_FOPEN(fn, "wb"); if (!fp) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing", fn); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing: %s", fn, strerror(errno)); RETURN_FALSE; } @@ -90,7 +108,7 @@ ctx->gd_free = _php_image_output_ctxfree; #else ctx->free = _php_image_output_ctxfree; -#endif +#endif #if APACHE && defined(CHARSET_EBCDIC) /* XXX this is unlikely to work any more thies@thieso.net */ @@ -107,27 +125,48 @@ case PHP_GDIMG_TYPE_JPG: (*func_p)(im, ctx, q); break; + case PHP_GDIMG_TYPE_PNG: + (*func_p)(im, ctx, q, f); + break; + case PHP_GDIMG_TYPE_XBM: case PHP_GDIMG_TYPE_WBM: - for(i=0; i < gdImageColorsTotal(im); i++) { - if(gdImageRed(im, i) == 0) break; - } - (*func_p)(im, i, ctx); + if (argc < 3) { + for(i=0; i < gdImageColorsTotal(im); i++) { + if(!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break; + } + q = i; + } + if (image_type == PHP_GDIMG_TYPE_XBM) { + (*func_p)(im, fn, q, ctx); + } else { + (*func_p)(im, q, ctx); + } break; default: (*func_p)(im, ctx); break; } -#if HAVE_LIBGD204 +#if HAVE_LIBGD204 ctx->gd_free(ctx); #else ctx->free(ctx); -#endif +#endif if(fp) { fflush(fp); fclose(fp); } - + RETURN_TRUE; } +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ diff -urN php-4.4.8.org/ext/gd/gdttf.c php-4.4.8/ext/gd/gdttf.c --- php-4.4.8.org/ext/gd/gdttf.c 2005-01-09 22:05:31.000000000 +0100 +++ php-4.4.8/ext/gd/gdttf.c 2008-01-22 22:38:05.887151436 +0100 @@ -42,15 +42,15 @@ /* ptsize below which anti-aliasing is ineffective */ #define MINANTIALIASPTSIZE 0 -/* display resolution - (Not really. This has to be 72 or hinting is wrong) */ +/* display resolution - (Not really. This has to be 72 or hinting is wrong) */ #define RESOLUTION 72 /* Number of colors used for anti-aliasing */ #undef NUMCOLORS #define NUMCOLORS 4 -/* Line separation as a factor of font height. - No space between if LINESPACE = 1.00 +/* Line separation as a factor of font height. + No space between if LINESPACE = 1.00 Line separation will be rounded up to next pixel row*/ #define LINESPACE 1.05 @@ -125,7 +125,7 @@ glyph_t *glyph; } bitmapkey_t; -typedef struct { +typedef struct { unsigned char pixel; /* key */ unsigned char bgcolor; /* key */ int fgcolor; /* key */ /* -ve means no antialias */ @@ -138,7 +138,7 @@ unsigned char bgcolor; /* key */ int fgcolor; /* key */ /* -ve means no antialias */ gdImagePtr im; /* key */ -} tweencolorkey_t; +} tweencolorkey_t; /* forward declarations so that glyphCache can be initialized by font code */ static int glyphTest ( void *element, void *key ); @@ -196,7 +196,7 @@ * *--------------------------------------------------------------------------- */ - + #ifndef CHARSET_EBCDIC #define ASC(ch) (ch) #else /*CHARSET_EBCDIC*/ @@ -205,17 +205,16 @@ #define Tcl_UniChar int #define TCL_UTF_MAX 3 -static int -gdTcl_UtfToUniChar(char *str, Tcl_UniChar *chPtr) +static int gdTcl_UtfToUniChar(char *str, Tcl_UniChar *chPtr) /* str is the UTF8 next character pointer */ /* chPtr is the int for the result */ { - int byte; - + int byte; + /* HTML4.0 entities in decimal form, e.g. Å */ - byte = *((unsigned char *) str); + byte = *((unsigned char *) str); if (byte == '&') { - int i, n=0; + int i, n = 0; byte = *((unsigned char *) (str+1)); if (byte == '#') { @@ -223,9 +222,9 @@ byte = *((unsigned char *) (str+i)); if (byte >= '0' && byte <= '9') { n = (n * 10) + (byte - '0'); - } - else + } else { break; + } } if (byte == ';') { *chPtr = (Tcl_UniChar) n; @@ -233,105 +232,91 @@ } } } - - /* - * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. - */ - - byte = ASC(*((unsigned char *) str)); - if (byte < 0xC0) { - /* - * Handles properly formed UTF-8 characters between 0x01 and 0x7F. - * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid - * characters representing themselves. - */ - *chPtr = (Tcl_UniChar) byte; - return 1; - } else if (byte < 0xE0) { - if ((ASC(str[1]) & 0xC0) == 0x80) { - /* - * Two-byte-character lead-byte followed by a trail-byte. - */ - - *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (ASC(str[1]) & 0x3F)); - return 2; - } - /* - * A two-byte-character lead-byte not followed by trail-byte - * represents itself. - */ - - *chPtr = (Tcl_UniChar) byte; - return 1; - } else if (byte < 0xF0) { - if (((ASC(str[1]) & 0xC0) == 0x80) && ((ASC(str[2]) & 0xC0) == 0x80)) { - /* - * Three-byte-character lead byte followed by two trail bytes. - */ - - *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) - | ((ASC(str[1]) & 0x3F) << 6) | (ASC(str[2]) & 0x3F)); - return 3; - } - /* - * A three-byte-character lead-byte not followed by two trail-bytes - * represents itself. - */ + /* Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ - *chPtr = (Tcl_UniChar) byte; - return 1; - } + byte = ASC(*((unsigned char *) str)); + if (byte < 0xC0) { + /* + * Handles properly formed UTF-8 characters between 0x01 and 0x7F. + * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid + * characters representing themselves. + */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } else if (byte < 0xE0) { + if ((ASC(str[1]) & 0xC0) == 0x80) { + /* Two-byte-character lead-byte followed by a trail-byte. */ + + *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (ASC(str[1]) & 0x3F)); + return 2; + } + /* + * A two-byte-character lead-byte not followed by trail-byte + * represents itself. + */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } else if (byte < 0xF0) { + if (((ASC(str[1]) & 0xC0) == 0x80) && ((ASC(str[2]) & 0xC0) == 0x80)) { + /* Three-byte-character lead byte followed by two trail bytes. */ + + *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((ASC(str[1]) & 0x3F) << 6) | (ASC(str[2]) & 0x3F)); + return 3; + } + /* A three-byte-character lead-byte not followed by two trail-bytes represents itself. */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } #if TCL_UTF_MAX > 3 - else { - int ch, total, trail; + else { + int ch, total, trail; - total = totalBytes[byte]; - trail = total - 1; - if (trail > 0) { - ch = byte & (0x3F >> trail); - do { - str++; - if ((ASC(*str) & 0xC0) != 0x80) { - *chPtr = byte; - return 1; - } - ch <<= 6; - ch |= (ASC(*str) & 0x3F); - trail--; - } while (trail > 0); - *chPtr = ch; - return total; + total = totalBytes[byte]; + trail = total - 1; + if (trail > 0) { + ch = byte & (0x3F >> trail); + do { + str++; + if ((ASC(*str) & 0xC0) != 0x80) { + *chPtr = byte; + return 1; + } + ch <<= 6; + ch |= (ASC(*str) & 0x3F); + trail--; + } while (trail > 0); + *chPtr = ch; + return total; + } } - } #endif - *chPtr = (Tcl_UniChar) byte; - return 1; + *chPtr = (Tcl_UniChar) byte; + return 1; } /********************************************************************/ /* font cache functions */ -static int -fontTest ( void *element, void *key ) +static int fontTest ( void *element, void *key ) { - font_t *a=(font_t *)element; - fontkey_t *b=(fontkey_t *)key; + font_t *a = (font_t *)element; + fontkey_t *b = (fontkey_t *)key; - return ( strcmp(a->fontname, b->fontname) == 0 - && a->ptsize == b->ptsize - && a->angle == b->angle); + return (strcmp(a->fontname, b->fontname) == 0 && a->ptsize == b->ptsize && a->angle == b->angle); } -static void * -fontFetch ( char **error, void *key ) +static void * fontFetch ( char **error, void *key ) { - TT_Error err; - font_t *a; - fontkey_t *b=(fontkey_t *)key; - int i, n, map_found; - short platform, encoding; + TT_Error err; + font_t *a; + fontkey_t *b = (fontkey_t *)key; + int i, n, map_found; + short platform, encoding; TSRMLS_FETCH(); a = (font_t *)pemalloc(sizeof(font_t), 1); @@ -354,8 +339,7 @@ if ((err = TT_Open_Face(*b->engine, a->fontname, &a->face))) { if (err == TT_Err_Could_Not_Open_File) { *error = "Could not find/open font"; - } - else { + } else { *error = "Could not read font"; } pefree(a, 1); @@ -370,7 +354,7 @@ pefree(a, 1); return NULL; } - + if (TT_Set_Instance_Resolutions(a->instance, RESOLUTION, RESOLUTION)) { *error = "Could not set device resolutions"; pefree(a, 1); @@ -384,12 +368,12 @@ } TT_Get_Instance_Metrics(a->instance, &a->imetrics); - + /* First, look for a Unicode charmap */ n = TT_Get_CharMap_Count(a->face); for (i = 0; i < n; i++) { - TT_Get_CharMap_ID(a->face, i, &platform, &encoding); + TT_Get_CharMap_ID(a->face, i, &platform, &encoding); if ((platform == 3 && encoding == 1) /* Windows Unicode */ || (platform == 2 && encoding == 1) || (platform == 0)) { /* ?? Unicode */ @@ -407,7 +391,7 @@ } } - if (! map_found) { + if (!map_found) { *error = "Unable to find a CharMap that I can handle"; pefree(a, 1); return NULL; @@ -418,16 +402,14 @@ a->matrix.xy = - a->matrix.yx; a->matrix.yy = a->matrix.xx; - a->glyphCache = gdCacheCreate( GLYPHCACHESIZE, - glyphTest, glyphFetch, glyphRelease); + a->glyphCache = gdCacheCreate(GLYPHCACHESIZE, glyphTest, glyphFetch, glyphRelease); return (void *)a; } -static void -fontRelease( void *element ) +static void fontRelease( void *element ) { - font_t *a=(font_t *)element; + font_t *a = (font_t *)element; gdCacheDelete(a->glyphCache); TT_Done_Instance(a->instance); @@ -439,26 +421,22 @@ /********************************************************************/ /* glyph cache functions */ -static int -glyphTest ( void *element, void *key ) +static int glyphTest ( void *element, void *key ) { - glyph_t *a=(glyph_t *)element; - glyphkey_t *b=(glyphkey_t *)key; + glyph_t *a = (glyph_t *)element; + glyphkey_t *b = (glyphkey_t *)key; + + return (a->character == b->character && a->hinting == b->hinting && a->gray_render == b->gray_render); +} - return (a->character == b->character - && a->hinting == b->hinting - && a->gray_render == b->gray_render); -} - -static void * -glyphFetch ( char **error, void *key ) -{ - glyph_t *a; - glyphkey_t *b=(glyphkey_t *)key; - short glyph_code; - int flags, err; - int crect[8], xmin, xmax, ymin, ymax; - double cos_a, sin_a; +static void * glyphFetch ( char **error, void *key ) +{ + glyph_t *a; + glyphkey_t *b = (glyphkey_t *)key; + short glyph_code; + int flags, err; + int crect[8], xmin, xmax, ymin, ymax; + double cos_a, sin_a; a = (glyph_t *)pemalloc(sizeof(glyph_t), 1); a->character = b->character; @@ -523,38 +501,34 @@ a->Bit.flow = TT_Flow_Up; if (a->gray_render) { a->Bit.cols = a->Bit.width; /* 1 byte per pixel */ - } - else { + } else { a->Bit.cols = (a->Bit.width + 7) / 8; /* 1 bit per pixel */ } a->Bit.cols = (a->Bit.cols + 3) & ~3; /* pad to 32 bits */ a->Bit.size = a->Bit.rows * a->Bit.cols; /* # of bytes in buffer */ a->Bit.bitmap = NULL; - a->bitmapCache = gdCacheCreate( BITMAPCACHESIZE, - bitmapTest, bitmapFetch, bitmapRelease); + a->bitmapCache = gdCacheCreate(BITMAPCACHESIZE, bitmapTest, bitmapFetch, bitmapRelease); return (void *)a; } -static void -glyphRelease( void *element ) +static void glyphRelease( void *element ) { - glyph_t *a=(glyph_t *)element; + glyph_t *a = (glyph_t *)element; gdCacheDelete(a->bitmapCache); - TT_Done_Glyph( a->glyph ); - pefree ((char *)element, 1); + TT_Done_Glyph(a->glyph); + pefree((char *)element, 1); } /********************************************************************/ /* bitmap cache functions */ -static int -bitmapTest ( void *element, void *key ) +static int bitmapTest ( void *element, void *key ) { - bitmap_t *a=(bitmap_t *)element; - bitmapkey_t *b=(bitmapkey_t *)key; + bitmap_t *a = (bitmap_t *)element; + bitmapkey_t *b = (bitmapkey_t *)key; if (a->xoffset == b->xoffset && a->yoffset == b->yoffset) { b->glyph->Bit.bitmap = a->bitmap; @@ -563,11 +537,10 @@ return FALSE; } -static void * -bitmapFetch ( char **error, void *key ) +static void * bitmapFetch ( char **error, void *key ) { - bitmap_t *a; - bitmapkey_t *b=(bitmapkey_t *)key; + bitmap_t *a; + bitmapkey_t *b = (bitmapkey_t *)key; a = (bitmap_t *)pemalloc(sizeof(bitmap_t), 1); a->xoffset = b->xoffset; @@ -577,56 +550,47 @@ memset(a->bitmap, 0, b->glyph->Bit.size); /* render glyph */ if (b->glyph->gray_render) { - TT_Get_Glyph_Pixmap(b->glyph->glyph, &b->glyph->Bit, - a->xoffset, a->yoffset); - } - else { - TT_Get_Glyph_Bitmap(b->glyph->glyph, &b->glyph->Bit, - a->xoffset, a->yoffset); + TT_Get_Glyph_Pixmap(b->glyph->glyph, &b->glyph->Bit, a->xoffset, a->yoffset); + } else { + TT_Get_Glyph_Bitmap(b->glyph->glyph, &b->glyph->Bit, a->xoffset, a->yoffset); } return (void *)a; } -static void -bitmapRelease( void *element ) +static void bitmapRelease( void *element ) { - bitmap_t *a=(bitmap_t *)element; + bitmap_t *a = (bitmap_t *)element; - pefree (a->bitmap, 1); - pefree ((char *)element, 1); + pefree(a->bitmap, 1); + pefree((char *)element, 1); } /********************************************************************/ /* tweencolor cache functions */ -static int -tweenColorTest (void *element, void *key) -{ - tweencolor_t *a=(tweencolor_t *)element; - tweencolorkey_t *b=(tweencolorkey_t *)key; - - return (a->pixel == b->pixel - && a->bgcolor == b->bgcolor - && a->fgcolor == b->fgcolor - && a->im == b->im); -} +static int tweenColorTest (void *element, void *key) +{ + tweencolor_t *a = (tweencolor_t *)element; + tweencolorkey_t *b = (tweencolorkey_t *)key; + + return (a->pixel == b->pixel && a->bgcolor == b->bgcolor && a->fgcolor == b->fgcolor && a->im == b->im); +} -static void * -tweenColorFetch (char **error, void *key) +static void * tweenColorFetch (char **error, void *key) { - tweencolor_t *a; - tweencolorkey_t *b=(tweencolorkey_t *)key; + tweencolor_t *a; + tweencolorkey_t *b = (tweencolorkey_t *)key; int pixel, npixel, bg, fg; gdImagePtr im; - - a = (tweencolor_t *)pemalloc(sizeof(tweencolor_t), 1); + + a = (tweencolor_t *)pemalloc(sizeof(tweencolor_t), 1); pixel = a->pixel = b->pixel; bg = a->bgcolor = b->bgcolor; fg = a->fgcolor = b->fgcolor; im = b->im; /* if fg is specified by a negative color idx, then don't antialias */ - if (fg <0) { + if (fg < 0) { a->tweencolor = -fg; } else { npixel = NUMCOLORS - pixel; @@ -635,20 +599,19 @@ (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS, (pixel * im->blue [fg] + npixel * im->blue [bg]) / NUMCOLORS); } - *error = NULL; - return (void *)a; -} - -static void -tweenColorRelease(void *element) -{ - pefree((char *)element, 1); -} + *error = NULL; + return (void *)a; +} + +static void tweenColorRelease(void *element) +{ + pefree((char *)element, 1); +} /********************************************************************/ /* gdttfchar - render one character onto a gd image */ -static int OneTime=0; +static int OneTime = 0; static gdCache_head_t *tweenColorCache; char * @@ -656,38 +619,37 @@ int x, int y, /* string start pos in pixels */ TT_F26Dot6 x1, TT_F26Dot6 y1, /* char start offset (*64) from x,y */ TT_F26Dot6 *advance, - TT_BBox **bbox, + TT_BBox **bbox, char **next) { - int pc, ch, len; + int pc, ch, len; int row, col; - int x2, y2; /* char start pos in pixels */ + int x2, y2; /* char start pos in pixels */ int x3, y3; /* current pixel pos */ unsigned char *pixel; - glyph_t *glyph; - glyphkey_t glyphkey; - bitmapkey_t bitmapkey; + glyph_t *glyph; + glyphkey_t glyphkey; + bitmapkey_t bitmapkey; tweencolor_t *tweencolor; tweencolorkey_t tweencolorkey; /****** set up tweenColorCache on first call ************/ - if (! OneTime) { - tweenColorCache = gdCacheCreate(TWEENCOLORCACHESIZE, - tweenColorTest, tweenColorFetch, tweenColorRelease); + if (!OneTime) { + tweenColorCache = gdCacheCreate(TWEENCOLORCACHESIZE, tweenColorTest, tweenColorFetch, tweenColorRelease); OneTime++; } /**************/ if (font->have_char_map_Unicode) { /* use UTF-8 mapping from ASCII */ - len = gdTcl_UtfToUniChar(*next, &ch); - *next += len; + len = gdTcl_UtfToUniChar(*next, &ch); + *next += len; } else { - /* - * Big 5 mapping: - * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref: - * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs - */ + /* + * Big 5 mapping: + * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref: + * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs + */ ch = (**next) & 255; /* don't extend sign */ (*next)++; if (ch >= 161 /* first code of JIS-8 pair */ @@ -700,18 +662,20 @@ glyphkey.character = ch; glyphkey.hinting = 1; /* if fg is specified by a negative color idx, then don't antialias */ - glyphkey.gray_render = ((font->ptsize < MINANTIALIASPTSIZE) || (fg <0))?FALSE:TRUE; - glyphkey.font = font; - glyph = (glyph_t *)gdCacheGet(font->glyphCache, &glyphkey); - if (! glyph) + glyphkey.gray_render = ((font->ptsize < MINANTIALIASPTSIZE) || (fg < 0)) ? FALSE : TRUE; + glyphkey.font = font; + glyph = (glyph_t *)gdCacheGet(font->glyphCache, &glyphkey); + if (!glyph) { return font->glyphCache->error; + } *bbox = &glyph->metrics.bbox; *advance = glyph->metrics.advance; /* if null *im, or invalid color, then assume user just wants brect */ - if (!im || fg > 255 || fg < -255) + if (!im || fg > 255 || fg < -255) { return (char *)NULL; + } /* render (via cache) a bitmap for the current fractional offset */ bitmapkey.xoffset = ((x1+32) & 63) - 32 - ((glyph->xmin+32) & -64); @@ -720,30 +684,32 @@ gdCacheGet(glyph->bitmapCache, &bitmapkey); /* copy to gif, mapping colors */ - x2 = x + (((glyph->xmin+32) & -64) + ((x1+32) & -64)) / 64; - y2 = y - (((glyph->ymin+32) & -64) + ((y1+32) & -64)) / 64; + x2 = x + (((glyph->xmin+32) & -64) + ((x1+32) & -64)) / 64; + y2 = y - (((glyph->ymin+32) & -64) + ((y1+32) & -64)) / 64; tweencolorkey.fgcolor = fg; tweencolorkey.im = im; for (row = 0; row < glyph->Bit.rows; row++) { - if (glyph->gray_render) + if (glyph->gray_render) { pc = row * glyph->Bit.cols; - else + } else { pc = row * glyph->Bit.cols * 8; + } y3 = y2 - row; - if (y3 >= im->sy || y3 < 0) continue; + if (y3 >= im->sy || y3 < 0) { + continue; + } for (col = 0; col < glyph->Bit.width; col++, pc++) { if (glyph->gray_render) { - tweencolorkey.pixel = - *((unsigned char *)(glyph->Bit.bitmap) + pc); + tweencolorkey.pixel = *((unsigned char *)(glyph->Bit.bitmap) + pc); } else { - tweencolorkey.pixel = - (((*((unsigned char *)(glyph->Bit.bitmap) + pc/8)) - <<(pc%8))&128)?4:0; + tweencolorkey.pixel = (((*((unsigned char *)(glyph->Bit.bitmap) + pc/8)) << (pc%8))&128)?4:0; } /* if not background */ if (tweencolorkey.pixel > 0) { x3 = x2 + col; - if (x3 >= im->sx || x3 < 0) continue; + if (x3 >= im->sx || x3 < 0) { + continue; + } #if HAVE_LIBGD20 if (im->trueColor) { pixel = &im->tpixels[y3][x3]; @@ -757,8 +723,7 @@ #endif } tweencolorkey.bgcolor = *pixel; - tweencolor = (tweencolor_t *)gdCacheGet( - tweenColorCache, &tweencolorkey); + tweencolor = (tweencolor_t *)gdCacheGet(tweenColorCache, &tweencolorkey); *pixel = tweencolor->tweencolor; } } @@ -769,29 +734,26 @@ /********************************************************************/ /* gdttf - render a utf8 string onto a gd image */ -char * -gdttf(gdImage *im, int *brect, int fg, char *fontname, - double ptsize, double angle, int x, int y, char *str) +char * gdttf(gdImage *im, int *brect, int fg, char *fontname, double ptsize, double angle, int x, int y, char *str) { - TT_F26Dot6 ur_x=0, ur_y=0, ll_x=0, ll_y=0; + TT_F26Dot6 ur_x = 0, ur_y = 0, ll_x = 0, ll_y = 0; TT_F26Dot6 advance_x, advance_y, advance, x1, y1; TT_BBox *bbox; double sin_a, cos_a; - int i=0, ch; + int i=0, ch; font_t *font; fontkey_t fontkey; char *error, *next; /****** initialize font engine on first call ************/ - static gdCache_head_t *fontCache; + static gdCache_head_t *fontCache; static TT_Engine engine; - if (! fontCache) { + if (!fontCache) { if (TT_Init_FreeType(&engine)) { return "Failure to initialize font engine"; } - fontCache = gdCacheCreate( FONTCACHESIZE, - fontTest, fontFetch, fontRelease); + fontCache = gdCacheCreate(FONTCACHESIZE, fontTest, fontFetch, fontRelease); } /**************/ @@ -801,15 +763,15 @@ fontkey.angle = angle; fontkey.engine = &engine; font = (font_t *)gdCacheGet(fontCache, &fontkey); - if (! font) { + if (!font) { return fontCache->error; } sin_a = font->sin_a; cos_a = font->cos_a; advance_x = advance_y = 0; - next=str; - while (*next) { + next = str; + while (*next) { ch = *next; /* carriage returns */ @@ -820,8 +782,8 @@ } /* newlines */ if (ch == '\n') { - advance_y -= (TT_F26Dot6)(font->imetrics.y_ppem * LINESPACE * 64); - advance_y = (advance_y-32) & -64; /* round to next pixel row */ + advance_y -= (TT_F26Dot6)(font->imetrics.y_ppem * LINESPACE * 64); + advance_y = (advance_y-32) & -64; /* round to next pixel row */ next++; continue; } @@ -829,20 +791,24 @@ x1 = (TT_F26Dot6)(advance_x * cos_a - advance_y * sin_a); y1 = (TT_F26Dot6)(advance_x * sin_a + advance_y * cos_a); - if ((error=gdttfchar(im, fg, font, x, y, x1, y1, &advance, &bbox, &next))) + if ((error = gdttfchar(im, fg, font, x, y, x1, y1, &advance, &bbox, &next))) { return error; + } - if (! i++) { /* if first character, init BB corner values */ + if (!i++) { /* if first character, init BB corner values */ ll_x = bbox->xMin; ll_y = bbox->yMin; ur_x = bbox->xMax; ur_y = bbox->yMax; - } - else { - if (! advance_x) ll_x = MIN(bbox->xMin, ll_x); + } else { + if (!advance_x) { + ll_x = MIN(bbox->xMin, ll_x); + } ll_y = MIN(advance_y + bbox->yMin, ll_y); ur_x = MAX(advance_x + bbox->xMax, ur_x); - if (! advance_y) ur_y = MAX(bbox->yMax, ur_y); + if (!advance_y) { + ur_y = MAX(bbox->yMax, ur_y); + } } advance_x += advance; } @@ -859,7 +825,7 @@ /* scale, round and offset brect */ i = 0; - while (i<8) { + while (i < 8) { brect[i] = x + (brect[i] + 32) / 64; i++; brect[i] = y - (brect[i] + 32) / 64; @@ -868,7 +834,7 @@ return (char *)NULL; } - + #endif /* HAVE_LIBTTF */ /* diff -urN php-4.4.8.org/ext/gd/libgd/gd_arc_f_buggy.c php-4.4.8/ext/gd/libgd/gd_arc_f_buggy.c --- php-4.4.8.org/ext/gd/libgd/gd_arc_f_buggy.c 2003-03-05 17:04:20.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_arc_f_buggy.c 2005-08-18 14:54:43.000000000 +0200 @@ -698,7 +698,7 @@ #define WIDTH 500 #define HEIGHT 300 -int +int main (int argc, char *argv[]) { gdImagePtr im = gdImageCreate (WIDTH, HEIGHT); @@ -726,12 +726,12 @@ out = fopen ("test/arctest.png", "wb"); if (!out) { - php_gd_error("Can't create test/arctest.png\n"); + php_gd_error("Can't create test/arctest.png"); exit (1); } gdImagePng (im, out); fclose (out); - php_gd_error("Test image written to test/arctest.png\n"); + php_gd_error("Test image written to test/arctest.png"); /* Destroy it */ gdImageDestroy (im); diff -urN php-4.4.8.org/ext/gd/libgd/gd.c php-4.4.8/ext/gd/libgd/gd.c --- php-4.4.8.org/ext/gd/libgd/gd.c 2007-10-20 17:29:04.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd.c 2007-11-05 00:56:00.000000000 +0100 @@ -1,4 +1,4 @@ -#include + #include #include #include @@ -90,18 +90,16 @@ static void gdImageBrushApply(gdImagePtr im, int x, int y); static void gdImageTileApply(gdImagePtr im, int x, int y); static void gdImageAntiAliasedApply(gdImagePtr im, int x, int y); -static int gdFullAlphaBlend(int dst, int src); static int gdLayerOverlay(int dst, int src); -static int gdAlphaBlendColor(int b1, int b2, int a1, int a2); static int gdAlphaOverlayColor(int src, int dst, int max); int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y); -void php_gd_error_ex(int type, const char *format, ...) +void php_gd_error_ex(int type, const char *format, ...) { va_list args; - + TSRMLS_FETCH(); - + va_start(args, format); php_verror(NULL, "", type, format, args TSRMLS_CC); va_end(args); @@ -110,9 +108,9 @@ void php_gd_error(const char *format, ...) { va_list args; - + TSRMLS_FETCH(); - + va_start(args, format); php_verror(NULL, "", E_WARNING, format, args TSRMLS_CC); va_end(args); @@ -122,11 +120,20 @@ { int i; gdImagePtr im; - im = (gdImage *) gdMalloc(sizeof(gdImage)); - memset(im, 0, sizeof(gdImage)); + + if (overflow2(sx, sy)) { + return NULL; + } + + if (overflow2(sizeof(unsigned char *), sy)) { + return NULL; + } + + im = (gdImage *) gdCalloc(1, sizeof(gdImage)); + /* Row-major ever since gd 1.3 */ - im->pixels = (unsigned char **) safe_emalloc(sizeof(unsigned char *), sy, 0); - im->AA_opacity = (unsigned char **) safe_emalloc(sizeof(unsigned char *), sy, 0); + im->pixels = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy); + im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy); im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; @@ -164,10 +171,23 @@ { int i; gdImagePtr im; + + if (overflow2(sx, sy)) { + return NULL; + } + + if (overflow2(sizeof(unsigned char *), sy)) { + return NULL; + } + + if (overflow2(sizeof(int), sx)) { + return NULL; + } + im = (gdImage *) gdMalloc(sizeof(gdImage)); memset(im, 0, sizeof(gdImage)); - im->tpixels = (int **) safe_emalloc(sizeof(int *), sy, 0); - im->AA_opacity = (unsigned char **) safe_emalloc(sizeof(unsigned char *), sy, 0); + im->tpixels = (int **) gdMalloc(sizeof(int *) * sy); + im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy); im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; @@ -305,8 +325,8 @@ static HWBType * RGB_to_HWB (RGBType RGB, HWBType * HWB) { /* - * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is - * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B. + * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is + * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B. */ float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f; @@ -320,7 +340,7 @@ } f = (R == w) ? G - B : ((G == w) ? B - R : R - G); i = (R == w) ? 3 : ((G == w) ? 5 : 1); - + RETURN_HWB(i - f / (v - w), w, b); } @@ -363,9 +383,9 @@ */ static RGBType * HWB_to_RGB (HWBType HWB, RGBType * RGB) { - /* - * H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1]. - * RGB are each returned on [0, 1]. + /* + * H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1]. + * RGB are each returned on [0, 1]. */ float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f; @@ -478,7 +498,7 @@ im->blue[ct] = b; im->alpha[ct] = a; im->open[ct] = 0; - + return ct; } @@ -664,7 +684,7 @@ } m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ *y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right boundary */ - *x0 = maxdim; + *x0 = maxdim; /* now, perhaps, adjust the end of the line */ if (*x1 < 0) { *y1 -= (int)(m * *x1); @@ -737,7 +757,7 @@ im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color); break; case gdEffectNormal: - im->tpixels[y][x] = gdFullAlphaBlend(im->tpixels[y][x], color); + im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color); break; case gdEffectOverlay : im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color); @@ -756,7 +776,7 @@ int p = gdImageGetPixel(im, x, y); if (!im->trueColor) { - return gdTrueColorAlpha(im->red[p], im->green[p], im->blue[p], (im->transparent == p) ? gdAlphaTransparent : gdAlphaOpaque); + return gdTrueColorAlpha(im->red[p], im->green[p], im->blue[p], (im->transparent == p) ? gdAlphaTransparent : im->alpha[p]); } else { return p; } @@ -780,7 +800,7 @@ x1 = x - hx; x2 = x1 + gdImageSX(im->brush); srcy = 0; - + if (im->trueColor) { if (im->brush->trueColor) { for (ly = y1; ly < y2; ly++) { @@ -823,8 +843,8 @@ if (p != gdImageGetTransparent(im->brush)) { /* Truecolor brush. Very slow on a palette destination. */ if (im->brush->trueColor) { - gdImageSetPixel(im, lx, ly, gdImageColorResolveAlpha(im, gdTrueColorGetRed(p), - gdTrueColorGetGreen(p), + gdImageSetPixel(im, lx, ly, gdImageColorResolveAlpha(im, gdTrueColorGetRed(p), + gdTrueColorGetGreen(p), gdTrueColorGetBlue(p), gdTrueColorGetAlpha(p))); } else { @@ -849,7 +869,9 @@ srcy = y % gdImageSY(im->tile); if (im->trueColor) { p = gdImageGetTrueColorPixel(im->tile, srcx, srcy); - gdImageSetPixel(im, x, y, p); + if (p != gdImageGetTransparent (im->tile)) { + gdImageSetPixel(im, x, y, p); + } } else { p = gdImageGetPixel(im->tile, srcx, srcy); /* Allow for transparency */ @@ -903,8 +925,8 @@ float p_dist, p_alpha; unsigned char opacity; - /* - * Find the perpendicular distance from point C (px, py) to the line + /* + * Find the perpendicular distance from point C (px, py) to the line * segment AB that is being drawn. (Adapted from an algorithm from the * comp.graphics.algorithms FAQ.) */ @@ -918,7 +940,7 @@ int By_Cy = im->AAL_y2 - py; /* 2.0.13: bounds check! AA_opacity is just as capable of - * overflowing as the main pixel array. Arne Jorgensen. + * overflowing as the main pixel array. Arne Jorgensen. * 2.0.14: typo fixed. 2.0.15: moved down below declarations * to satisfy non-C++ compilers. */ @@ -931,12 +953,12 @@ LBC_2 = (Bx_Cx * Bx_Cx) + (By_Cy * By_Cy); if (((im->AAL_LAB_2 + LAC_2) >= LBC_2) && ((im->AAL_LAB_2 + LBC_2) >= LAC_2)) { - /* The two angles are acute. The point lies inside the portion of the + /* The two angles are acute. The point lies inside the portion of the * plane spanned by the line segment. */ p_dist = fabs ((float) ((Ay_Cy * im->AAL_Bx_Ax) - (Ax_Cx * im->AAL_By_Ay)) / im->AAL_LAB); } else { - /* The point is past an end of the line segment. It's length from the + /* The point is past an end of the line segment. It's length from the * segment is the shorter of the lengths from the endpoints, but call * the distance -1, so as not to compute the alpha nor draw the pixel. */ @@ -1017,6 +1039,43 @@ } } +static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col) +{ + if (im->thick > 1) { + int thickhalf = im->thick >> 1; + gdImageFilledRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col); + } else { + if (x2 < x1) { + int t = x2; + x2 = x1; + x1 = t; + } + + for (;x1 <= x2; x1++) { + gdImageSetPixel(im, x1, y, col); + } + } + return; +} + +static void gdImageVLine(gdImagePtr im, int x, int y1, int y2, int col) +{ + if (im->thick > 1) { + int thickhalf = im->thick >> 1; + gdImageFilledRectangle(im, x - thickhalf, y1, x + im->thick - thickhalf - 1, y2, col); + } else { + if (y2 < y1) { + int t = y1; + y1 = y2; + y2 = t; + } + + for (;y1 <= y2; y1++) { + gdImageSetPixel(im, x, y1, col); + } + } + return; +} /* Bresenham as presented in Foley & Van Dam */ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color) @@ -1026,39 +1085,47 @@ int w, wstart; int thick = im->thick; + if (color == gdAntiAliased) + { + /* + gdAntiAliased passed as color: use the much faster, much cheaper + and equally attractive gdImageAALine implementation. That + clips too, so don't clip twice. + */ + gdImageAALine(im, x1, y1, x2, y2, im->AA_color); + return; + } + /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */ if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) { return; } - /* gdAntiAliased passed as color: set anti-aliased line (AAL) global vars. */ - if (color == gdAntiAliased) { - im->AAL_x1 = x1; - im->AAL_y1 = y1; - im->AAL_x2 = x2; - im->AAL_y2 = y2; - - /* Compute what we can for point-to-line distance calculation later. */ - im->AAL_Bx_Ax = x2 - x1; - im->AAL_By_Ay = y2 - y1; - im->AAL_LAB_2 = (im->AAL_Bx_Ax * im->AAL_Bx_Ax) + (im->AAL_By_Ay * im->AAL_By_Ay); - im->AAL_LAB = sqrt (im->AAL_LAB_2); + dx = abs (x2 - x1); + dy = abs (y2 - y1); - /* For AA, we must draw pixels outside the width of the line. Keep in - * mind that this will be curtailed by cos/sin of theta later. - */ - thick += 4; + if (dx == 0) { + gdImageVLine(im, x1, y1, y2, color); + return; + } else if (dy == 0) { + gdImageHLine(im, y1, x1, x2, color); + return; } - - dx = abs(x2 - x1); - dy = abs(y2 - y1); + if (dy <= dx) { /* More-or-less horizontal. use wid for vertical stroke */ /* Doug Claar: watch out for NaN in atan2 (2.0.5) */ if ((dx == 0) && (dy == 0)) { wid = 1; } else { - wid = (int)(thick * cos (atan2 (dy, dx))); + /* 2.0.12: Michael Schwartz: divide rather than multiply; +TBB: but watch out for /0! */ + double ac = cos (atan2 (dy, dx)); + if (ac != 0) { + wid = thick / ac; + } else { + wid = 1; + } if (wid == 0) { wid = 1; } @@ -1115,16 +1182,17 @@ } } else { /* More-or-less vertical. use wid for horizontal stroke */ - /* 2.0.12: Michael Schwartz: divide rather than multiply; - TBB: but watch out for /0! */ - double as = sin(atan2(dy, dx)); + /* 2.0.12: Michael Schwartz: divide rather than multiply; + TBB: but watch out for /0! */ + double as = sin (atan2 (dy, dx)); if (as != 0) { - if (!(wid = thick / as)) { - wid = 1; - } + wid = thick / as; } else { wid = 1; } + if (wid == 0) { + wid = 1; + } d = 2 * dx - dy; incr1 = 2 * dx; @@ -1177,11 +1245,6 @@ } } } - - /* If this is the only line we are drawing, go ahead and blend. */ - if (color == gdAntiAliased && !im->AA_polygon) { - gdImageAABlend(im); - } } @@ -1207,7 +1270,7 @@ BLEND_COLOR(t, dg, g, dg); BLEND_COLOR(t, db, b, db); im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque); -} +} /* * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org) @@ -1586,9 +1649,9 @@ /* s and e are integers modulo 360 (degrees), with 0 degrees being the rightmost extreme and degrees changing clockwise. - cx and cy are the center in pixels; w and h are the horizontal + cx and cy are the center in pixels; w and h are the horizontal and vertical diameter in pixels. Nice interface, but slow. - See gd_arc_f_buggy.c for a better version that doesn't + See gd_arc_f_buggy.c for a better version that doesn't seem to be bug-free yet. */ void gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color) @@ -1607,29 +1670,30 @@ int lx = 0, ly = 0; int fx = 0, fy = 0; - if ((s % 360) == (e % 360)) { + + if ((s % 360) == (e % 360)) { s = 0; e = 360; - } else { - if (s > 360) { - s = s % 360; - } + } else { + if (s > 360) { + s = s % 360; + } - if (e > 360) { - e = e % 360; - } + if (e > 360) { + e = e % 360; + } - while (s < 0) { - s += 360; - } + while (s < 0) { + s += 360; + } - while (e < s) { - e += 360; - } + while (e < s) { + e += 360; + } - if (s == e) { + if (s == e) { s = 0; e = 360; - } - } + } + } for (i = s; i <= e; i++) { int x, y; @@ -1787,17 +1851,15 @@ int lastBorder; /* Seek left */ int leftLimit = -1, rightLimit; - int i, restoreAlphaBleding=0; + int i, restoreAlphaBlending = 0; if (border < 0) { /* Refuse to fill to a non-solid border */ return; } - if (im->alphaBlendingFlag) { - restoreAlphaBleding = 1; - im->alphaBlendingFlag = 0; - } + restoreAlphaBlending = im->alphaBlendingFlag; + im->alphaBlendingFlag = 0; if (x >= im->sx) { x = im->sx - 1; @@ -1814,9 +1876,7 @@ leftLimit = i; } if (leftLimit == -1) { - if (restoreAlphaBleding) { - im->alphaBlendingFlag = 1; - } + im->alphaBlendingFlag = restoreAlphaBlending; return; } /* Seek right */ @@ -1844,6 +1904,7 @@ } } } + /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; @@ -1860,12 +1921,9 @@ } } } - if (restoreAlphaBleding) { - im->alphaBlendingFlag = 1; - } + im->alphaBlendingFlag = restoreAlphaBlending; } - /* * set the pixel at (x,y) and its 4-connected neighbors * with the same pixel value to the new pixel value nc (new color). @@ -1888,25 +1946,31 @@ #define FILL_POP(Y, XL, XR, DY) \ {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;} -void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc); +static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc); void gdImageFill(gdImagePtr im, int x, int y, int nc) { int l, x1, x2, dy; int oc; /* old pixel value */ int wx2,wy2; + int alphablending_bak; + /* stack of filled segments */ /* struct seg stack[FILL_MAX],*sp = stack;; */ - struct seg *stack; + struct seg *stack = NULL; struct seg *sp; + if (!im->trueColor && nc > (im->colorsTotal -1)) { + return; + } + alphablending_bak = im->alphaBlendingFlag; im->alphaBlendingFlag = 0; if (nc==gdTiled){ _gdImageFillTiled(im,x,y,nc); - im->alphaBlendingFlag = alphablending_bak; + im->alphaBlendingFlag = alphablending_bak; return; } @@ -1916,8 +1980,31 @@ im->alphaBlendingFlag = alphablending_bak; return; } - - stack = (struct seg *)emalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)+1); + + /* Do not use the 4 neighbors implementation with + * small images + */ + if (im->sx < 4) { + int ix = x, iy = y, c; + do { + c = gdImageGetPixel(im, ix, iy); + if (c != oc) { + goto done; + } + gdImageSetPixel(im, ix, iy, nc); + } while(ix++ < (im->sx -1)); + ix = x; iy = y + 1; + do { + c = gdImageGetPixel(im, ix, iy); + if (c != oc) { + goto done; + } + gdImageSetPixel(im, ix, iy, nc); + } while(ix++ < (im->sx -1)); + goto done; + } + + stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1); sp = stack; /* required! */ @@ -1954,22 +2041,25 @@ l = x; } while (x<=x2); } + efree(stack); + +done: im->alphaBlendingFlag = alphablending_bak; } -void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) +static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) { - int i,l, x1, x2, dy; + int i, l, x1, x2, dy; int oc; /* old pixel value */ int tiled; int wx2,wy2; /* stack of filled segments */ struct seg *stack; struct seg *sp; + char **pts; - int **pts; - if(!im->tile){ + if (!im->tile) { return; } @@ -1977,30 +2067,26 @@ tiled = nc==gdTiled; nc = gdImageTileGet(im,x,y); - pts = (int **) ecalloc(sizeof(int *) * im->sy, sizeof(int)); - for (i=0; isy;i++) { - pts[i] = (int *) ecalloc(im->sx, sizeof(int)); + pts = (char **) ecalloc(im->sy + 1, sizeof(char *)); + for (i = 0; i < im->sy + 1; i++) { + pts[i] = (char *) ecalloc(im->sx + 1, sizeof(char)); } - stack = (struct seg *)emalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)+1); + stack = (struct seg *)safe_emalloc(sizeof(struct seg), ((int)(im->sy*im->sx)/4), 1); sp = stack; oc = gdImageGetPixel(im, x, y); - /* required! */ +/* required! */ FILL_PUSH(y,x,x,1); /* seed segment (popped 1st) */ FILL_PUSH(y+1, x, x, -1); while (sp>stack) { FILL_POP(y, x1, x2, dy); for (x=x1; x>=0 && (!pts[y][x] && gdImageGetPixel(im,x,y)==oc); x--) { - if (pts[y][x]){ - /* we should never be here */ - break; - } nc = gdImageTileGet(im,x,y); - pts[y][x]=1; + pts[y][x] = 1; gdImageSetPixel(im,x, y, nc); } if (x>=x1) { @@ -2014,13 +2100,9 @@ } x = x1+1; do { - for (; x<=wx2 && (!pts[y][x] && gdImageGetPixel(im,x, y)==oc) ; x++) { - if (pts[y][x]){ - /* we should never be here */ - break; - } + for(; xx2+1) { FILL_PUSH(y, x2+1, x-1, -dy); } -skip: for (x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++); +skip: for(x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++); l = x; } while (x<=x2); } - for (i=0; isy;i++) { + + for(i = 0; i < im->sy + 1; i++) { efree(pts[i]); } + efree(pts); efree(stack); } @@ -2048,6 +2132,11 @@ int half1 = 1; int t; + if (x1 == x2 && y1 == y2 && thick == 1) { + gdImageSetPixel(im, x1, y1, color); + return; + } + if (y2 < y1) { t=y1; y1 = y2; @@ -2110,16 +2199,15 @@ gdImageLine(im, x1v, y1v, x1v, y2v, color); gdImageLine(im, x2v, y1v, x2v, y2v, color); } - } void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { int x, y; - + /* Nick Atty: limit the points at the edge. Note that this also * nicely kills any plotting for rectangles completely outside the - * window as it makes the tests in the for loops fail + * window as it makes the tests in the for loops fail */ if (x1 < 0) { x1 = 0; @@ -2133,15 +2221,15 @@ if (y1 > gdImageSY(im)) { y1 = gdImageSY(im); } - if (y2 < y1) { - int t; - t=y1; - y1 = y2; - y2 = t; - - t = x1; + if (x1 > x2) { + x = x1; x1 = x2; - x2 = t; + x2 = x; + } + if (y1 > y2) { + y = y1; + y1 = y2; + y2 = y; } for (y = y1; (y <= y2); y++) { @@ -2162,9 +2250,9 @@ if (dst->trueColor) { /* 2.0: much easier when the destination is truecolor. */ /* 2.0.10: needs a transparent-index check that is still valid if - * the source is not truecolor. Thanks to Frank Warmerdam. + * the source is not truecolor. Thanks to Frank Warmerdam. */ - + if (src->trueColor) { for (y = 0; (y < h); y++) { for (x = 0; (x < w); x++) { @@ -2178,7 +2266,7 @@ for (x = 0; (x < w); x++) { int c = gdImageGetPixel (src, srcX + x, srcY + y); if (c != src->transparent) { - gdImageSetPixel (dst, dstX + x, dstY + y, gdTrueColor(src->red[c], src->green[c], src->blue[c])); + gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c])); } } } @@ -2225,7 +2313,7 @@ /* Have we established a mapping for this color? */ if (src->trueColor) { /* 2.05: remap to the palette available in the destination image. This is slow and - * works badly, but it beats crashing! Thanks to Padhrig McCarthy. + * works badly, but it beats crashing! Thanks to Padhrig McCarthy. */ mapTo = gdImageColorResolveAlpha (dst, gdTrueColorGetRed (c), gdTrueColorGetGreen (c), gdTrueColorGetBlue (c), gdTrueColorGetAlpha (c)); } else if (colorMap[c] == (-1)) { @@ -2237,9 +2325,9 @@ nc = gdImageColorResolveAlpha (dst, src->red[c], src->green[c], src->blue[c], src->alpha[c]); } colorMap[c] = nc; - mapTo = colorMap[c]; + mapTo = colorMap[c]; } else { - mapTo = colorMap[c]; + mapTo = colorMap[c]; } gdImageSetPixel (dst, tox, toy, mapTo); tox++; @@ -2257,7 +2345,7 @@ int tox, toy; int ncR, ncG, ncB; toy = dstY; - + for (y = srcY; y < (srcY + h); y++) { tox = dstX; for (x = srcX; x < (srcX + w); x++) { @@ -2304,15 +2392,17 @@ for (x = srcX; (x < (srcX + w)); x++) { int nc; c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ if (gdImageGetTransparent(src) == c) { tox++; continue; } - /* - * If it's the same image, mapping is NOT trivial since we - * merge with greyscale target, but if pct is 100, the grey - * value is not used, so it becomes trivial. pjw 2.0.12. + + /* + * If it's the same image, mapping is NOT trivial since we + * merge with greyscale target, but if pct is 100, the grey + * value is not used, so it becomes trivial. pjw 2.0.12. */ if (dst == src && pct == 100) { nc = c; @@ -2320,9 +2410,10 @@ dc = gdImageGetPixel(dst, tox, toy); g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc)); - ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); - ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); - ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); + ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + g * ((100 - pct) / 100.0)); + /* First look for an exact match */ nc = gdImageColorExact(dst, ncR, ncG, ncB); @@ -2354,10 +2445,18 @@ int *stx, *sty; /* We only need to use floating point to determine the correct stretch vector for one line's worth. */ double accum; - stx = (int *) safe_emalloc(sizeof(int), srcW, 0); - sty = (int *) safe_emalloc(sizeof(int), srcH, 0); - accum = 0; + if (overflow2(sizeof(int), srcW)) { + return; + } + if (overflow2(sizeof(int), srcH)) { + return; + } + + stx = (int *) gdMalloc (sizeof (int) * srcW); + sty = (int *) gdMalloc (sizeof (int) * srcH); + accum = 0; + /* Fixed by Mao Morimoto 2.0.16 */ for (i = 0; (i < srcW); i++) { stx[i] = dstW * (i+1) / srcW - dstW * i / srcW ; @@ -2387,7 +2486,7 @@ /* 2.0.21, TK: not tox++ */ tox += stx[x - srcX]; continue; - } + } } else { /* TK: old code follows */ mapTo = gdImageGetTrueColorPixel (src, x, y); @@ -2397,7 +2496,7 @@ tox += stx[x - srcX]; continue; } - } + } } else { c = gdImageGetPixel (src, x, y); /* Added 7/24/95: support transparent copies */ @@ -2451,6 +2550,7 @@ { int x, y; double sy1, sy2, sx1, sx2; + if (!dst->trueColor) { gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH); return; @@ -2497,7 +2597,7 @@ } pcontribution = xportion * yportion; p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY); - + alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution; red += gdTrueColorGetRed (p) * alpha_factor; green += gdTrueColorGetGreen (p) * alpha_factor; @@ -2509,12 +2609,12 @@ sx += 1.0f; } while (sx < sx2); - + sy += 1.0f; } - + while (sy < sy2); - + if (spixels != 0.0f) { red /= spixels; green /= spixels; @@ -2524,7 +2624,7 @@ if ( alpha_sum != 0.0f) { if( contrib_sum != 0.0f) { alpha_sum /= contrib_sum; - } + } red /= alpha_sum; green /= alpha_sum; blue /= alpha_sum; @@ -2549,7 +2649,7 @@ /* - * Rotate function Added on 2003/12 + * Rotate function Added on 2003/12 * by Pierre-Alain Joye (pajoye@pearfr.org) **/ /* Begin rotate function */ @@ -2558,7 +2658,7 @@ #endif /* ROTATE_PI */ #define ROTATE_DEG2RAD 3.1415926535897932384626433832795/180 -void gdImageSkewX (gdImagePtr dst, gdImagePtr src, int uRow, int iOffset, double dWeight, int clrBack) +void gdImageSkewX (gdImagePtr dst, gdImagePtr src, int uRow, int iOffset, double dWeight, int clrBack, int ignoretransparent) { typedef int (*FuncPtr)(gdImagePtr, int, int); int i, r, g, b, a, clrBackR, clrBackG, clrBackB, clrBackA; @@ -2623,10 +2723,14 @@ a = 127; } - pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a); + if (ignoretransparent && pxlSrc == dst->transparent) { + pxlSrc = dst->transparent; + } else { + pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a); - if (pxlSrc == -1) { - pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a); + if (pxlSrc == -1) { + pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a); + } } if ((i + iOffset >= 0) && (i + iOffset < dst->sx)) { @@ -2651,7 +2755,7 @@ } } -void gdImageSkewY (gdImagePtr dst, gdImagePtr src, int uCol, int iOffset, double dWeight, int clrBack) +void gdImageSkewY (gdImagePtr dst, gdImagePtr src, int uCol, int iOffset, double dWeight, int clrBack, int ignoretransparent) { typedef int (*FuncPtr)(gdImagePtr, int, int); int i, iYPos=0, r, g, b, a; @@ -2710,10 +2814,14 @@ a = 127; } - pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a); + if (ignoretransparent && pxlSrc == dst->transparent) { + pxlSrc = dst->transparent; + } else { + pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a); - if (pxlSrc == -1) { - pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a); + if (pxlSrc == -1) { + pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a); + } } if ((iYPos >= 0) && (iYPos < dst->sy)) { @@ -2735,10 +2843,10 @@ } /* Rotates an image by 90 degrees (counter clockwise) */ -gdImagePtr gdImageRotate90 (gdImagePtr src) +gdImagePtr gdImageRotate90 (gdImagePtr src, int ignoretransparent) { int uY, uX; - int c, r,g,b,a; + int c,r,g,b,a; gdImagePtr dst; typedef int (*FuncPtr)(gdImagePtr, int, int); FuncPtr f; @@ -2749,8 +2857,12 @@ f = gdImageGetPixel; } dst = gdImageCreateTrueColor(src->sy, src->sx); + dst->transparent = src->transparent; if (dst != NULL) { + int old_blendmode = dst->alphaBlendingFlag; + dst->alphaBlendingFlag = 0; + gdImagePaletteCopy (dst, src); for (uY = 0; uYsy; uY++) { @@ -2763,16 +2875,21 @@ a = gdImageAlpha(src,c); c = gdTrueColorAlpha(r, g, b, a); } - gdImageSetPixel(dst, uY, (dst->sy - uX - 1), c); + if (ignoretransparent && c == dst->transparent) { + gdImageSetPixel(dst, uY, (dst->sy - uX - 1), dst->transparent); + } else { + gdImageSetPixel(dst, uY, (dst->sy - uX - 1), c); + } } } + dst->alphaBlendingFlag = old_blendmode; } return dst; } /* Rotates an image by 180 degrees (counter clockwise) */ -gdImagePtr gdImageRotate180 (gdImagePtr src) +gdImagePtr gdImageRotate180 (gdImagePtr src, int ignoretransparent) { int uY, uX; int c,r,g,b,a; @@ -2786,8 +2903,12 @@ f = gdImageGetPixel; } dst = gdImageCreateTrueColor(src->sx, src->sy); + dst->transparent = src->transparent; if (dst != NULL) { + int old_blendmode = dst->alphaBlendingFlag; + dst->alphaBlendingFlag = 0; + gdImagePaletteCopy (dst, src); for (uY = 0; uYsy; uY++) { @@ -2800,16 +2921,22 @@ a = gdImageAlpha(src,c); c = gdTrueColorAlpha(r, g, b, a); } - gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), c); + + if (ignoretransparent && c == dst->transparent) { + gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), dst->transparent); + } else { + gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), c); + } } } + dst->alphaBlendingFlag = old_blendmode; } return dst; } /* Rotates an image by 270 degrees (counter clockwise) */ -gdImagePtr gdImageRotate270 ( gdImagePtr src ) +gdImagePtr gdImageRotate270 (gdImagePtr src, int ignoretransparent) { int uY, uX; int c,r,g,b,a; @@ -2822,9 +2949,13 @@ } else { f = gdImageGetPixel; } - dst = gdImageCreateTrueColor(src->sy, src->sx); + dst = gdImageCreateTrueColor (src->sy, src->sx); + dst->transparent = src->transparent; if (dst != NULL) { + int old_blendmode = dst->alphaBlendingFlag; + dst->alphaBlendingFlag = 0; + gdImagePaletteCopy (dst, src); for (uY = 0; uYsy; uY++) { @@ -2837,15 +2968,21 @@ a = gdImageAlpha(src,c); c = gdTrueColorAlpha(r, g, b, a); } - gdImageSetPixel(dst, (dst->sx - uY - 1), uX, c); + + if (ignoretransparent && c == dst->transparent) { + gdImageSetPixel(dst, (dst->sx - uY - 1), uX, dst->transparent); + } else { + gdImageSetPixel(dst, (dst->sx - uY - 1), uX, c); + } } } + dst->alphaBlendingFlag = old_blendmode; } return dst; } -gdImagePtr gdImageRotate45 (gdImagePtr src, double dAngle, int clrBack) +gdImagePtr gdImageRotate45 (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent) { typedef int (*FuncPtr)(gdImagePtr, int, int); gdImagePtr dst1,dst2,dst3; @@ -2869,8 +3006,8 @@ } else { f = gdImageGetPixel; } - dst1 = gdImageCreateTrueColor(newx, newy); + dst1 = gdImageCreateTrueColor(newx, newy); /******* Perform 1st shear (horizontal) ******/ if (dst1 == NULL) { return NULL; @@ -2885,6 +3022,15 @@ gdImagePaletteCopy (dst1, src); + if (ignoretransparent) { + if (gdImageTrueColor(src)) { + dst1->transparent = src->transparent; + } else { + + dst1->transparent = gdTrueColorAlpha(gdImageRed(src, src->transparent), gdImageBlue(src, src->transparent), gdImageGreen(src, src->transparent), 127); + } + } + dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */ dSinE = sin (dRadAngle); dTan = tan (dRadAngle / 2.0); @@ -2897,7 +3043,7 @@ } iShear = (int)floor(dShear); - gdImageSkewX(dst1, src, u, iShear, (dShear - iShear), clrBack); + gdImageSkewX(dst1, src, u, iShear, (dShear - iShear), clrBack, ignoretransparent); } /* @@ -2933,10 +3079,13 @@ return NULL; } dst2->alphaBlendingFlag = gdEffectReplace; + if (ignoretransparent) { + dst2->transparent = dst1->transparent; + } for (u = 0; u < dst2->sx; u++, dOffset -= dSinE) { iShear = (int)floor (dOffset); - gdImageSkewY(dst2, dst1, u, iShear, (dOffset - (double)iShear), clrBack); + gdImageSkewY(dst2, dst1, u, iShear, (dOffset - (double)iShear), clrBack, ignoretransparent); } /* 3rd shear */ @@ -2955,6 +3104,12 @@ gdImageDestroy(dst2); return NULL; } + + dst3->alphaBlendingFlag = gdEffectReplace; + if (ignoretransparent) { + dst3->transparent = dst2->transparent; + } + if (dSinE >= 0.0) { dOffset = (double)(src->sx - 1) * dSinE * -dTan; } else { @@ -2962,8 +3117,8 @@ } for (u = 0; u < dst3->sy; u++, dOffset += dTan) { - int iShear = (int)floor(dOffset); - gdImageSkewX(dst3, dst2, u, iShear, (dOffset - iShear), clrBack); + int iShear = (int)floor(dOffset); + gdImageSkewX(dst3, dst2, u, iShear, (dOffset - iShear), clrBack, ignoretransparent); } gdImageDestroy(dst2); @@ -2971,11 +3126,11 @@ return dst3; } -gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack) +gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent) { gdImagePtr pMidImg; gdImagePtr rotatedImg; - int r,g,b,a; + if (src == NULL) { return NULL; } @@ -2993,41 +3148,33 @@ } if (dAngle == 90.00) { - return gdImageRotate90(src); + return gdImageRotate90(src, ignoretransparent); } if (dAngle == 180.00) { - return gdImageRotate180(src); + return gdImageRotate180(src, ignoretransparent); } if(dAngle == 270.00) { - return gdImageRotate270 ( src); + return gdImageRotate270 (src, ignoretransparent); } if ((dAngle > 45.0) && (dAngle <= 135.0)) { - pMidImg = gdImageRotate90 (src); + pMidImg = gdImageRotate90 (src, ignoretransparent); dAngle -= 90.0; } else if ((dAngle > 135.0) && (dAngle <= 225.0)) { - pMidImg = gdImageRotate180 (src); + pMidImg = gdImageRotate180 (src, ignoretransparent); dAngle -= 180.0; } else if ((dAngle > 225.0) && (dAngle <= 315.0)) { - pMidImg = gdImageRotate270 (src); + pMidImg = gdImageRotate270 (src, ignoretransparent); dAngle -= 270.0; } else { - return gdImageRotate45 (src, dAngle, clrBack); + return gdImageRotate45 (src, dAngle, clrBack, ignoretransparent); } if (pMidImg == NULL) { return NULL; } - if(!src->trueColor) { - r = gdImageRed(src, clrBack); - g = gdImageGreen(src, clrBack); - b = gdImageBlue(src, clrBack); - a = gdImageAlpha(src, clrBack); - clrBack = gdTrueColorAlpha(r,g,b,a); - } - - rotatedImg = gdImageRotate45 (pMidImg, dAngle, clrBack); + rotatedImg = gdImageRotate45 (pMidImg, dAngle, clrBack, ignoretransparent); gdImageDestroy(pMidImg); return rotatedImg; @@ -3098,20 +3245,27 @@ return; } + if (overflow2(sizeof(int), n)) { + return; + } + if (c == gdAntiAliased) { fill_color = im->AA_color; } else { fill_color = c; } - + if (!im->polyAllocated) { - im->polyInts = (int *) safe_emalloc(sizeof(int), n, 0); + im->polyInts = (int *) gdMalloc(sizeof(int) * n); im->polyAllocated = n; } if (im->polyAllocated < n) { while (im->polyAllocated < n) { im->polyAllocated *= 2; } + if (overflow2(sizeof(int), im->polyAllocated)) { + return; + } im->polyInts = (int *) gdRealloc(im->polyInts, sizeof(int) * im->polyAllocated); } miny = p[0].y; @@ -3131,7 +3285,7 @@ } if (maxy >= gdImageSY(im)) { maxy = gdImageSY(im) - 1; - } + } /* Fix in 1.3: count a vertex only once */ for (y = miny; y <= maxy; y++) { @@ -3193,7 +3347,7 @@ if (im->style) { gdFree(im->style); } - im->style = (int *) safe_emalloc(sizeof(int), noOfPixels, 0); + im->style = (int *) gdMalloc(sizeof(int) * noOfPixels); memcpy(im->style, style, sizeof(int) * noOfPixels); im->styleLength = noOfPixels; im->stylePos = 0; @@ -3323,9 +3477,9 @@ } int -gdAlphaBlend (int dst, int src) +gdAlphaBlendOld (int dst, int src) { - /* 2.0.12: TBB: alpha in the destination should be a + /* 2.0.12: TBB: alpha in the destination should be a * component of the result. Thanks to Frank Warmerdam for * pointing out the issue. */ @@ -3345,6 +3499,51 @@ gdTrueColorGetBlue (dst)) / gdAlphaMax)); } +int gdAlphaBlend (int dst, int src) { + int src_alpha = gdTrueColorGetAlpha(src); + int dst_alpha, alpha, red, green, blue; + int src_weight, dst_weight, tot_weight; + +/* -------------------------------------------------------------------- */ +/* Simple cases we want to handle fast. */ +/* -------------------------------------------------------------------- */ + if( src_alpha == gdAlphaOpaque ) + return src; + + dst_alpha = gdTrueColorGetAlpha(dst); + if( src_alpha == gdAlphaTransparent ) + return dst; + if( dst_alpha == gdAlphaTransparent ) + return src; + +/* -------------------------------------------------------------------- */ +/* What will the source and destination alphas be? Note that */ +/* the destination weighting is substantially reduced as the */ +/* overlay becomes quite opaque. */ +/* -------------------------------------------------------------------- */ + src_weight = gdAlphaTransparent - src_alpha; + dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax; + tot_weight = src_weight + dst_weight; + +/* -------------------------------------------------------------------- */ +/* What red, green and blue result values will we use? */ +/* -------------------------------------------------------------------- */ + alpha = src_alpha * dst_alpha / gdAlphaMax; + + red = (gdTrueColorGetRed(src) * src_weight + + gdTrueColorGetRed(dst) * dst_weight) / tot_weight; + green = (gdTrueColorGetGreen(src) * src_weight + + gdTrueColorGetGreen(dst) * dst_weight) / tot_weight; + blue = (gdTrueColorGetBlue(src) * src_weight + + gdTrueColorGetBlue(dst) * dst_weight) / tot_weight; + +/* -------------------------------------------------------------------- */ +/* Return merged result. */ +/* -------------------------------------------------------------------- */ + return ((alpha << 24) + (red << 16) + (green << 8) + blue); + +} + void gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg) { im->alphaBlendingFlag = alphaBlendingArg; @@ -3362,44 +3561,6 @@ im->saveAlphaFlag = saveAlphaArg; } -static int gdFullAlphaBlend (int dst, int src) -{ - int a1, a2; - a1 = gdAlphaTransparent - gdTrueColorGetAlpha(src); - a2 = gdAlphaTransparent - gdTrueColorGetAlpha(dst); - - return ( ((gdAlphaTransparent - ((a1+a2)-(a1*a2/gdAlphaMax))) << 24) + - (gdAlphaBlendColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), a1, a2 ) << 16) + - (gdAlphaBlendColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), a1, a2 ) << 8) + - (gdAlphaBlendColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), a1, a2 )) - ); -} - -static int gdAlphaBlendColor( int b1, int b2, int a1, int a2 ) -{ - int c; - int w; - - /* deal with special cases */ - - if( (gdAlphaMax == a1) || (0 == a2) ) { - /* the back pixel can't be seen */ - return b1; - } else if(0 == a1) { - /* the front pixel can't be seen */ - return b2; - } else if(gdAlphaMax == a2) { - /* the back pixel is opaque */ - return ( a1 * b1 + ( gdAlphaMax - a1 ) * b2 ) / gdAlphaMax; - } - - /* the general case */ - w = ( a1 * ( gdAlphaMax - a2 ) / ( gdAlphaMax - a1 * a2 / gdAlphaMax ) * b1 + \ - a2 * ( gdAlphaMax - a1 ) / ( gdAlphaMax - a1 * a2 / gdAlphaMax ) * b2 ) / gdAlphaMax; - c = (a2 * b2 + ( gdAlphaMax - a2 ) * w ) / gdAlphaMax; - return ( a1 * b1 + ( gdAlphaMax - a1 ) * c ) / gdAlphaMax; -} - static int gdLayerOverlay (int dst, int src) { int a1, a2; @@ -3415,12 +3576,12 @@ static int gdAlphaOverlayColor (int src, int dst, int max ) { /* this function implements the algorithm - * + * * for dst[rgb] < 0.5, * c[rgb] = 2.src[rgb].dst[rgb] * and for dst[rgb] > 0.5, * c[rgb] = -2.src[rgb].dst[rgb] + 2.dst[rgb] + 2.src[rgb] - 1 - * + * */ dst = dst << 1; @@ -3472,3 +3633,457 @@ *x2P = im->cx2; *y2P = im->cy2; } + + +/* Filters function added on 2003/12 + * by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +/* Begin filters function */ +#ifndef HAVE_GET_TRUE_COLOR +#define GET_PIXEL_FUNCTION(src)(src->trueColor?gdImageGetTrueColorPixel:gdImageGetPixel) +#endif + +/* invert src image */ +int gdImageNegate(gdImagePtr src) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for (y=0; ysy; ++y) { + for (x=0; xsx; ++x) { + pxl = f (src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + new_pxl = gdImageColorAllocateAlpha(src, 255-r, 255-g, 255-b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, 255-r, 255-g, 255-b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +/* Convert the image src to a grayscale image */ +int gdImageGrayScale(gdImagePtr src) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL) { + return 0; + } + + for (y=0; ysy; ++y) { + for (x=0; xsx; ++x) { + pxl = f (src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + r = g = b = (int) (.299 * r + .587 * g + .114 * b); + + new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +/* Set the brightness level for the image src */ +int gdImageBrightness(gdImagePtr src, int brightness) +{ + int x, y; + int r,g,b,a; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL || (brightness < -255 || brightness>255)) { + return 0; + } + + if (brightness==0) { + return 1; + } + + for (y=0; ysy; ++y) { + for (x=0; xsx; ++x) { + pxl = f (src, x, y); + + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + r = r + brightness; + g = g + brightness; + b = b + brightness; + + r = (r > 255)? 255 : ((r < 0)? 0:r); + g = (g > 255)? 255 : ((g < 0)? 0:g); + b = (b > 255)? 255 : ((b < 0)? 0:b); + + new_pxl = gdImageColorAllocateAlpha(src, (int)r, (int)g, (int)b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)r, (int)g, (int)b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + + +int gdImageContrast(gdImagePtr src, double contrast) +{ + int x, y; + int r,g,b,a; + double rf,gf,bf; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + + FuncPtr f; + f = GET_PIXEL_FUNCTION(src); + + if (src==NULL) { + return 0; + } + + contrast = (double)(100.0-contrast)/100.0; + contrast = contrast*contrast; + + for (y=0; ysy; ++y) { + for (x=0; xsx; ++x) { + pxl = f(src, x, y); + + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + rf = (double)r/255.0; + rf = rf-0.5; + rf = rf*contrast; + rf = rf+0.5; + rf = rf*255.0; + + bf = (double)b/255.0; + bf = bf-0.5; + bf = bf*contrast; + bf = bf+0.5; + bf = bf*255.0; + + gf = (double)g/255.0; + gf = gf-0.5; + gf = gf*contrast; + gf = gf+0.5; + gf = gf*255.0; + + rf = (rf > 255.0)? 255.0 : ((rf < 0.0)? 0.0:rf); + gf = (gf > 255.0)? 255.0 : ((gf < 0.0)? 0.0:gf); + bf = (bf > 255.0)? 255.0 : ((bf < 0.0)? 0.0:bf); + + new_pxl = gdImageColorAllocateAlpha(src, (int)rf, (int)gf, (int)bf, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)rf, (int)gf, (int)bf, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + + +int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha) +{ + int x, y; + int new_pxl, pxl; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src == NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for (y=0; ysy; ++y) { + for (x=0; xsx; ++x) { + int r,g,b,a; + + pxl = f(src, x, y); + r = gdImageRed(src, pxl); + g = gdImageGreen(src, pxl); + b = gdImageBlue(src, pxl); + a = gdImageAlpha(src, pxl); + + r = r + red; + g = g + green; + b = b + blue; + a = a + alpha; + + r = (r > 255)? 255 : ((r < 0)? 0 : r); + g = (g > 255)? 255 : ((g < 0)? 0 : g); + b = (b > 255)? 255 : ((b < 0)? 0 : b); + a = (a > 127)? 127 : ((a < 0)? 0 : a); + + new_pxl = gdImageColorAllocateAlpha(src, r, g, b, a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, r, g, b, a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + return 1; +} + +int gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset) +{ + int x, y, i, j, new_a; + float new_r, new_g, new_b; + int new_pxl, pxl=0; + gdImagePtr srcback; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + /* We need the orinal image with each safe neoghb. pixel */ + srcback = gdImageCreateTrueColor (src->sx, src->sy); + gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); + + if (srcback==NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for ( y=0; ysy; y++) { + for(x=0; xsx; x++) { + new_r = new_g = new_b = 0; + new_a = gdImageAlpha(srcback, pxl); + + for (j=0; j<3; j++) { + int yv = MIN(MAX(y - 1 + j, 0), src->sy - 1); + for (i=0; i<3; i++) { + pxl = f(srcback, MIN(MAX(x - 1 + i, 0), src->sx - 1), yv); + new_r += (float)gdImageRed(srcback, pxl) * filter[j][i]; + new_g += (float)gdImageGreen(srcback, pxl) * filter[j][i]; + new_b += (float)gdImageBlue(srcback, pxl) * filter[j][i]; + } + } + + new_r = (new_r/filter_div)+offset; + new_g = (new_g/filter_div)+offset; + new_b = (new_b/filter_div)+offset; + + new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); + new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); + new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); + + new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + gdImageDestroy(srcback); + return 1; +} + +int gdImageSelectiveBlur( gdImagePtr src) +{ + int x, y, i, j; + float new_r, new_g, new_b; + int new_pxl, cpxl, pxl, new_a=0; + float flt_r [3][3]; + float flt_g [3][3]; + float flt_b [3][3]; + float flt_r_sum, flt_g_sum, flt_b_sum; + + gdImagePtr srcback; + typedef int (*FuncPtr)(gdImagePtr, int, int); + FuncPtr f; + + if (src==NULL) { + return 0; + } + + /* We need the orinal image with each safe neoghb. pixel */ + srcback = gdImageCreateTrueColor (src->sx, src->sy); + gdImageCopy(srcback, src,0,0,0,0,src->sx,src->sy); + + if (srcback==NULL) { + return 0; + } + + f = GET_PIXEL_FUNCTION(src); + + for(y = 0; ysy; y++) { + for (x=0; xsx; x++) { + flt_r_sum = flt_g_sum = flt_b_sum = 0.0; + cpxl = f(src, x, y); + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + if ((j == 1) && (i == 1)) { + flt_r[1][1] = flt_g[1][1] = flt_b[1][1] = 0.5; + } else { + pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); + new_a = gdImageAlpha(srcback, pxl); + + new_r = ((float)gdImageRed(srcback, cpxl)) - ((float)gdImageRed (srcback, pxl)); + + if (new_r < 0.0f) { + new_r = -new_r; + } + if (new_r != 0) { + flt_r[j][i] = 1.0f/new_r; + } else { + flt_r[j][i] = 1.0f; + } + + new_g = ((float)gdImageGreen(srcback, cpxl)) - ((float)gdImageGreen(srcback, pxl)); + + if (new_g < 0.0f) { + new_g = -new_g; + } + if (new_g != 0) { + flt_g[j][i] = 1.0f/new_g; + } else { + flt_g[j][i] = 1.0f; + } + + new_b = ((float)gdImageBlue(srcback, cpxl)) - ((float)gdImageBlue(srcback, pxl)); + + if (new_b < 0.0f) { + new_b = -new_b; + } + if (new_b != 0) { + flt_b[j][i] = 1.0f/new_b; + } else { + flt_b[j][i] = 1.0f; + } + } + + flt_r_sum += flt_r[j][i]; + flt_g_sum += flt_g[j][i]; + flt_b_sum += flt_b [j][i]; + } + } + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + if (flt_r_sum != 0.0) { + flt_r[j][i] /= flt_r_sum; + } + if (flt_g_sum != 0.0) { + flt_g[j][i] /= flt_g_sum; + } + if (flt_b_sum != 0.0) { + flt_b [j][i] /= flt_b_sum; + } + } + } + + new_r = new_g = new_b = 0.0; + + for (j=0; j<3; j++) { + for (i=0; i<3; i++) { + pxl = f(src, x-(3>>1)+i, y-(3>>1)+j); + new_r += (float)gdImageRed(srcback, pxl) * flt_r[j][i]; + new_g += (float)gdImageGreen(srcback, pxl) * flt_g[j][i]; + new_b += (float)gdImageBlue(srcback, pxl) * flt_b[j][i]; + } + } + + new_r = (new_r > 255.0f)? 255.0f : ((new_r < 0.0f)? 0.0f:new_r); + new_g = (new_g > 255.0f)? 255.0f : ((new_g < 0.0f)? 0.0f:new_g); + new_b = (new_b > 255.0f)? 255.0f : ((new_b < 0.0f)? 0.0f:new_b); + new_pxl = gdImageColorAllocateAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + if (new_pxl == -1) { + new_pxl = gdImageColorClosestAlpha(src, (int)new_r, (int)new_g, (int)new_b, new_a); + } + gdImageSetPixel (src, x, y, new_pxl); + } + } + gdImageDestroy(srcback); + return 1; +} + +int gdImageEdgeDetectQuick(gdImagePtr src) +{ + float filter[3][3] = {{-1.0,0.0,-1.0}, + {0.0,4.0,0.0}, + {-1.0,0.0,-1.0}}; + + return gdImageConvolution(src, filter, 1, 127); +} + +int gdImageGaussianBlur(gdImagePtr im) +{ + float filter[3][3] = {{1.0,2.0,1.0}, + {2.0,4.0,2.0}, + {1.0,2.0,1.0}}; + + return gdImageConvolution(im, filter, 16, 0); +} + +int gdImageEmboss(gdImagePtr im) +{ +/* + float filter[3][3] = {{1.0,1.0,1.0}, + {0.0,0.0,0.0}, + {-1.0,-1.0,-1.0}}; +*/ + float filter[3][3] = {{ 1.5, 0.0, 0.0}, + { 0.0, 0.0, 0.0}, + { 0.0, 0.0,-1.5}}; + + return gdImageConvolution(im, filter, 1, 127); +} + +int gdImageMeanRemoval(gdImagePtr im) +{ + float filter[3][3] = {{-1.0,-1.0,-1.0}, + {-1.0,9.0,-1.0}, + {-1.0,-1.0,-1.0}}; + + return gdImageConvolution(im, filter, 1, 0); +} + +int gdImageSmooth(gdImagePtr im, float weight) +{ + float filter[3][3] = {{1.0,1.0,1.0}, + {1.0,0.0,1.0}, + {1.0,1.0,1.0}}; + + filter[1][1] = weight; + + return gdImageConvolution(im, filter, weight+8, 0); +} +/* End filters function */ diff -urN php-4.4.8.org/ext/gd/libgd/gdcache.c php-4.4.8/ext/gd/libgd/gdcache.c --- php-4.4.8.org/ext/gd/libgd/gdcache.c 2003-04-05 19:24:16.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdcache.c 2003-12-28 21:11:08.000000000 +0100 @@ -11,11 +11,11 @@ #ifdef NEED_CACHE -/* +/* * gdcache.c * - * Caches of pointers to user structs in which the least-recently-used - * element is replaced in the event of a cache miss after the cache has + * Caches of pointers to user structs in which the least-recently-used + * element is replaced in the event of a cache miss after the cache has * reached a given size. * * John Ellson (ellson@graphviz.org) Oct 31, 1997 @@ -30,17 +30,17 @@ * The head structure has a pointer to the most-recently-used * element, and elements are moved to this position in the list each * time they are used. The head also contains pointers to three - * user defined functions: - * - a function to test if a cached userdata matches some keydata - * - a function to provide a new userdata struct to the cache + * user defined functions: + * - a function to test if a cached userdata matches some keydata + * - a function to provide a new userdata struct to the cache * if there has been a cache miss. * - a function to release a userdata struct when it is * no longer being managed by the cache * * In the event of a cache miss the cache is allowed to grow up to * a specified maximum size. After the maximum size is reached then - * the least-recently-used element is discarded to make room for the - * new. The most-recently-returned value is always left at the + * the least-recently-used element is discarded to make room for the + * new. The most-recently-returned value is always left at the * beginning of the list after retrieval. * * In the current implementation the cache is traversed by a linear diff -urN php-4.4.8.org/ext/gd/libgd/gdcache.h php-4.4.8/ext/gd/libgd/gdcache.h --- php-4.4.8.org/ext/gd/libgd/gdcache.h 2003-04-05 19:24:16.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdcache.h 2003-12-28 21:11:08.000000000 +0100 @@ -1,8 +1,8 @@ -/* +/* * gdcache.h * - * Caches of pointers to user structs in which the least-recently-used - * element is replaced in the event of a cache miss after the cache has + * Caches of pointers to user structs in which the least-recently-used + * element is replaced in the event of a cache miss after the cache has * reached a given size. * * John Ellson (ellson@graphviz.org) Oct 31, 1997 @@ -17,17 +17,17 @@ * The head structure has a pointer to the most-recently-used * element, and elements are moved to this position in the list each * time they are used. The head also contains pointers to three - * user defined functions: - * - a function to test if a cached userdata matches some keydata - * - a function to provide a new userdata struct to the cache + * user defined functions: + * - a function to test if a cached userdata matches some keydata + * - a function to provide a new userdata struct to the cache * if there has been a cache miss. * - a function to release a userdata struct when it is * no longer being managed by the cache * * In the event of a cache miss the cache is allowed to grow up to * a specified maximum size. After the maximum size is reached then - * the least-recently-used element is discarded to make room for the - * new. The most-recently-returned value is always left at the + * the least-recently-used element is discarded to make room for the + * new. The most-recently-returned value is always left at the * beginning of the list after retrieval. * * In the current implementation the cache is traversed by a linear diff -urN php-4.4.8.org/ext/gd/libgd/gdfontg.c php-4.4.8/ext/gd/libgd/gdfontg.c --- php-4.4.8.org/ext/gd/libgd/gdfontg.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdfontg.c 2006-09-16 21:07:45.000000000 +0200 @@ -13,7 +13,7 @@ #include "gdfontg.h" -char gdFontGiantData[] = +static const char gdFontGiantData[] = { /* Char 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4376,7 +4376,7 @@ 0, 9, 15, - gdFontGiantData + (char*)gdFontGiantData }; gdFontPtr gdFontGiant = &gdFontGiantRep; diff -urN php-4.4.8.org/ext/gd/libgd/gdfontl.c php-4.4.8/ext/gd/libgd/gdfontl.c --- php-4.4.8.org/ext/gd/libgd/gdfontl.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdfontl.c 2006-09-16 21:07:45.000000000 +0200 @@ -14,7 +14,7 @@ #include "gdfontl.h" -char gdFontLargeData[] = +static const char gdFontLargeData[] = { /* Char 0 */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -4633,7 +4633,7 @@ 0, 8, 16, - gdFontLargeData + (char*)gdFontLargeData }; gdFontPtr gdFontLarge = &gdFontLargeRep; diff -urN php-4.4.8.org/ext/gd/libgd/gdfontmb.c php-4.4.8/ext/gd/libgd/gdfontmb.c --- php-4.4.8.org/ext/gd/libgd/gdfontmb.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdfontmb.c 2006-09-16 21:07:46.000000000 +0200 @@ -12,7 +12,7 @@ #include "gdfontmb.h" -char gdFontMediumBoldData[] = +static const char gdFontMediumBoldData[] = { /* Char 0 */ 0, 0, 0, 0, 0, 0, 0, @@ -3863,7 +3863,7 @@ 0, 7, 13, - gdFontMediumBoldData + (char*)gdFontMediumBoldData }; gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep; diff -urN php-4.4.8.org/ext/gd/libgd/gdfonts.c php-4.4.8/ext/gd/libgd/gdfonts.c --- php-4.4.8.org/ext/gd/libgd/gdfonts.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdfonts.c 2006-09-16 21:07:46.000000000 +0200 @@ -12,7 +12,7 @@ #include "gdfonts.h" -char gdFontSmallData[] = +static const char gdFontSmallData[] = { /* Char 0 */ 0, 0, 0, 0, 0, 0, @@ -3863,7 +3863,7 @@ 0, 6, 13, - gdFontSmallData + (char*)gdFontSmallData }; gdFontPtr gdFontSmall = &gdFontSmallRep; diff -urN php-4.4.8.org/ext/gd/libgd/gdfontt.c php-4.4.8/ext/gd/libgd/gdfontt.c --- php-4.4.8.org/ext/gd/libgd/gdfontt.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdfontt.c 2006-09-16 21:07:46.000000000 +0200 @@ -13,7 +13,7 @@ #include "gdfontt.h" -char gdFontTinyData[] = +static const char gdFontTinyData[] = { /* Char 0 */ 0, 0, 0, 0, 0, @@ -2584,7 +2584,7 @@ 0, 5, 8, - gdFontTinyData + (char*)gdFontTinyData }; gdFontPtr gdFontTiny = &gdFontTinyRep; diff -urN php-4.4.8.org/ext/gd/libgd/gdft.c php-4.4.8/ext/gd/libgd/gdft.c --- php-4.4.8.org/ext/gd/libgd/gdft.c 2007-03-10 13:51:07.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gdft.c 2007-04-23 17:17:47.000000000 +0200 @@ -16,7 +16,9 @@ #include #else #include -#define R_OK 04 /* Needed in Windows */ +#ifndef R_OK +# define R_OK 04 /* Needed in Windows */ +#endif #endif #ifdef WIN32 @@ -37,9 +39,8 @@ gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { - /* 2.0.6: valid return */ - return gdImageStringFT (im, brect, fg, fontlist, ptsize, - angle, x, y, string); + /* 2.0.6: valid return */ + return gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y, string); } #ifndef HAVE_LIBFREETYPE @@ -48,14 +49,14 @@ double ptsize, double angle, int x, int y, char *string, gdFTStringExtraPtr strex) { - return "libgd was not built with FreeType font support\n"; + return "libgd was not built with FreeType font support\n"; } char * gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { - return "libgd was not built with FreeType font support\n"; + return "libgd was not built with FreeType font support\n"; } #else @@ -71,8 +72,8 @@ #define TWEENCOLORCACHESIZE 32 /* - * Line separation as a factor of font height. - * No space between if LINESPACE = 1.00 + * Line separation as a factor of font height. + * No space between if LINESPACE = 1.00 * Line separation will be rounded up to next pixel row. */ #define LINESPACE 1.05 @@ -115,40 +116,35 @@ typedef struct { - char *fontlist; /* key */ - FT_Library *library; - FT_Face face; - FT_Bool have_char_map_unicode, have_char_map_big5, have_char_map_sjis, - have_char_map_apple_roman; - gdCache_head_t *glyphCache; -} -font_t; + char *fontlist; /* key */ + FT_Library *library; + FT_Face face; + FT_Bool have_char_map_unicode, have_char_map_big5, have_char_map_sjis, have_char_map_apple_roman; + gdCache_head_t *glyphCache; +} font_t; typedef struct - { - char *fontlist; /* key */ - FT_Library *library; - } -fontkey_t; +{ + char *fontlist; /* key */ + FT_Library *library; +} fontkey_t; typedef struct - { - int pixel; /* key */ - int bgcolor; /* key */ - int fgcolor; /* key *//* -ve means no antialias */ - gdImagePtr im; /* key */ - int tweencolor; - } -tweencolor_t; +{ + int pixel; /* key */ + int bgcolor; /* key */ + int fgcolor; /* key *//* -ve means no antialias */ + gdImagePtr im; /* key */ + int tweencolor; +} tweencolor_t; typedef struct - { - int pixel; /* key */ - int bgcolor; /* key */ - int fgcolor; /* key *//* -ve means no antialias */ - gdImagePtr im; /* key */ - } -tweencolorkey_t; +{ + int pixel; /* key */ + int bgcolor; /* key */ + int fgcolor; /* key *//* -ve means no antialias */ + gdImagePtr im; /* key */ +} tweencolorkey_t; /******************************************************************** * gdTcl_UtfToUniChar is borrowed from Tcl ... @@ -208,160 +204,141 @@ #define Tcl_UniChar int #define TCL_UTF_MAX 3 -static int -gdTcl_UtfToUniChar (char *str, Tcl_UniChar * chPtr) +static int gdTcl_UtfToUniChar (char *str, Tcl_UniChar * chPtr) /* str is the UTF8 next character pointer */ /* chPtr is the int for the result */ { - int byte; + int byte; + + /* HTML4.0 entities in decimal form, e.g. Å */ + byte = *((unsigned char *) str); + if (byte == '&') { + int i, n = 0; + + byte = *((unsigned char *) (str + 1)); + if (byte == '#') { + byte = *((unsigned char *) (str + 2)); + if (byte == 'x' || byte == 'X') { + for (i = 3; i < 8; i++) { + byte = *((unsigned char *) (str + i)); + if (byte >= 'A' && byte <= 'F') + byte = byte - 'A' + 10; + else if (byte >= 'a' && byte <= 'f') + byte = byte - 'a' + 10; + else if (byte >= '0' && byte <= '9') + byte = byte - '0'; + else + break; + n = (n * 16) + byte; + } + } else { + for (i = 2; i < 8; i++) { + byte = *((unsigned char *) (str + i)); + if (byte >= '0' && byte <= '9') { + n = (n * 10) + (byte - '0'); + } else { + break; + } + } + } + if (byte == ';') { + *chPtr = (Tcl_UniChar) n; + return ++i; + } + } + } - /* HTML4.0 entities in decimal form, e.g. Å */ - byte = *((unsigned char *) str); - if (byte == '&') - { - int i, n = 0; - - byte = *((unsigned char *) (str + 1)); - if (byte == '#') - { - for (i = 2; i < 8; i++) - { - byte = *((unsigned char *) (str + i)); - if (byte >= '0' && byte <= '9') - { - n = (n * 10) + (byte - '0'); - } - else - break; - } - if (byte == ';') - { - *chPtr = (Tcl_UniChar) n; - return ++i; - } - } - } - - /* - * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. - */ + /* Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ - byte = *((unsigned char *) str); + byte = *((unsigned char *) str); #ifdef JISX0208 - if (0xA1 <= byte && byte <= 0xFE) - { - int ku, ten; - - ku = (byte & 0x7F) - 0x20; - ten = (str[1] & 0x7F) - 0x20; - if ((ku < 1 || ku > 92) || (ten < 1 || ten > 94)) - { - *chPtr = (Tcl_UniChar) byte; - return 1; - } - - *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1]; - return 2; - } - else + if (0xA1 <= byte && byte <= 0xFE) { + int ku, ten; + + ku = (byte & 0x7F) - 0x20; + ten = (str[1] & 0x7F) - 0x20; + if ((ku < 1 || ku > 92) || (ten < 1 || ten > 94)) { + *chPtr = (Tcl_UniChar) byte; + return 1; + } + + *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1]; + return 2; + } else #endif /* JISX0208 */ - if (byte < 0xC0) - { - /* - * Handles properly formed UTF-8 characters between - * 0x01 and 0x7F. Also treats \0 and naked trail - * bytes 0x80 to 0xBF as valid characters representing - * themselves. - */ - - *chPtr = (Tcl_UniChar) byte; - return 1; - } - else if (byte < 0xE0) - { - if ((str[1] & 0xC0) == 0x80) - { - /* - * Two-byte-character lead-byte followed - * by a trail-byte. - */ - - *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) - | (str[1] & 0x3F)); - return 2; - } - /* - * A two-byte-character lead-byte not followed by trail-byte - * represents itself. - */ - - *chPtr = (Tcl_UniChar) byte; - return 1; - } - else if (byte < 0xF0) - { - if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) - { - /* - * Three-byte-character lead byte followed by - * two trail bytes. - */ - - *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) - | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); - return 3; - } - /* - * A three-byte-character lead-byte not followed by - * two trail-bytes represents itself. - */ - - *chPtr = (Tcl_UniChar) byte; - return 1; - } + if (byte < 0xC0) { + /* Handles properly formed UTF-8 characters between + * 0x01 and 0x7F. Also treats \0 and naked trail + * bytes 0x80 to 0xBF as valid characters representing + * themselves. + */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } else if (byte < 0xE0) { + if ((str[1] & 0xC0) == 0x80) { + /* Two-byte-character lead-byte followed by a trail-byte. */ + + *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F)); + return 2; + } + /* + * A two-byte-character lead-byte not followed by trail-byte + * represents itself. + */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } else if (byte < 0xF0) { + if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) { + /* Three-byte-character lead byte followed by two trail bytes. */ + + *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); + return 3; + } + /* A three-byte-character lead-byte not followed by two trail-bytes represents itself. */ + + *chPtr = (Tcl_UniChar) byte; + return 1; + } #if TCL_UTF_MAX > 3 - else - { - int ch, total, trail; - - total = totalBytes[byte]; - trail = total - 1; - if (trail > 0) - { - ch = byte & (0x3F >> trail); - do - { - str++; - if ((*str & 0xC0) != 0x80) - { - *chPtr = byte; - return 1; - } - ch <<= 6; - ch |= (*str & 0x3F); - trail--; - } - while (trail > 0); - *chPtr = ch; - return total; + else { + int ch, total, trail; + + total = totalBytes[byte]; + trail = total - 1; + + if (trail > 0) { + ch = byte & (0x3F >> trail); + do { + str++; + if ((*str & 0xC0) != 0x80) { + *chPtr = byte; + return 1; + } + ch <<= 6; + ch |= (*str & 0x3F); + trail--; + } while (trail > 0); + *chPtr = ch; + return total; + } } - } #endif - *chPtr = (Tcl_UniChar) byte; - return 1; + *chPtr = (Tcl_UniChar) byte; + return 1; } /********************************************************************/ /* font cache functions */ -static int -fontTest (void *element, void *key) +static int fontTest (void *element, void *key) { - font_t *a = (font_t *) element; - fontkey_t *b = (fontkey_t *) key; + font_t *a = (font_t *) element; + fontkey_t *b = (fontkey_t *) key; - return (strcmp (a->fontlist, b->fontlist) == 0); + return (strcmp (a->fontlist, b->fontlist) == 0); } static void *fontFetch (char **error, void *key) @@ -389,7 +366,7 @@ fontsearchpath = getenv ("GDFONTPATH"); if (!fontsearchpath) { fontsearchpath = DEFAULT_FONTPATH; - } + } fontlist = gdEstrdup(a->fontlist); /* @@ -399,8 +376,12 @@ /* make a fresh copy each time - strtok corrupts it. */ path = gdEstrdup (fontsearchpath); - /* if name is an absolute filename then test directly */ + /* if name is an absolute filename then test directly */ +#ifdef NETWARE + if (*name == '/' || (name[0] != 0 && strstr(name, ":/"))) { +#else if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) { +#endif snprintf(fullname, sizeof(fullname) - 1, "%s", name); if (access(fullname, R_OK) == 0) { font_found++; @@ -437,15 +418,15 @@ path = NULL; if (font_found) { break; - } + } } - + if (path) { gdFree(path); } - + gdFree(fontlist); - + if (!font_found) { gdPFree(a->fontlist); gdPFree(a); @@ -556,257 +537,234 @@ * does the work so that text can be alpha blended across a complex * background (TBB; and for real in 2.0.2). */ -static void * -tweenColorFetch (char **error, void *key) +static void * tweenColorFetch (char **error, void *key) { - tweencolor_t *a; - tweencolorkey_t *b = (tweencolorkey_t *) key; - int pixel, npixel, bg, fg; - gdImagePtr im; - - a = (tweencolor_t *) gdMalloc (sizeof (tweencolor_t)); - pixel = a->pixel = b->pixel; - bg = a->bgcolor = b->bgcolor; - fg = a->fgcolor = b->fgcolor; - im = b->im; - - /* if fg is specified by a negative color idx, then don't antialias */ - if (fg < 0) - { - if ((pixel + pixel) >= NUMCOLORS) - a->tweencolor = -fg; - else - a->tweencolor = bg; - } - else - { - npixel = NUMCOLORS - pixel; - if (im->trueColor) - { - /* 2.0.1: use gdImageSetPixel to do the alpha blending work, - or to just store the alpha level. All we have to do here - is incorporate our knowledge of the percentage of this - pixel that is really "lit" by pushing the alpha value - up toward transparency in edge regions. */ - a->tweencolor = gdTrueColorAlpha ( - gdTrueColorGetRed (fg), - gdTrueColorGetGreen (fg), - gdTrueColorGetBlue (fg), - gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS)); - } - else - { - a->tweencolor = gdImageColorResolve (im, - (pixel * im->red[fg] + npixel * im->red[bg]) / NUMCOLORS, - (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS, - (pixel * im->blue[fg] + npixel * im->blue[bg]) / NUMCOLORS); - } - } - return (void *) a; + tweencolor_t *a; + tweencolorkey_t *b = (tweencolorkey_t *) key; + int pixel, npixel, bg, fg; + gdImagePtr im; + + a = (tweencolor_t *) gdMalloc (sizeof (tweencolor_t)); + pixel = a->pixel = b->pixel; + bg = a->bgcolor = b->bgcolor; + fg = a->fgcolor = b->fgcolor; + im = a->im = b->im; + + /* if fg is specified by a negative color idx, then don't antialias */ + if (fg < 0) { + if ((pixel + pixel) >= NUMCOLORS) { + a->tweencolor = -fg; + } else { + a->tweencolor = bg; + } + } else { + npixel = NUMCOLORS - pixel; + if (im->trueColor) { + /* 2.0.1: use gdImageSetPixel to do the alpha blending work, + * or to just store the alpha level. All we have to do here + * is incorporate our knowledge of the percentage of this + * pixel that is really "lit" by pushing the alpha value + * up toward transparency in edge regions. + */ + a->tweencolor = gdTrueColorAlpha( + gdTrueColorGetRed(fg), + gdTrueColorGetGreen(fg), + gdTrueColorGetBlue(fg), + gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS)); + } else { + a->tweencolor = gdImageColorResolve(im, + (pixel * im->red[fg] + npixel * im->red[bg]) / NUMCOLORS, + (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS, + (pixel * im->blue[fg] + npixel * im->blue[bg]) / NUMCOLORS); + } + } + return (void *) a; } -static void -tweenColorRelease (void *element) +static void tweenColorRelease (void *element) { - gdFree ((char *) element); + gdFree((char *) element); } /* draw_bitmap - transfers glyph bitmap to GD image */ -static char * -gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y) +static char * gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y) { - unsigned char *pixel = NULL; - int *tpixel = NULL; - int x, y, row, col, pc, pcr; - - tweencolor_t *tc_elem; - tweencolorkey_t tc_key; - - /* copy to image, mapping colors */ - tc_key.fgcolor = fg; - tc_key.im = im; - /* Truecolor version; does not require the cache */ - if (im->trueColor) - { - for (row = 0; row < bitmap.rows; row++) - { - pc = row * bitmap.pitch; - pcr = pc; - y = pen_y + row; - /* clip if out of bounds */ - /* 2.0.16: clipping rectangle, not image bounds */ - if ((y > im->cy2) || (y < im->cy1)) - continue; - for (col = 0; col < bitmap.width; col++, pc++) - { - int level; - if (bitmap.pixel_mode == ft_pixel_mode_grays) - { - /* - * Scale to 128 levels of alpha for gd use. - * alpha 0 is opacity, so be sure to invert at the end - */ - level = (bitmap.buffer[pc] * gdAlphaMax / - (bitmap.num_grays - 1)); - } - else if (bitmap.pixel_mode == ft_pixel_mode_mono) - { - /* 2.0.5: mode_mono fix from Giuliano Pochini */ - level = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) - ? gdAlphaTransparent : - gdAlphaOpaque; - } - else - { - return "Unsupported ft_pixel_mode"; - } - if ((fg >= 0) && (im->trueColor)) { - /* Consider alpha in the foreground color itself to be an - upper bound on how opaque things get, when truecolor is - available. Without truecolor this results in far too many - color indexes. */ - level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax; - } - level = gdAlphaMax - level; - x = pen_x + col; - /* clip if out of bounds */ - /* 2.0.16: clip to clipping rectangle, Matt McNabb */ - if ((x > im->cx2) || (x < im->cx1)) - continue; - /* get pixel location in gd buffer */ - tpixel = &im->tpixels[y][x]; - if (fg < 0) { - if (level < (gdAlphaMax / 2)) { - *tpixel = -fg; - } - } else { - if (im->alphaBlendingFlag) { - *tpixel = gdAlphaBlend(*tpixel, (level << 24) + (fg & 0xFFFFFF)); - } else { - *tpixel = (level << 24) + (fg & 0xFFFFFF); - } - } - } - } - return (char *) NULL; - } - /* Non-truecolor case, restored to its more or less original form */ - for (row = 0; row < bitmap.rows; row++) - { - int pcr; - pc = row * bitmap.pitch; - pcr = pc; - if(bitmap.pixel_mode==ft_pixel_mode_mono) - pc *= 8; /* pc is measured in bits for monochrome images */ - - y = pen_y + row; - - /* clip if out of bounds */ - if (y >= im->sy || y < 0) - continue; - - for (col = 0; col < bitmap.width; col++, pc++) - { - if (bitmap.pixel_mode == ft_pixel_mode_grays) - { - /* - * Round to NUMCOLORS levels of antialiasing for - * index color images since only 256 colors are - * available. - */ - tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS) - + bitmap.num_grays / 2) - / (bitmap.num_grays - 1); - } - else if (bitmap.pixel_mode == ft_pixel_mode_mono) - { - tc_key.pixel = ((bitmap.buffer[pc / 8] - << (pc % 8)) & 128) ? NUMCOLORS : 0; - /* 2.0.5: mode_mono fix from Giuliano Pochini */ - tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) - ? NUMCOLORS : 0; - } - else - { - return "Unsupported ft_pixel_mode"; - } - if (tc_key.pixel > 0) /* if not background */ - { - x = pen_x + col; - - /* clip if out of bounds */ - if (x >= im->sx || x < 0) - continue; - /* get pixel location in gd buffer */ - pixel = &im->pixels[y][x]; - if (tc_key.pixel == NUMCOLORS) - { - /* use fg color directly. gd 2.0.2: watch out for - negative indexes (thanks to David Marwood). */ - *pixel = (fg < 0) ? -fg : fg; - } - else - { - /* find antialised color */ - - tc_key.bgcolor = *pixel; - gdMutexLock(gdFontCacheMutex); - tc_elem = (tweencolor_t *) gdCacheGet (tc_cache, &tc_key); - *pixel = tc_elem->tweencolor; - gdMutexUnlock(gdFontCacheMutex); + unsigned char *pixel = NULL; + int *tpixel = NULL; + int x, y, row, col, pc, pcr; + + tweencolor_t *tc_elem; + tweencolorkey_t tc_key; + + /* copy to image, mapping colors */ + tc_key.fgcolor = fg; + tc_key.im = im; + /* Truecolor version; does not require the cache */ + if (im->trueColor) { + for (row = 0; row < bitmap.rows; row++) { + pc = row * bitmap.pitch; + pcr = pc; + y = pen_y + row; + /* clip if out of bounds */ + /* 2.0.16: clipping rectangle, not image bounds */ + if ((y > im->cy2) || (y < im->cy1)) { + continue; + } + for (col = 0; col < bitmap.width; col++, pc++) { + int level; + if (bitmap.pixel_mode == ft_pixel_mode_grays) { + /* Scale to 128 levels of alpha for gd use. + * alpha 0 is opacity, so be sure to invert at the end + */ + level = (bitmap.buffer[pc] * gdAlphaMax / (bitmap.num_grays - 1)); + } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + level = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) ? gdAlphaTransparent : gdAlphaOpaque; + } else { + return "Unsupported ft_pixel_mode"; + } + if ((fg >= 0) && (im->trueColor)) { + /* Consider alpha in the foreground color itself to be an + * upper bound on how opaque things get, when truecolor is + * available. Without truecolor this results in far too many + * color indexes. + */ + level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax; + } + level = gdAlphaMax - level; + x = pen_x + col; + /* clip if out of bounds */ + /* 2.0.16: clip to clipping rectangle, Matt McNabb */ + if ((x > im->cx2) || (x < im->cx1)) { + continue; + } + /* get pixel location in gd buffer */ + tpixel = &im->tpixels[y][x]; + if (fg < 0) { + if (level < (gdAlphaMax / 2)) { + *tpixel = -fg; + } + } else { + if (im->alphaBlendingFlag) { + *tpixel = gdAlphaBlend(*tpixel, (level << 24) + (fg & 0xFFFFFF)); + } else { + *tpixel = (level << 24) + (fg & 0xFFFFFF); + } + } + } + } + return (char *) NULL; + } + /* Non-truecolor case, restored to its more or less original form */ + for (row = 0; row < bitmap.rows; row++) { + int pcr; + pc = row * bitmap.pitch; + pcr = pc; + if (bitmap.pixel_mode==ft_pixel_mode_mono) { + pc *= 8; /* pc is measured in bits for monochrome images */ + } + y = pen_y + row; + + /* clip if out of bounds */ + if (y >= im->sy || y < 0) { + continue; + } + + for (col = 0; col < bitmap.width; col++, pc++) { + if (bitmap.pixel_mode == ft_pixel_mode_grays) { + /* + * Round to NUMCOLORS levels of antialiasing for + * index color images since only 256 colors are + * available. + */ + tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS) + bitmap.num_grays / 2) / (bitmap.num_grays - 1); + } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { + tc_key.pixel = ((bitmap.buffer[pc / 8] << (pc % 8)) & 128) ? NUMCOLORS : 0; + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) ? NUMCOLORS : 0; + } else { + return "Unsupported ft_pixel_mode"; + } + if (tc_key.pixel > 0) { /* if not background */ + x = pen_x + col; + + /* clip if out of bounds */ + if (x >= im->sx || x < 0) { + continue; + } + /* get pixel location in gd buffer */ + pixel = &im->pixels[y][x]; + if (tc_key.pixel == NUMCOLORS) { + /* use fg color directly. gd 2.0.2: watch out for + * negative indexes (thanks to David Marwood). + */ + *pixel = (fg < 0) ? -fg : fg; + } else { + /* find antialised color */ + tc_key.bgcolor = *pixel; + tc_elem = (tweencolor_t *) gdCacheGet(tc_cache, &tc_key); + *pixel = tc_elem->tweencolor; + } + } } - } } - } - return (char *) NULL; + return (char *) NULL; } static int gdroundupdown (FT_F26Dot6 v1, int updown) { - return (!updown) - ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6) - : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6); + return (!updown) ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6) : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6); } void gdFontCacheShutdown() { + gdMutexLock(gdFontCacheMutex); + if (fontCache) { - gdMutexLock(gdFontCacheMutex); gdCacheDelete(fontCache); fontCache = NULL; - gdMutexUnlock(gdFontCacheMutex); - gdMutexShutdown(gdFontCacheMutex); FT_Done_FreeType(library); } + + gdMutexUnlock(gdFontCacheMutex); } void gdFreeFontCache() { gdFontCacheShutdown(); } - + +void gdFontCacheMutexSetup() +{ + gdMutexSetup(gdFontCacheMutex); +} + +void gdFontCacheMutexShutdown() +{ + gdMutexShutdown(gdFontCacheMutex); +} + int gdFontCacheSetup(void) { if (fontCache) { /* Already set up */ return 0; } - gdMutexSetup(gdFontCacheMutex); if (FT_Init_FreeType(&library)) { - gdMutexShutdown(gdFontCacheMutex); return -1; } fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease); return 0; } + /********************************************************************/ /* gdImageStringFT - render a utf8 string onto a gd image */ char * -gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) +gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string) { return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, 0); } @@ -856,15 +814,16 @@ /***** initialize font library and font cache on first call ******/ + gdMutexLock(gdFontCacheMutex); if (!fontCache) { if (gdFontCacheSetup() != 0) { gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return "Failure to initialize font library"; } } /*****/ - - gdMutexLock(gdFontCacheMutex); + /* get the font (via font cache) */ fontkey.fontlist = fontlist; fontkey.library = &library; @@ -961,6 +920,7 @@ while (*next) { ch = *next; + /* carriage returns */ if (ch == '\r') { penf.x = 0; @@ -991,8 +951,9 @@ /* I do not know the significance of the constant 0xf000. * It was determined by inspection of the character codes * stored in Microsoft font symbol. + * Added by Pierre (pajoye@php.net): + * Convert to the Symbol glyph range only for a Symbol family member */ - /* Convert to the Symbol glyph range only for a Symbol family member */ len = gdTcl_UtfToUniChar (next, &ch); ch |= 0xf000; next += len; @@ -1008,7 +969,7 @@ next += len; } break; - case gdFTEX_Shift_JIS: + case gdFTEX_Shift_JIS: if (font->have_char_map_sjis) { unsigned char c; int jiscode; @@ -1063,7 +1024,7 @@ FT_Set_Transform(face, &matrix, NULL); /* Convert character code to glyph index */ glyph_index = FT_Get_Char_Index(face, ch); - + /* retrieve kerning distance and move pen position */ if (use_kerning && previous && glyph_index) { FT_Get_Kerning(face, previous, glyph_index, ft_kerning_default, &delta); diff -urN php-4.4.8.org/ext/gd/libgd/gd_gd2.c php-4.4.8/ext/gd/libgd/gd_gd2.c --- php-4.4.8.org/ext/gd/libgd/gd_gd2.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_gd2.c 2006-08-08 13:56:36.000000000 +0200 @@ -26,7 +26,7 @@ /* 2.11: not part of the API, as the save routine can figure it out * from im->trueColor, and the load routine doesn't need to tell * the end user the saved format. NOTE: adding 2 is assumed - * to result in the correct format value for truecolor! + * to result in the correct format value for truecolor! */ #define GD2_FMT_TRUECOLOR_RAW 3 #define GD2_FMT_TRUECOLOR_COMPRESSED 4 @@ -43,8 +43,7 @@ { int offset; int size; -} -t_chunk_info; +} t_chunk_info; extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag); extern void _gdPutColors(gdImagePtr im, gdIOCtx * out); @@ -61,7 +60,7 @@ int sidx; int nc; - GD2_DBG(php_gd_error("Reading gd2 header info\n")); + GD2_DBG(php_gd_error("Reading gd2 header info")); for (i = 0; i < 4; i++) { ch = gdGetC(in); @@ -72,11 +71,11 @@ } id[4] = 0; - GD2_DBG(php_gd_error("Got file code: %s\n", id)); + GD2_DBG(php_gd_error("Got file code: %s", id)); /* Equiv. of 'magick'. */ if (strcmp(id, GD2_ID) != 0) { - GD2_DBG(php_gd_error("Not a valid gd2 file\n")); + GD2_DBG(php_gd_error("Not a valid gd2 file")); goto fail1; } @@ -84,32 +83,32 @@ if (gdGetWord(vers, in) != 1) { goto fail1; } - GD2_DBG(php_gd_error("Version: %d\n", *vers)); + GD2_DBG(php_gd_error("Version: %d", *vers)); if ((*vers != 1) && (*vers != 2)) { - GD2_DBG(php_gd_error("Bad version: %d\n", *vers)); + GD2_DBG(php_gd_error("Bad version: %d", *vers)); goto fail1; } /* Image Size */ if (!gdGetWord(sx, in)) { - GD2_DBG(php_gd_error("Could not get x-size\n")); + GD2_DBG(php_gd_error("Could not get x-size")); goto fail1; } if (!gdGetWord(sy, in)) { - GD2_DBG(php_gd_error("Could not get y-size\n")); + GD2_DBG(php_gd_error("Could not get y-size")); goto fail1; } - GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy)); + GD2_DBG(php_gd_error("Image is %dx%d", *sx, *sy)); /* Chunk Size (pixels, not bytes!) */ if (gdGetWord(cs, in) != 1) { goto fail1; } - GD2_DBG(php_gd_error("ChunkSize: %d\n", *cs)); + GD2_DBG(php_gd_error("ChunkSize: %d", *cs)); if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) { - GD2_DBG(php_gd_error("Bad chunk size: %d\n", *cs)); + GD2_DBG(php_gd_error("Bad chunk size: %d", *cs)); goto fail1; } @@ -117,10 +116,10 @@ if (gdGetWord(fmt, in) != 1) { goto fail1; } - GD2_DBG(php_gd_error("Format: %d\n", *fmt)); + GD2_DBG(php_gd_error("Format: %d", *fmt)); if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) && (*fmt != GD2_FMT_TRUECOLOR_RAW) && (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) { - GD2_DBG(php_gd_error("Bad data format: %d\n", *fmt)); + GD2_DBG(php_gd_error("Bad data format: %d", *fmt)); goto fail1; } @@ -128,17 +127,17 @@ if (gdGetWord(ncx, in) != 1) { goto fail1; } - GD2_DBG(php_gd_error("%d Chunks Wide\n", *ncx)); + GD2_DBG(php_gd_error("%d Chunks Wide", *ncx)); /* # of chunks high */ if (gdGetWord(ncy, in) != 1) { goto fail1; } - GD2_DBG(php_gd_error("%d Chunks vertically\n", *ncy)); + GD2_DBG(php_gd_error("%d Chunks vertically", *ncy)); if (gd2_compressed(*fmt)) { nc = (*ncx) * (*ncy); - GD2_DBG(php_gd_error("Reading %d chunk index entries\n", nc)); + GD2_DBG(php_gd_error("Reading %d chunk index entries", nc)); sidx = sizeof(t_chunk_info) * nc; if (sidx <= 0) { goto fail1; @@ -155,7 +154,7 @@ *chunkIdx = cidx; } - GD2_DBG(php_gd_error("gd2 header complete\n")); + GD2_DBG(php_gd_error("gd2 header complete")); return 1; @@ -168,7 +167,7 @@ gdImagePtr im; if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) { - GD2_DBG(php_gd_error("Bad GD2 header\n")); + GD2_DBG(php_gd_error("Bad GD2 header")); goto fail1; } @@ -178,15 +177,15 @@ im = gdImageCreate(*sx, *sy); } if (im == NULL) { - GD2_DBG(php_gd_error("Could not create gdImage\n")); + GD2_DBG(php_gd_error("Could not create gdImage")); goto fail1; } if (!_gdGetColors(in, im, (*vers) == 2)) { - GD2_DBG(php_gd_error("Could not read color palette\n")); + GD2_DBG(php_gd_error("Could not read color palette")); goto fail2; } - GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + GD2_DBG(php_gd_error("Image palette completed: %d colours", im->colorsTotal)); return im; @@ -203,25 +202,25 @@ int zerr; if (gdTell(in) != offset) { - GD2_DBG(php_gd_error("Positioning in file to %d\n", offset)); + GD2_DBG(php_gd_error("Positioning in file to %d", offset)); gdSeek(in, offset); } else { - GD2_DBG(php_gd_error("Already Positioned in file to %d\n", offset)); + GD2_DBG(php_gd_error("Already Positioned in file to %d", offset)); } /* Read and uncompress an entire chunk. */ - GD2_DBG(php_gd_error("Reading file\n")); + GD2_DBG(php_gd_error("Reading file")); if (gdGetBuf(compBuf, compSize, in) != compSize) { return FALSE; } - GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, (int)*chunkLen)); + GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes", compSize, (int)*chunkLen)); zerr = uncompress((unsigned char *) chunkBuf, chunkLen, (unsigned char *) compBuf, compSize); if (zerr != Z_OK) { - GD2_DBG(php_gd_error("Error %d from uncompress\n", zerr)); + GD2_DBG(php_gd_error("Error %d from uncompress", zerr)); return FALSE; } - GD2_DBG(php_gd_error("Got chunk\n")); - + GD2_DBG(php_gd_error("Got chunk")); + return TRUE; } @@ -291,8 +290,8 @@ } chunkBuf = gdCalloc(chunkMax, 1); compBuf = gdCalloc(compMax, 1); - - GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes\n", compMax)); + + GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes", compMax)); } /* Read the data... */ @@ -304,13 +303,13 @@ yhi = im->sy; } - GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d\n", chunkNum, cx, cy, ylo, yhi)); + GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d", chunkNum, cx, cy, ylo, yhi)); if (gd2_compressed(fmt)) { chunkLen = chunkMax; if (!_gd2ReadChunk(chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, (char *) chunkBuf, &chunkLen, in)) { - GD2_DBG(php_gd_error("Error reading comproessed chunk\n")); + GD2_DBG(php_gd_error("Error reading comproessed chunk")); goto fail2; } @@ -357,7 +356,7 @@ } } - GD2_DBG(php_gd_error("Freeing memory\n")); + GD2_DBG(php_gd_error("Freeing memory")); if (chunkBuf) { gdFree(chunkBuf); @@ -369,7 +368,7 @@ gdFree(chunkIdx); } - GD2_DBG(php_gd_error("Done\n")); + GD2_DBG(php_gd_error("Done")); return im; @@ -398,7 +397,7 @@ return im; } -gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) +gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) { gdImagePtr im; gdIOCtx *in = gdNewFileCtx(inFile); @@ -431,6 +430,10 @@ gdImagePtr im; + if (w<1 || h <1) { + return 0; + } + /* The next few lines are basically copied from gd2CreateFromFile * we change the file size, so don't want to use the code directly. * but we do need to know the file size. @@ -439,7 +442,7 @@ goto fail1; } - GD2_DBG(php_gd_error("File size is %dx%d\n", fsx, fsy)); + GD2_DBG(php_gd_error("File size is %dx%d", fsx, fsy)); /* This is the difference - make a file based on size of chunks. */ if (gd2_truecolor(fmt)) { @@ -454,7 +457,7 @@ if (!_gdGetColors(in, im, vers == 2)) { goto fail2; } - GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + GD2_DBG(php_gd_error("Image palette completed: %d colours", im->colorsTotal)); /* Process the header info */ nc = ncx * ncy; @@ -477,7 +480,7 @@ if (chunkMax <= 0) { goto fail2; } - + chunkBuf = gdCalloc(chunkMax, 1); compBuf = gdCalloc(compMax, 1); } @@ -503,7 +506,7 @@ /* Remember file position of image data. */ dstart = gdTell(in); - GD2_DBG(php_gd_error("Data starts at %d\n", dstart)); + GD2_DBG(php_gd_error("Data starts at %d", dstart)); /* Loop through the chunks. */ for (cy = scy; (cy <= ecy); cy++) { @@ -521,10 +524,10 @@ xhi = fsx; } - GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo, yhi)); + GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d", cx, cy, ylo, yhi)); if (!gd2_compressed(fmt)) { - GD2_DBG(php_gd_error("Using raw format data\n")); + GD2_DBG(php_gd_error("Using raw format data")); if (im->trueColor) { dpos = (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) + dstart; } else { @@ -533,29 +536,29 @@ /* gd 2.0.11: gdSeek returns TRUE on success, not 0. Longstanding bug. 01/16/03 */ if (!gdSeek(in, dpos)) { - php_gd_error_ex(E_WARNING, "Error from seek: %d\n", errno); + php_gd_error_ex(E_WARNING, "Error from seek: %d", errno); goto fail2; } - GD2_DBG(php_gd_error("Reading (%d, %d) from position %d\n", cx, cy, dpos - dstart)); + GD2_DBG(php_gd_error("Reading (%d, %d) from position %d", cx, cy, dpos - dstart)); } else { chunkNum = cx + cy * ncx; chunkLen = chunkMax; - if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { - php_gd_error("Error reading comproessed chunk\n"); + if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, (char *)chunkBuf, &chunkLen, in)) { + php_gd_error("Error reading comproessed chunk"); goto fail2; } chunkPos = 0; - GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d\n", cx, cy, chunkNum)); + GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d", cx, cy, chunkNum)); } - GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi)); + GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)", xlo, ylo, xhi, yhi)); for (y = ylo; (y < yhi); y++) { for (x = xlo; x < xhi; x++) { if (!gd2_compressed(fmt)) { if (im->trueColor) { - if (!gdGetInt(&ch, in)) { + if (!gdGetInt((int *)&ch, in)) { ch = 0; } } else { @@ -577,11 +580,11 @@ /* Only use a point that is in the image. */ if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)) { - if (im->trueColor) { + if (im->trueColor) { im->tpixels[y - srcy][x - srcx] = ch; } else { im->pixels[y - srcy][x - srcx] = ch; - } + } } } } @@ -597,7 +600,7 @@ if (chunkIdx) { gdFree(chunkIdx); } - + return im; fail2: @@ -653,7 +656,7 @@ int compMax = 0; /* Force fmt to a valid value since we don't return anything. */ - if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { + if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED; } if (im->trueColor) { @@ -693,16 +696,16 @@ chunkData = safe_emalloc(cs * bytesPerPixel, cs, 0); memset(chunkData, 0, cs * bytesPerPixel * cs); if (compMax <= 0) { - goto fail; + goto fail; } compData = gdCalloc(compMax, 1); /* Save the file position of chunk index, and allocate enough space for - * each chunk_info block . + * each chunk_info block . */ idxPos = gdTell(out); idxSize = ncx * ncy * sizeof(t_chunk_info); - GD2_DBG(php_gd_error("Index size is %d\n", idxSize)); + GD2_DBG(php_gd_error("Index size is %d", idxSize)); gdSeek(out, idxPos + idxSize); chunkIdx = safe_emalloc(idxSize, sizeof(t_chunk_info), 0); @@ -711,8 +714,8 @@ _gdPutColors (im, out); - GD2_DBG(php_gd_error("Size: %dx%d\n", im->sx, im->sy)); - GD2_DBG(php_gd_error("Chunks: %dx%d\n", ncx, ncy)); + GD2_DBG(php_gd_error("Size: %dx%d", im->sx, im->sy)); + GD2_DBG(php_gd_error("Chunks: %dx%d", ncx, ncy)); for (cy = 0; (cy < ncy); cy++) { for (cx = 0; (cx < ncx); cx++) { @@ -722,7 +725,7 @@ yhi = im->sy; } - GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); + GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d", cx, cy, ylo, yhi)); chunkLen = 0; for (y = ylo; (y < yhi); y++) { GD2_DBG(php_gd_error("y=%d: ",y)); @@ -747,7 +750,7 @@ } } else { for (x = xlo; x < xhi; x++) { - GD2_DBG(php_gd_error("%d, ",x)); + GD2_DBG(php_gd_error("%d, ",x)); if (im->trueColor) { gdPutInt(im->tpixels[y][x], out); @@ -756,21 +759,21 @@ } } } - GD2_DBG(php_gd_error("y=%d done.\n",y)); + GD2_DBG(php_gd_error("y=%d done.",y)); } if (gd2_compressed(fmt)) { compLen = compMax; if (compress((unsigned char *) &compData[0], &compLen, (unsigned char *) &chunkData[0], chunkLen) != Z_OK) { - php_gd_error("Error from compressing\n"); + php_gd_error("Error from compressing"); } else { chunkIdx[chunkNum].offset = gdTell(out); chunkIdx[chunkNum++].size = compLen; - GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); + GD2_DBG(php_gd_error("Chunk %d size %d offset %d", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); if (gdPutBuf (compData, compLen, out) <= 0) { /* Any alternate suggestions for handling this? */ - php_gd_error_ex(E_WARNING, "Error %d on write\n", errno); + php_gd_error_ex(E_WARNING, "Error %d on write", errno); } } } @@ -779,29 +782,29 @@ if (gd2_compressed(fmt)) { /* Save the position, write the index, restore position (paranoia). */ - GD2_DBG(php_gd_error("Seeking %d to write index\n", idxPos)); + GD2_DBG(php_gd_error("Seeking %d to write index", idxPos)); posSave = gdTell(out); gdSeek(out, idxPos); - GD2_DBG(php_gd_error("Writing index\n")); + GD2_DBG(php_gd_error("Writing index")); for (x = 0; x < chunkNum; x++) { - GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); + GD2_DBG(php_gd_error("Chunk %d size %d offset %d", x, chunkIdx[x].size, chunkIdx[x].offset)); gdPutInt(chunkIdx[x].offset, out); gdPutInt(chunkIdx[x].size, out); } gdSeek(out, posSave); } fail: - GD2_DBG(php_gd_error("Freeing memory\n")); + GD2_DBG(php_gd_error("Freeing memory")); if (chunkData) { gdFree(chunkData); } - if (compData) { + if (compData) { gdFree(compData); } if (chunkIdx) { gdFree(chunkIdx); } - GD2_DBG(php_gd_error("Done\n")); + GD2_DBG(php_gd_error("Done")); } void gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt) @@ -809,7 +812,7 @@ gdIOCtx *out = gdNewFileCtx(outFile); _gdImageGd2(im, out, cs, fmt); - + out->gd_free(out); } @@ -821,6 +824,6 @@ _gdImageGd2(im, out, cs, fmt); rv = gdDPExtractData(out, size); out->gd_free(out); - + return rv; } diff -urN php-4.4.8.org/ext/gd/libgd/gd_gd.c php-4.4.8/ext/gd/libgd/gd_gd.c --- php-4.4.8.org/ext/gd/libgd/gd_gd.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_gd.c 2007-08-09 16:21:38.000000000 +0200 @@ -1,4 +1,3 @@ - #include #include #include @@ -58,7 +57,7 @@ } GD2_DBG(printf("Pallette had %d colours (T=%d)\n", im->colorsTotal, im->transparent)); - + if (im->trueColor) { return TRUE; } @@ -123,6 +122,9 @@ } else { im = gdImageCreate(*sx, *sy); } + if(!im) { + goto fail1; + } if (!_gdGetColors(in, im, gd2xFlag)) { goto fail2; } @@ -225,7 +227,7 @@ static void _gdPutHeader (gdImagePtr im, gdIOCtx * out) { - /* 65535 indicates this is a gd 2.x .gd file. + /* 65535 indicates this is a gd 2.x .gd file. * 2.0.12: 65534 indicates truecolor. */ if (im->trueColor) { diff -urN php-4.4.8.org/ext/gd/libgd/gd_gif_in.c php-4.4.8/ext/gd/libgd/gd_gif_in.c --- php-4.4.8.org/ext/gd/libgd/gd_gif_in.c 2007-06-08 07:31:02.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_gif_in.c 2007-06-07 23:07:33.000000000 +0200 @@ -17,9 +17,9 @@ static int set_verbose(void) { - verbose = !!getenv("GIF_VERBOSE"); - verbose_set = 1; - return(verbose); + verbose = !!getenv("GIF_VERBOSE"); + verbose_set = 1; + return(verbose); } #else @@ -44,270 +44,313 @@ #define LOCALCOLORMAP 0x80 #define BitSet(byte, bit) (((byte) & (bit)) == (bit)) -#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) != 0) +#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) > 0) #define LM_to_uint(a,b) (((b)<<8)|(a)) /* We may eventually want to use this information, but def it out for now */ #if 0 static struct { - unsigned int Width; - unsigned int Height; - unsigned char ColorMap[3][MAXCOLORMAPSIZE]; - unsigned int BitPixel; - unsigned int ColorResolution; - unsigned int Background; - unsigned int AspectRatio; + unsigned int Width; + unsigned int Height; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned int BitPixel; + unsigned int ColorResolution; + unsigned int Background; + unsigned int AspectRatio; } GifScreen; #endif +#if 0 static struct { - int transparent; - int delayTime; - int inputFlag; - int disposal; + int transparent; + int delayTime; + int inputFlag; + int disposal; } Gif89 = { -1, -1, -1, 0 }; +#endif -static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]); -static int DoExtension (gdIOCtx *fd, int label, int *Transparent); -static int GetDataBlock (gdIOCtx *fd, unsigned char *buf); -static int GetCode (gdIOCtx *fd, int code_size, int flag); -static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size); +#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) -static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace); /*1.4//, int ignore); */ +typedef struct { + unsigned char buf[280]; + int curbit, lastbit, done, last_byte; +} CODE_STATIC_DATA; + +typedef struct { + int fresh; + int code_size, set_code_size; + int max_code, max_code_size; + int firstcode, oldcode; + int clear_code, end_code; + int table[2][(1<< MAX_LWZ_BITS)]; + int stack[STACK_SIZE], *sp; + CODE_STATIC_DATA scd; +} LZW_STATIC_DATA; -int ZeroDataBlock; +static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]); +static int DoExtension (gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP); +static int GetDataBlock (gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP); +static int GetCode (gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP); +static int LWZReadByte (gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP); + +static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP); /*1.4//, int ignore); */ -gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource) +gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource) /* {{{ */ { - gdIOCtx *in = gdNewSSCtx(inSource, NULL); - gdImagePtr im; + gdIOCtx *in = gdNewSSCtx(inSource, NULL); + gdImagePtr im; - im = gdImageCreateFromGifCtx(in); + im = gdImageCreateFromGifCtx(in); - in->gd_free(in); + in->gd_free(in); - return im; + return im; } +/* }}} */ -gdImagePtr -gdImageCreateFromGif(FILE *fdFile) +gdImagePtr gdImageCreateFromGif(FILE *fdFile) /* {{{ */ { - gdIOCtx *fd = gdNewFileCtx(fdFile); - gdImagePtr im = 0; + gdIOCtx *fd = gdNewFileCtx(fdFile); + gdImagePtr im = 0; - im = gdImageCreateFromGifCtx(fd); + im = gdImageCreateFromGifCtx(fd); - fd->gd_free(fd); + fd->gd_free(fd); - return im; + return im; } +/* }}} */ -gdImagePtr -gdImageCreateFromGifCtx(gdIOCtxPtr fd) +gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr fd) /* {{{ */ { -/* 1.4 int imageNumber; */ - int BitPixel; - int ColorResolution; - int Background; - int AspectRatio; - int Transparent = (-1); - unsigned char buf[16]; - unsigned char c; - unsigned char ColorMap[3][MAXCOLORMAPSIZE]; - unsigned char localColorMap[3][MAXCOLORMAPSIZE]; - int imw, imh; - int useGlobalColormap; - int bitPixel; - int i; - /*1.4//int imageCount = 0; */ - char version[4]; - - gdImagePtr im = 0; - ZeroDataBlock = FALSE; + int BitPixel; +#if 0 + int ColorResolution; + int Background; + int AspectRatio; +#endif + int Transparent = (-1); + unsigned char buf[16]; + unsigned char c; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned char localColorMap[3][MAXCOLORMAPSIZE]; + int imw, imh, screen_width, screen_height; + int gif87a, useGlobalColormap; + int bitPixel; + int i; + /*1.4//int imageCount = 0; */ + + int ZeroDataBlock = FALSE; + int haveGlobalColormap; + gdImagePtr im = 0; - /*1.4//imageNumber = 1; */ - if (! ReadOK(fd,buf,6)) { + /*1.4//imageNumber = 1; */ + if (! ReadOK(fd,buf,6)) { return 0; } - if (strncmp((char *)buf,"GIF",3) != 0) { + if (strncmp((char *)buf,"GIF",3) != 0) { return 0; } - strncpy(version, (char *)buf + 3, 3); - version[3] = '\0'; - if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { + if (memcmp((char *)buf+3, "87a", 3) == 0) { + gif87a = 1; + } else if (memcmp((char *)buf+3, "89a", 3) == 0) { + gif87a = 0; + } else { return 0; } - if (! ReadOK(fd,buf,7)) { + + if (! ReadOK(fd,buf,7)) { return 0; } - BitPixel = 2<<(buf[4]&0x07); - ColorResolution = (int) (((buf[4]&0x70)>>3)+1); - Background = buf[5]; - AspectRatio = buf[6]; - imw = LM_to_uint(buf[0],buf[1]); - imh = LM_to_uint(buf[2],buf[3]); + BitPixel = 2<<(buf[4]&0x07); +#if 0 + ColorResolution = (int) (((buf[4]&0x70)>>3)+1); + Background = buf[5]; + AspectRatio = buf[6]; +#endif + screen_width = imw = LM_to_uint(buf[0],buf[1]); + screen_height = imh = LM_to_uint(buf[2],buf[3]); - if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ - if (ReadColorMap(fd, BitPixel, ColorMap)) { + haveGlobalColormap = BitSet(buf[4], LOCALCOLORMAP); /* Global Colormap */ + if (haveGlobalColormap) { + if (ReadColorMap(fd, BitPixel, ColorMap)) { return 0; } - } - for (;;) { - if (! ReadOK(fd,&c,1)) { - return 0; - } - if (c == ';') { /* GIF terminator */ + } + + for (;;) { + int top, left; + int width, height; + + if (! ReadOK(fd,&c,1)) { + return 0; + } + if (c == ';') { /* GIF terminator */ goto terminated; - } + } + + if (c == '!') { /* Extension */ + if (! ReadOK(fd,&c,1)) { + return 0; + } + DoExtension(fd, c, &Transparent, &ZeroDataBlock); + continue; + } - if (c == '!') { /* Extension */ - if (! ReadOK(fd,&c,1)) { - return 0; - } - DoExtension(fd, c, &Transparent); - continue; - } - - if (c != ',') { /* Not a valid start character */ - continue; - } - - /*1.4//++imageCount; */ - - if (! ReadOK(fd,buf,9)) { - return 0; - } - - useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); - - bitPixel = 1<<((buf[8]&0x07)+1); - - if (!useGlobalColormap) { - if (ReadColorMap(fd, bitPixel, localColorMap)) { - return 0; - } - } - - if (!(im = gdImageCreate(imw, imh))) { - return 0; - } - im->interlace = BitSet(buf[8], INTERLACE); - if (! useGlobalColormap) { - ReadImage(im, fd, imw, imh, localColorMap, - BitSet(buf[8], INTERLACE)); - /*1.4//imageCount != imageNumber); */ - } else { - ReadImage(im, fd, imw, imh, - ColorMap, - BitSet(buf[8], INTERLACE)); - /*1.4//imageCount != imageNumber); */ - } - if (Transparent != (-1)) { - gdImageColorTransparent(im, Transparent); - } - goto terminated; - } + if (c != ',') { /* Not a valid start character */ + continue; + } -terminated: - /* Terminator before any image was declared! */ - if (!im) { - return 0; - } + /*1.4//++imageCount; */ - if (!im->colorsTotal) { - gdImageDestroy(im); + if (! ReadOK(fd,buf,9)) { return 0; } - /* Check for open colors at the end, so - we can reduce colorsTotal and ultimately - BitsPerPixel */ - for (i=((im->colorsTotal-1)); (i>=0); i--) { + useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); + + bitPixel = 1<<((buf[8]&0x07)+1); + left = LM_to_uint(buf[0], buf[1]); + top = LM_to_uint(buf[2], buf[3]); + width = LM_to_uint(buf[4], buf[5]); + height = LM_to_uint(buf[6], buf[7]); + + if (left + width > screen_width || top + height > screen_height) { + if (VERBOSE) { + printf("Frame is not confined to screen dimension.\n"); + } + return 0; + } + + if (!(im = gdImageCreate(width, height))) { + return 0; + } + im->interlace = BitSet(buf[8], INTERLACE); + if (!useGlobalColormap) { + if (ReadColorMap(fd, bitPixel, localColorMap)) { + gdImageDestroy(im); + return 0; + } + ReadImage(im, fd, width, height, localColorMap, + BitSet(buf[8], INTERLACE), &ZeroDataBlock); + } else { + if (!haveGlobalColormap) { + gdImageDestroy(im); + return 0; + } + ReadImage(im, fd, width, height, + ColorMap, + BitSet(buf[8], INTERLACE), &ZeroDataBlock); + } + if (Transparent != (-1)) { + gdImageColorTransparent(im, Transparent); + } + goto terminated; + } + +terminated: + /* Terminator before any image was declared! */ + if (!im) { + return 0; + } + if (!im->colorsTotal) { + gdImageDestroy(im); + return 0; + } + /* Check for open colors at the end, so + we can reduce colorsTotal and ultimately + BitsPerPixel */ + for (i=((im->colorsTotal-1)); (i>=0); i--) { if (im->open[i]) { - im->colorsTotal--; - } else { - break; - } - } - return im; + im->colorsTotal--; + } else { + break; + } + } + return im; } +/* }}} */ -static int -ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) +static int ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) /* {{{ */ { - int i; - unsigned char rgb[3]; + int i; + unsigned char rgb[3]; - for (i = 0; i < number; ++i) { - if (! ReadOK(fd, rgb, sizeof(rgb))) { - return TRUE; - } - buffer[CM_RED][i] = rgb[0] ; - buffer[CM_GREEN][i] = rgb[1] ; - buffer[CM_BLUE][i] = rgb[2] ; - } + for (i = 0; i < number; ++i) { + if (! ReadOK(fd, rgb, sizeof(rgb))) { + return TRUE; + } + buffer[CM_RED][i] = rgb[0] ; + buffer[CM_GREEN][i] = rgb[1] ; + buffer[CM_BLUE][i] = rgb[2] ; + } - return FALSE; + return FALSE; } +/* }}} */ static int -DoExtension(gdIOCtx *fd, int label, int *Transparent) +DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP) { - static unsigned char buf[256]; + unsigned char buf[256]; + + switch (label) { + case 0xf9: /* Graphic Control Extension */ + memset(buf, 0, 4); /* initialize a few bytes in the case the next function fails */ + (void) GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP); +#if 0 + Gif89.disposal = (buf[0] >> 2) & 0x7; + Gif89.inputFlag = (buf[0] >> 1) & 0x1; + Gif89.delayTime = LM_to_uint(buf[1],buf[2]); +#endif + if ((buf[0] & 0x1) != 0) + *Transparent = buf[3]; - switch (label) { - case 0xf9: /* Graphic Control Extension */ - (void) GetDataBlock(fd, (unsigned char*) buf); - Gif89.disposal = (buf[0] >> 2) & 0x7; - Gif89.inputFlag = (buf[0] >> 1) & 0x1; - Gif89.delayTime = LM_to_uint(buf[1],buf[2]); - if ((buf[0] & 0x1) != 0) - *Transparent = buf[3]; - - while (GetDataBlock(fd, (unsigned char*) buf) > 0) - ; - return FALSE; - default: - break; - } - while (GetDataBlock(fd, (unsigned char*) buf) > 0) - ; + while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0); + return FALSE; + default: + break; + } + while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0) + ; - return FALSE; + return FALSE; } +/* }}} */ static int -GetDataBlock_(gdIOCtx *fd, unsigned char *buf) +GetDataBlock_(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP) { - unsigned char count; + unsigned char count; - if (! ReadOK(fd,&count,1)) { - return -1; - } + if (! ReadOK(fd,&count,1)) { + return -1; + } - ZeroDataBlock = count == 0; + *ZeroDataBlockP = count == 0; - if ((count != 0) && (! ReadOK(fd, buf, count))) { - return -1; - } + if ((count != 0) && (! ReadOK(fd, buf, count))) { + return -1; + } - return count; + return count; } +/* }}} */ static int -GetDataBlock(gdIOCtx *fd, unsigned char *buf) +GetDataBlock(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP) { int rv; int i; - char *tmp = NULL; - - rv = GetDataBlock_(fd,buf); + + rv = GetDataBlock_(fd,buf, ZeroDataBlockP); if (VERBOSE) { + char *tmp = NULL; if (rv > 0) { tmp = safe_emalloc(3 * rv, sizeof(char), 1); for (i=0;i= lastbit) { - if (done) { - if (curbit >= lastbit) { - /* Oh well */ - } - return -1; - } - buf[0] = buf[last_byte-2]; - buf[1] = buf[last_byte-1]; - - if ((count = GetDataBlock(fd, &buf[2])) <= 0) - done = TRUE; - - last_byte = 2 + count; - curbit = (curbit - lastbit) + 16; - lastbit = (2+count)*8 ; - } - - ret = 0; - for (i = curbit, j = 0; j < code_size; ++i, ++j) - ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + int i, j, ret; + unsigned char count; + + if (flag) { + scd->curbit = 0; + scd->lastbit = 0; + scd->last_byte = 0; + scd->done = FALSE; + return 0; + } + + if ( (scd->curbit + code_size) >= scd->lastbit) { + if (scd->done) { + if (scd->curbit >= scd->lastbit) { + /* Oh well */ + } + return -1; + } + scd->buf[0] = scd->buf[scd->last_byte-2]; + scd->buf[1] = scd->buf[scd->last_byte-1]; + + if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0) + scd->done = TRUE; + + scd->last_byte = 2 + count; + scd->curbit = (scd->curbit - scd->lastbit) + 16; + scd->lastbit = (2+count)*8 ; + } - curbit += code_size; - return ret; + ret = 0; + for (i = scd->curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((scd->buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + + scd->curbit += code_size; + return ret; } static int -GetCode(gdIOCtx *fd, int code_size, int flag) +GetCode(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { - int rv; + int rv; - rv = GetCode_(fd,code_size,flag); - if (VERBOSE) php_gd_error_ex(E_NOTICE, "[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); - return(rv); + rv = GetCode_(fd, scd, code_size,flag, ZeroDataBlockP); + if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); + return(rv); } +/* }}} */ -#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) static int -LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size) +LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { - static int fresh = FALSE; - int code, incode; - static int code_size, set_code_size; - static int max_code, max_code_size; - static int firstcode, oldcode; - static int clear_code, end_code; - static int table[2][(1<< MAX_LWZ_BITS)]; - static int stack[STACK_SIZE], *sp; - register int i; - - if (flag) { - set_code_size = input_code_size; - code_size = set_code_size+1; - clear_code = 1 << set_code_size ; - end_code = clear_code + 1; - max_code_size = 2*clear_code; - max_code = clear_code+2; - - GetCode(fd, 0, TRUE); - - fresh = TRUE; - - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; - } - for (; i < (1< stack) - return *--sp; - - while ((code = GetCode(fd, code_size, FALSE)) >= 0) { - if (code == clear_code) { - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; - } - for (; i < (1< 0) - ; - - if (count != 0) - return -2; - } - - incode = code; - - if (sp == (stack + STACK_SIZE)) { - /* Bad compressed data stream */ - return -1; - } - - if (code >= max_code) { - *sp++ = firstcode; - code = oldcode; - } - - while (code >= clear_code) { - if (sp == (stack + STACK_SIZE)) { - /* Bad compressed data stream */ - return -1; - } - *sp++ = table[1][code]; - if (code == table[0][code]) { - /* Oh well */ - } - code = table[0][code]; - } - - *sp++ = firstcode = table[1][code]; - - if ((code = max_code) <(1<= max_code_size) && - (max_code_size < (1< stack) - return *--sp; - } - return code; + int code, incode, i; + + if (flag) { + sd->set_code_size = input_code_size; + sd->code_size = sd->set_code_size+1; + sd->clear_code = 1 << sd->set_code_size ; + sd->end_code = sd->clear_code + 1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + + GetCode(fd, &sd->scd, 0, TRUE, ZeroDataBlockP); + + sd->fresh = TRUE; + + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; + } + for (; i < (1<table[0][i] = sd->table[1][0] = 0; + + sd->sp = sd->stack; + + return 0; + } else if (sd->fresh) { + sd->fresh = FALSE; + do { + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + } while (sd->firstcode == sd->clear_code); + return sd->firstcode; + } + + if (sd->sp > sd->stack) + return *--sd->sp; + + while ((code = GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP)) >= 0) { + if (code == sd->clear_code) { + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; + } + for (; i < (1<table[0][i] = sd->table[1][i] = 0; + sd->code_size = sd->set_code_size+1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + sd->sp = sd->stack; + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + return sd->firstcode; + } else if (code == sd->end_code) { + int count; + unsigned char buf[260]; + + if (*ZeroDataBlockP) + return -2; + + while ((count = GetDataBlock(fd, buf, ZeroDataBlockP)) > 0) + ; + + if (count != 0) + return -2; + } + + incode = code; + + if (sd->sp == (sd->stack + STACK_SIZE)) { + /* Bad compressed data stream */ + return -1; + } + + if (code >= sd->max_code) { + *sd->sp++ = sd->firstcode; + code = sd->oldcode; + } + + while (code >= sd->clear_code) { + if (sd->sp == (sd->stack + STACK_SIZE)) { + /* Bad compressed data stream */ + return -1; + } + *sd->sp++ = sd->table[1][code]; + if (code == sd->table[0][code]) { + /* Oh well */ + } + code = sd->table[0][code]; + } + + *sd->sp++ = sd->firstcode = sd->table[1][code]; + + if ((code = sd->max_code) <(1<table[0][code] = sd->oldcode; + sd->table[1][code] = sd->firstcode; + ++sd->max_code; + if ((sd->max_code >= sd->max_code_size) && + (sd->max_code_size < (1<max_code_size *= 2; + ++sd->code_size; + } + } + + sd->oldcode = incode; + + if (sd->sp > sd->stack) + return *--sd->sp; + } + return code; } +/* }}} */ static int -LWZReadByte(gdIOCtx *fd, int flag, int input_code_size) +LWZReadByte(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { - int rv; + int rv; - rv = LWZReadByte_(fd,flag,input_code_size); - if (VERBOSE) php_gd_error_ex(E_NOTICE, "[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); - return(rv); + rv = LWZReadByte_(fd, sd, flag, input_code_size, ZeroDataBlockP); + if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); + return(rv); } +/* }}} */ static void -ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace) /*1.4//, int ignore) */ +ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP) /*1.4//, int ignore) */ { - unsigned char c; - int v; - int xpos = 0, ypos = 0, pass = 0; - int i; - - /* - ** Initialize the Compression routines - */ - if (! ReadOK(fd,&c,1)) { - return; - } - - if (c > MAX_LWZ_BITS) { - return; - } - - - /* Stash the color map into the image */ - for (i=0; (ired[i] = cmap[CM_RED][i]; - im->green[i] = cmap[CM_GREEN][i]; - im->blue[i] = cmap[CM_BLUE][i]; - im->open[i] = 1; - } - /* Many (perhaps most) of these colors will remain marked open. */ - im->colorsTotal = gdMaxColors; - - if (LWZReadByte(fd, TRUE, c) < 0) { - return; - } - - /* - ** If this is an "uninteresting picture" ignore it. - ** REMOVED For 1.4 - */ - /*if (ignore) { */ - /* while (LWZReadByte(fd, FALSE, c) >= 0) */ - /* ; */ - /* return; */ - /*} */ - - while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) { - if (v >= gdMaxColors) { - v = 0; + unsigned char c; + int v; + int xpos = 0, ypos = 0, pass = 0; + int i; + LZW_STATIC_DATA sd; + + + /* + ** Initialize the Compression routines + */ + if (! ReadOK(fd,&c,1)) { + return; + } + + if (c > MAX_LWZ_BITS) { + return; + } + + /* Stash the color map into the image */ + for (i=0; (ired[i] = cmap[CM_RED][i]; + im->green[i] = cmap[CM_GREEN][i]; + im->blue[i] = cmap[CM_BLUE][i]; + im->open[i] = 1; + } + /* Many (perhaps most) of these colors will remain marked open. */ + im->colorsTotal = gdMaxColors; + if (LWZReadByte(fd, &sd, TRUE, c, ZeroDataBlockP) < 0) { + return; + } + + /* + ** If this is an "uninteresting picture" ignore it. + ** REMOVED For 1.4 + */ + /*if (ignore) { */ + /* while (LWZReadByte(fd, &sd, FALSE, c) >= 0) */ + /* ; */ + /* return; */ + /*} */ + + while ((v = LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP)) >= 0) { + if (v >= gdMaxColors) { + v = 0; + } + /* This how we recognize which colors are actually used. */ + if (im->open[v]) { + im->open[v] = 0; + } + gdImageSetPixel(im, xpos, ypos, v); + ++xpos; + if (xpos == len) { + xpos = 0; + if (interlace) { + switch (pass) { + case 0: + case 1: + ypos += 8; break; + case 2: + ypos += 4; break; + case 3: + ypos += 2; break; } - /* This how we recognize which colors are actually used. */ - if (im->open[v]) { - im->open[v] = 0; - } - gdImageSetPixel(im, xpos, ypos, v); - ++xpos; - if (xpos == len) { - xpos = 0; - if (interlace) { - switch (pass) { - case 0: - case 1: - ypos += 8; break; - case 2: - ypos += 4; break; - case 3: - ypos += 2; break; - } - - if (ypos >= height) { - ++pass; - switch (pass) { - case 1: - ypos = 4; break; - case 2: - ypos = 2; break; - case 3: - ypos = 1; break; - default: - goto fini; - } - } - } else { - ++ypos; - } - } - if (ypos >= height) - break; - } + + if (ypos >= height) { + ++pass; + switch (pass) { + case 1: + ypos = 4; break; + case 2: + ypos = 2; break; + case 3: + ypos = 1; break; + default: + goto fini; + } + } + } else { + ++ypos; + } + } + if (ypos >= height) + break; + } fini: - if (LWZReadByte(fd,FALSE,c)>=0) { - /* Ignore extra */ - } + if (LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP) >=0) { + /* Ignore extra */ + } } - +/* }}} */ diff -urN php-4.4.8.org/ext/gd/libgd/gd_gif_out.c php-4.4.8/ext/gd/libgd/gd_gif_out.c --- php-4.4.8.org/ext/gd/libgd/gd_gif_out.c 2004-07-23 01:09:24.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_gif_out.c 2006-07-26 12:03:09.000000000 +0200 @@ -133,7 +133,7 @@ BitsPerPixel = colorstobpp(tim->colorsTotal); /* All set, let's do it. */ GIFEncode( - out, tim->sx, tim->sy, interlace, 0, transparent, BitsPerPixel, + out, tim->sx, tim->sy, tim->interlace, 0, tim->transparent, BitsPerPixel, tim->red, tim->green, tim->blue, tim); if (pim) { /* Destroy palette based temporary image. */ @@ -264,10 +264,12 @@ int ColorMapSize; int InitCodeSize; int i; - GifCtx ctx; + GifCtx ctx; + + memset(&ctx, 0, sizeof(ctx)); ctx.Interlace = GInterlace; - ctx.in_count = 1; - memset(&ctx, 0, sizeof(ctx)); + ctx.in_count = 1; + ColorMapSize = 1 << BitsPerPixel; RWidth = ctx.Width = GWidth; diff -urN php-4.4.8.org/ext/gd/libgd/gd.h php-4.4.8/ext/gd/libgd/gd.h --- php-4.4.8.org/ext/gd/libgd/gd.h 2004-07-23 01:09:24.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd.h 2007-09-12 01:34:25.000000000 +0200 @@ -5,14 +5,30 @@ extern "C" { #endif -#ifndef WIN32 -/* default fontpath for unix systems */ -#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1:." -#define PATHSEPARATOR ":" -#else +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_compat.h" + +#define GD_MAJOR_VERSION 2 +#define GD_MINOR_VERSION 0 +#define GD_RELEASE_VERSION 35 +#define GD_EXTRA_VERSION "" +#define GD_VERSION_STRING "2.0.35" + +#ifdef NETWARE +/* default fontpath for netware systems */ +#define DEFAULT_FONTPATH "sys:/java/nwgfx/lib/x11/fonts/ttf;." +#define PATHSEPARATOR ";" +#elif defined(WIN32) /* default fontpath for windows systems */ #define DEFAULT_FONTPATH "c:\\winnt\\fonts;c:\\windows\\fonts;." #define PATHSEPARATOR ";" +#else +/* default fontpath for unix systems */ +#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1:." +#define PATHSEPARATOR ":" #endif /* gd.h: declarations file for the graphic-draw module. @@ -231,8 +247,8 @@ gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in); gdImagePtr gdImageCreateFromWBMP(FILE *inFile); gdImagePtr gdImageCreateFromWBMPCtx(gdIOCtx *infile); -gdImagePtr gdImageCreateFromJpeg(FILE *infile); -gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile); +gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning); +gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning); /* A custom data source. */ /* The source function must return -1 on error, otherwise the number @@ -295,6 +311,14 @@ void gdImageString16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); void gdImageStringUp16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); +/* + * The following functions are required to be called prior to the + * use of any sort of threads in a module load / shutdown function + * respectively. + */ +void gdFontCacheMutexSetup(); +void gdFontCacheMutexShutdown(); + /* 2.0.16: for thread-safe use of gdImageStringFT and friends, * call this before allowing any thread to call gdImageStringFT. * Otherwise it is invoked by the first thread to invoke @@ -438,8 +462,8 @@ * compression (smallest files) but takes a long time to compress, and * -1 selects the default compiled into the zlib library. */ -void gdImagePngEx(gdImagePtr im, FILE * out, int level); -void gdImagePngCtxEx(gdImagePtr im, gdIOCtx * out, int level); +void gdImagePngEx(gdImagePtr im, FILE * out, int level, int basefilter); +void gdImagePngCtxEx(gdImagePtr im, gdIOCtx * out, int level, int basefilter); void gdImageWBMP(gdImagePtr image, int fg, FILE *out); void gdImageWBMPCtx(gdImagePtr image, int fg, gdIOCtx *out); @@ -483,7 +507,7 @@ /* Best to free this memory with gdFree(), not free() */ void* gdImageGdPtr(gdImagePtr im, int *size); -void *gdImagePngPtrEx(gdImagePtr im, int *size, int level); +void *gdImagePngPtrEx(gdImagePtr im, int *size, int level, int basefilter); /* Best to free this memory with gdFree(), not free() */ void* gdImageGd2Ptr(gdImagePtr im, int cs, int fmt, int *size); @@ -534,11 +558,11 @@ substituted automatically. */ void gdImageCopyResampled(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH); -gdImagePtr gdImageRotate90(gdImagePtr src); -gdImagePtr gdImageRotate180(gdImagePtr src); -gdImagePtr gdImageRotate270(gdImagePtr src); -gdImagePtr gdImageRotate45(gdImagePtr src, double dAngle, int clrBack); -gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack); +gdImagePtr gdImageRotate90(gdImagePtr src, int ignoretransparent); +gdImagePtr gdImageRotate180(gdImagePtr src, int ignoretransparent); +gdImagePtr gdImageRotate270(gdImagePtr src, int ignoretransparent); +gdImagePtr gdImageRotate45(gdImagePtr src, double dAngle, int clrBack, int ignoretransparent); +gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent); void gdImageSetBrush(gdImagePtr im, gdImagePtr brush); void gdImageSetTile(gdImagePtr im, gdImagePtr tile); @@ -619,7 +643,7 @@ int gdImageContrast(gdImagePtr src, double contrast); /* Simply adds or substracts respectively red, green or blue to a pixel */ -int gdImageColor(gdImagePtr src, int red, int green, int blue); +int gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha); /* Image convolution by a 3x3 custom matrix */ int gdImageConvolution(gdImagePtr src, float ft[3][3], float filter_div, float offset); diff -urN php-4.4.8.org/ext/gd/libgd/gdhelpers.h php-4.4.8/ext/gd/libgd/gdhelpers.h --- php-4.4.8.org/ext/gd/libgd/gdhelpers.h 2007-03-10 14:06:37.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gdhelpers.h 2007-03-10 13:18:36.000000000 +0100 @@ -1,4 +1,4 @@ -#ifndef GDHELPERS_H +#ifndef GDHELPERS_H #define GDHELPERS_H 1 #include diff -urN php-4.4.8.org/ext/gd/libgd/gd_io.c php-4.4.8/ext/gd/libgd/gd_io.c --- php-4.4.8.org/ext/gd/libgd/gd_io.c 2003-12-25 23:33:03.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_io.c 2005-08-18 14:54:43.000000000 +0200 @@ -23,153 +23,124 @@ #define IO_DBG(s) +#define GD_IO_EOF_CHK(r) \ + if (r == EOF) { \ + return 0; \ + } \ + /* * Write out a word to the I/O context pointer */ -void -Putword (int w, gdIOCtx * ctx) +void Putword (int w, gdIOCtx * ctx) { - unsigned char buf[2]; - buf[0] = w & 0xff; - buf[1] = (w / 256) & 0xff; - (ctx->putBuf) (ctx, (char *) buf, 2); + unsigned char buf[2]; + + buf[0] = w & 0xff; + buf[1] = (w / 256) & 0xff; + (ctx->putBuf) (ctx, (char *) buf, 2); } -void -Putchar (int c, gdIOCtx * ctx) +void Putchar (int c, gdIOCtx * ctx) { - (ctx->putC) (ctx, c & 0xff); + (ctx->putC) (ctx, c & 0xff); } -void -gdPutC (const unsigned char c, gdIOCtx * ctx) +void gdPutC (const unsigned char c, gdIOCtx * ctx) { - (ctx->putC) (ctx, c); + (ctx->putC) (ctx, c); } -void -gdPutWord (int w, gdIOCtx * ctx) +void gdPutWord (int w, gdIOCtx * ctx) { - IO_DBG (printf ("Putting word...\n")); - (ctx->putC) (ctx, (unsigned char) (w >> 8)); - (ctx->putC) (ctx, (unsigned char) (w & 0xFF)); - IO_DBG (printf ("put.\n")); + IO_DBG (php_gd_error("Putting word...")); + (ctx->putC) (ctx, (unsigned char) (w >> 8)); + (ctx->putC) (ctx, (unsigned char) (w & 0xFF)); + IO_DBG (php_gd_error("put.")); } -void -gdPutInt (int w, gdIOCtx * ctx) +void gdPutInt (int w, gdIOCtx * ctx) { - IO_DBG (printf ("Putting int...\n")); - (ctx->putC) (ctx, (unsigned char) (w >> 24)); - (ctx->putC) (ctx, (unsigned char) ((w >> 16) & 0xFF)); - (ctx->putC) (ctx, (unsigned char) ((w >> 8) & 0xFF)); - (ctx->putC) (ctx, (unsigned char) (w & 0xFF)); - IO_DBG (printf ("put.\n")); + IO_DBG (php_gd_error("Putting int...")); + (ctx->putC) (ctx, (unsigned char) (w >> 24)); + (ctx->putC) (ctx, (unsigned char) ((w >> 16) & 0xFF)); + (ctx->putC) (ctx, (unsigned char) ((w >> 8) & 0xFF)); + (ctx->putC) (ctx, (unsigned char) (w & 0xFF)); + IO_DBG (php_gd_error("put.")); } -int -gdGetC (gdIOCtx * ctx) +int gdGetC (gdIOCtx * ctx) { - return ((ctx->getC) (ctx)); + return ((ctx->getC) (ctx)); } - - -int -gdGetByte (int *result, gdIOCtx * ctx) +int gdGetByte (int *result, gdIOCtx * ctx) { - int r; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result = r; - return 1; + int r; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result = r; + return 1; } -int -gdGetWord (int *result, gdIOCtx * ctx) +int gdGetWord (int *result, gdIOCtx * ctx) { - int r; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result = r << 8; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result += r; - return 1; + int r; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result = r << 8; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result += r; + return 1; } -int -gdGetInt (int *result, gdIOCtx * ctx) +int gdGetInt (int *result, gdIOCtx * ctx) { - int r; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result = r << 24; + int r; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result = r << 24; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result += r << 16; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result += r << 16; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result += r << 8; + r = (ctx->getC) (ctx); + if (r == EOF) { + return 0; + } + *result += r << 8; - r = (ctx->getC) (ctx); - if (r == EOF) - { - return 0; - } - *result += r; + r = (ctx->getC) (ctx); + GD_IO_EOF_CHK(r); + *result += r; - return 1; + return 1; } -int -gdPutBuf (const void *buf, int size, gdIOCtx * ctx) +int gdPutBuf (const void *buf, int size, gdIOCtx * ctx) { - IO_DBG (printf ("Putting buf...\n")); - return (ctx->putBuf) (ctx, buf, size); - IO_DBG (printf ("put.\n")); + IO_DBG (php_gd_error("Putting buf...")); + return (ctx->putBuf) (ctx, buf, size); + IO_DBG (php_gd_error("put.")); } -int -gdGetBuf (void *buf, int size, gdIOCtx * ctx) +int gdGetBuf (void *buf, int size, gdIOCtx * ctx) { - return (ctx->getBuf) (ctx, buf, size); + return (ctx->getBuf) (ctx, buf, size); } - -int -gdSeek (gdIOCtx * ctx, const int pos) +int gdSeek (gdIOCtx * ctx, const int pos) { - IO_DBG (printf ("Seeking...\n")); - return ((ctx->seek) (ctx, pos)); - IO_DBG (printf ("Done.\n")); + IO_DBG (php_gd_error("Seeking...")); + return ((ctx->seek) (ctx, pos)); + IO_DBG (php_gd_error("Done.")); } -long -gdTell (gdIOCtx * ctx) +long gdTell (gdIOCtx * ctx) { - IO_DBG (printf ("Telling...\n")); - return ((ctx->tell) (ctx)); - IO_DBG (printf ("told.\n")); + IO_DBG (php_gd_error("Telling...")); + return ((ctx->tell) (ctx)); + IO_DBG (php_gd_error ("told.")); } diff -urN php-4.4.8.org/ext/gd/libgd/gd_io_dp.c php-4.4.8/ext/gd/libgd/gd_io_dp.c --- php-4.4.8.org/ext/gd/libgd/gd_io_dp.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_io_dp.c 2004-03-29 20:20:33.000000000 +0200 @@ -27,26 +27,23 @@ /* this is used for creating images in main memory */ typedef struct dpStruct - { - void *data; - int logicalSize; - int realSize; - int dataGood; - int pos; - int freeOK; - } -dynamicPtr; +{ + void *data; + int logicalSize; + int realSize; + int dataGood; + int pos; + int freeOK; +} dynamicPtr; typedef struct dpIOCtx - { - gdIOCtx ctx; - dynamicPtr *dp; - } -dpIOCtx; +{ + gdIOCtx ctx; + dynamicPtr *dp; +} dpIOCtx; typedef struct dpIOCtx *dpIOCtxPtr; - /* these functions operate on in-memory dynamic pointers */ static int allocDynamic (dynamicPtr * dp, int initialSize, void *data); static int appendDynamic (dynamicPtr * dp, const void *src, int size); @@ -65,166 +62,136 @@ static long dynamicTell (struct gdIOCtx *); /* return data as a dynamic pointer */ -gdIOCtx * -gdNewDynamicCtx (int initialSize, void *data) +gdIOCtx * gdNewDynamicCtx (int initialSize, void *data) { - return gdNewDynamicCtxEx(initialSize, data, 1); + return gdNewDynamicCtxEx(initialSize, data, 1); } - + gdIOCtx * gdNewDynamicCtxEx (int initialSize, void *data, int freeOKFlag) { - dpIOCtx *ctx; - dynamicPtr *dp; + dpIOCtx *ctx; + dynamicPtr *dp; - ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx)); - if (ctx == NULL) - { - return NULL; - } + ctx = (dpIOCtx *) gdMalloc (sizeof (dpIOCtx)); - dp = newDynamic (initialSize, data, freeOKFlag); - if (!dp) - { - gdFree (ctx); - return NULL; - }; + dp = newDynamic(initialSize, data, freeOKFlag); - ctx->dp = dp; + ctx->dp = dp; - ctx->ctx.getC = dynamicGetchar; - ctx->ctx.putC = dynamicPutchar; + ctx->ctx.getC = dynamicGetchar; + ctx->ctx.putC = dynamicPutchar; - ctx->ctx.getBuf = dynamicGetbuf; - ctx->ctx.putBuf = dynamicPutbuf; + ctx->ctx.getBuf = dynamicGetbuf; + ctx->ctx.putBuf = dynamicPutbuf; - ctx->ctx.seek = dynamicSeek; - ctx->ctx.tell = dynamicTell; + ctx->ctx.seek = dynamicSeek; + ctx->ctx.tell = dynamicTell; - ctx->ctx.gd_free = gdFreeDynamicCtx; + ctx->ctx.gd_free = gdFreeDynamicCtx; - return (gdIOCtx *) ctx; + return (gdIOCtx *) ctx; } -void * -gdDPExtractData (struct gdIOCtx *ctx, int *size) +void * gdDPExtractData (struct gdIOCtx *ctx, int *size) { - dynamicPtr *dp; - dpIOCtx *dctx; - void *data; + dynamicPtr *dp; + dpIOCtx *dctx; + void *data; - dctx = (dpIOCtx *) ctx; - dp = dctx->dp; + dctx = (dpIOCtx *) ctx; + dp = dctx->dp; - /* clean up the data block and return it */ - if (dp->dataGood) - { - trimDynamic (dp); - *size = dp->logicalSize; - data = dp->data; - } - else - { - *size = 0; - data = NULL; - if (dp->data != NULL && dp->freeOK) - { - gdFree (dp->data); + /* clean up the data block and return it */ + if (dp->dataGood) { + trimDynamic (dp); + *size = dp->logicalSize; + data = dp->data; + } else { + *size = 0; + data = NULL; + if (dp->data != NULL && dp->freeOK) { + gdFree(dp->data); + } } - } - dp->data = NULL; - dp->realSize = 0; - dp->logicalSize = 0; + dp->data = NULL; + dp->realSize = 0; + dp->logicalSize = 0; - return data; + return data; } -static -void -gdFreeDynamicCtx (struct gdIOCtx *ctx) +static void gdFreeDynamicCtx (struct gdIOCtx *ctx) { - dynamicPtr *dp; - dpIOCtx *dctx; - - dctx = (dpIOCtx *) ctx; - dp = dctx->dp; + dynamicPtr *dp; + dpIOCtx *dctx; - gdFree (ctx); + dctx = (dpIOCtx *) ctx; + dp = dctx->dp; - dp->realSize = 0; - dp->logicalSize = 0; + gdFree(ctx); - gdFree (dp); + dp->realSize = 0; + dp->logicalSize = 0; + gdFree(dp); } -static long -dynamicTell (struct gdIOCtx *ctx) +static long dynamicTell (struct gdIOCtx *ctx) { - dpIOCtx *dctx; + dpIOCtx *dctx; - dctx = (dpIOCtx *) ctx; - return (dctx->dp->pos); + dctx = (dpIOCtx *) ctx; + + return (dctx->dp->pos); } -static int -dynamicSeek (struct gdIOCtx *ctx, const int pos) +static int dynamicSeek (struct gdIOCtx *ctx, const int pos) { - int bytesNeeded; - dynamicPtr *dp; - dpIOCtx *dctx; + int bytesNeeded; + dynamicPtr *dp; + dpIOCtx *dctx; - dctx = (dpIOCtx *) ctx; - dp = dctx->dp; + dctx = (dpIOCtx *) ctx; + dp = dctx->dp; - if (!dp->dataGood) - return FALSE; + if (!dp->dataGood) { + return FALSE; + } - bytesNeeded = pos; - if (bytesNeeded > dp->realSize) - { - /* 2.0.21 */ - if (!dp->freeOK) { - return FALSE; - } - if (!gdReallocDynamic (dp, dp->realSize * 2)) - { - dp->dataGood = FALSE; - return FALSE; + bytesNeeded = pos; + if (bytesNeeded > dp->realSize) { + /* 2.0.21 */ + if (!dp->freeOK) { + return FALSE; + } + gdReallocDynamic (dp, dp->realSize * 2); } - } - /* if we get here, we can be sure that we have enough bytes - to copy safely */ + /* if we get here, we can be sure that we have enough bytes to copy safely */ - /* Extend the logical size if we seek beyond EOF. */ - if (pos > dp->logicalSize) - { - dp->logicalSize = pos; - }; + /* Extend the logical size if we seek beyond EOF. */ + if (pos > dp->logicalSize) { + dp->logicalSize = pos; + } - dp->pos = pos; + dp->pos = pos; - return TRUE; + return TRUE; } /* return data as a dynamic pointer */ static dynamicPtr * newDynamic (int initialSize, void *data, int freeOKFlag) { - dynamicPtr *dp; - dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr)); - if (dp == NULL) - { - return NULL; - } + dynamicPtr *dp; + dp = (dynamicPtr *) gdMalloc (sizeof (dynamicPtr)); - if (!allocDynamic (dp, initialSize, data)) - return NULL; + allocDynamic (dp, initialSize, data); - dp->pos = 0; - dp->freeOK = freeOKFlag; + dp->pos = 0; + dp->freeOK = freeOKFlag; - return dp; + return dp; } static int @@ -246,64 +213,53 @@ } -static void -dynamicPutchar (struct gdIOCtx *ctx, int a) +static void dynamicPutchar (struct gdIOCtx *ctx, int a) { - unsigned char b; - dpIOCtxPtr dctx; + unsigned char b; + dpIOCtxPtr dctx; - b = a; - dctx = (dpIOCtxPtr) ctx; + b = a; + dctx = (dpIOCtxPtr) ctx; - appendDynamic (dctx->dp, &b, 1); + appendDynamic(dctx->dp, &b, 1); } -static int -dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len) +static int dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len) { - int rlen, remain; - dpIOCtxPtr dctx; - dynamicPtr *dp; + int rlen, remain; + dpIOCtxPtr dctx; + dynamicPtr *dp; - dctx = (dpIOCtxPtr) ctx; - dp = dctx->dp; + dctx = (dpIOCtxPtr) ctx; + dp = dctx->dp; - remain = dp->logicalSize - dp->pos; - if (remain >= len) - { - rlen = len; - } - else - { - if (remain == 0) - { - return EOF; + remain = dp->logicalSize - dp->pos; + if (remain >= len) { + rlen = len; + } else { + if (remain == 0) { + return EOF; + } + rlen = remain; } - rlen = remain; - } - memcpy (buf, (void *) ((char *) dp->data + dp->pos), rlen); - dp->pos += rlen; + memcpy(buf, (void *) ((char *) dp->data + dp->pos), rlen); + dp->pos += rlen; - return rlen; + return rlen; } -static int -dynamicGetchar (gdIOCtxPtr ctx) +static int dynamicGetchar (gdIOCtxPtr ctx) { - unsigned char b; - int rv; - - rv = dynamicGetbuf (ctx, &b, 1); + unsigned char b; + int rv; - if (rv != 1) - { - return EOF; - } - else - { - return b; /* (b & 0xff); */ - } + rv = dynamicGetbuf (ctx, &b, 1); + if (rv != 1) { + return EOF; + } else { + return b; /* (b & 0xff); */ + } } /* ********************************************************************* @@ -316,114 +272,89 @@ allocDynamic (dynamicPtr * dp, int initialSize, void *data) { - if (data == NULL) - { - dp->logicalSize = 0; - dp->dataGood = FALSE; - dp->data = gdMalloc (initialSize); - } - else - { - dp->logicalSize = initialSize; - dp->dataGood = TRUE; - dp->data = data; - } + if (data == NULL) { + dp->logicalSize = 0; + dp->dataGood = FALSE; + dp->data = gdMalloc(initialSize); + } else { + dp->logicalSize = initialSize; + dp->dataGood = TRUE; + dp->data = data; + } - if (dp->data != NULL) - { - dp->realSize = initialSize; - dp->dataGood = TRUE; - dp->pos = 0; - return TRUE; - } - else - { - dp->realSize = 0; - return FALSE; - } + dp->realSize = initialSize; + dp->dataGood = TRUE; + dp->pos = 0; + + return TRUE; } /* append bytes to the end of a dynamic pointer */ -static int -appendDynamic (dynamicPtr * dp, const void *src, int size) +static int appendDynamic (dynamicPtr * dp, const void *src, int size) { - int bytesNeeded; - char *tmp; + int bytesNeeded; + char *tmp; - if (!dp->dataGood) - return FALSE; + if (!dp->dataGood) { + return FALSE; + } -/* bytesNeeded = dp->logicalSize + size; */ - bytesNeeded = dp->pos + size; + /* bytesNeeded = dp->logicalSize + size; */ + bytesNeeded = dp->pos + size; - if (bytesNeeded > dp->realSize) - { + if (bytesNeeded > dp->realSize) { /* 2.0.21 */ if (!dp->freeOK) { return FALSE; } - if (!gdReallocDynamic (dp, bytesNeeded * 2)) - { - dp->dataGood = FALSE; - return FALSE; + gdReallocDynamic(dp, bytesNeeded * 2); } - } - /* if we get here, we can be sure that we have enough bytes - to copy safely */ - /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */ - - tmp = (char *) dp->data; - memcpy ((void *) (tmp + (dp->pos)), src, size); - dp->pos += size; + /* if we get here, we can be sure that we have enough bytes to copy safely */ + /*printf("Mem OK Size: %d, Pos: %d\n", dp->realSize, dp->pos); */ - if (dp->pos > dp->logicalSize) - { - dp->logicalSize = dp->pos; - }; + tmp = (char *) dp->data; + memcpy((void *) (tmp + (dp->pos)), src, size); + dp->pos += size; + + if (dp->pos > dp->logicalSize) { + dp->logicalSize = dp->pos; + } - return TRUE; + return TRUE; } /* grow (or shrink) dynamic pointer */ -static int -gdReallocDynamic (dynamicPtr * dp, int required) +static int gdReallocDynamic (dynamicPtr * dp, int required) { - void *newPtr; + void *newPtr; - /* First try gdRealloc(). If that doesn't work, make a new - memory block and copy. */ - if ((newPtr = gdRealloc (dp->data, required))) - { - dp->realSize = required; - dp->data = newPtr; - return TRUE; - } + /* First try gdRealloc(). If that doesn't work, make a new memory block and copy. */ + if ((newPtr = gdRealloc(dp->data, required))) { + dp->realSize = required; + dp->data = newPtr; + return TRUE; + } - /* create a new pointer */ - newPtr = gdMalloc (required); - if (!newPtr) - { - dp->dataGood = FALSE; - return FALSE; - } + /* create a new pointer */ + newPtr = gdMalloc(required); + + /* copy the old data into it */ + memcpy(newPtr, dp->data, dp->logicalSize); + gdFree(dp->data); + dp->data = newPtr; - /* copy the old data into it */ - memcpy (newPtr, dp->data, dp->logicalSize); - gdFree (dp->data); - dp->data = newPtr; + dp->realSize = required; - dp->realSize = required; - return TRUE; + return TRUE; } /* trim pointer so that its real and logical sizes match */ -static int -trimDynamic (dynamicPtr * dp) +static int trimDynamic (dynamicPtr * dp) { - /* 2.0.21: we don't reallocate memory we don't own */ - if (!dp->freeOK) { - return FALSE; - } - return gdReallocDynamic (dp, dp->logicalSize); + /* 2.0.21: we don't reallocate memory we don't own */ + if (!dp->freeOK) { + return FALSE; + } + return gdReallocDynamic(dp, dp->logicalSize); } diff -urN php-4.4.8.org/ext/gd/libgd/gd_io_file.c php-4.4.8/ext/gd/libgd/gd_io_file.c --- php-4.4.8.org/ext/gd/libgd/gd_io_file.c 2003-12-25 23:33:03.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_io_file.c 2003-12-25 23:12:12.000000000 +0100 @@ -29,11 +29,10 @@ /* this is used for creating images in main memory */ typedef struct fileIOCtx - { - gdIOCtx ctx; - FILE *f; - } -fileIOCtx; +{ + gdIOCtx ctx; + FILE *f; +} fileIOCtx; gdIOCtx *newFileCtx (FILE * f); @@ -47,97 +46,83 @@ static void gdFreeFileCtx (gdIOCtx * ctx); /* return data as a dynamic pointer */ -gdIOCtx * -gdNewFileCtx (FILE * f) +gdIOCtx * gdNewFileCtx (FILE * f) { - fileIOCtx *ctx; + fileIOCtx *ctx; - ctx = (fileIOCtx *) gdMalloc (sizeof (fileIOCtx)); - if (ctx == NULL) - { - return NULL; - } + ctx = (fileIOCtx *) gdMalloc(sizeof (fileIOCtx)); - ctx->f = f; + ctx->f = f; - ctx->ctx.getC = fileGetchar; - ctx->ctx.putC = filePutchar; + ctx->ctx.getC = fileGetchar; + ctx->ctx.putC = filePutchar; - ctx->ctx.getBuf = fileGetbuf; - ctx->ctx.putBuf = filePutbuf; + ctx->ctx.getBuf = fileGetbuf; + ctx->ctx.putBuf = filePutbuf; - ctx->ctx.tell = fileTell; - ctx->ctx.seek = fileSeek; + ctx->ctx.tell = fileTell; + ctx->ctx.seek = fileSeek; - ctx->ctx.gd_free = gdFreeFileCtx; + ctx->ctx.gd_free = gdFreeFileCtx; - return (gdIOCtx *) ctx; + return (gdIOCtx *) ctx; } -static -void -gdFreeFileCtx (gdIOCtx * ctx) +static void gdFreeFileCtx (gdIOCtx * ctx) { - gdFree (ctx); + gdFree(ctx); } -static int -filePutbuf (gdIOCtx * ctx, const void *buf, int size) +static int filePutbuf (gdIOCtx * ctx, const void *buf, int size) { - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; - return fwrite (buf, 1, size, fctx->f); + return fwrite(buf, 1, size, fctx->f); } -static int -fileGetbuf (gdIOCtx * ctx, void *buf, int size) +static int fileGetbuf (gdIOCtx * ctx, void *buf, int size) { - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; - - return (fread (buf, 1, size, fctx->f)); + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; + return fread(buf, 1, size, fctx->f); } -static void -filePutchar (gdIOCtx * ctx, int a) +static void filePutchar (gdIOCtx * ctx, int a) { - unsigned char b; - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; + unsigned char b; + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; - b = a; + b = a; - putc (b, fctx->f); + putc (b, fctx->f); } -static int -fileGetchar (gdIOCtx * ctx) +static int fileGetchar (gdIOCtx * ctx) { - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; - return getc (fctx->f); + return getc (fctx->f); } -static int -fileSeek (struct gdIOCtx *ctx, const int pos) +static int fileSeek (struct gdIOCtx *ctx, const int pos) { - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; - return (fseek (fctx->f, pos, SEEK_SET) == 0); + return (fseek (fctx->f, pos, SEEK_SET) == 0); } -static long -fileTell (struct gdIOCtx *ctx) +static long fileTell (struct gdIOCtx *ctx) { - fileIOCtx *fctx; - fctx = (fileIOCtx *) ctx; + fileIOCtx *fctx; + fctx = (fileIOCtx *) ctx; - return ftell (fctx->f); + return ftell (fctx->f); } diff -urN php-4.4.8.org/ext/gd/libgd/gd_io.h php-4.4.8/ext/gd/libgd/gd_io.h --- php-4.4.8.org/ext/gd/libgd/gd_io.h 2003-04-05 19:24:16.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_io.h 2003-12-28 21:11:08.000000000 +0100 @@ -6,18 +6,18 @@ #ifdef VMS #define Putchar gdPutchar #endif - + typedef struct gdIOCtx { int (*getC)(struct gdIOCtx*); int (*getBuf)(struct gdIOCtx*, void*, int); - void (*putC)(struct gdIOCtx*, int); + void (*putC)(struct gdIOCtx*, int); int (*putBuf)(struct gdIOCtx*, const void*, int); int (*seek)(struct gdIOCtx*, const int); long (*tell)(struct gdIOCtx*); - void (*gd_free)(struct gdIOCtx*); + void (*gd_free)(struct gdIOCtx*); } gdIOCtx; diff -urN php-4.4.8.org/ext/gd/libgd/gd_io_ss.c php-4.4.8/ext/gd/libgd/gd_io_ss.c --- php-4.4.8.org/ext/gd/libgd/gd_io_ss.c 2002-10-30 00:08:01.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_io_ss.c 2003-12-28 21:11:08.000000000 +0100 @@ -12,7 +12,7 @@ * used internally until it settles down a bit. * * This module just layers the Source/Sink interface on top of the IOCtx; no - * support is provided for tell/seek, so GD2 writing is not possible, and + * support is provided for tell/seek, so GD2 writing is not possible, and * retrieving parts of GD2 files is also not possible. * * A new SS context does not need to be created with both a Source and a Sink. @@ -30,12 +30,11 @@ /* this is used for creating images in main memory */ typedef struct ssIOCtx - { - gdIOCtx ctx; - gdSourcePtr src; - gdSinkPtr snk; - } -ssIOCtx; +{ + gdIOCtx ctx; + gdSourcePtr src; + gdSinkPtr snk; +} ssIOCtx; typedef struct ssIOCtx *ssIOCtxPtr; @@ -48,118 +47,92 @@ static void gdFreeSsCtx (gdIOCtx * ctx); /* return data as a dynamic pointer */ -gdIOCtx * -gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk) +gdIOCtx * gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk) { - ssIOCtxPtr ctx; + ssIOCtxPtr ctx; - ctx = (ssIOCtxPtr) gdMalloc (sizeof (ssIOCtx)); - if (ctx == NULL) - { - return NULL; - } + ctx = (ssIOCtxPtr) gdMalloc (sizeof (ssIOCtx)); - ctx->src = src; - ctx->snk = snk; + ctx->src = src; + ctx->snk = snk; - ctx->ctx.getC = sourceGetchar; - ctx->ctx.getBuf = sourceGetbuf; + ctx->ctx.getC = sourceGetchar; + ctx->ctx.getBuf = sourceGetbuf; - ctx->ctx.putC = sinkPutchar; - ctx->ctx.putBuf = sinkPutbuf; + ctx->ctx.putC = sinkPutchar; + ctx->ctx.putBuf = sinkPutbuf; - ctx->ctx.tell = NULL; - ctx->ctx.seek = NULL; + ctx->ctx.tell = NULL; + ctx->ctx.seek = NULL; - ctx->ctx.gd_free = gdFreeSsCtx; + ctx->ctx.gd_free = gdFreeSsCtx; - return (gdIOCtx *) ctx; + return (gdIOCtx *) ctx; } -static -void -gdFreeSsCtx (gdIOCtx * ctx) +static void gdFreeSsCtx (gdIOCtx * ctx) { - gdFree (ctx); + gdFree(ctx); } -static int -sourceGetbuf (gdIOCtx * ctx, void *buf, int size) +static int sourceGetbuf (gdIOCtx * ctx, void *buf, int size) { - ssIOCtx *lctx; - int res; - - lctx = (ssIOCtx *) ctx; + ssIOCtx *lctx; + int res; - res = ((lctx->src->source) (lctx->src->context, buf, size)); + lctx = (ssIOCtx *) ctx; -/* - ** Translate the return values from the Source object: - ** 0 is EOF, -1 is error - */ + res = ((lctx->src->source) (lctx->src->context, buf, size)); - if (res == 0) - { - return EOF; - } - else if (res < 0) - { - return 0; - } - else - { - return res; - }; + /* + * Translate the return values from the Source object: + * 0 is EOF, -1 is error + */ + if (res == 0) { + return EOF; + } else if (res < 0) { + return 0; + } else { + return res; + } } -static int -sourceGetchar (gdIOCtx * ctx) +static int sourceGetchar (gdIOCtx * ctx) { - int res; - unsigned char buf; + int res; + unsigned char buf; - res = sourceGetbuf (ctx, &buf, 1); - - if (res == 1) - { - return buf; - } - else - { - return EOF; - }; + res = sourceGetbuf (ctx, &buf, 1); + if (res == 1) { + return buf; + } else { + return EOF; + } } -static int -sinkPutbuf (gdIOCtx * ctx, const void *buf, int size) +static int sinkPutbuf (gdIOCtx * ctx, const void *buf, int size) { - ssIOCtxPtr lctx; - int res; - - lctx = (ssIOCtx *) ctx; + ssIOCtxPtr lctx; + int res; - res = (lctx->snk->sink) (lctx->snk->context, buf, size); + lctx = (ssIOCtx *) ctx; - if (res <= 0) - { - return 0; - } - else - { - return res; - }; + res = (lctx->snk->sink) (lctx->snk->context, buf, size); + if (res <= 0) { + return 0; + } else { + return res; + } } -static void -sinkPutchar (gdIOCtx * ctx, int a) +static void sinkPutchar (gdIOCtx * ctx, int a) { - unsigned char b; - - b = a; - sinkPutbuf (ctx, &b, 1); + unsigned char b; + b = a; + sinkPutbuf (ctx, &b, 1); } diff -urN php-4.4.8.org/ext/gd/libgd/gd_jpeg.c php-4.4.8/ext/gd/libgd/gd_jpeg.c --- php-4.4.8.org/ext/gd/libgd/gd_jpeg.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_jpeg.c 2006-02-05 16:53:58.000000000 +0100 @@ -1,7 +1,7 @@ /* * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the * gd graphics library (http://www.boutell.com/gd/). - * + * * This software is based in part on the work of the Independent JPEG * Group. For more information on the IJG JPEG software (and JPEG * documentation, etc.), see ftp://ftp.uu.net/graphics/jpeg/. @@ -18,13 +18,9 @@ * major CGI brain damage * * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to - * Christian Aberger + * Christian Aberger */ -#if PHP_WIN32 && !defined(ssize_t) -typedef int ssize_t; -#endif - #include #include #include @@ -47,8 +43,44 @@ typedef struct _jmpbuf_wrapper { jmp_buf jmpbuf; + int ignore_warning; } jmpbuf_wrapper; +static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level) +{ + char message[JMSG_LENGTH_MAX]; + jmpbuf_wrapper *jmpbufw; + int ignore_warning = 0; + + jmpbufw = (jmpbuf_wrapper *) jpeg_info->client_data; + + if (jmpbufw != 0) { + ignore_warning = jmpbufw->ignore_warning; + } + + (jpeg_info->err->format_message)(jpeg_info,message); + + /* It is a warning message */ + if (level < 0) { + /* display only the 1st warning, as would do a default libjpeg + * unless strace_level >= 3 + */ + if ((jpeg_info->err->num_warnings == 0) || (jpeg_info->err->trace_level >= 3)) { + php_gd_error_ex(ignore_warning ? E_NOTICE : E_WARNING, "gd-jpeg, libjpeg: recoverable error: %s\n", message); + } + + jpeg_info->err->num_warnings++; + } else { + /* strace msg, Show it if trace_level >= level. */ + if (jpeg_info->err->trace_level >= level) { + php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: strace message: %s\n", message); + } + } + return 1; +} + + + /* Called by the IJG JPEG library upon encountering a fatal error */ static void fatal_jpeg_error (j_common_ptr cinfo) { @@ -174,7 +206,7 @@ nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); if (nlines != 1) { - php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines); } } } else { @@ -201,7 +233,7 @@ nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); if (nlines != 1) { - php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines); } } } @@ -211,21 +243,21 @@ gdFree (row); } -gdImagePtr gdImageCreateFromJpeg (FILE * inFile) +gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning) { gdImagePtr im; gdIOCtx *in = gdNewFileCtx(inFile); - im = gdImageCreateFromJpegCtx(in); + im = gdImageCreateFromJpegCtx(in, ignore_warning); in->gd_free (in); return im; } -gdImagePtr gdImageCreateFromJpegPtr (int size, void *data) +gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning) { gdImagePtr im; gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0); - im = gdImageCreateFromJpegCtx(in); + im = gdImageCreateFromJpegCtx(in, ignore_warning); in->gd_free(in); return im; @@ -235,11 +267,12 @@ static int CMYKToRGB(int c, int m, int y, int k, int inverted); -/* + +/* * Create a gd-format image from the JPEG-format INFILE. Returns the * image, or NULL upon error. */ -gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile) +gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; @@ -257,8 +290,13 @@ memset (&cinfo, 0, sizeof (cinfo)); memset (&jerr, 0, sizeof (jerr)); + jmpbufw.ignore_warning = ignore_warning; + cinfo.err = jpeg_std_error (&jerr); cinfo.client_data = &jmpbufw; + + cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message; + if (setjmp (jmpbufw.jmpbuf) != 0) { /* we're here courtesy of longjmp */ if (row) { @@ -280,7 +318,7 @@ jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256); retval = jpeg_read_header (&cinfo, TRUE); - if (retval != JPEG_HEADER_OK) { + if (retval != JPEG_HEADER_OK) { php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK); } @@ -316,9 +354,9 @@ * latest libjpeg, replaced by something else. Unfortunately * there is still no right way to find out if the file was * progressive or not; just declare your intent before you - * write one by calling gdImageInterlace(im, 1) yourself. + * write one by calling gdImageInterlace(im, 1) yourself. * After all, we're not really supposed to rework JPEGs and - * write them out again anyway. Lossy compression, remember? + * write them out again anyway. Lossy compression, remember? */ #if 0 gdImageInterlace (im, cinfo.progressive_mode != 0); @@ -390,12 +428,12 @@ if (jpeg_finish_decompress (&cinfo) != TRUE) { php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source"); } - - /* Thanks to Truxton Fulton */ - if (cinfo.err->num_warnings > 0) { - goto error; + if (!ignore_warning) { + if (cinfo.err->num_warnings > 0) { + goto error; + } } - + jpeg_destroy_decompress (&cinfo); gdFree (row); @@ -524,7 +562,7 @@ int got = gdGetBuf(src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile); if (got == EOF || got == 0) { - /* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */ + /* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */ if (!nbytes) { nbytes = -1; } @@ -532,7 +570,7 @@ } nbytes += got; } - + if (nbytes <= 0) { if (src->start_of_file) { /* Treat empty input file as fatal error */ ERREXIT (cinfo, JERR_INPUT_EMPTY); @@ -634,7 +672,7 @@ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof (unsigned char)); - + } src = (my_src_ptr) cinfo->src; diff -urN php-4.4.8.org/ext/gd/libgd/gdkanji.c php-4.4.8/ext/gd/libgd/gdkanji.c --- php-4.4.8.org/ext/gd/libgd/gdkanji.c 2003-04-05 19:24:16.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdkanji.c 2003-12-28 21:11:08.000000000 +0100 @@ -75,7 +75,7 @@ va_list args; char *tmp; TSRMLS_FETCH(); - + va_start(args, format); vspprintf(&tmp, 0, format, args); va_end(args); diff -urN php-4.4.8.org/ext/gd/libgd/gd_png.c php-4.4.8/ext/gd/libgd/gd_png.c --- php-4.4.8.org/ext/gd/libgd/gd_png.c 2007-05-17 00:54:11.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_png.c 2007-05-17 00:19:08.000000000 +0200 @@ -23,7 +23,7 @@ out all fprintf() statements to disable that). GD 2.0 supports RGBA truecolor and will read and write truecolor PNGs. - GD 2.0 supports 8 bits of color resolution per channel and + GD 2.0 supports 8 bits of color resolution per channel and 7 bits of alpha channel resolution. Images with more than 8 bits per channel are reduced to 8 bits. Images with an alpha channel are only able to resolve down to '1/128th opaque' instead of '1/256th', @@ -58,11 +58,11 @@ * been defined. */ - php_gd_error_ex(E_ERROR, "gd-png: fatal libpng error: %s\n", msg); + php_gd_error_ex(E_WARNING, "gd-png: fatal libpng error: %s", msg); jmpbuf_ptr = png_get_error_ptr (png_ptr); if (jmpbuf_ptr == NULL) { /* we are completely hosed now */ - php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); + php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating."); } longjmp (jmpbuf_ptr->jmpbuf, 1); @@ -130,12 +130,15 @@ /* Make sure the signature can't match by dumb luck -- TBB */ /* GRR: isn't sizeof(infile) equal to the size of the pointer? */ - memset (infile, 0, sizeof(infile)); + memset (sig, 0, sizeof(sig)); /* first do a quick check that the file really is a PNG image; could - * have used slightly more general png_sig_cmp() function instead + * have used slightly more general png_sig_cmp() function instead */ - gdGetBuf(sig, 8, infile); + if (gdGetBuf(sig, 8, infile) < 8) { + return NULL; + } + if (!png_check_sig (sig, 8)) { /* bad signature */ return NULL; } @@ -146,13 +149,13 @@ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if (png_ptr == NULL) { - php_gd_error("gd-png error: cannot allocate libpng main struct\n"); + php_gd_error("gd-png error: cannot allocate libpng main struct"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { - php_gd_error("gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct"); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; @@ -160,7 +163,7 @@ /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated - * (mainly for PNG-aware image editors and converters) + * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every non-callback function that calls a @@ -168,7 +171,7 @@ */ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp(gdPngJmpbufStruct.jmpbuf)) { - php_gd_error("gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; @@ -187,7 +190,7 @@ im = gdImageCreate((int) width, (int) height); } if (im == NULL) { - php_gd_error("gd-png error: cannot allocate gdImage struct\n"); + php_gd_error("gd-png error: cannot allocate gdImage struct"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); gdFree(image_data); gdFree(row_pointers); @@ -201,15 +204,32 @@ png_set_packing (png_ptr); /* expand to 1 byte per pixel */ } + /* setjmp() must be called in every non-callback function that calls a + * PNG-reading libpng function + */ +#ifndef PNG_SETJMP_NOT_SUPPORTED + if (setjmp(gdPngJmpbufStruct.jmpbuf)) { + php_gd_error("gd-png error: setjmp returns error condition"); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + gdFree(image_data); + gdFree(row_pointers); + if (im) { + gdImageDestroy(im); + } + return NULL; + } +#endif + + switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); #ifdef DEBUG - php_gd_error("gd-png color_type is palette, colors: %d\n", num_palette); + php_gd_error("gd-png color_type is palette, colors: %d", num_palette); #endif /* DEBUG */ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { /* gd 2.0: we support this rather thoroughly now. Grab the - * first fully transparent entry, if any, as the value of + * first fully transparent entry, if any, as the value of * the simple-transparency index, mostly for backwards * binary compatibility. The alpha channel is where it's * really at these days. @@ -228,8 +248,8 @@ case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: /* create a fake palette and check for single-shade transparency */ - if ((palette = (png_colorp) safe_emalloc(256, sizeof(png_color), 0)) == NULL) { - php_gd_error("gd-png error: cannot allocate gray palette\n"); + if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) { + php_gd_error("gd-png error: cannot allocate gray palette"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; @@ -263,7 +283,7 @@ * custom 16-bit code to handle the case where there are gdFree * palette entries. This error will be extremely rare in * general, though. (Quite possibly there is only one such - * image in existence.) + * image in existence.) */ } break; @@ -272,16 +292,16 @@ case PNG_COLOR_TYPE_RGB_ALPHA: /* gd 2.0: we now support truecolor. See the comment above * for a rare situation in which the transparent pixel may not - * work properly with 16-bit channels. + * work properly with 16-bit channels. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_color_rgb); if (bit_depth == 16) { /* png_set_strip_16() not yet in effect */ - transparent = gdTrueColor(trans_color_rgb->red >> 8, + transparent = gdTrueColor(trans_color_rgb->red >> 8, trans_color_rgb->green >> 8, trans_color_rgb->blue >> 8); } else { - transparent = gdTrueColor(trans_color_rgb->red, + transparent = gdTrueColor(trans_color_rgb->red, trans_color_rgb->green, trans_color_rgb->blue); } @@ -295,7 +315,7 @@ rowbytes = png_get_rowbytes(png_ptr, info_ptr); image_data = (png_bytep) safe_emalloc(rowbytes, height, 0); - row_pointers = (png_bytepp) safe_emalloc(height, sizeof (png_bytep), 0); + row_pointers = (png_bytepp) safe_emalloc(height, sizeof(png_bytep), 0); /* set the individual row_pointers to point at the correct offsets */ for (h = 0; h < height; ++h) { @@ -349,7 +369,7 @@ register png_byte b = row_pointers[h][boffset++]; /* gd has only 7 bits of alpha channel resolution, and - * 127 is transparent, 0 opaque. A moment of convenience, + * 127 is transparent, 0 opaque. A moment of convenience, * a lifetime of compatibility. */ @@ -373,7 +393,7 @@ if (!im->trueColor) { for (i = num_palette; i < gdMaxColors; ++i) { if (!open[i]) { - php_gd_error("gd-png warning: image data references out-of-range color index (%d)\n", i); + php_gd_error("gd-png warning: image data references out-of-range color index (%d)", i); } } } @@ -388,17 +408,17 @@ return im; } -void gdImagePngEx (gdImagePtr im, FILE * outFile, int level) +void gdImagePngEx (gdImagePtr im, FILE * outFile, int level, int basefilter) { gdIOCtx *out = gdNewFileCtx(outFile); - gdImagePngCtxEx(im, out, level); + gdImagePngCtxEx(im, out, level, basefilter); out->gd_free(out); } void gdImagePng (gdImagePtr im, FILE * outFile) { gdIOCtx *out = gdNewFileCtx(outFile); - gdImagePngCtxEx(im, out, -1); + gdImagePngCtxEx(im, out, -1, -1); out->gd_free(out); } @@ -406,18 +426,18 @@ { void *rv; gdIOCtx *out = gdNewDynamicCtx(2048, NULL); - gdImagePngCtxEx(im, out, -1); + gdImagePngCtxEx(im, out, -1, -1); rv = gdDPExtractData(out, size); out->gd_free(out); return rv; } -void * gdImagePngPtrEx (gdImagePtr im, int *size, int level) +void * gdImagePngPtrEx (gdImagePtr im, int *size, int level, int basefilter) { void *rv; gdIOCtx *out = gdNewDynamicCtx(2048, NULL); - gdImagePngCtxEx(im, out, level); + gdImagePngCtxEx(im, out, level, basefilter); rv = gdDPExtractData(out, size); out->gd_free(out); return rv; @@ -425,14 +445,14 @@ void gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile) { - gdImagePngCtxEx(im, outfile, -1); + gdImagePngCtxEx(im, outfile, -1, -1); } /* This routine is based in part on code from Dale Lutz (Safe Software Inc.) * and in part on demo code from Chapter 15 of "PNG: The Definitive Guide" * (http://www.cdrom.com/pub/png/pngbook.html). */ -void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level) +void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level, int basefilter) { int i, j, bit_depth = 0, interlace_type; int width = im->sx; @@ -454,13 +474,13 @@ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if (png_ptr == NULL) { - php_gd_error("gd-png error: cannot allocate libpng main struct\n"); + php_gd_error("gd-png error: cannot allocate libpng main struct"); return; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { - php_gd_error("gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct"); png_destroy_write_struct (&png_ptr, (png_infopp) NULL); return; @@ -468,7 +488,7 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { - php_gd_error("gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition"); png_destroy_write_struct (&png_ptr, &info_ptr); return; @@ -483,14 +503,17 @@ * gd is intentionally imperfect and doesn't spend a lot of time * fussing with such things. */ - + /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE); */ /* 2.0.12: this is finally a parameter */ png_set_compression_level(png_ptr, level); + if (basefilter >= 0) { + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, basefilter); + } /* can set this to a smaller value without compromising compression if all - * image data is 16K or less; will save some decoder memory [min == 8] + * image data is 16K or less; will save some decoder memory [min == 8] */ /* png_set_compression_window_bits(png_ptr, 15); */ @@ -519,13 +542,13 @@ bit_depth = 1; } else if (colors <= 4) { bit_depth = 2; - } else if (colors <= 16) { + } else if (colors <= 16) { bit_depth = 4; } else { bit_depth = 8; } } - + interlace_type = im->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; if (im->trueColor) { @@ -552,9 +575,9 @@ if (!im->trueColor) { /* Oy veh. Remap the PNG palette to put the entries with interesting alpha channel * values first. This minimizes the size of the tRNS chunk and thus the size - * of the PNG file as a whole. + * of the PNG file as a whole. */ - + int tc = 0; int i; int j; @@ -585,7 +608,7 @@ for (i = 0; i < im->colorsTotal; i++) { if (!im->open[i]) { if (im->alpha[i] != gdAlphaOpaque) { - /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ trans_values[j] = 255 - ((im->alpha[i] << 1) + (im->alpha[i] >> 6)); mapping[i] = j++; } else { @@ -665,7 +688,7 @@ * PNG's convention in which 255 is opaque. */ a = gdTrueColorGetAlpha(thisPixel); - /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ *pOutputRow++ = 255 - ((a << 1) + (a >> 6)); } } @@ -677,12 +700,12 @@ for (j = 0; j < height; ++j) { gdFree(row_pointers[j]); } - + gdFree(row_pointers); } else { if (remap) { png_bytep *row_pointers; - row_pointers = safe_emalloc(sizeof(png_bytep), height, 0); + row_pointers = safe_emalloc(height, sizeof(png_bytep), 0); for (j = 0; j < height; ++j) { row_pointers[j] = (png_bytep) gdMalloc(width); for (i = 0; i < width; ++i) { diff -urN php-4.4.8.org/ext/gd/libgd/gd_security.c php-4.4.8/ext/gd/libgd/gd_security.c --- php-4.4.8.org/ext/gd/libgd/gd_security.c 2007-03-10 14:06:37.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_security.c 2007-10-23 03:58:08.000000000 +0200 @@ -19,12 +19,10 @@ int overflow2(int a, int b) { - if(a < 0 || b < 0) { - php_gd_error("gd warning: one parameter to a memory allocation multiplication is negative, failing operation gracefully\n"); + if(a <= 0 || b <= 0) { + php_gd_error("gd warning: one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully\n"); return 1; } - if(b == 0) - return 0; if(a > INT_MAX / b) { php_gd_error("gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully\n"); return 1; diff -urN php-4.4.8.org/ext/gd/libgd/gd_ss.c php-4.4.8/ext/gd/libgd/gd_ss.c --- php-4.4.8.org/ext/gd/libgd/gd_ss.c 2003-03-05 17:04:20.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gd_ss.c 2005-08-18 14:54:44.000000000 +0200 @@ -17,37 +17,33 @@ #define GD_SS_DBG(s) #ifdef HAVE_LIBPNG -void -gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) +void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - gdIOCtx *out = gdNewSSCtx (NULL, outSink); - gdImagePngCtx (im, out); - out->gd_free (out); + gdIOCtx *out = gdNewSSCtx(NULL, outSink); + gdImagePngCtx(im, out); + out->gd_free(out); } -gdImagePtr -gdImageCreateFromPngSource (gdSourcePtr inSource) +gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - gdIOCtx *in = gdNewSSCtx (inSource, NULL); - gdImagePtr im; + gdIOCtx *in = gdNewSSCtx(inSource, NULL); + gdImagePtr im; - im = gdImageCreateFromPngCtx (in); + im = gdImageCreateFromPngCtx(in); - in->gd_free (in); + in->gd_free(in); - return im; + return im; } #else /* no HAVE_LIBPNG */ -void -gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) +void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - php_gd_error("PNG support is not available\n"); + php_gd_error("PNG support is not available"); } -gdImagePtr -gdImageCreateFromPngSource (gdSourcePtr inSource) +gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - php_gd_error("PNG support is not available\n"); - return NULL; + php_gd_error("PNG support is not available"); + return NULL; } #endif /* HAVE_LIBPNG */ diff -urN php-4.4.8.org/ext/gd/libgd/gdtables.c php-4.4.8/ext/gd/libgd/gdtables.c --- php-4.4.8.org/ext/gd/libgd/gdtables.c 2002-04-13 04:03:09.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdtables.c 2006-09-15 17:11:54.000000000 +0200 @@ -1,5 +1,11 @@ -int gdCosT[] = +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_compat.h" + +const int gdCosT[] = { 1024, 1023, @@ -363,7 +369,7 @@ 1023 }; -int gdSinT[] = +const int gdSinT[] = { 0, 17, diff -urN php-4.4.8.org/ext/gd/libgd/gdtest.c php-4.4.8/ext/gd/libgd/gdtest.c --- php-4.4.8.org/ext/gd/libgd/gdtest.c 2002-10-30 00:08:01.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/gdtest.c 2007-02-24 03:17:24.000000000 +0100 @@ -56,7 +56,7 @@ /* */ /* Send to PNG File then Ptr */ /* */ - sprintf (of, "%s.png", argv[1]); + snprintf (of, sizeof(of), "%s.png", argv[1]); out = fopen (of, "wb"); gdImagePng (im, out); fclose (out); @@ -88,7 +88,7 @@ /* */ /* Send to GD2 File then Ptr */ /* */ - sprintf (of, "%s.gd2", argv[1]); + snprintf (of, sizeof(of), "%s.gd2", argv[1]); out = fopen (of, "wb"); gdImageGd2 (im, out, 128, 2); fclose (out); @@ -123,7 +123,7 @@ /* */ /* Send to GD File then Ptr */ /* */ - sprintf (of, "%s.gd", argv[1]); + snprintf (of, sizeof(of), "%s.gd", argv[1]); out = fopen (of, "wb"); gdImageGd (im, out); fclose (out); @@ -180,7 +180,7 @@ ** Test gdImagePngToSink' * */ - sprintf (of, "%s.snk", argv[1]); + snprintf (of, sizeof(of), "%s.snk", argv[1]); out = fopen (of, "wb"); imgsnk.sink = fwriteWrapper; imgsnk.context = out; diff -urN php-4.4.8.org/ext/gd/libgd/gd_topal.c php-4.4.8/ext/gd/libgd/gd_topal.c --- php-4.4.8.org/ext/gd/libgd/gd_topal.c 2004-08-12 01:25:54.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_topal.c 2007-04-04 02:30:18.000000000 +0200 @@ -772,6 +772,7 @@ nim->green[icolor] = 255; nim->blue[icolor] = 255; } + nim->open[icolor] = 0; #endif } @@ -2086,6 +2087,9 @@ if( (im1->sx != im2->sx) || (im1->sy != im2->sy) ) { return -3; /* the images are meant to be the same dimensions */ } + if (im2->colorsTotal<1) { + return -4; /* At least 1 color must be allocated */ + } buf = (unsigned long *)safe_emalloc(sizeof(unsigned long), 5 * im2->colorsTotal, 0); memset( buf, 0, sizeof(unsigned long) * 5 * im2->colorsTotal ); diff -urN php-4.4.8.org/ext/gd/libgd/gd_wbmp.c php-4.4.8/ext/gd/libgd/gd_wbmp.c --- php-4.4.8.org/ext/gd/libgd/gd_wbmp.c 2004-03-29 20:21:00.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gd_wbmp.c 2005-08-18 14:54:44.000000000 +0200 @@ -1,10 +1,8 @@ - - /* WBMP: Wireless Bitmap Type 0: B/W, Uncompressed Bitmap - Specification of the WBMP format can be found in the file: + Specification of the WBMP format can be found in the file: SPEC-WAESpec-19990524.pdf - You can download the WAP specification on: http://www.wapforum.com/ + You can download the WAP specification on: http://www.wapforum.com/ gd_wbmp.c @@ -16,7 +14,7 @@ (wbmp library included, but you can find the latest distribution at http://www.vandenbrande.com/wbmp) - Implemented: gdImageCreateFromWBMPCtx, gdImageCreateFromWBMP + Implemented: gdImageCreateFromWBMPCtx, gdImageCreateFromWBMP --------------------------------------------------------------------------- @@ -34,7 +32,7 @@ ** implied warranty. --------------------------------------------------------------------------- - Parts od this code are inspired by 'pbmtowbmp.c' and 'wbmptopbm.c' by + Parts od this code are inspired by 'pbmtowbmp.c' and 'wbmptopbm.c' by Terje Sannum . ** ** Permission to use, copy, modify, and distribute this software and its @@ -67,10 +65,9 @@ ** Wrapper around gdPutC for use with writewbmp ** */ -void -gd_putout (int i, void *out) +void gd_putout (int i, void *out) { - gdPutC (i, (gdIOCtx *) out); + gdPutC(i, (gdIOCtx *) out); } @@ -79,10 +76,9 @@ ** Wrapper around gdGetC for use with readwbmp ** */ -int -gd_getin (void *in) +int gd_getin (void *in) { - return (gdGetC ((gdIOCtx *) in)); + return (gdGetC((gdIOCtx *) in)); } @@ -91,105 +87,93 @@ ** Write the image as a wbmp file ** Parameters are: ** image: gd image structure; - ** fg: the index of the foreground color. any other value will be + ** fg: the index of the foreground color. any other value will be ** considered as background and will not be written ** out: the stream where to write */ -void -gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out) +void gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out) { + int x, y, pos; + Wbmp *wbmp; - int x, y, pos; - Wbmp *wbmp; + /* create the WBMP */ + if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) { + php_gd_error("Could not create WBMP"); + } + /* fill up the WBMP structure */ + pos = 0; + for (y = 0; y < gdImageSY(image); y++) { + for (x = 0; x < gdImageSX(image); x++) { + if (gdImageGetPixel (image, x, y) == fg) { + wbmp->bitmap[pos] = WBMP_BLACK; + } + pos++; + } + } - /* create the WBMP */ - if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) - php_gd_error("Could not create WBMP\n"); - - /* fill up the WBMP structure */ - pos = 0; - for (y = 0; y < gdImageSY (image); y++) - { - for (x = 0; x < gdImageSX (image); x++) - { - if (gdImageGetPixel (image, x, y) == fg) - { - wbmp->bitmap[pos] = WBMP_BLACK; - } - pos++; - } - } - - /* write the WBMP to a gd file descriptor */ - if (writewbmp (wbmp, &gd_putout, out)) - php_gd_error("Could not save WBMP\n"); - /* des submitted this bugfix: gdFree the memory. */ - freewbmp (wbmp); + /* write the WBMP to a gd file descriptor */ + if (writewbmp (wbmp, &gd_putout, out)) { + php_gd_error("Could not save WBMP"); + } + /* des submitted this bugfix: gdFree the memory. */ + freewbmp(wbmp); } - /* gdImageCreateFromWBMPCtx ** ------------------------ ** Create a gdImage from a WBMP file input from an gdIOCtx */ -gdImagePtr -gdImageCreateFromWBMPCtx (gdIOCtx * infile) +gdImagePtr gdImageCreateFromWBMPCtx (gdIOCtx * infile) { - /* FILE *wbmp_file; */ - Wbmp *wbmp; - gdImagePtr im = NULL; - int black, white; - int col, row, pos; - - if (readwbmp (&gd_getin, infile, &wbmp)) - return (NULL); - - if (!(im = gdImageCreate (wbmp->width, wbmp->height))) - { - freewbmp (wbmp); - return (NULL); - } - - /* create the background color */ - white = gdImageColorAllocate (im, 255, 255, 255); - /* create foreground color */ - black = gdImageColorAllocate (im, 0, 0, 0); - - /* fill in image (in a wbmp 1 = white/ 0 = black) */ - pos = 0; - for (row = 0; row < wbmp->height; row++) - { - for (col = 0; col < wbmp->width; col++) - { - if (wbmp->bitmap[pos++] == WBMP_WHITE) - { - gdImageSetPixel (im, col, row, white); - } - else - { - gdImageSetPixel (im, col, row, black); - } + /* FILE *wbmp_file; */ + Wbmp *wbmp; + gdImagePtr im = NULL; + int black, white; + int col, row, pos; + + if (readwbmp (&gd_getin, infile, &wbmp)) { + return NULL; } - } - freewbmp (wbmp); + if (!(im = gdImageCreate (wbmp->width, wbmp->height))) { + freewbmp (wbmp); + return NULL; + } - return (im); -} + /* create the background color */ + white = gdImageColorAllocate(im, 255, 255, 255); + /* create foreground color */ + black = gdImageColorAllocate(im, 0, 0, 0); + + /* fill in image (in a wbmp 1 = white/ 0 = black) */ + pos = 0; + for (row = 0; row < wbmp->height; row++) { + for (col = 0; col < wbmp->width; col++) { + if (wbmp->bitmap[pos++] == WBMP_WHITE) { + gdImageSetPixel(im, col, row, white); + } else { + gdImageSetPixel(im, col, row, black); + } + } + } + freewbmp(wbmp); + + return im; +} /* gdImageCreateFromWBMP ** --------------------- */ -gdImagePtr -gdImageCreateFromWBMP (FILE * inFile) +gdImagePtr gdImageCreateFromWBMP (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); - im = gdImageCreateFromWBMPCtx (in); - in->gd_free (in); - return (im); + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx(inFile); + im = gdImageCreateFromWBMPCtx(in); + in->gd_free(in); + + return im; } gdImagePtr gdImageCreateFromWBMPPtr (int size, void *data) @@ -204,24 +188,23 @@ /* gdImageWBMP ** ----------- */ -void -gdImageWBMP (gdImagePtr im, int fg, FILE * outFile) +void gdImageWBMP (gdImagePtr im, int fg, FILE * outFile) { - gdIOCtx *out = gdNewFileCtx (outFile); - gdImageWBMPCtx (im, fg, out); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx(outFile); + gdImageWBMPCtx(im, fg, out); + out->gd_free(out); } /* gdImageWBMPPtr ** -------------- */ -void * -gdImageWBMPPtr (gdImagePtr im, int *size, int fg) +void * gdImageWBMPPtr (gdImagePtr im, int *size, int fg) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - gdImageWBMPCtx (im, fg, out); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + gdImageWBMPCtx(im, fg, out); + rv = gdDPExtractData(out, size); + out->gd_free(out); + + return rv; } diff -urN php-4.4.8.org/ext/gd/libgd/gdxpm.c php-4.4.8/ext/gd/libgd/gdxpm.c --- php-4.4.8.org/ext/gd/libgd/gdxpm.c 2003-06-04 01:42:49.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/gdxpm.c 2005-08-18 14:54:44.000000000 +0200 @@ -1,8 +1,8 @@ -/* +/* add ability to load xpm files to gd, requires the xpm library. - Caolan.McNamara@ul.ie + Caolan.McNamara@ul.ie http://www.csn.ul.ie/~caolan */ #include @@ -15,123 +15,125 @@ #include -gdImagePtr -gdImageCreateFromXpm (char *filename) +gdImagePtr gdImageCreateFromXpm (char *filename) { - XpmInfo info; - XpmImage image; - int i, j, k, number; - char buf[5]; - gdImagePtr im = 0; - char *apixel; - int *pointer; - int red = 0, green = 0, blue = 0; - int *colors; - int ret; - - ret = XpmReadFileToXpmImage (filename, &image, &info); - if (ret != XpmSuccess) - return 0; - - if (!(im = gdImageCreate (image.width, image.height))) - return 0; - - number = image.ncolors; - colors = (int *) safe_emalloc(number, sizeof(int), 0); - for (i = 0; i < number; i++) - { - switch (strlen (image.colorTable[i].c_color)) - { - case 4: - buf[1] = '\0'; - buf[0] = image.colorTable[i].c_color[1]; - red = strtol (buf, NULL, 16); - - buf[0] = image.colorTable[i].c_color[3]; - green = strtol (buf, NULL, 16); - - buf[0] = image.colorTable[i].c_color[5]; - blue = strtol (buf, NULL, 16); - break; - case 7: - buf[2] = '\0'; - buf[0] = image.colorTable[i].c_color[1]; - buf[1] = image.colorTable[i].c_color[2]; - red = strtol (buf, NULL, 16); - - buf[0] = image.colorTable[i].c_color[3]; - buf[1] = image.colorTable[i].c_color[4]; - green = strtol (buf, NULL, 16); - - buf[0] = image.colorTable[i].c_color[5]; - buf[1] = image.colorTable[i].c_color[6]; - blue = strtol (buf, NULL, 16); - break; - case 10: - buf[3] = '\0'; - buf[0] = image.colorTable[i].c_color[1]; - buf[1] = image.colorTable[i].c_color[2]; - buf[2] = image.colorTable[i].c_color[3]; - red = strtol (buf, NULL, 16); - red /= 64; - - buf[0] = image.colorTable[i].c_color[4]; - buf[1] = image.colorTable[i].c_color[5]; - buf[2] = image.colorTable[i].c_color[6]; - green = strtol (buf, NULL, 16); - green /= 64; - - buf[0] = image.colorTable[i].c_color[7]; - buf[1] = image.colorTable[i].c_color[8]; - buf[2] = image.colorTable[i].c_color[9]; - blue = strtol (buf, NULL, 16); - blue /= 64; - break; - case 13: - buf[4] = '\0'; - buf[0] = image.colorTable[i].c_color[1]; - buf[1] = image.colorTable[i].c_color[2]; - buf[2] = image.colorTable[i].c_color[3]; - buf[3] = image.colorTable[i].c_color[4]; - red = strtol (buf, NULL, 16); - red /= 256; - - buf[0] = image.colorTable[i].c_color[5]; - buf[1] = image.colorTable[i].c_color[6]; - buf[2] = image.colorTable[i].c_color[7]; - buf[3] = image.colorTable[i].c_color[8]; - green = strtol (buf, NULL, 16); - green /= 256; - - buf[0] = image.colorTable[i].c_color[9]; - buf[1] = image.colorTable[i].c_color[10]; - buf[2] = image.colorTable[i].c_color[11]; - buf[3] = image.colorTable[i].c_color[12]; - blue = strtol (buf, NULL, 16); - blue /= 256; - break; + XpmInfo info; + XpmImage image; + int i, j, k, number; + char buf[5]; + gdImagePtr im = 0; + char *apixel; + int *pointer; + int red = 0, green = 0, blue = 0; + int *colors; + int ret; + + ret = XpmReadFileToXpmImage(filename, &image, &info); + if (ret != XpmSuccess) { + return 0; } + if (!(im = gdImageCreate(image.width, image.height))) { + return 0; + } - colors[i] = gdImageColorResolve (im, red, green, blue); - if (colors[i] == -1) - php_gd_error("ARRRGH\n"); - } - - apixel = (char *) gdMalloc (image.cpp + 1); - apixel[image.cpp] = '\0'; - - pointer = (int *) image.data; - for (i = 0; i < image.height; i++) - { - for (j = 0; j < image.width; j++) - { - k = *pointer++; - gdImageSetPixel (im, j, i, colors[k]); + number = image.ncolors; + colors = (int *) safe_emalloc(number, sizeof(int), 0); + for (i = 0; i < number; i++) { + switch (strlen (image.colorTable[i].c_color)) { + case 4: + buf[1] = '\0'; + buf[0] = image.colorTable[i].c_color[1]; + red = strtol(buf, NULL, 16); + + buf[0] = image.colorTable[i].c_color[2]; + green = strtol(buf, NULL, 16); + + buf[0] = image.colorTable[i].c_color[3]; + blue = strtol(buf, NULL, 16); + break; + + case 7: + buf[2] = '\0'; + buf[0] = image.colorTable[i].c_color[1]; + buf[1] = image.colorTable[i].c_color[2]; + red = strtol(buf, NULL, 16); + + buf[0] = image.colorTable[i].c_color[3]; + buf[1] = image.colorTable[i].c_color[4]; + green = strtol(buf, NULL, 16); + + buf[0] = image.colorTable[i].c_color[5]; + buf[1] = image.colorTable[i].c_color[6]; + blue = strtol(buf, NULL, 16); + break; + + case 10: + buf[3] = '\0'; + buf[0] = image.colorTable[i].c_color[1]; + buf[1] = image.colorTable[i].c_color[2]; + buf[2] = image.colorTable[i].c_color[3]; + red = strtol(buf, NULL, 16); + red /= 64; + + buf[0] = image.colorTable[i].c_color[4]; + buf[1] = image.colorTable[i].c_color[5]; + buf[2] = image.colorTable[i].c_color[6]; + green = strtol(buf, NULL, 16); + green /= 64; + + buf[0] = image.colorTable[i].c_color[7]; + buf[1] = image.colorTable[i].c_color[8]; + buf[2] = image.colorTable[i].c_color[9]; + blue = strtol(buf, NULL, 16); + blue /= 64; + break; + + case 13: + buf[4] = '\0'; + buf[0] = image.colorTable[i].c_color[1]; + buf[1] = image.colorTable[i].c_color[2]; + buf[2] = image.colorTable[i].c_color[3]; + buf[3] = image.colorTable[i].c_color[4]; + red = strtol(buf, NULL, 16); + red /= 256; + + buf[0] = image.colorTable[i].c_color[5]; + buf[1] = image.colorTable[i].c_color[6]; + buf[2] = image.colorTable[i].c_color[7]; + buf[3] = image.colorTable[i].c_color[8]; + green = strtol(buf, NULL, 16); + green /= 256; + + buf[0] = image.colorTable[i].c_color[9]; + buf[1] = image.colorTable[i].c_color[10]; + buf[2] = image.colorTable[i].c_color[11]; + buf[3] = image.colorTable[i].c_color[12]; + blue = strtol(buf, NULL, 16); + blue /= 256; + break; + } + + + colors[i] = gdImageColorResolve(im, red, green, blue); + if (colors[i] == -1) { + php_gd_error("ARRRGH"); + } } - } - gdFree (apixel); - gdFree (colors); - return (im); + + apixel = (char *) gdMalloc(image.cpp + 1); + apixel[image.cpp] = '\0'; + + pointer = (int *) image.data; + for (i = 0; i < image.height; i++) { + for (j = 0; j < image.width; j++) { + k = *pointer++; + gdImageSetPixel(im, j, i, colors[k]); + } + } + + gdFree(apixel); + gdFree(colors); + return im; } #endif diff -urN php-4.4.8.org/ext/gd/libgd/testac.c php-4.4.8/ext/gd/libgd/testac.c --- php-4.4.8.org/ext/gd/libgd/testac.c 2002-04-13 04:03:09.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/testac.c 2003-12-28 21:11:08.000000000 +0100 @@ -33,7 +33,7 @@ } /* Load original PNG, which should contain alpha channel information. We will use it in two ways: preserving it - literally, for use with compatible browsers, and + literally, for use with compatible browsers, and compositing it ourselves against a background of our choosing (alpha blending). We'll change its size and try creating palette versions of it. */ @@ -80,7 +80,7 @@ /* Create output image. */ im_out = gdImageCreateTrueColor ((int) (gdImageSX (im_in) * scale), (int) (gdImageSY (im_in) * scale)); - /* + /* Request alpha blending. This causes future drawing operations to perform alpha channel blending with the background, resulting in an opaque image. @@ -111,7 +111,7 @@ /* If this image is the result of alpha channel blending, it will not contain an interesting alpha channel itself. - Save a little file size by not saving the alpha channel. + Save a little file size by not saving the alpha channel. Otherwise the file would typically be slightly larger. */ gdImageSaveAlpha (im_out, !blending); diff -urN php-4.4.8.org/ext/gd/libgd/wbmp.c php-4.4.8/ext/gd/libgd/wbmp.c --- php-4.4.8.org/ext/gd/libgd/wbmp.c 2007-03-10 14:06:37.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/wbmp.c 2007-03-10 13:18:36.000000000 +0100 @@ -28,7 +28,7 @@ /* getmbi ** ------ - ** Get a multibyte integer from a generic getin function + ** Get a multibyte integer from a generic getin function ** 'getin' can be getc, with in = NULL ** you can find getin as a function just above the main function ** This way you gain a lot of flexibilty about how this package @@ -125,7 +125,7 @@ return NULL; } - if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), (width * height), 0)) == NULL) + if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), width * height, 0)) == NULL) { gdFree (wbmp); return (NULL); @@ -192,7 +192,7 @@ return (-1); } - if ((wbmp->bitmap = (int *) safe_emalloc(sizeof(int), (wbmp->width * wbmp->height), 0)) == NULL) + if ((wbmp->bitmap = (int *) safe_emalloc((size_t)wbmp->width * wbmp->height, sizeof(int), 0)) == NULL) { gdFree (wbmp); return (-1); @@ -240,7 +240,7 @@ ** Why not just giving a filedescriptor to this function? ** Well, the incentive to write this function was the complete ** integration in gd library from www.boutell.com. They use - ** their own io functions, so the passing of a function seemed to be + ** their own io functions, so the passing of a function seemed to be ** a logic(?) decision ... ** */ @@ -335,7 +335,7 @@ return (putc (c, (FILE *) out)); } -/* getin from file descriptor +/* getin from file descriptor ** -------------------------- */ int diff -urN php-4.4.8.org/ext/gd/libgd/wbmp.h php-4.4.8/ext/gd/libgd/wbmp.h --- php-4.4.8.org/ext/gd/libgd/wbmp.h 2002-04-13 04:03:09.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/wbmp.h 2005-10-09 14:06:27.000000000 +0200 @@ -8,17 +8,22 @@ ** (c) 2000 Johan Van den Brande ** ** Header file -*/ +*/ #ifndef __WBMP_H #define __WBMP_H 1 +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php_compat.h" /* WBMP struct ** ----------- ** A Wireless bitmap structure ** */ - + typedef struct Wbmp_ { int type; /* type of the wbmp */ @@ -26,22 +31,22 @@ int height; /* height of the image */ int *bitmap; /* pointer to data: 0 = WHITE , 1 = BLACK */ } Wbmp; - + #define WBMP_WHITE 1 #define WBMP_BLACK 0 - + /* Proto's ** ------- ** */ -void putmbi( int i, void (*putout)(int c, void *out), void *out); +void putmbi( int i, void (*putout)(int c, void *out), void *out); int getmbi ( int (*getin)(void *in), void *in ); int skipheader( int (*getin)(void *in), void *in ); Wbmp *createwbmp( int width, int height, int color ); int readwbmp( int (*getin)(void *in), void *in, Wbmp **wbmp ); int writewbmp( Wbmp *wbmp, void (*putout)( int c, void *out), void *out); void freewbmp( Wbmp *wbmp ); -void printwbmp( Wbmp *wbmp ); +void printwbmp( Wbmp *wbmp ); #endif diff -urN php-4.4.8.org/ext/gd/libgd/webpng.c php-4.4.8/ext/gd/libgd/webpng.c --- php-4.4.8.org/ext/gd/libgd/webpng.c 2002-04-21 15:48:22.000000000 +0200 +++ php-4.4.8/ext/gd/libgd/webpng.c 2007-02-24 03:17:24.000000000 +0100 @@ -193,7 +193,7 @@ maxy = gdImageSY(im); printf("alpha channel information:\n"); - + if (im->trueColor) { for (y = 0; y < maxy; y++) { for (x = 0; x < maxx; x++) { @@ -215,9 +215,9 @@ } else printf("NOT a true color image\n"); - no = 0; + no = 0; printf("%d alpha channels\n", nalpha); - + } else { @@ -252,7 +252,7 @@ /* Open a temporary file. */ /* "temp.tmp" is not good temporary filename. */ - sprintf (outFn, "webpng.tmp%d", getpid ()); + snprintf (outFn, sizeof(outFn), "webpng.tmp%d", getpid ()); out = fopen (outFn, "wb"); if (!out) diff -urN php-4.4.8.org/ext/gd/libgd/xbm.c php-4.4.8/ext/gd/libgd/xbm.c --- php-4.4.8.org/ext/gd/libgd/xbm.c 2007-12-31 08:22:47.000000000 +0100 +++ php-4.4.8/ext/gd/libgd/xbm.c 2007-08-09 14:08:29.000000000 +0200 @@ -29,8 +29,8 @@ #define MAX_XBM_LINE_SIZE 255 -gdImagePtr -gdImageCreateFromXbm (FILE * fd) +/* {{{ gdImagePtr gdImageCreateFromXbm */ +gdImagePtr gdImageCreateFromXbm(FILE * fd) { char fline[MAX_XBM_LINE_SIZE]; char iname[MAX_XBM_LINE_SIZE]; @@ -46,7 +46,7 @@ int ch; char h[8]; unsigned int b; - + rewind(fd); while (fgets(fline, MAX_XBM_LINE_SIZE, fd)) { fline[MAX_XBM_LINE_SIZE-1] = '\0'; @@ -59,7 +59,7 @@ } else { type++; } - + if (!strcmp("width", type)) { width = (unsigned int) value; } @@ -96,7 +96,9 @@ return 0; } - im = gdImageCreate(width, height); + if(!(im = gdImageCreate(width, height))) { + return 0; + } gdImageColorAllocate(im, 255, 255, 255); gdImageColorAllocate(im, 0, 0, 0); h[2] = '\0'; @@ -147,7 +149,93 @@ } } - php_gd_error("EOF before image was complete\n"); + php_gd_error("EOF before image was complete"); gdImageDestroy(im); return 0; } +/* }}} */ + +/* {{{ gdCtxPrintf */ +void gdCtxPrintf(gdIOCtx * out, const char *format, ...) +{ + char *buf; + int len; + va_list args; + + va_start(args, format); + len = vspprintf(&buf, 0, format, args); + va_end(args); + out->putBuf(out, buf, len); + efree(buf); +} +/* }}} */ + +/* {{{ gdImageXbmCtx */ +void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out) +{ + int x, y, c, b, sx, sy, p; + char *name, *f; + size_t i, l; + + name = file_name; + if ((f = strrchr(name, '/')) != NULL) name = f+1; + if ((f = strrchr(name, '\\')) != NULL) name = f+1; + name = estrdup(name); + if ((f = strrchr(name, '.')) != NULL && !strcasecmp(f, ".XBM")) *f = '\0'; + if ((l = strlen(name)) == 0) { + efree(name); + name = estrdup("image"); + } else { + for (i=0; i