- sync to 2.0.23
parent
480330b083
commit
0a3439a3e7
|
@ -7,56 +7,60 @@
|
|||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
/* 2.0.22: can't depend on PNG either */
|
||||
/* 2.0.22: can't depend on PNG either */
|
||||
#ifndef HAVE_LIBPNG
|
||||
fprintf(stderr, "Requires PNG support, gd was compiled without it\n");
|
||||
exit(0);
|
||||
fprintf (stderr, "Requires PNG support, gd was compiled without it\n");
|
||||
exit (0);
|
||||
#else
|
||||
FILE *in = 0;
|
||||
FILE *out;
|
||||
gdImagePtr im;
|
||||
int radius;
|
||||
/* Create an image of text on a circle, with an
|
||||
alpha channel so that we can copy it onto a
|
||||
background */
|
||||
/* TBB: 2.0.18: shouldn't depend on JPEG */
|
||||
FILE *in = 0;
|
||||
FILE *out;
|
||||
gdImagePtr im;
|
||||
int radius;
|
||||
/* Create an image of text on a circle, with an
|
||||
alpha channel so that we can copy it onto a
|
||||
background */
|
||||
/* TBB: 2.0.18: shouldn't depend on JPEG */
|
||||
#ifdef HAVE_LIBJPEG
|
||||
in = fopen("eleanor.jpg", "rb");
|
||||
if (!in) {
|
||||
im = gdImageCreateTrueColor(300, 300);
|
||||
} else {
|
||||
im = gdImageCreateFromJpeg(in);
|
||||
fclose(in);
|
||||
}
|
||||
in = fopen ("eleanor.jpg", "rb");
|
||||
if (!in)
|
||||
{
|
||||
im = gdImageCreateTrueColor (300, 300);
|
||||
}
|
||||
else
|
||||
{
|
||||
im = gdImageCreateFromJpeg (in);
|
||||
fclose (in);
|
||||
}
|
||||
#else
|
||||
im = gdImageCreateTrueColor(300, 300);
|
||||
#endif /* HAVE_LIBJPEG */
|
||||
if (gdImageSX(im) < gdImageSY(im)) {
|
||||
radius = gdImageSX(im) / 2;
|
||||
} else {
|
||||
radius = gdImageSY(im) / 2;
|
||||
}
|
||||
gdImageStringFTCircle(
|
||||
im,
|
||||
gdImageSX(im) / 2,
|
||||
gdImageSY(im) / 2,
|
||||
radius,
|
||||
radius / 2,
|
||||
0.8,
|
||||
"arial",
|
||||
24,
|
||||
"top text",
|
||||
"bottom text",
|
||||
gdTrueColorAlpha(192, 100, 255, 32));
|
||||
out = fopen("gdfx.png", "wb");
|
||||
if (!out) {
|
||||
fprintf(stderr, "Can't create gdfx.png\n");
|
||||
return 1;
|
||||
}
|
||||
gdImagePng(im, out);
|
||||
fclose(out);
|
||||
gdImageDestroy(im);
|
||||
im = gdImageCreateTrueColor (300, 300);
|
||||
#endif /* HAVE_LIBJPEG */
|
||||
if (gdImageSX (im) < gdImageSY (im))
|
||||
{
|
||||
radius = gdImageSX (im) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
radius = gdImageSY (im) / 2;
|
||||
}
|
||||
gdImageStringFTCircle (im,
|
||||
gdImageSX (im) / 2,
|
||||
gdImageSY (im) / 2,
|
||||
radius,
|
||||
radius / 2,
|
||||
0.8,
|
||||
"arial",
|
||||
24,
|
||||
"top text",
|
||||
"bottom text", gdTrueColorAlpha (192, 100, 255, 32));
|
||||
out = fopen ("gdfx.png", "wb");
|
||||
if (!out)
|
||||
{
|
||||
fprintf (stderr, "Can't create gdfx.png\n");
|
||||
return 1;
|
||||
}
|
||||
gdImagePng (im, out);
|
||||
fclose (out);
|
||||
gdImageDestroy (im);
|
||||
#endif /* HAVE_LIBPNG */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.57 for GD 2.0.22.
|
||||
# Generated by GNU Autoconf 2.57 for GD 2.0.23.
|
||||
#
|
||||
# Report bugs to <gd@boutell.com>.
|
||||
#
|
||||
|
@ -427,8 +427,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='GD'
|
||||
PACKAGE_TARNAME='gd'
|
||||
PACKAGE_VERSION='2.0.22'
|
||||
PACKAGE_STRING='GD 2.0.22'
|
||||
PACKAGE_VERSION='2.0.23'
|
||||
PACKAGE_STRING='GD 2.0.23'
|
||||
PACKAGE_BUGREPORT='gd@boutell.com'
|
||||
|
||||
ac_unique_file="gd.c"
|
||||
|
@ -938,7 +938,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures GD 2.0.22 to adapt to many kinds of systems.
|
||||
\`configure' configures GD 2.0.23 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of GD 2.0.22:";;
|
||||
short | recursive ) echo "Configuration of GD 2.0.23:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1111,7 +1111,7 @@ fi
|
|||
test -n "$ac_init_help" && exit 0
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
GD configure 2.0.22
|
||||
GD configure 2.0.23
|
||||
generated by GNU Autoconf 2.57
|
||||
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
|
||||
|
@ -1126,7 +1126,7 @@ cat >&5 <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by GD $as_me 2.0.22, which was
|
||||
It was created by GD $as_me 2.0.23, which was
|
||||
generated by GNU Autoconf 2.57. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -1491,7 +1491,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
|
|||
|
||||
GDLIB_MAJOR=2
|
||||
GDLIB_MINOR=0
|
||||
GDLIB_REVISION=22
|
||||
GDLIB_REVISION=23
|
||||
GDLIBNAME=gd
|
||||
|
||||
|
||||
|
@ -1738,7 +1738,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=gd
|
||||
VERSION=2.0.22
|
||||
VERSION=2.0.23
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -10371,8 +10371,8 @@ echo "$as_me: WARNING: libpng is required - see http://www.libpng.org/pub/png/"
|
|||
fi
|
||||
|
||||
#TBB: png12's png_create_read_struct is just as good
|
||||
|
||||
if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
|
||||
#2.0.23: should be = not ==
|
||||
if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
|
||||
ac_cv_lib_png_png_create_read_struct=yes
|
||||
fi
|
||||
|
||||
|
@ -11683,7 +11683,7 @@ _ASBOX
|
|||
} >&5
|
||||
cat >&5 <<_CSEOF
|
||||
|
||||
This file was extended by GD $as_me 2.0.22, which was
|
||||
This file was extended by GD $as_me 2.0.23, which was
|
||||
generated by GNU Autoconf 2.57. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -11746,7 +11746,7 @@ _ACEOF
|
|||
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
GD config.status 2.0.22
|
||||
GD config.status 2.0.23
|
||||
configured by $0, generated by GNU Autoconf 2.57,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
AC_PREREQ(2.54)
|
||||
|
||||
#HEY! Change BOTH the vesion number and the GDLIB_REVISION setting!
|
||||
AC_INIT([GD], [2.0.22], [gd@boutell.com])
|
||||
AC_INIT([GD], [2.0.23], [gd@boutell.com])
|
||||
AC_CONFIG_SRCDIR([gd.c])
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
|
||||
GDLIB_MAJOR=2
|
||||
GDLIB_MINOR=0
|
||||
GDLIB_REVISION=22
|
||||
GDLIB_REVISION=23
|
||||
GDLIBNAME=gd
|
||||
|
||||
AC_SUBST(GDLIB_MAJOR)
|
||||
|
@ -320,8 +320,8 @@ else
|
|||
fi
|
||||
|
||||
#TBB: png12's png_create_read_struct is just as good
|
||||
|
||||
if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
|
||||
#2.0.23: should be = not ==
|
||||
if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
|
||||
ac_cv_lib_png_png_create_read_struct=yes
|
||||
fi
|
||||
|
||||
|
|
8
src/gd.h
8
src/gd.h
|
@ -36,9 +36,11 @@ extern "C"
|
|||
#endif
|
||||
|
||||
/* some might want to set DEFAULT_FONTPATH from configure in config.h */
|
||||
|
||||
/* 2.0.23: more Type 1 fonts */
|
||||
#ifndef DEFAULT_FONTPATH
|
||||
/* default fontpath for unix systems - whatever happened to standards ! */
|
||||
#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 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:/usr/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/Type1"
|
||||
#endif
|
||||
#ifndef PATHSEPARATOR
|
||||
#define PATHSEPARATOR ":"
|
||||
|
@ -373,11 +375,15 @@ extern "C"
|
|||
gdFTEX_Shift_JIS, or gdFTEX_Big5;
|
||||
when not specified, maps are searched
|
||||
for in the above order. */
|
||||
int hdpi; /* if (flags & gdFTEX_RESOLUTION) */
|
||||
int vdpi; /* if (flags & gdFTEX_RESOLUTION) */
|
||||
|
||||
}
|
||||
gdFTStringExtra, *gdFTStringExtraPtr;
|
||||
|
||||
#define gdFTEX_LINESPACE 1
|
||||
#define gdFTEX_CHARMAP 2
|
||||
#define gdFTEX_RESOLUTION 4
|
||||
|
||||
/* These are NOT flags; set one in 'charmap' if you set the
|
||||
gdFTEX_CHARMAP bit in 'flags'. */
|
||||
|
|
|
@ -486,7 +486,8 @@ gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
|
|||
}
|
||||
|
||||
gdImagePtr
|
||||
gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w, int h)
|
||||
gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w,
|
||||
int h)
|
||||
{
|
||||
gdImagePtr im;
|
||||
gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
|
||||
|
@ -669,7 +670,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
|
|||
if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
|
||||
compBuf,
|
||||
chunkIdx[chunkNum].size,
|
||||
(char*) chunkBuf, &chunkLen, in))
|
||||
(char *) chunkBuf, &chunkLen, in))
|
||||
{
|
||||
printf ("Error reading comproessed chunk\n");
|
||||
goto fail2;
|
||||
|
@ -691,7 +692,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
|
|||
{
|
||||
if (im->trueColor)
|
||||
{
|
||||
if (!gdGetInt ( (int*) &ch, in))
|
||||
if (!gdGetInt ((int *) &ch, in))
|
||||
{
|
||||
ch = 0;
|
||||
/*printf("EOF while reading file\n"); */
|
||||
|
@ -701,7 +702,7 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
|
|||
else
|
||||
{
|
||||
ch = gdGetC (in);
|
||||
if ((int)ch == EOF)
|
||||
if ((int) ch == EOF)
|
||||
{
|
||||
ch = 0;
|
||||
/*printf("EOF while reading file\n"); */
|
||||
|
|
|
@ -72,7 +72,8 @@ static long dynamicTell (struct gdIOCtx *);
|
|||
gdIOCtx *
|
||||
gdNewDynamicCtx (int initialSize, void *data)
|
||||
{
|
||||
gdNewDynamicCtxEx(initialSize, data, 1);
|
||||
/* 2.0.23: Phil Moore: 'return' keyword was missing! */
|
||||
return gdNewDynamicCtxEx (initialSize, data, 1);
|
||||
}
|
||||
|
||||
gdIOCtx *
|
||||
|
@ -197,9 +198,10 @@ dynamicSeek (struct gdIOCtx *ctx, const int pos)
|
|||
if (bytesNeeded > dp->realSize)
|
||||
{
|
||||
/* 2.0.21 */
|
||||
if (!dp->freeOK) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!dp->freeOK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdReallocDynamic (dp, dp->realSize * 2))
|
||||
{
|
||||
dp->dataGood = FALSE;
|
||||
|
@ -372,9 +374,10 @@ appendDynamic (dynamicPtr * dp, const void *src, int size)
|
|||
if (bytesNeeded > dp->realSize)
|
||||
{
|
||||
/* 2.0.21 */
|
||||
if (!dp->freeOK) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!dp->freeOK)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!gdReallocDynamic (dp, bytesNeeded * 2))
|
||||
{
|
||||
dp->dataGood = FALSE;
|
||||
|
@ -435,8 +438,9 @@ static int
|
|||
trimDynamic (dynamicPtr * dp)
|
||||
{
|
||||
/* 2.0.21: we don't reallocate memory we don't own */
|
||||
if (!dp->freeOK) {
|
||||
return TRUE;
|
||||
}
|
||||
if (!dp->freeOK)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return gdReallocDynamic (dp, dp->logicalSize);
|
||||
}
|
||||
|
|
257
src/gd_jpeg.c
257
src/gd_jpeg.c
|
@ -281,7 +281,7 @@ gdImageCreateFromJpegPtr (int size, void *data)
|
|||
|
||||
void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
|
||||
|
||||
static int CMYKToRGB(int c, int m, int y, int k, int inverted);
|
||||
static int CMYKToRGB (int c, int m, int y, int k, int inverted);
|
||||
|
||||
/*
|
||||
* Create a gd-format image from the JPEG-format INFILE. Returns the
|
||||
|
@ -329,14 +329,14 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
jpeg_gdIOCtx_src (&cinfo, infile);
|
||||
|
||||
/* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK
|
||||
files with inverted components. */
|
||||
jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
|
||||
files with inverted components. */
|
||||
jpeg_save_markers (&cinfo, JPEG_APP0 + 14, 256);
|
||||
|
||||
retval = jpeg_read_header (&cinfo, TRUE);
|
||||
if (retval != JPEG_HEADER_OK)
|
||||
fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns"
|
||||
" %d, expected %d\n", retval, JPEG_HEADER_OK);
|
||||
|
||||
|
||||
if (cinfo.image_height > INT_MAX)
|
||||
fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is"
|
||||
" greater than INT_MAX (%d) (and thus greater than"
|
||||
|
@ -355,15 +355,17 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
goto error;
|
||||
}
|
||||
/* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
|
||||
thumbnails but there's no support for fussy adjustment of the
|
||||
assumed properties of inks and paper. */
|
||||
thumbnails but there's no support for fussy adjustment of the
|
||||
assumed properties of inks and paper. */
|
||||
if ((cinfo.jpeg_color_space == JCS_CMYK) ||
|
||||
(cinfo.jpeg_color_space == JCS_YCCK))
|
||||
{
|
||||
cinfo.out_color_space = JCS_CMYK;
|
||||
} else {
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
}
|
||||
(cinfo.jpeg_color_space == JCS_YCCK))
|
||||
{
|
||||
cinfo.out_color_space = JCS_CMYK;
|
||||
}
|
||||
else
|
||||
{
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
}
|
||||
|
||||
if (jpeg_start_decompress (&cinfo) != TRUE)
|
||||
fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress"
|
||||
|
@ -426,41 +428,46 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
#if 0
|
||||
gdImageInterlace (im, cinfo.progressive_mode != 0);
|
||||
#endif
|
||||
if (cinfo.out_color_space == JCS_RGB)
|
||||
{
|
||||
if (cinfo.output_components != 3)
|
||||
if (cinfo.out_color_space == JCS_RGB)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
|
||||
" request resulted in output_components == %d"
|
||||
" (expected 3 for RGB)\n", cinfo.output_components);
|
||||
if (cinfo.output_components != 3)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
|
||||
" request resulted in output_components == %d"
|
||||
" (expected 3 for RGB)\n", cinfo.output_components);
|
||||
goto error;
|
||||
}
|
||||
channels = 3;
|
||||
}
|
||||
else if (cinfo.out_color_space == JCS_CMYK)
|
||||
{
|
||||
jpeg_saved_marker_ptr marker;
|
||||
if (cinfo.output_components != 4)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
|
||||
" request resulted in output_components == %d"
|
||||
" (expected 4 for CMYK)\n", cinfo.output_components);
|
||||
goto error;
|
||||
}
|
||||
channels = 4;
|
||||
marker = cinfo.marker_list;
|
||||
while (marker)
|
||||
{
|
||||
if ((marker->marker == (JPEG_APP0 + 14)) &&
|
||||
(marker->data_length >= 12)
|
||||
&& (!strncmp ((const char *) marker->data, "Adobe", 5)))
|
||||
{
|
||||
inverted = 1;
|
||||
break;
|
||||
}
|
||||
marker = marker->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
|
||||
goto error;
|
||||
}
|
||||
channels = 3;
|
||||
} else if (cinfo.out_color_space == JCS_CMYK) {
|
||||
jpeg_saved_marker_ptr marker;
|
||||
if (cinfo.output_components != 4)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
|
||||
" request resulted in output_components == %d"
|
||||
" (expected 4 for CMYK)\n", cinfo.output_components);
|
||||
goto error;
|
||||
}
|
||||
channels = 4;
|
||||
marker = cinfo.marker_list;
|
||||
while (marker) {
|
||||
if ((marker->marker == (JPEG_APP0 + 14)) &&
|
||||
(marker->data_length >= 12) && (!strncmp((const char *) marker->data,
|
||||
"Adobe", 5)))
|
||||
{
|
||||
inverted = 1;
|
||||
break;
|
||||
}
|
||||
marker = marker->next;
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
|
||||
goto error;
|
||||
}
|
||||
#if BITS_IN_JSAMPLE == 12
|
||||
fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
|
||||
"precision. This is mostly useless, because JPEGs on the web are\n"
|
||||
|
@ -479,47 +486,52 @@ gdImageCreateFromJpegCtx (gdIOCtx * infile)
|
|||
goto error;
|
||||
}
|
||||
rowptr[0] = row;
|
||||
if (cinfo.out_color_space == JCS_CMYK) {
|
||||
for (i = 0; i < cinfo.output_height; i++)
|
||||
{
|
||||
register JSAMPROW currow = row;
|
||||
register int *tpix = im->tpixels[i];
|
||||
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
|
||||
if (nrows != 1)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
|
||||
" returns %u, expected 1\n", nrows);
|
||||
goto error;
|
||||
}
|
||||
for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++)
|
||||
{
|
||||
*tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < cinfo.output_height; i++)
|
||||
{
|
||||
register JSAMPROW currow = row;
|
||||
register int *tpix = im->tpixels[i];
|
||||
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
|
||||
if (nrows != 1)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
|
||||
" returns %u, expected 1\n", nrows);
|
||||
goto error;
|
||||
}
|
||||
for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++)
|
||||
{
|
||||
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cinfo.out_color_space == JCS_CMYK)
|
||||
{
|
||||
for (i = 0; i < cinfo.output_height; i++)
|
||||
{
|
||||
register JSAMPROW currow = row;
|
||||
register int *tpix = im->tpixels[i];
|
||||
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
|
||||
if (nrows != 1)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
|
||||
" returns %u, expected 1\n", nrows);
|
||||
goto error;
|
||||
}
|
||||
for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++)
|
||||
{
|
||||
*tpix =
|
||||
CMYKToRGB (currow[0], currow[1], currow[2], currow[3],
|
||||
inverted);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < cinfo.output_height; i++)
|
||||
{
|
||||
register JSAMPROW currow = row;
|
||||
register int *tpix = im->tpixels[i];
|
||||
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
|
||||
if (nrows != 1)
|
||||
{
|
||||
fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
|
||||
" returns %u, expected 1\n", nrows);
|
||||
goto error;
|
||||
}
|
||||
for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++)
|
||||
{
|
||||
*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jpeg_finish_decompress (&cinfo) != TRUE)
|
||||
fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
|
||||
" reports suspended data source\n");
|
||||
/* Thanks to Truxton Fulton */
|
||||
if(cinfo.err->num_warnings>0)
|
||||
goto error ;
|
||||
if (cinfo.err->num_warnings > 0)
|
||||
goto error;
|
||||
|
||||
jpeg_destroy_decompress (&cinfo);
|
||||
gdFree (row);
|
||||
|
@ -535,50 +547,59 @@ error:
|
|||
}
|
||||
|
||||
/* A very basic conversion approach, TBB */
|
||||
|
||||
static int CMYKToRGB(int c, int m, int y, int k, int inverted)
|
||||
|
||||
static int
|
||||
CMYKToRGB (int c, int m, int y, int k, int inverted)
|
||||
{
|
||||
if (inverted) {
|
||||
c = 255 - c;
|
||||
m = 255 - m;
|
||||
y = 255 - y;
|
||||
k = 255 - k;
|
||||
}
|
||||
return gdTrueColor((255 - c) * (255 - k) / 255,
|
||||
(255 - m) * (255 - k) / 255,
|
||||
(255 - y) * (255 - k) / 255);
|
||||
if (inverted)
|
||||
{
|
||||
c = 255 - c;
|
||||
m = 255 - m;
|
||||
y = 255 - y;
|
||||
k = 255 - k;
|
||||
}
|
||||
return gdTrueColor ((255 - c) * (255 - k) / 255,
|
||||
(255 - m) * (255 - k) / 255,
|
||||
(255 - y) * (255 - k) / 255);
|
||||
#if 0
|
||||
if (inverted) {
|
||||
c = 255 - c;
|
||||
m = 255 - m;
|
||||
y = 255 - y;
|
||||
k = 255 - k;
|
||||
}
|
||||
if (inverted)
|
||||
{
|
||||
c = 255 - c;
|
||||
m = 255 - m;
|
||||
y = 255 - y;
|
||||
k = 255 - k;
|
||||
}
|
||||
c = c * (255 - k) / 255 + k;
|
||||
if (c > 255) {
|
||||
c = 255;
|
||||
}
|
||||
if (c < 0) {
|
||||
c = 0;
|
||||
}
|
||||
if (c > 255)
|
||||
{
|
||||
c = 255;
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
m = m * (255 - k) / 255 + k;
|
||||
if (m > 255) {
|
||||
m = 255;
|
||||
}
|
||||
if (m < 0) {
|
||||
m = 0;
|
||||
}
|
||||
if (m > 255)
|
||||
{
|
||||
m = 255;
|
||||
}
|
||||
if (m < 0)
|
||||
{
|
||||
m = 0;
|
||||
}
|
||||
y = y * (255 - k) / 255 + k;
|
||||
if (y > 255) {
|
||||
y = 255;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
if (y > 255)
|
||||
{
|
||||
y = 255;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
}
|
||||
c = 255 - c;
|
||||
m = 255 - m;
|
||||
y = 255 - y;
|
||||
return gdTrueColor(c, m, y);
|
||||
return gdTrueColor (c, m, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -677,7 +698,7 @@ fill_input_buffer (j_decompress_ptr cinfo)
|
|||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
/* 2.0.12: signed size. Thanks to Geert Jansen */
|
||||
/* 2.0.14: some platforms (mingw-msys) don't have ssize_t. Call
|
||||
an int an int. */
|
||||
an int an int. */
|
||||
int nbytes = 0;
|
||||
memset (src->buffer, 0, INPUT_BUF_SIZE);
|
||||
|
||||
|
|
32
src/gd_png.c
32
src/gd_png.c
|
@ -539,9 +539,9 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
|
|||
fussing with such things. */
|
||||
|
||||
/* Faster if this is uncommented, but may produce larger truecolor files.
|
||||
Wait for gdImagePngCtxEx. */
|
||||
Wait for gdImagePngCtxEx. */
|
||||
#if 0
|
||||
png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
|
||||
png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
|
||||
#endif
|
||||
|
||||
/* 2.0.12: this is finally a parameter */
|
||||
|
@ -718,22 +718,22 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
|
|||
int channels = im->saveAlphaFlag ? 4 : 3;
|
||||
/* Our little 7-bit alpha channel trick costs us a bit here. */
|
||||
png_bytep *row_pointers;
|
||||
unsigned char* pOutputRow;
|
||||
int **ptpixels=im->tpixels;
|
||||
unsigned char *pOutputRow;
|
||||
int **ptpixels = im->tpixels;
|
||||
int *pThisRow;
|
||||
unsigned char a;
|
||||
int thisPixel;
|
||||
png_bytep *prow_pointers;
|
||||
int saveAlphaFlag=im->saveAlphaFlag;
|
||||
int saveAlphaFlag = im->saveAlphaFlag;
|
||||
row_pointers = gdMalloc (sizeof (png_bytep) * height);
|
||||
if (row_pointers == NULL)
|
||||
{
|
||||
fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
|
||||
}
|
||||
prow_pointers=row_pointers;
|
||||
prow_pointers = row_pointers;
|
||||
for (j = 0; j < height; ++j)
|
||||
{
|
||||
if ((*prow_pointers =
|
||||
if ((*prow_pointers =
|
||||
(png_bytep) gdMalloc (width * channels)) == NULL)
|
||||
{
|
||||
fprintf (stderr, "gd-png error: unable to allocate rows\n");
|
||||
|
@ -741,25 +741,25 @@ gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
|
|||
gdFree (row_pointers[i]);
|
||||
return;
|
||||
}
|
||||
pOutputRow=*prow_pointers++;
|
||||
pThisRow=*ptpixels++;
|
||||
pOutputRow = *prow_pointers++;
|
||||
pThisRow = *ptpixels++;
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
thisPixel=*pThisRow++;
|
||||
*pOutputRow++=gdTrueColorGetRed(thisPixel);
|
||||
*pOutputRow++=gdTrueColorGetGreen(thisPixel);
|
||||
*pOutputRow++=gdTrueColorGetBlue(thisPixel);
|
||||
thisPixel = *pThisRow++;
|
||||
*pOutputRow++ = gdTrueColorGetRed (thisPixel);
|
||||
*pOutputRow++ = gdTrueColorGetGreen (thisPixel);
|
||||
*pOutputRow++ = gdTrueColorGetBlue (thisPixel);
|
||||
|
||||
if (saveAlphaFlag)
|
||||
if (saveAlphaFlag)
|
||||
{
|
||||
/* convert the 7-bit alpha channel to an 8-bit alpha channel.
|
||||
We do a little bit-flipping magic, repeating the MSB
|
||||
as the LSB, to ensure that 0 maps to 0 and
|
||||
127 maps to 255. We also have to invert to match
|
||||
PNG's convention in which 255 is opaque. */
|
||||
a = gdTrueColorGetAlpha (thisPixel);
|
||||
a = gdTrueColorGetAlpha (thisPixel);
|
||||
/* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */
|
||||
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
|
||||
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -757,15 +757,18 @@ LOCAL (void)
|
|||
cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total);
|
||||
#else
|
||||
/* 2.0.16: Paul den Dulk found an occasion where total can be 0 */
|
||||
if (count) {
|
||||
im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
|
||||
im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
|
||||
im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
|
||||
} else {
|
||||
im->red[icolor] = 255;
|
||||
im->green[icolor] = 255;
|
||||
im->blue[icolor] = 255;
|
||||
}
|
||||
if (count)
|
||||
{
|
||||
im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
|
||||
im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
|
||||
im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
|
||||
}
|
||||
else
|
||||
{
|
||||
im->red[icolor] = 255;
|
||||
im->green[icolor] = 255;
|
||||
im->blue[icolor] = 255;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
56
src/gddemo.c
56
src/gddemo.c
|
@ -137,36 +137,40 @@ main (void)
|
|||
gdImageLine (im_out, 0, 255, 255, 0, gdStyledBrushed);
|
||||
}
|
||||
/* Text (non-truetype; see gdtestft for a freetype demo) */
|
||||
fonts[0] = gdFontGetTiny();
|
||||
fonts[1] = gdFontGetSmall();
|
||||
fonts[2] = gdFontGetMediumBold();
|
||||
fonts[3] = gdFontGetLarge();
|
||||
fonts[4] = gdFontGetGiant();
|
||||
fonts[0] = gdFontGetTiny ();
|
||||
fonts[1] = gdFontGetSmall ();
|
||||
fonts[2] = gdFontGetMediumBold ();
|
||||
fonts[3] = gdFontGetLarge ();
|
||||
fonts[4] = gdFontGetGiant ();
|
||||
y = 0;
|
||||
for (i = 0; (i <= 4); i++) {
|
||||
gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi", red);
|
||||
y += fonts[i]->h;
|
||||
}
|
||||
for (i = 0; (i <= 4); i++)
|
||||
{
|
||||
gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi",
|
||||
red);
|
||||
y += fonts[i]->h;
|
||||
}
|
||||
y = 0;
|
||||
for (i = 0; (i <= 4); i++) {
|
||||
gdImageStringUp (im_out, fonts[i], 64 + y, 64,
|
||||
(unsigned char *) "hi", red);
|
||||
y += fonts[i]->h;
|
||||
}
|
||||
for (i = 0; (i <= 4); i++)
|
||||
{
|
||||
gdImageStringUp (im_out, fonts[i], 64 + y, 64,
|
||||
(unsigned char *) "hi", red);
|
||||
y += fonts[i]->h;
|
||||
}
|
||||
/* Random antialiased lines; coordinates all over the image,
|
||||
but the output will respect a small clipping rectangle */
|
||||
gdImageSetClip(im_out, 0, gdImageSY(im_out) - 100,
|
||||
100, gdImageSY(im_out));
|
||||
but the output will respect a small clipping rectangle */
|
||||
gdImageSetClip (im_out, 0, gdImageSY (im_out) - 100,
|
||||
100, gdImageSY (im_out));
|
||||
/* Fixed seed for reproducibility of results */
|
||||
srand(100);
|
||||
for (i = 0; (i < 100); i++) {
|
||||
int x1 = rand() % gdImageSX(im_out);
|
||||
int y1 = rand() % gdImageSY(im_out);
|
||||
int x2 = rand() % gdImageSX(im_out);
|
||||
int y2 = rand() % gdImageSY(im_out);
|
||||
gdImageSetAntiAliased(im_out, white);
|
||||
gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
|
||||
}
|
||||
srand (100);
|
||||
for (i = 0; (i < 100); i++)
|
||||
{
|
||||
int x1 = rand () % gdImageSX (im_out);
|
||||
int y1 = rand () % gdImageSY (im_out);
|
||||
int x2 = rand () % gdImageSX (im_out);
|
||||
int y2 = rand () % gdImageSY (im_out);
|
||||
gdImageSetAntiAliased (im_out, white);
|
||||
gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
|
||||
}
|
||||
/* Make output image interlaced (progressive, in the case of JPEG) */
|
||||
gdImageInterlace (im_out, 1);
|
||||
out = fopen ("demoout.png", "wb");
|
||||
|
|
|
@ -4379,9 +4379,10 @@ gdFont gdFontGiantRep = {
|
|||
|
||||
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontGiant = &gdFontGiantRep;
|
||||
|
||||
gdFontPtr gdFontGetGiant(void)
|
||||
gdFontPtr
|
||||
gdFontGetGiant (void)
|
||||
{
|
||||
return gdFontGiant;
|
||||
return gdFontGiant;
|
||||
}
|
||||
|
||||
/* This file has not been truncated. */
|
||||
|
|
|
@ -4636,9 +4636,10 @@ gdFont gdFontLargeRep = {
|
|||
|
||||
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontLarge = &gdFontLargeRep;
|
||||
|
||||
gdFontPtr gdFontGetLarge(void)
|
||||
gdFontPtr
|
||||
gdFontGetLarge (void)
|
||||
{
|
||||
return gdFontLarge;
|
||||
return gdFontLarge;
|
||||
}
|
||||
|
||||
/* This file has not been truncated. */
|
||||
|
|
|
@ -3866,9 +3866,10 @@ gdFont gdFontMediumBoldRep = {
|
|||
|
||||
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
|
||||
|
||||
gdFontPtr gdFontGetMediumBold(void)
|
||||
gdFontPtr
|
||||
gdFontGetMediumBold (void)
|
||||
{
|
||||
return gdFontMediumBold;
|
||||
return gdFontMediumBold;
|
||||
}
|
||||
|
||||
/* This file has not been truncated. */
|
||||
|
|
|
@ -3866,9 +3866,10 @@ gdFont gdFontSmallRep = {
|
|||
|
||||
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontSmall = &gdFontSmallRep;
|
||||
|
||||
gdFontPtr gdFontGetSmall(void)
|
||||
gdFontPtr
|
||||
gdFontGetSmall (void)
|
||||
{
|
||||
return gdFontSmall;
|
||||
return gdFontSmall;
|
||||
}
|
||||
|
||||
/* This file has not been truncated. */
|
||||
|
|
|
@ -2587,9 +2587,10 @@ gdFont gdFontTinyRep = {
|
|||
|
||||
BGD_EXPORT_DATA_IMPL gdFontPtr gdFontTiny = &gdFontTinyRep;
|
||||
|
||||
gdFontPtr gdFontGetTiny(void)
|
||||
gdFontPtr
|
||||
gdFontGetTiny (void)
|
||||
{
|
||||
return gdFontTiny;
|
||||
return gdFontTiny;
|
||||
}
|
||||
|
||||
/* This file has not been truncated. */
|
||||
|
|
247
src/gdft.c
247
src/gdft.c
|
@ -386,8 +386,9 @@ fontFetch (char **error, void *key)
|
|||
* Allocate an oversized buffer that is guaranteed to be
|
||||
* big enough for all paths to be tested.
|
||||
*/
|
||||
/* 2.0.22: Thorben Kundinger: +8 is needed, not +6. */
|
||||
fullname = gdRealloc (fullname,
|
||||
strlen (fontsearchpath) + strlen (name) + 6);
|
||||
strlen (fontsearchpath) + strlen (name) + 8);
|
||||
/* if name is an absolute or relative pathname then test directly */
|
||||
if (strchr (name, '/')
|
||||
|| (name[0] != 0 && name[1] == ':'
|
||||
|
@ -397,8 +398,8 @@ fontFetch (char **error, void *key)
|
|||
if (access (fullname, R_OK) == 0)
|
||||
{
|
||||
font_found++;
|
||||
/* 2.0.16: memory leak fixed, Gustavo Scotti */
|
||||
gdFree(path);
|
||||
/* 2.0.16: memory leak fixed, Gustavo Scotti */
|
||||
gdFree (path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -479,16 +480,20 @@ fontFetch (char **error, void *key)
|
|||
platform = charmap->platform_id;
|
||||
encoding = charmap->encoding_id;
|
||||
|
||||
/* EAM DEBUG - Newer versions of libfree2 make it easier by defining encodings */
|
||||
#if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
|
||||
/* EAM DEBUG - Newer versions of libfree2 make it easier
|
||||
by defining encodings */
|
||||
/* TBB: get this exactly right: 2.1.3 *or better*, all possible cases. */
|
||||
|
||||
#if ((defined(FREETYPE_MAJOR)) && (((FREETYPE_MAJOR == 2) && (((FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 3)) || (FREETYPE_MINOR > 1))) || (FREETYPE_MAJOR > 2)))
|
||||
if (charmap->encoding == FT_ENCODING_MS_SYMBOL
|
||||
|| charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
|
||||
|| charmap->encoding == FT_ENCODING_ADOBE_STANDARD) {
|
||||
a->have_char_map_unicode = 1;
|
||||
found = charmap;
|
||||
a->face->charmap = charmap;
|
||||
return (void *)a;
|
||||
}
|
||||
|| charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
|
||||
|| charmap->encoding == FT_ENCODING_ADOBE_STANDARD)
|
||||
{
|
||||
a->have_char_map_unicode = 1;
|
||||
found = charmap;
|
||||
a->face->charmap = charmap;
|
||||
return (void *) a;
|
||||
}
|
||||
#endif /* Freetype 2.1 or better */
|
||||
/* EAM DEBUG */
|
||||
|
||||
|
@ -649,7 +654,7 @@ gdft_draw_bitmap (gdCache_head_t * tc_cache, gdImage * im, int fg,
|
|||
pcr = pc;
|
||||
y = pen_y + row;
|
||||
/* clip if out of bounds */
|
||||
/* 2.0.16: clipping rectangle, not image 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++)
|
||||
|
@ -690,7 +695,7 @@ gdft_draw_bitmap (gdCache_head_t * tc_cache, gdImage * im, int fg,
|
|||
level = gdAlphaMax - level;
|
||||
x = pen_x + col;
|
||||
/* clip if out of bounds */
|
||||
/* 2.0.16: clip to clipping rectangle, Matt McNabb */
|
||||
/* 2.0.16: clip to clipping rectangle, Matt McNabb */
|
||||
if ((x > im->cx2) || (x < im->cx1))
|
||||
continue;
|
||||
/* get pixel location in gd buffer */
|
||||
|
@ -804,14 +809,14 @@ extern int any2eucjp (char *, char *, unsigned int);
|
|||
/* Fonts can be used across multiple images */
|
||||
|
||||
/* 2.0.16: thread safety (the font cache is shared) */
|
||||
gdMutexDeclare(gdFontCacheMutex);
|
||||
gdMutexDeclare (gdFontCacheMutex);
|
||||
static gdCache_head_t *fontCache;
|
||||
static FT_Library library;
|
||||
|
||||
void
|
||||
gdFreeFontCache ()
|
||||
{
|
||||
gdFontCacheShutdown();
|
||||
gdFontCacheShutdown ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -819,7 +824,7 @@ gdFontCacheShutdown ()
|
|||
{
|
||||
if (fontCache)
|
||||
{
|
||||
gdMutexShutdown(gdFontCacheMutex);
|
||||
gdMutexShutdown (gdFontCacheMutex);
|
||||
gdCacheDelete (fontCache);
|
||||
FT_Done_FreeType (library);
|
||||
/* 2.0.16: Gustavo Scotti: make sure we don't free this twice */
|
||||
|
@ -838,23 +843,25 @@ gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
ptsize, angle, x, y, string, 0);
|
||||
}
|
||||
|
||||
int gdFontCacheSetup(void)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
||||
double ptsize, double angle, int x, int y, char *string,
|
||||
|
@ -880,7 +887,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
|
||||
FT_BitmapGlyph bm;
|
||||
/* 2.0.13: Bob Ostermann: don't force autohint, that's just for testing
|
||||
freetype and doesn't look as good */
|
||||
freetype and doesn't look as good */
|
||||
int render_mode = FT_LOAD_DEFAULT;
|
||||
int m, mfound;
|
||||
/* Now tuneable thanks to Wez Furlong */
|
||||
|
@ -894,6 +901,8 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
* colorindexes. -- 27.06.2001 <krisku@arrak.fi>
|
||||
*/
|
||||
gdCache_head_t *tc_cache;
|
||||
/* Tuneable horizontal and vertical resolution in dots per inch */
|
||||
int hdpi, vdpi;
|
||||
if (strex)
|
||||
{
|
||||
if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE)
|
||||
|
@ -908,13 +917,14 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
/***** initialize font library and font cache on first call ******/
|
||||
if (!fontCache)
|
||||
{
|
||||
if (gdFontCacheSetup() != 0) {
|
||||
gdCacheDelete (tc_cache);
|
||||
return "Failure to initialize font library";
|
||||
}
|
||||
if (gdFontCacheSetup () != 0)
|
||||
{
|
||||
gdCacheDelete (tc_cache);
|
||||
return "Failure to initialize font library";
|
||||
}
|
||||
}
|
||||
/*****/
|
||||
gdMutexLock(gdFontCacheMutex);
|
||||
gdMutexLock (gdFontCacheMutex);
|
||||
/* get the font (via font cache) */
|
||||
fontkey.fontlist = fontlist;
|
||||
fontkey.library = &library;
|
||||
|
@ -922,17 +932,29 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
if (!font)
|
||||
{
|
||||
gdCacheDelete (tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return fontCache->error;
|
||||
}
|
||||
face = font->face; /* shortcut */
|
||||
slot = face->glyph; /* shortcut */
|
||||
|
||||
if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
|
||||
GD_RESOLUTION, GD_RESOLUTION))
|
||||
/*
|
||||
* Added hdpi and vdpi to support images at non-screen resolutions, i.e. 300 dpi TIFF,
|
||||
* or 100h x 50v dpi FAX format. 2.0.23.
|
||||
* 2004/02/27 Mark Shackelford, mark.shackelford@acs-inc.com
|
||||
*/
|
||||
hdpi = GD_RESOLUTION;
|
||||
vdpi = GD_RESOLUTION;
|
||||
if (strex && (strex->flags & gdFTEX_RESOLUTION))
|
||||
{
|
||||
hdpi = strex->hdpi;
|
||||
vdpi = strex->vdpi;
|
||||
}
|
||||
|
||||
if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64), hdpi, vdpi))
|
||||
{
|
||||
gdCacheDelete (tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return "Could not set character size";
|
||||
}
|
||||
|
||||
|
@ -993,7 +1015,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
if (!mfound)
|
||||
{
|
||||
/* No character set found! */
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return "No character set found";
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1057,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
/* newlines */
|
||||
if (ch == '\n')
|
||||
{
|
||||
/* 2.0.13: reset penf.x. Christopher J. Grayce */
|
||||
/* 2.0.13: reset penf.x. Christopher J. Grayce */
|
||||
penf.x = 0;
|
||||
penf.y -= face->size->metrics.height * linespace;
|
||||
penf.y = (penf.y - 32) & -64; /* round to next pixel row */
|
||||
|
@ -1051,79 +1073,80 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
#if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
|
||||
if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
|
||||
{
|
||||
/* I do not know the significance of the constant 0xf000. */
|
||||
/* It was determined by inspection of the character codes */
|
||||
/* stored in Microsoft font symbol.ttf */
|
||||
len = gdTcl_UtfToUniChar (next, &ch);
|
||||
ch |= 0xf000;
|
||||
next += len;
|
||||
} else
|
||||
/* I do not know the significance of the constant 0xf000. */
|
||||
/* It was determined by inspection of the character codes */
|
||||
/* stored in Microsoft font symbol.ttf */
|
||||
len = gdTcl_UtfToUniChar (next, &ch);
|
||||
ch |= 0xf000;
|
||||
next += len;
|
||||
}
|
||||
else
|
||||
#endif /* Freetype 2.1 or better */
|
||||
/* EAM DEBUG */
|
||||
|
||||
switch (m)
|
||||
{
|
||||
case gdFTEX_Unicode:
|
||||
if (font->have_char_map_unicode)
|
||||
{
|
||||
/* use UTF-8 mapping from ASCII */
|
||||
len = gdTcl_UtfToUniChar (next, &ch);
|
||||
next += len;
|
||||
}
|
||||
break;
|
||||
case gdFTEX_Shift_JIS:
|
||||
if (font->have_char_map_sjis)
|
||||
{
|
||||
unsigned char c;
|
||||
int jiscode;
|
||||
c = *next;
|
||||
if (0xA1 <= c && c <= 0xFE)
|
||||
{
|
||||
next++;
|
||||
jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
|
||||
|
||||
ch = (jiscode >> 8) & 0xFF;
|
||||
jiscode &= 0xFF;
|
||||
|
||||
if (ch & 1)
|
||||
jiscode += 0x40 - 0x21;
|
||||
else
|
||||
jiscode += 0x9E - 0x21;
|
||||
|
||||
if (jiscode >= 0x7F)
|
||||
jiscode++;
|
||||
ch = (ch - 0x21) / 2 + 0x81;
|
||||
if (ch >= 0xA0)
|
||||
ch += 0x40;
|
||||
|
||||
ch = (ch << 8) + jiscode;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = c & 0xFF; /* don't extend sign */
|
||||
}
|
||||
next++;
|
||||
}
|
||||
break;
|
||||
case gdFTEX_Big5:
|
||||
switch (m)
|
||||
{
|
||||
/*
|
||||
* 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) & 0xFF; /* don't extend sign */
|
||||
next++;
|
||||
if (ch >= 161 /* first code of JIS-8 pair */
|
||||
&& *next)
|
||||
{ /* don't advance past '\0' */
|
||||
/* TBB: Fix from Kwok Wah On: & 255 needed */
|
||||
ch = (ch * 256) + ((*next) & 255);
|
||||
case gdFTEX_Unicode:
|
||||
if (font->have_char_map_unicode)
|
||||
{
|
||||
/* use UTF-8 mapping from ASCII */
|
||||
len = gdTcl_UtfToUniChar (next, &ch);
|
||||
next += len;
|
||||
}
|
||||
break;
|
||||
case gdFTEX_Shift_JIS:
|
||||
if (font->have_char_map_sjis)
|
||||
{
|
||||
unsigned char c;
|
||||
int jiscode;
|
||||
c = *next;
|
||||
if (0xA1 <= c && c <= 0xFE)
|
||||
{
|
||||
next++;
|
||||
jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
|
||||
|
||||
ch = (jiscode >> 8) & 0xFF;
|
||||
jiscode &= 0xFF;
|
||||
|
||||
if (ch & 1)
|
||||
jiscode += 0x40 - 0x21;
|
||||
else
|
||||
jiscode += 0x9E - 0x21;
|
||||
|
||||
if (jiscode >= 0x7F)
|
||||
jiscode++;
|
||||
ch = (ch - 0x21) / 2 + 0x81;
|
||||
if (ch >= 0xA0)
|
||||
ch += 0x40;
|
||||
|
||||
ch = (ch << 8) + jiscode;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = c & 0xFF; /* don't extend sign */
|
||||
}
|
||||
next++;
|
||||
}
|
||||
break;
|
||||
case gdFTEX_Big5:
|
||||
{
|
||||
/*
|
||||
* 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) & 0xFF; /* don't extend sign */
|
||||
next++;
|
||||
if (ch >= 161 /* first code of JIS-8 pair */
|
||||
&& *next)
|
||||
{ /* don't advance past '\0' */
|
||||
/* TBB: Fix from Kwok Wah On: & 255 needed */
|
||||
ch = (ch * 256) + ((*next) & 255);
|
||||
next++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* set rotation transform */
|
||||
FT_Set_Transform (face, &matrix, NULL);
|
||||
/* Convert character code to glyph index */
|
||||
|
@ -1144,7 +1167,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
if (err)
|
||||
{
|
||||
gdCacheDelete (tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return "Problem loading glyph";
|
||||
}
|
||||
|
||||
|
@ -1188,7 +1211,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
if (err)
|
||||
{
|
||||
gdCacheDelete (tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return "Problem rendering glyph";
|
||||
}
|
||||
}
|
||||
|
@ -1242,7 +1265,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
|
|||
if (tmpstr)
|
||||
gdFree (tmpstr);
|
||||
gdCacheDelete (tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
gdMutexUnlock (gdFontCacheMutex);
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
|
|
780
src/gdfx.c
780
src/gdfx.c
|
@ -20,180 +20,200 @@
|
|||
#define MAXY(x) MAX4(x[1],x[3],x[5],x[7])
|
||||
#define MINY(x) MIN4(x[1],x[3],x[5],x[7])
|
||||
|
||||
char *gdImageStringFTCircle(
|
||||
gdImagePtr im,
|
||||
int cx,
|
||||
int cy,
|
||||
double radius,
|
||||
double textRadius,
|
||||
double fillPortion,
|
||||
char *font,
|
||||
double points,
|
||||
char *top,
|
||||
char *bottom,
|
||||
int fgcolor)
|
||||
char *
|
||||
gdImageStringFTCircle (gdImagePtr im,
|
||||
int cx,
|
||||
int cy,
|
||||
double radius,
|
||||
double textRadius,
|
||||
double fillPortion,
|
||||
char *font,
|
||||
double points, char *top, char *bottom, int fgcolor)
|
||||
{
|
||||
char *err;
|
||||
int w;
|
||||
int brect[8];
|
||||
int sx1, sx2, sy1, sy2, sx, sy;
|
||||
int x, y;
|
||||
int fr, fg, fb, fa;
|
||||
int ox, oy;
|
||||
double prop;
|
||||
gdImagePtr im1;
|
||||
gdImagePtr im2;
|
||||
gdImagePtr im3;
|
||||
/* obtain brect so that we can size the image */
|
||||
err = gdImageStringFT ((gdImagePtr) NULL,
|
||||
&brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
|
||||
if (err)
|
||||
char *err;
|
||||
int w;
|
||||
int brect[8];
|
||||
int sx1, sx2, sy1, sy2, sx, sy;
|
||||
int x, y;
|
||||
int fr, fg, fb, fa;
|
||||
int ox, oy;
|
||||
double prop;
|
||||
gdImagePtr im1;
|
||||
gdImagePtr im2;
|
||||
gdImagePtr im3;
|
||||
/* obtain brect so that we can size the image */
|
||||
err = gdImageStringFT ((gdImagePtr) NULL,
|
||||
&brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
sx1 = MAXX (brect) - MINX (brect) + 6;
|
||||
sy1 = MAXY (brect) - MINY (brect) + 6;
|
||||
err = gdImageStringFT ((gdImagePtr) NULL,
|
||||
&brect[0], 0, font, points * MAG, 0, 0, 0, top);
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
sx2 = MAXX (brect) - MINX (brect) + 6;
|
||||
sy2 = MAXY (brect) - MINY (brect) + 6;
|
||||
/* Pad by 4 pixels to allow for slight errors
|
||||
observed in the bounding box returned by freetype */
|
||||
if (sx1 > sx2)
|
||||
{
|
||||
sx = sx1 * 2 + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sx = sx2 * 2 + 4;
|
||||
}
|
||||
if (sy1 > sy2)
|
||||
{
|
||||
sy = sy1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sy = sy2;
|
||||
}
|
||||
im1 = gdImageCreateTrueColor (sx, sy);
|
||||
if (!im1)
|
||||
{
|
||||
return "could not create first image";
|
||||
}
|
||||
err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
|
||||
font, points * MAG,
|
||||
0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
|
||||
if (err)
|
||||
{
|
||||
gdImageDestroy (im1);
|
||||
return err;
|
||||
}
|
||||
/* We don't know the descent, which would be needed to do this
|
||||
with the angle parameter. Instead, implement a simple
|
||||
flip operation ourselves. */
|
||||
err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
|
||||
font, points * MAG,
|
||||
0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
|
||||
if (err)
|
||||
{
|
||||
gdImageDestroy (im1);
|
||||
return err;
|
||||
}
|
||||
/* Flip in place is tricky, be careful not to double-swap things */
|
||||
if (sy & 1)
|
||||
{
|
||||
for (y = 0; (y <= (sy / 2)); y++)
|
||||
{
|
||||
return err;
|
||||
int xlimit = sx - 2;
|
||||
if (y == (sy / 2))
|
||||
{
|
||||
/* If there is a "middle" row, be careful
|
||||
not to swap twice! */
|
||||
xlimit -= (sx / 4);
|
||||
}
|
||||
for (x = (sx / 2) + 2; (x < xlimit); x++)
|
||||
{
|
||||
int t;
|
||||
int ox = sx - x + (sx / 2) - 1;
|
||||
int oy = sy - y - 1;
|
||||
t = im1->tpixels[oy][ox];
|
||||
im1->tpixels[oy][ox] = im1->tpixels[y][x];
|
||||
im1->tpixels[y][x] = t;
|
||||
}
|
||||
}
|
||||
sx1 = MAXX (brect) - MINX (brect) + 6;
|
||||
sy1 = MAXY (brect) - MINY (brect) + 6;
|
||||
err = gdImageStringFT ((gdImagePtr) NULL,
|
||||
&brect[0], 0, font, points * MAG, 0, 0, 0, top);
|
||||
if (err)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; (y < (sy / 2)); y++)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
sx2 = MAXX (brect) - MINX (brect) + 6;
|
||||
sy2 = MAXY (brect) - MINY (brect) + 6;
|
||||
/* Pad by 4 pixels to allow for slight errors
|
||||
observed in the bounding box returned by freetype */
|
||||
if (sx1 > sx2) {
|
||||
sx = sx1 * 2 + 4;
|
||||
} else {
|
||||
sx = sx2 * 2 + 4;
|
||||
}
|
||||
if (sy1 > sy2) {
|
||||
sy = sy1;
|
||||
} else {
|
||||
sy = sy2;
|
||||
}
|
||||
im1 = gdImageCreateTrueColor(sx, sy);
|
||||
if (!im1) {
|
||||
return "could not create first image";
|
||||
}
|
||||
err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255),
|
||||
font, points * MAG,
|
||||
0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
|
||||
if (err) {
|
||||
gdImageDestroy(im1);
|
||||
return err;
|
||||
}
|
||||
/* We don't know the descent, which would be needed to do this
|
||||
with the angle parameter. Instead, implement a simple
|
||||
flip operation ourselves. */
|
||||
err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255),
|
||||
font, points * MAG,
|
||||
0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
|
||||
if (err) {
|
||||
gdImageDestroy(im1);
|
||||
return err;
|
||||
}
|
||||
/* Flip in place is tricky, be careful not to double-swap things */
|
||||
if (sy & 1) {
|
||||
for (y = 0; (y <= (sy / 2)); y++) {
|
||||
int xlimit = sx - 2;
|
||||
if (y == (sy / 2)) {
|
||||
/* If there is a "middle" row, be careful
|
||||
not to swap twice! */
|
||||
xlimit -= (sx / 4);
|
||||
}
|
||||
for (x = (sx / 2) + 2; (x < xlimit); x++) {
|
||||
int t;
|
||||
int ox = sx - x + (sx / 2) - 1;
|
||||
int oy = sy - y - 1;
|
||||
t = im1->tpixels[oy][ox];
|
||||
im1->tpixels[oy][ox] = im1->tpixels[y][x];
|
||||
im1->tpixels[y][x] = t;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (y = 0; (y < (sy / 2)); y++) {
|
||||
int xlimit = sx - 2;
|
||||
for (x = (sx / 2) + 2; (x < xlimit); x++) {
|
||||
int t;
|
||||
int ox = sx - x + (sx / 2) - 1;
|
||||
int oy = sy - y - 1;
|
||||
t = im1->tpixels[oy][ox];
|
||||
im1->tpixels[oy][ox] = im1->tpixels[y][x];
|
||||
im1->tpixels[y][x] = t;
|
||||
}
|
||||
}
|
||||
int xlimit = sx - 2;
|
||||
for (x = (sx / 2) + 2; (x < xlimit); x++)
|
||||
{
|
||||
int t;
|
||||
int ox = sx - x + (sx / 2) - 1;
|
||||
int oy = sy - y - 1;
|
||||
t = im1->tpixels[oy][ox];
|
||||
im1->tpixels[oy][ox] = im1->tpixels[y][x];
|
||||
im1->tpixels[y][x] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if STEP_PNGS
|
||||
{
|
||||
FILE *out = fopen("gdfx1.png", "wb");
|
||||
gdImagePng(im1, out);
|
||||
fclose(out);
|
||||
}
|
||||
{
|
||||
FILE *out = fopen ("gdfx1.png", "wb");
|
||||
gdImagePng (im1, out);
|
||||
fclose (out);
|
||||
}
|
||||
#endif /* STEP_PNGS */
|
||||
/* Resample taller; the exact proportions of the text depend on the
|
||||
ratio of textRadius to radius, and the value of fillPortion */
|
||||
if (sx > sy * 10) {
|
||||
w = sx;
|
||||
} else {
|
||||
w = sy * 10;
|
||||
}
|
||||
im2 = gdImageCreateTrueColor(w, w);
|
||||
if (!im2) {
|
||||
gdImageDestroy(im1);
|
||||
return "could not create resampled image";
|
||||
}
|
||||
prop = textRadius / radius;
|
||||
gdImageCopyResampled(im2, im1,
|
||||
gdImageSX(im2) * (1.0 - fillPortion) / 4,
|
||||
sy * 10 * (1.0 - prop),
|
||||
0, 0,
|
||||
gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
|
||||
gdImageSX(im1) / 2, gdImageSY(im1));
|
||||
gdImageCopyResampled(im2, im1,
|
||||
(gdImageSX(im2) / 2) +
|
||||
gdImageSX(im2) * (1.0 - fillPortion) / 4,
|
||||
sy * 10 * (1.0 - prop),
|
||||
gdImageSX(im1) / 2, 0,
|
||||
gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
|
||||
gdImageSX(im1) / 2, gdImageSY(im1));
|
||||
/* Resample taller; the exact proportions of the text depend on the
|
||||
ratio of textRadius to radius, and the value of fillPortion */
|
||||
if (sx > sy * 10)
|
||||
{
|
||||
w = sx;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = sy * 10;
|
||||
}
|
||||
im2 = gdImageCreateTrueColor (w, w);
|
||||
if (!im2)
|
||||
{
|
||||
gdImageDestroy (im1);
|
||||
return "could not create resampled image";
|
||||
}
|
||||
prop = textRadius / radius;
|
||||
gdImageCopyResampled (im2, im1,
|
||||
gdImageSX (im2) * (1.0 - fillPortion) / 4,
|
||||
sy * 10 * (1.0 - prop),
|
||||
0, 0,
|
||||
gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
|
||||
gdImageSX (im1) / 2, gdImageSY (im1));
|
||||
gdImageCopyResampled (im2, im1,
|
||||
(gdImageSX (im2) / 2) +
|
||||
gdImageSX (im2) * (1.0 - fillPortion) / 4,
|
||||
sy * 10 * (1.0 - prop),
|
||||
gdImageSX (im1) / 2, 0,
|
||||
gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
|
||||
gdImageSX (im1) / 2, gdImageSY (im1));
|
||||
#if STEP_PNGS
|
||||
{
|
||||
FILE *out = fopen("gdfx2.png", "wb");
|
||||
gdImagePng(im2, out);
|
||||
fclose(out);
|
||||
}
|
||||
{
|
||||
FILE *out = fopen ("gdfx2.png", "wb");
|
||||
gdImagePng (im2, out);
|
||||
fclose (out);
|
||||
}
|
||||
#endif /* STEP_PNGS */
|
||||
/* Ready to produce a circle */
|
||||
im3 = gdImageSquareToCircle(im2, radius);
|
||||
gdImageDestroy(im1);
|
||||
gdImageDestroy(im2);
|
||||
/* Now blend im3 with the destination. Cheat a little. The
|
||||
source (im3) is white-on-black, so we can use the
|
||||
red component as a basis for alpha as long as we're
|
||||
careful to shift off the extra bit and invert
|
||||
(alpha ranges from 0 to 127 where 0 is OPAQUE).
|
||||
Also be careful to allow for an alpha component
|
||||
in the fgcolor parameter itself (gug!) */
|
||||
fr = gdTrueColorGetRed(fgcolor);
|
||||
fg = gdTrueColorGetGreen(fgcolor);
|
||||
fb = gdTrueColorGetBlue(fgcolor);
|
||||
fa = gdTrueColorGetAlpha(fgcolor);
|
||||
ox = cx - (im3->sx / 2);
|
||||
oy = cy - (im3->sy / 2);
|
||||
for (y = 0; (y < im3->sy); y++) {
|
||||
for (x = 0; (x < im3->sx); x++) {
|
||||
int a = gdTrueColorGetRed(im3->tpixels[y][x]) >> 1;
|
||||
a *= (127 - fa);
|
||||
a /= 127;
|
||||
a = 127 - a;
|
||||
gdImageSetPixel(im, x + ox, y + oy,
|
||||
gdTrueColorAlpha(fr, fg, fb, a));
|
||||
}
|
||||
}
|
||||
gdImageDestroy(im3);
|
||||
return 0;
|
||||
/* Ready to produce a circle */
|
||||
im3 = gdImageSquareToCircle (im2, radius);
|
||||
gdImageDestroy (im1);
|
||||
gdImageDestroy (im2);
|
||||
/* Now blend im3 with the destination. Cheat a little. The
|
||||
source (im3) is white-on-black, so we can use the
|
||||
red component as a basis for alpha as long as we're
|
||||
careful to shift off the extra bit and invert
|
||||
(alpha ranges from 0 to 127 where 0 is OPAQUE).
|
||||
Also be careful to allow for an alpha component
|
||||
in the fgcolor parameter itself (gug!) */
|
||||
fr = gdTrueColorGetRed (fgcolor);
|
||||
fg = gdTrueColorGetGreen (fgcolor);
|
||||
fb = gdTrueColorGetBlue (fgcolor);
|
||||
fa = gdTrueColorGetAlpha (fgcolor);
|
||||
ox = cx - (im3->sx / 2);
|
||||
oy = cy - (im3->sy / 2);
|
||||
for (y = 0; (y < im3->sy); y++)
|
||||
{
|
||||
for (x = 0; (x < im3->sx); x++)
|
||||
{
|
||||
int a = gdTrueColorGetRed (im3->tpixels[y][x]) >> 1;
|
||||
a *= (127 - fa);
|
||||
a /= 127;
|
||||
a = 127 - a;
|
||||
gdImageSetPixel (im, x + ox, y + oy,
|
||||
gdTrueColorAlpha (fr, fg, fb, a));
|
||||
}
|
||||
}
|
||||
gdImageDestroy (im3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if GDFX_MAIN
|
||||
|
@ -201,46 +221,51 @@ char *gdImageStringFTCircle(
|
|||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
gdImagePtr im;
|
||||
int radius;
|
||||
/* Create an image of text on a circle, with an
|
||||
alpha channel so that we can copy it onto a
|
||||
background */
|
||||
in = fopen("eleanor.jpg", "rb");
|
||||
if (!in) {
|
||||
im = gdImageCreateTrueColor(300, 300);
|
||||
} else {
|
||||
im = gdImageCreateFromJpeg(in);
|
||||
fclose(in);
|
||||
}
|
||||
if (gdImageSX(im) < gdImageSY(im)) {
|
||||
radius = gdImageSX(im) / 2;
|
||||
} else {
|
||||
radius = gdImageSY(im) / 2;
|
||||
}
|
||||
gdStringFTCircle(
|
||||
im,
|
||||
gdImageSX(im) / 2,
|
||||
gdImageSY(im) / 2,
|
||||
radius,
|
||||
radius / 2,
|
||||
0.8,
|
||||
"arial",
|
||||
24,
|
||||
"top text",
|
||||
"bottom text",
|
||||
gdTrueColorAlpha(240, 240, 255, 32));
|
||||
out = fopen("gdfx.png", "wb");
|
||||
if (!out) {
|
||||
fprintf(stderr, "Can't create gdfx.png\n");
|
||||
return 1;
|
||||
}
|
||||
gdImagePng(im, out);
|
||||
fclose(out);
|
||||
gdImageDestroy(im);
|
||||
return 0;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
gdImagePtr im;
|
||||
int radius;
|
||||
/* Create an image of text on a circle, with an
|
||||
alpha channel so that we can copy it onto a
|
||||
background */
|
||||
in = fopen ("eleanor.jpg", "rb");
|
||||
if (!in)
|
||||
{
|
||||
im = gdImageCreateTrueColor (300, 300);
|
||||
}
|
||||
else
|
||||
{
|
||||
im = gdImageCreateFromJpeg (in);
|
||||
fclose (in);
|
||||
}
|
||||
if (gdImageSX (im) < gdImageSY (im))
|
||||
{
|
||||
radius = gdImageSX (im) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
radius = gdImageSY (im) / 2;
|
||||
}
|
||||
gdStringFTCircle (im,
|
||||
gdImageSX (im) / 2,
|
||||
gdImageSY (im) / 2,
|
||||
radius,
|
||||
radius / 2,
|
||||
0.8,
|
||||
"arial",
|
||||
24,
|
||||
"top text",
|
||||
"bottom text", gdTrueColorAlpha (240, 240, 255, 32));
|
||||
out = fopen ("gdfx.png", "wb");
|
||||
if (!out)
|
||||
{
|
||||
fprintf (stderr, "Can't create gdfx.png\n");
|
||||
return 1;
|
||||
}
|
||||
gdImagePng (im, out);
|
||||
fclose (out);
|
||||
gdImageDestroy (im);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* GDFX_MAIN */
|
||||
|
@ -250,70 +275,90 @@ main (int argc, char *argv[])
|
|||
#define SUPERBITS1 1
|
||||
#define SUPERBITS2 2
|
||||
|
||||
gdImagePtr gdImageSquareToCircle(gdImagePtr im, int radius)
|
||||
gdImagePtr
|
||||
gdImageSquareToCircle (gdImagePtr im, int radius)
|
||||
{
|
||||
int x, y;
|
||||
double c;
|
||||
gdImagePtr im2;
|
||||
if (im->sx != im->sy) {
|
||||
/* Source image must be square */
|
||||
return 0;
|
||||
int x, y;
|
||||
double c;
|
||||
gdImagePtr im2;
|
||||
if (im->sx != im->sy)
|
||||
{
|
||||
/* Source image must be square */
|
||||
return 0;
|
||||
}
|
||||
im2 = gdImageCreateTrueColor (radius * 2, radius * 2);
|
||||
/* Supersampling for a nicer result */
|
||||
c = (im2->sx / 2) * SUPER;
|
||||
for (y = 0; (y < im2->sy * SUPER); y++)
|
||||
{
|
||||
for (x = 0; (x < im2->sx * SUPER); x++)
|
||||
{
|
||||
double rho = sqrt ((x - c) * (x - c) + (y - c) * (y - c));
|
||||
int pix;
|
||||
int cpix;
|
||||
double theta;
|
||||
double ox;
|
||||
double oy;
|
||||
int red, green, blue, alpha;
|
||||
if (rho > c)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
theta = atan2 (x - c, y - c) + PI / 2;
|
||||
if (theta < 0)
|
||||
{
|
||||
theta += 2 * PI;
|
||||
}
|
||||
/* Undo supersampling */
|
||||
oy = (rho * im->sx) / (im2->sx * SUPER / 2);
|
||||
ox = theta * im->sx / (3.141592653 * 2);
|
||||
pix = gdImageGetPixel (im, ox, oy);
|
||||
cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
|
||||
red =
|
||||
(gdImageRed (im, pix) >> SUPERBITS2) + gdTrueColorGetRed (cpix);
|
||||
green =
|
||||
(gdImageGreen (im, pix) >> SUPERBITS2) +
|
||||
gdTrueColorGetGreen (cpix);
|
||||
blue =
|
||||
(gdImageBlue (im, pix) >> SUPERBITS2) + gdTrueColorGetBlue (cpix);
|
||||
alpha =
|
||||
(gdImageAlpha (im, pix) >> SUPERBITS2) +
|
||||
gdTrueColorGetAlpha (cpix);
|
||||
im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] =
|
||||
gdTrueColorAlpha (red, green, blue, alpha);
|
||||
}
|
||||
im2 = gdImageCreateTrueColor(radius * 2, radius * 2);
|
||||
/* Supersampling for a nicer result */
|
||||
c = (im2->sx / 2) * SUPER;
|
||||
for (y = 0; (y < im2->sy * SUPER); y++) {
|
||||
for (x = 0; (x < im2->sx * SUPER); x++) {
|
||||
double rho = sqrt((x - c) * (x - c) +
|
||||
(y - c) * (y - c));
|
||||
int pix;
|
||||
int cpix;
|
||||
double theta;
|
||||
double ox;
|
||||
double oy;
|
||||
int red, green, blue, alpha;
|
||||
if (rho > c) {
|
||||
continue;
|
||||
}
|
||||
theta = atan2(x - c, y - c) + PI / 2;
|
||||
if (theta < 0) {
|
||||
theta += 2 * PI;
|
||||
}
|
||||
/* Undo supersampling */
|
||||
oy = (rho * im->sx) / (im2->sx * SUPER / 2);
|
||||
ox = theta * im->sx / (3.141592653 * 2);
|
||||
pix = gdImageGetPixel(im, ox, oy);
|
||||
cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
|
||||
red = (gdImageRed(im, pix) >> SUPERBITS2) + gdTrueColorGetRed(cpix);
|
||||
green = (gdImageGreen(im, pix) >> SUPERBITS2) + gdTrueColorGetGreen(cpix);
|
||||
blue = (gdImageBlue(im, pix) >> SUPERBITS2) + gdTrueColorGetBlue(cpix);
|
||||
alpha = (gdImageAlpha(im, pix) >> SUPERBITS2) + gdTrueColorGetAlpha(cpix);
|
||||
im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] = gdTrueColorAlpha(
|
||||
red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
/* Restore full dynamic range, 0-63 yields 0-252. Replication of
|
||||
first 2 bits in last 2 bits has the desired effect. Note
|
||||
slightly different arithmetic for alpha which is 7-bit.
|
||||
NOTE: only correct for SUPER == 2 */
|
||||
for (y = 0; (y < im2->sy); y++) {
|
||||
for (x = 0; (x < im2->sx); x++) {
|
||||
/* Copy first 2 bits to last 2 bits, matching the
|
||||
dynamic range of the original cheaply */
|
||||
int cpix = im2->tpixels[y][x];
|
||||
}
|
||||
/* Restore full dynamic range, 0-63 yields 0-252. Replication of
|
||||
first 2 bits in last 2 bits has the desired effect. Note
|
||||
slightly different arithmetic for alpha which is 7-bit.
|
||||
NOTE: only correct for SUPER == 2 */
|
||||
for (y = 0; (y < im2->sy); y++)
|
||||
{
|
||||
for (x = 0; (x < im2->sx); x++)
|
||||
{
|
||||
/* Copy first 2 bits to last 2 bits, matching the
|
||||
dynamic range of the original cheaply */
|
||||
int cpix = im2->tpixels[y][x];
|
||||
|
||||
im2->tpixels[y][x] = gdTrueColorAlpha(
|
||||
(gdTrueColorGetRed(cpix) & 0xFC) +
|
||||
((gdTrueColorGetRed(cpix) & 0xC0) >> 6),
|
||||
(gdTrueColorGetGreen(cpix) & 0xFC) +
|
||||
((gdTrueColorGetGreen(cpix) & 0xC0) >> 6),
|
||||
(gdTrueColorGetBlue(cpix) & 0xFC) +
|
||||
((gdTrueColorGetBlue(cpix) & 0xC0) >> 6),
|
||||
(gdTrueColorGetAlpha(cpix) & 0x7C) +
|
||||
((gdTrueColorGetAlpha(cpix) & 0x60) >> 6));
|
||||
}
|
||||
}
|
||||
return im2;
|
||||
im2->tpixels[y][x] = gdTrueColorAlpha ((gdTrueColorGetRed (cpix) &
|
||||
0xFC) +
|
||||
((gdTrueColorGetRed (cpix) &
|
||||
0xC0) >> 6),
|
||||
(gdTrueColorGetGreen (cpix) &
|
||||
0xFC) +
|
||||
((gdTrueColorGetGreen (cpix)
|
||||
& 0xC0) >> 6),
|
||||
(gdTrueColorGetBlue (cpix) &
|
||||
0xFC) +
|
||||
((gdTrueColorGetBlue (cpix) &
|
||||
0xC0) >> 6),
|
||||
(gdTrueColorGetAlpha (cpix) &
|
||||
0x7C) +
|
||||
((gdTrueColorGetAlpha (cpix)
|
||||
& 0x60) >> 6));
|
||||
}
|
||||
}
|
||||
return im2;
|
||||
}
|
||||
|
||||
/* 2.0.16: Called by gdImageSharpen to avoid excessive code repetition
|
||||
|
@ -323,40 +368,47 @@ gdImagePtr gdImageSquareToCircle(gdImagePtr im, int radius)
|
|||
returns new colour for centre pixel
|
||||
*/
|
||||
|
||||
int gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float
|
||||
outer_coeff) {
|
||||
float red, green, blue, alpha;
|
||||
int
|
||||
gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float
|
||||
outer_coeff)
|
||||
{
|
||||
float red, green, blue, alpha;
|
||||
|
||||
red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff *
|
||||
(gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
|
||||
green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff *
|
||||
(gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
|
||||
blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff *
|
||||
(gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
|
||||
alpha = gdTrueColorGetAlpha (c);
|
||||
red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff *
|
||||
(gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
|
||||
green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff *
|
||||
(gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
|
||||
blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff *
|
||||
(gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
|
||||
alpha = gdTrueColorGetAlpha (c);
|
||||
|
||||
/* Clamping, as can overshoot bounds in either direction */
|
||||
if (red > 255.0f) {
|
||||
red = 255.0f;
|
||||
}
|
||||
if (green > 255.0f) {
|
||||
green = 255.0f;
|
||||
}
|
||||
if (blue > 255.0f) {
|
||||
blue = 255.0f;
|
||||
}
|
||||
if (red < 0.0f) {
|
||||
red = 0.0f;
|
||||
}
|
||||
if (green < 0.0f) {
|
||||
green = 0.0f;
|
||||
}
|
||||
if (blue < 0.0f) {
|
||||
blue = 0.0f;
|
||||
}
|
||||
/* Clamping, as can overshoot bounds in either direction */
|
||||
if (red > 255.0f)
|
||||
{
|
||||
red = 255.0f;
|
||||
}
|
||||
if (green > 255.0f)
|
||||
{
|
||||
green = 255.0f;
|
||||
}
|
||||
if (blue > 255.0f)
|
||||
{
|
||||
blue = 255.0f;
|
||||
}
|
||||
if (red < 0.0f)
|
||||
{
|
||||
red = 0.0f;
|
||||
}
|
||||
if (green < 0.0f)
|
||||
{
|
||||
green = 0.0f;
|
||||
}
|
||||
if (blue < 0.0f)
|
||||
{
|
||||
blue = 0.0f;
|
||||
}
|
||||
|
||||
return gdTrueColorAlpha ((int) red, (int) green, (int) blue,
|
||||
(int) alpha);
|
||||
return gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -370,84 +422,88 @@ outer_coeff) {
|
|||
* Silently does nothing for pct<0, as not a useful blurring function
|
||||
* Leaves transparency/alpha-channel untouched
|
||||
*/
|
||||
void gdImageSharpen (gdImagePtr im, int pct)
|
||||
void
|
||||
gdImageSharpen (gdImagePtr im, int pct)
|
||||
{
|
||||
int x, y;
|
||||
int sx, sy;
|
||||
float inner_coeff, outer_coeff;
|
||||
int x, y;
|
||||
int sx, sy;
|
||||
float inner_coeff, outer_coeff;
|
||||
|
||||
sx = im->sx;
|
||||
sy = im->sy;
|
||||
sx = im->sx;
|
||||
sy = im->sy;
|
||||
|
||||
/* Must sum to 1 to avoid overall change in brightness.
|
||||
* Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
|
||||
* resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
|
||||
* which gives noticeable, but not excessive, sharpening
|
||||
*/
|
||||
/* Must sum to 1 to avoid overall change in brightness.
|
||||
* Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
|
||||
* resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
|
||||
* which gives noticeable, but not excessive, sharpening
|
||||
*/
|
||||
|
||||
outer_coeff = -pct / 400.0;
|
||||
inner_coeff = 1 - 2 * outer_coeff;
|
||||
outer_coeff = -pct / 400.0;
|
||||
inner_coeff = 1 - 2 * outer_coeff;
|
||||
|
||||
/* Don't try to do anything with non-truecolor images, as
|
||||
pointless,
|
||||
* nor for pct<=0, as small kernel size leads to nasty
|
||||
artefacts when blurring
|
||||
*/
|
||||
if ( (im->trueColor) && (pct>0) ) {
|
||||
/* Don't try to do anything with non-truecolor images, as
|
||||
pointless,
|
||||
* nor for pct<=0, as small kernel size leads to nasty
|
||||
artefacts when blurring
|
||||
*/
|
||||
if ((im->trueColor) && (pct > 0))
|
||||
{
|
||||
|
||||
/* First pass, 1-D convolution column-wise */
|
||||
for (x = 0; x < sx; x++) {
|
||||
/* First pass, 1-D convolution column-wise */
|
||||
for (x = 0; x < sx; x++)
|
||||
{
|
||||
|
||||
/* pc is colour of previous pixel; c of the
|
||||
current pixel and nc of the next */
|
||||
int pc, c, nc;
|
||||
/* pc is colour of previous pixel; c of the
|
||||
current pixel and nc of the next */
|
||||
int pc, c, nc;
|
||||
|
||||
/* Replicate edge pixel at image boundary */
|
||||
pc = gdImageGetPixel (im, x, 0);
|
||||
/* Replicate edge pixel at image boundary */
|
||||
pc = gdImageGetPixel (im, x, 0);
|
||||
|
||||
/* Stop looping before last pixel to avoid
|
||||
conditional within loop */
|
||||
for (y = 0; y < sy-1; y++) {
|
||||
/* Stop looping before last pixel to avoid
|
||||
conditional within loop */
|
||||
for (y = 0; y < sy - 1; y++)
|
||||
{
|
||||
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
|
||||
nc = gdImageGetTrueColorPixel (im, x,
|
||||
y+1);
|
||||
nc = gdImageGetTrueColorPixel (im, x, y + 1);
|
||||
|
||||
/* Update centre pixel to new colour */
|
||||
gdImageSetPixel(im, x, y,
|
||||
gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
|
||||
/* Update centre pixel to new colour */
|
||||
gdImageSetPixel (im, x, y,
|
||||
gdImageSubSharpen (pc, c, nc, inner_coeff,
|
||||
outer_coeff));
|
||||
|
||||
/* Save original colour of current
|
||||
pixel for next time round */
|
||||
pc = c;
|
||||
}
|
||||
/* Save original colour of current
|
||||
pixel for next time round */
|
||||
pc = c;
|
||||
}
|
||||
|
||||
/* Deal with last pixel, replicating current
|
||||
pixel at image boundary */
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
gdImageSetPixel(im, x, y, gdImageSubSharpen
|
||||
(pc, c, c, inner_coeff, outer_coeff) );
|
||||
}
|
||||
/* Deal with last pixel, replicating current
|
||||
pixel at image boundary */
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
gdImageSetPixel (im, x, y, gdImageSubSharpen
|
||||
(pc, c, c, inner_coeff, outer_coeff));
|
||||
}
|
||||
|
||||
/* Second pass, 1-D convolution row-wise */
|
||||
for (y = 0; y < sy; y++) {
|
||||
int pc, c, nc;
|
||||
pc = gdImageGetPixel (im, 0, y);
|
||||
for (x = 0; x < sx-1; x++) {
|
||||
int c, nc;
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
nc = gdImageGetTrueColorPixel (im, x+1,
|
||||
y);
|
||||
gdImageSetPixel(im, x, y,
|
||||
gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
|
||||
pc = c;
|
||||
}
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
gdImageSetPixel(im, x, y, gdImageSubSharpen
|
||||
(pc, c, c, inner_coeff, outer_coeff) );
|
||||
}
|
||||
}
|
||||
/* Second pass, 1-D convolution row-wise */
|
||||
for (y = 0; y < sy; y++)
|
||||
{
|
||||
int pc, c, nc;
|
||||
pc = gdImageGetPixel (im, 0, y);
|
||||
for (x = 0; x < sx - 1; x++)
|
||||
{
|
||||
int c, nc;
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
nc = gdImageGetTrueColorPixel (im, x + 1, y);
|
||||
gdImageSetPixel (im, x, y,
|
||||
gdImageSubSharpen (pc, c, nc, inner_coeff,
|
||||
outer_coeff));
|
||||
pc = c;
|
||||
}
|
||||
c = gdImageGetPixel (im, x, y);
|
||||
gdImageSetPixel (im, x, y, gdImageSubSharpen
|
||||
(pc, c, c, inner_coeff, outer_coeff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
649
src/index.html
649
src/index.html
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue