---- php-4.4.7/ext/gd/libgd/gdft.c 2007-03-10 13:51:07.000000000 +0100
-+++ php-4.4.7.org/ext/gd/libgd/gdft.c 2007-05-30 21:08:19.917066032 +0200
-@@ -750,10 +750,8 @@
- /* find antialised color */
+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 <png.h>
++#endif
++
+ #include "php.h"
++#include "php_ini.h"
+ #include "ext/standard/head.h"
+ #include <math.h>
+ #include "SAPI.h"
+@@ -46,6 +52,9 @@
+ #ifdef PHP_WIN32
+ # include <io.h>
+ # include <fcntl.h>
++#include <windows.h>
++#include <Winuser.h>
++#include <Wingdi.h>
+ #endif
+
+ #if HAVE_LIBGD
+@@ -64,10 +73,20 @@
+ #include <gdfontmb.h> /* 3 Medium bold font */
+ #include <gdfontl.h> /* 4 Large font */
+ #include <gdfontg.h> /* 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 <ft2build.h>
++# include FT_FREETYPE_H
++# else
++# ifdef HAVE_LIBTTF
++# include <freetype.h>
++# 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 <stas@php.net> |
+ +----------------------------------------------------------------------+
+ */
+-#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<type>().
++ */
++
++ 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 <stdio.h>
++
+ #include <math.h>
+ #include <string.h>
+ #include <stdlib.h>
+@@ -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; i<im->sy;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(; x<wx2 && (!pts[y][x] && gdImageGetPixel(im,x, y)==oc); x++) {
+ nc = gdImageTileGet(im,x,y);
+- pts[y][x]=1;
++ pts[y][x] = 1;
+ gdImageSetPixel(im, x, y, nc);
+ }
+ FILL_PUSH(y, l, x-1, dy);
+@@ -2028,13 +2110,15 @@
+ if (x>x2+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; i<im->sy;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;
- tc_key.bgcolor = *pixel;
++ 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; uY<src->sy; 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; uY<src->sy; 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; uY<src->sy; 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; y<src->sy; ++y) {
++ for (x=0; x<src->sx; ++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; y<src->sy; ++y) {
++ for (x=0; x<src->sx; ++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 <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; y<src->sy; ++y) {
++ for (x=0; x<src->sx; ++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; y<src->sy; ++y) {
++ for (x=0; x<src->sx; ++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; y<src->sy; ++y) {
++ for (x=0; x<src->sx; ++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; y<src->sy; y++) {
++ for(x=0; x<src->sx; 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; y<src->sy; y++) {
++ for (x=0; x<src->sx; 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 <unistd.h>
+ #else
+ #include <io.h>
+-#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;
+- 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 <stdio.h>
+ #include <math.h>
+ #include <string.h>
+@@ -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<rv;i++) {
+@@ -321,281 +364,275 @@
+ }
+ return(rv);
+ }
++/* }}} */
+
+ static int
+-GetCode_(gdIOCtx *fd, int code_size, int flag)
++GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
+ {
+- static unsigned char buf[280];
+- static int curbit, lastbit, done, last_byte;
+- int i, j, ret;
+- unsigned char count;
+-
+- if (flag) {
+- curbit = 0;
+- lastbit = 0;
+- done = FALSE;
+- return 0;
+- }
+-
+- if ( (curbit+code_size) >= 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<<MAX_LWZ_BITS); ++i)
+- table[0][i] = table[1][0] = 0;
+-
+- sp = stack;
+-
+- return 0;
+- } else if (fresh) {
+- fresh = FALSE;
+- do {
+- firstcode = oldcode =
+- GetCode(fd, code_size, FALSE);
+- } while (firstcode == clear_code);
+- return firstcode;
+- }
+-
+- if (sp > 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<<MAX_LWZ_BITS); ++i)
+- table[0][i] = table[1][i] = 0;
+- code_size = set_code_size+1;
+- max_code_size = 2*clear_code;
+- max_code = clear_code+2;
+- sp = stack;
+- firstcode = oldcode =
+- GetCode(fd, code_size, FALSE);
+- return firstcode;
+- } else if (code == end_code) {
+- int count;
+- unsigned char buf[260];
+-
+- if (ZeroDataBlock)
+- return -2;
+-
+- while ((count = GetDataBlock(fd, buf)) > 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_LWZ_BITS)) {
+- table[0][code] = oldcode;
+- table[1][code] = firstcode;
+- ++max_code;
+- if ((max_code >= max_code_size) &&
+- (max_code_size < (1<<MAX_LWZ_BITS))) {
+- max_code_size *= 2;
+- ++code_size;
+- }
+- }
+-
+- oldcode = incode;
+-
+- if (sp > 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<<MAX_LWZ_BITS); ++i)
++ sd->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<<MAX_LWZ_BITS); ++i)
++ sd->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<<MAX_LWZ_BITS)) {
++ sd->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_LWZ_BITS))) {
++ sd->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; (i<gdMaxColors); i++) {
+- im->red[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; (i<gdMaxColors); i++) {
++ im->red[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 <sys/types.h>
+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 <stdio.h>
+ #include <stdlib.h>
+ #include <setjmp.h>
+@@ -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);
+ }
}
- }
}
-@@ -771,30 +769,39 @@
+@@ -211,21 +243,21 @@
+ gdFree (row);
+ }
- void gdFontCacheShutdown()
+-gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
++gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning)
{
-+ gdMutexLock(gdFontCacheMutex);
+ 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);
+
+-/*
+
- if (fontCache) {
-- gdMutexLock(gdFontCacheMutex);
- gdCacheDelete(fontCache);
- fontCache = NULL;
-- gdMutexUnlock(gdFontCacheMutex);
-- gdMutexShutdown(gdFontCacheMutex);
- FT_Done_FreeType(library);
++/*
+ * 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;
}
+-
+
-+ gdMutexUnlock(gdFontCacheMutex);
+ 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 gdFreeFontCache()
+-void gdImagePngEx (gdImagePtr im, FILE * outFile, int level)
++void gdImagePngEx (gdImagePtr im, FILE * outFile, int level, int basefilter)
{
- gdFontCacheShutdown();
+ 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.
+ */
+-
+
-+void gdFontCacheMutexSetup()
-+{
-+ gdMutexSetup(gdFontCacheMutex);
-+}
+ /* 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;
+ }
+ }
+-
+
-+void gdFontCacheMutexShutdown()
-+{
-+ gdMutexShutdown(gdFontCacheMutex);
+ 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 <terje@looplab.com>.
+ **
+ ** 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);
+
- int gdFontCacheSetup(void)
++ 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)
{
- if (fontCache) {
- /* Already set up */
- return 0;
+- 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 <stdio.h>
+@@ -15,123 +15,125 @@
+
+ #include <X11/xpm.h>
+
+-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;
}
-- gdMutexSetup(gdFontCacheMutex);
- if (FT_Init_FreeType(&library)) {
-- gdMutexShutdown(gdFontCacheMutex);
- return -1;
+
++ 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");
++ }
}
- fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease);
-@@ -856,15 +863,16 @@
+- }
+- 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 @@
- /***** initialize font library and font cache on first call ******/
+ /* 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);
-+ gdMutexLock(gdFontCacheMutex);
- if (!fontCache) {
- if (gdFontCacheSetup() != 0) {
- gdCacheDelete(tc_cache);
-+ gdMutexUnlock(gdFontCacheMutex);
- return "Failure to initialize font library";
+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 <johan@vandenbrande.com>
+ **
+ ** 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 @@
}
}
- /*****/
-
-- gdMutexLock(gdFontCacheMutex);
- /* get the font (via font cache) */
- fontkey.fontlist = fontlist;
- fontkey.library = &library;
+
+- 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<l; i++) {
++ /* only in C-locale isalnum() would work */
++ if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
++ name[i] = '_';
++ }
++ }
++ }
++
++ gdCtxPrintf(out, "#define %s_width %d\n", name, gdImageSX(image));
++ gdCtxPrintf(out, "#define %s_height %d\n", name, gdImageSY(image));
++ gdCtxPrintf(out, "static unsigned char %s_bits[] = {\n ", name);
++
++ efree(name);
++
++ b = 1;
++ p = 0;
++ c = 0;
++ sx = gdImageSX(image);
++ sy = gdImageSY(image);
++ for (y = 0; y < sy; y++) {
++ for (x = 0; x < sx; x++) {
++ if (gdImageGetPixel(image, x, y) == fg) {
++ c |= b;
++ }
++ if ((b == 128) || (x == sx && y == sy)) {
++ b = 1;
++ if (p) {
++ gdCtxPrintf(out, ", ");
++ if (!(p%12)) {
++ gdCtxPrintf(out, "\n ");
++ p = 12;
++ }
++ }
++ p++;
++ gdCtxPrintf(out, "0x%02X", c);
++ c = 0;
++ } else {
++ b <<= 1;
++ }
++ }
++ }
++ gdCtxPrintf(out, "};\n");
++}
++/* }}} */
++
++/*
++ * 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/php_gd.h php-4.4.8/ext/gd/php_gd.h
+--- php-4.4.8.org/ext/gd/php_gd.h 2007-12-31 08:22:47.000000000 +0100
++++ php-4.4.8/ext/gd/php_gd.h 2008-01-22 22:38:05.897151947 +0100
+@@ -32,7 +32,7 @@
+
+ /* open_basedir and safe_mode checks */
+ #define PHP_GD_CHECK_OPEN_BASEDIR(filename, errormsg) \
+- if (!filename || filename == empty_string || php_check_open_basedir(filename TSRMLS_CC) || \
++ if (!filename || php_check_open_basedir(filename TSRMLS_CC) || \
+ (PG(safe_mode) && !php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR)) \
+ ) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, errormsg); \
+@@ -66,7 +66,9 @@
+ /* gd.c functions */
+ PHP_MINFO_FUNCTION(gd);
+ PHP_MINIT_FUNCTION(gd);
++#if HAVE_LIBT1 || HAVE_GD_FONTMUTEX
+ PHP_MSHUTDOWN_FUNCTION(gd);
++#endif
+ #if HAVE_LIBGD20 && HAVE_GD_STRINGFT
+ PHP_RSHUTDOWN_FUNCTION(gd);
+ #endif
+@@ -112,6 +114,11 @@
+ PHP_FUNCTION(imagecopyresampled);
+ #endif
+
++#ifdef PHP_WIN32
++PHP_FUNCTION(imagegrabwindow);
++PHP_FUNCTION(imagegrabscreen);
++#endif
++
+ #ifdef HAVE_GD_BUNDLED
+ PHP_FUNCTION(imagerotate);
+ PHP_FUNCTION(imageantialias);
+@@ -184,6 +191,8 @@
+ PHP_FUNCTION(imagelayereffect);
+ PHP_FUNCTION(imagecolormatch);
+ PHP_FUNCTION(imagefilter);
++PHP_FUNCTION(imageconvolution);
++PHP_FUNCTION(imagexbm);
+ #endif
+
+ PHP_GD_API int phpi_get_le_gd(void);