diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2016-09-20 01:38:28 +0200 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2016-09-20 01:38:28 +0200 |
commit | dc59aafa77884db61607d908f46b3a18039693b5 (patch) | |
tree | 7a7a622e00da6afaa0f61e310518731f6c7377e0 /ext/gd | |
parent | be30c34fb8fd67998fdc27fca21b6ed008552e2a (diff) | |
parent | 474428943f0407052c72180e5b45a3f9259599c3 (diff) | |
download | php-git-dc59aafa77884db61607d908f46b3a18039693b5.tar.gz |
Merge branch 'PHP-7.1'
Diffstat (limited to 'ext/gd')
-rw-r--r-- | ext/gd/gd.c | 2 | ||||
-rw-r--r-- | ext/gd/libgd/gdft.c | 127 | ||||
-rw-r--r-- | ext/gd/tests/bug43073_1.phpt | 34 | ||||
-rw-r--r-- | ext/gd/tests/bug48732.phpt | 2 | ||||
-rw-r--r-- | ext/gd/tests/bug48801_1.phpt | 8 | ||||
-rw-r--r-- | ext/gd/tests/bug53504.phpt | 101 |
6 files changed, 191 insertions, 83 deletions
diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 6cfcce8c4c..fe81da1b21 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3843,7 +3843,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int { zval *IM, *EXT = NULL; gdImagePtr im=NULL; - zend_long col = -1, x = -1, y = -1; + zend_long col = -1, x = 0, y = 0; size_t str_len, fontname_len; int i, brect[8]; double ptsize, angle; diff --git a/ext/gd/libgd/gdft.c b/ext/gd/libgd/gdft.c index f91fcf738c..d68703aa32 100644 --- a/ext/gd/libgd/gdft.c +++ b/ext/gd/libgd/gdft.c @@ -756,9 +756,9 @@ static char * gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, } static int -gdroundupdown (FT_F26Dot6 v1, int updown) +gdroundupdown (FT_F26Dot6 v1, int roundup) { - return (!updown) ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6) : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6); + return (!roundup) ? v1 >> 6 : (v1 + 63) >> 6; } void gdFontCacheShutdown() @@ -828,8 +828,6 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi double cos_a = cos (angle); int len, i = 0, ch; int x1 = 0, y1 = 0; - int xb = x, yb = y; - int yd = 0; font_t *font; fontkey_t fontkey; char *next; @@ -990,9 +988,6 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi penf.y = (penf.y - 32) & -64; /* round to next pixel row */ x1 = (int)(- penf.y * sin_a + 32) / 64; y1 = (int)(- penf.y * cos_a + 32) / 64; - xb = x + x1; - yb = y + y1; - yd = 0; pen.x = pen.y = 0; previous = 0; /* clear kerning flag */ continue; @@ -1082,31 +1077,32 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi /* retrieve kerning distance and move pen position */ if (use_kerning && previous && glyph_index) { FT_Get_Kerning(face, previous, glyph_index, ft_kerning_default, &delta); - pen.x += delta.x; + pen.x += (int)(delta.x * cos_a); + pen.y -= (int)(delta.x * sin_a); penf.x += delta.x; } - /* load glyph image into the slot (erase previous one) */ - if (FT_Load_Glyph(face, glyph_index, render_mode)) { - if (tmpstr) { - gdFree(tmpstr); + if (brect) { /* only if need brect */ + /* load glyph image into the slot (erase previous one) */ + if (FT_Load_Glyph(face, glyph_index, render_mode | FT_LOAD_IGNORE_TRANSFORM)) { + if (tmpstr) { + gdFree(tmpstr); + } + gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); + return "Problem loading glyph"; } - gdCacheDelete(tc_cache); - gdMutexUnlock(gdFontCacheMutex); - return "Problem loading glyph"; - } - /* transform glyph image */ - if (FT_Get_Glyph(slot, &image)) { - if (tmpstr) { - gdFree(tmpstr); + /* transform glyph image */ + if (FT_Get_Glyph(slot, &image)) { + if (tmpstr) { + gdFree(tmpstr); + } + gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); + return "Problem loading glyph"; } - gdCacheDelete(tc_cache); - gdMutexUnlock(gdFontCacheMutex); - return "Problem loading glyph"; - } - if (brect) { /* only if need brect */ FT_Glyph_Get_CBox(image, ft_glyph_bbox_gridfit, &glyph_bbox); glyph_bbox.xMin += penf.x; glyph_bbox.yMin += penf.y; @@ -1116,17 +1112,11 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi glyph_bbox.xMax += slot->metrics.horiAdvance; } if (!i) { /* if first character, init BB corner values */ - yd = slot->metrics.height - slot->metrics.horiBearingY; bbox.xMin = glyph_bbox.xMin; bbox.yMin = glyph_bbox.yMin; bbox.xMax = glyph_bbox.xMax; bbox.yMax = glyph_bbox.yMax; } else { - FT_Pos desc; - - if ( (desc = (slot->metrics.height - slot->metrics.horiBearingY)) > yd) { - yd = desc; - } if (bbox.xMin > glyph_bbox.xMin) { bbox.xMin = glyph_bbox.xMin; } @@ -1143,7 +1133,35 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi i++; } + /* increment (unrotated) pen position */ + penf.x += slot->metrics.horiAdvance; + if (render) { + if (!brect || angle != 0) { + /* reload the rotated glyph (for bbox we needed FT_LOAD_IGNORE_TRANSFORM - bbox is rotated later) */ + FT_Done_Glyph(image); + + /* load glyph image into the slot (erase previous one) */ + if (FT_Load_Glyph(face, glyph_index, render_mode)) { + if (tmpstr) { + gdFree(tmpstr); + } + gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); + return "Problem loading glyph"; + } + + /* transform glyph image */ + if (FT_Get_Glyph(slot, &image)) { + if (tmpstr) { + gdFree(tmpstr); + } + gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); + return "Problem loading glyph"; + } + } + if (image->format != ft_glyph_format_bitmap && FT_Glyph_To_Bitmap(&image, ft_render_mode_normal, 0, 1)) { FT_Done_Glyph(image); if (tmpstr) { @@ -1166,8 +1184,6 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi pen.x += image->advance.x >> 10; pen.y -= image->advance.y >> 10; - penf.x += slot->metrics.horiAdvance; - FT_Done_Glyph(image); } @@ -1176,36 +1192,25 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi double d1 = sin (angle + 0.78539816339744830962); double d2 = sin (angle - 0.78539816339744830962); - /* make the center of rotation at (0, 0) */ - FT_BBox normbox; - - normbox.xMin = 0; - normbox.yMin = 0; - normbox.xMax = bbox.xMax - bbox.xMin; - normbox.yMax = bbox.yMax - bbox.yMin; - - brect[0] = brect[2] = brect[4] = brect[6] = (int) (yd * sin_a); - brect[1] = brect[3] = brect[5] = brect[7] = (int)(- yd * cos_a); - - /* rotate bounding rectangle */ - brect[0] += (int) (normbox.xMin * cos_a - normbox.yMin * sin_a); - brect[1] += (int) (normbox.xMin * sin_a + normbox.yMin * cos_a); - brect[2] += (int) (normbox.xMax * cos_a - normbox.yMin * sin_a); - brect[3] += (int) (normbox.xMax * sin_a + normbox.yMin * cos_a); - brect[4] += (int) (normbox.xMax * cos_a - normbox.yMax * sin_a); - brect[5] += (int) (normbox.xMax * sin_a + normbox.yMax * cos_a); - brect[6] += (int) (normbox.xMin * cos_a - normbox.yMax * sin_a); - brect[7] += (int) (normbox.xMin * sin_a + normbox.yMax * cos_a); + /* rotate bounding rectangle (at 0, 0) */ + brect[0] = (int) (bbox.xMin * cos_a - bbox.yMin * sin_a); + brect[1] = (int) (bbox.xMin * sin_a + bbox.yMin * cos_a); + brect[2] = (int) (bbox.xMax * cos_a - bbox.yMin * sin_a); + brect[3] = (int) (bbox.xMax * sin_a + bbox.yMin * cos_a); + brect[4] = (int) (bbox.xMax * cos_a - bbox.yMax * sin_a); + brect[5] = (int) (bbox.xMax * sin_a + bbox.yMax * cos_a); + brect[6] = (int) (bbox.xMin * cos_a - bbox.yMax * sin_a); + brect[7] = (int) (bbox.xMin * sin_a + bbox.yMax * cos_a); /* scale, round and offset brect */ - brect[0] = xb + gdroundupdown(brect[0], d2 > 0); - brect[1] = yb - gdroundupdown(brect[1], d1 < 0); - brect[2] = xb + gdroundupdown(brect[2], d1 > 0); - brect[3] = yb - gdroundupdown(brect[3], d2 > 0); - brect[4] = xb + gdroundupdown(brect[4], d2 < 0); - brect[5] = yb - gdroundupdown(brect[5], d1 > 0); - brect[6] = xb + gdroundupdown(brect[6], d1 < 0); - brect[7] = yb - gdroundupdown(brect[7], d2 < 0); + brect[0] = x + gdroundupdown(brect[0], d2 > 0); + brect[1] = y - gdroundupdown(brect[1], d1 < 0); + brect[2] = x + gdroundupdown(brect[2], d1 > 0); + brect[3] = y - gdroundupdown(brect[3], d2 > 0); + brect[4] = x + gdroundupdown(brect[4], d2 < 0); + brect[5] = y - gdroundupdown(brect[5], d1 > 0); + brect[6] = x + gdroundupdown(brect[6], d1 < 0); + brect[7] = y - gdroundupdown(brect[7], d2 < 0); } if (tmpstr) { diff --git a/ext/gd/tests/bug43073_1.phpt b/ext/gd/tests/bug43073_1.phpt index b69067d31b..a0682bcf63 100644 --- a/ext/gd/tests/bug43073_1.phpt +++ b/ext/gd/tests/bug43073_1.phpt @@ -16,12 +16,14 @@ $delta_t = 360.0 / 16; # Make 16 steps around $g = imagecreate(800, 800); $bgnd = imagecolorallocate($g, 255, 255, 255); $black = imagecolorallocate($g, 0, 0, 0); +$red = imagecolorallocate($g, 255, 0, 0); $x = 100; $y = 0; $cos_t = cos(deg2rad($delta_t)); $sin_t = sin(deg2rad($delta_t)); for ($angle = 0.0; $angle < 360.0; $angle += $delta_t) { $bbox = imagettftext($g, 24, $angle, 400+$x, 400+$y, $black, $font, 'ABCDEF'); + imagepolygon($g, $bbox, 4, $red); $s = vsprintf("(%d, %d), (%d, %d), (%d, %d), (%d, %d)\n", $bbox); echo $s; $temp = $cos_t * $x + $sin_t * $y; @@ -33,19 +35,19 @@ imagepng($g, "$cwd/bug43073.png"); --CLEAN-- <?php @unlink(dirname(__FILE__) . '/bug43073.png'); ?> --EXPECTF-- -(500, 400), (610, 400), (610, 376), (500, 376) -(492, 363), (591, 322), (580, 295), (480, 336) -(470, 331), (548, 254), (527, 233), (449, 310) -(439, 309), (483, 202), (461, 193), (416, 299) -(400, 300), (400, 183), (380, 183), (380, 300) -(362, 307), (316, 195), (291, 205), (337, 318) -(330, 329), (246, 244), (224, 265), (308, 350) -(308, 360), (202, 316), (190, 344), (296, 388) -(300, 400), (187, 400), (187, 425), (300, 425) -(306, 437), (195, 483), (206, 510), (318, 464) -(328, 469), (240, 557), (260, 578), (349, 491) -(359, 491), (312, 607), (334, 616), (382, 501) -(400, 500), (400, 618), (419, 618), (419, 500) -(436, 493), (483, 607), (507, 597), (461, 482) -(468, 471), (555, 558), (577, 538), (490, 450) -(490, 440), (600, 485), (611, 457), (502, 412) +(501, 400), (611, 400), (611, 376), (501, 376) +(492, 361), (595, 319), (586, 296), (483, 338) +(470, 329), (549, 251), (531, 233), (453, 312) +(439, 307), (481, 204), (458, 195), (416, 297) +(400, 299), (400, 189), (376, 189), (376, 299) +(361, 307), (319, 204), (296, 213), (338, 316) +(329, 329), (251, 250), (233, 267), (311, 346) +(307, 360), (204, 318), (195, 341), (297, 383) +(299, 400), (189, 400), (189, 424), (299, 424) +(307, 438), (204, 480), (213, 503), (316, 461) +(329, 470), (250, 548), (267, 566), (346, 488) +(360, 492), (318, 595), (341, 604), (383, 502) +(400, 501), (400, 611), (424, 611), (424, 501) +(438, 492), (480, 595), (503, 586), (461, 483) +(470, 470), (548, 549), (566, 532), (488, 453) +(492, 439), (595, 481), (604, 458), (502, 416) diff --git a/ext/gd/tests/bug48732.phpt b/ext/gd/tests/bug48732.phpt index f8cb5e2bac..38dc861a9d 100644 --- a/ext/gd/tests/bug48732.phpt +++ b/ext/gd/tests/bug48732.phpt @@ -19,4 +19,4 @@ echo 'Left Bottom: (' . $bbox[0] . ', ' . $bbox[1] . ')'; --CLEAN-- <?php @unlink(dirname(__FILE__) . '/bug48732.png'); ?> --EXPECTF-- -Left Bottom: (0, 47) +Left Bottom: (0, 46) diff --git a/ext/gd/tests/bug48801_1.phpt b/ext/gd/tests/bug48801_1.phpt index 0ab6d7cdd9..f0f3f93fd4 100644 --- a/ext/gd/tests/bug48801_1.phpt +++ b/ext/gd/tests/bug48801_1.phpt @@ -19,7 +19,7 @@ echo '(' . $bbox[4] . ', ' . $bbox[5] . ")\n"; echo '(' . $bbox[6] . ', ' . $bbox[7] . ")\n"; ?> --EXPECTF-- -(-1, 15) -(15%d, 15) -(15%d, -48) -(-1, -48) +(4, 15) +(161, 15) +(161, -47) +(4, -47) diff --git a/ext/gd/tests/bug53504.phpt b/ext/gd/tests/bug53504.phpt new file mode 100644 index 0000000000..c84ee78fdb --- /dev/null +++ b/ext/gd/tests/bug53504.phpt @@ -0,0 +1,101 @@ +--TEST-- +Bug #53504 imagettfbbox/imageftbbox gives incorrect values for bounding box +--SKIPIF-- +<?php + if(!extension_loaded('gd')){ die('skip gd extension not available'); } + if(!function_exists('imageftbbox')) die('skip imageftbbox() not available'); + + include dirname(__FILE__) . '/func.inc'; + if(version_compare(get_freetype_version(), '2.4.10') == -1) die('skip for freetype < 2.4.10'); +?> +--FILE-- +<?php +$cwd = dirname(__FILE__); +$font = "$cwd/Tuffy.ttf"; + +$g = imagecreate(800, 800); +$bgnd = imagecolorallocate($g, 255, 255, 255); +$black = imagecolorallocate($g, 0, 0, 0); +$red = imagecolorallocate($g, 255, 0, 0); +$blue = imagecolorallocate($g, 0, 0, 255); + +$tests = [ + // Kerning examples (unfortunately not available in "Tuffy" test font): + ['fontSize' => 50, 'angle' => 0, 'x' => 20, 'y' => 70, 'text' => 'AV Teg'], + ['fontSize' => 50, 'angle' => 90, 'x' => 70, 'y' => 350, 'text' => 'AV Teg'], + ['fontSize' => 50, 'angle' => 40, 'x' => 130, 'y' => 280, 'text' => 'AV Teg'], + + // Shift-Test: + ['fontSize' => 100, 'angle' => 0, 'x' => 350, 'y' => 110, 'text' => 'H-Shift'], + + // Small/single chars: + ['fontSize' => 100, 'angle' => 0, 'x' => 350, 'y' => 220, 'text' => '-'], + ['fontSize' => 100, 'angle' => 0, 'x' => 430, 'y' => 220, 'text' => ','], + ['fontSize' => 100, 'angle' => 0, 'x' => 510, 'y' => 220, 'text' => '.'], + ['fontSize' => 100, 'angle' => 0, 'x' => 590, 'y' => 220, 'text' => '|'], + ['fontSize' => 100, 'angle' => 0, 'x' => 670, 'y' => 220, 'text' => 'g'], + + // Multi-Line + rotation: + ['fontSize' => 30, 'angle' => 0, 'x' => 20, 'y' => 400, 'text' => "Multi\nLine\nTest"], + ['fontSize' => 30, 'angle' => 40, 'x' => 150, 'y' => 420, 'text' => "Multi\nLine\nTest"], + ['fontSize' => 30, 'angle' => 90, 'x' => 250, 'y' => 340, 'text' => "Multi\nLine\nTest"], + + // Some edge case glyphs: + ['fontSize' => 50, 'angle' => 90, 'x' => 70, 'y' => 750, 'text' => "iiiiiiiiiiii"], + ['fontSize' => 50, 'angle' => 90, 'x' => 150, 'y' => 750, 'text' => "~~~~~~~"], + ['fontSize' => 50, 'angle' => 50, 'x' => 210, 'y' => 750, 'text' => "iiiiiiiiiiii"], + ['fontSize' => 50, 'angle' => 50, 'x' => 300, 'y' => 750, 'text' => "~~~~~~~"], + ['fontSize' => 50, 'angle' => 0, 'x' => 430, 'y' => 650, 'text' => "iiiiiiiiiiii"], + ['fontSize' => 50, 'angle' => 0, 'x' => 430, 'y' => 750, 'text' => "~~~~~~~"], + + // "Big" test: + ['fontSize' => 200, 'angle' => 0, 'x' => 400, 'y' => 500, 'text' => "Big"], +]; + +foreach ($tests as $test) { + $bbox = imageftbbox($test['fontSize'], $test['angle'], $font, $test['text']); + vprintf("(%d, %d), (%d, %d), (%d, %d), (%d, %d)\n", $bbox); + + $bboxDrawn = imagefttext($g, $test['fontSize'], $test['angle'], + $test['x'], $test['y'], $black, $font, $test['text']); + + // check if both bboxes match when adding x/y offset: + for ($i = 0; $i < count($bbox); $i += 2) { + if ($bbox[$i] + $test['x'] !== $bboxDrawn[$i]) echo "imageftbbox and imagefttext differ!\n"; + if ($bbox[$i + 1] + $test['y'] !== $bboxDrawn[$i + 1]) echo "imageftbbox and imagefttext differ!\n"; + } + + // draw bounding box: + imagepolygon($g, $bboxDrawn, 4, $red); + + // draw baseline: + $width = sqrt(pow($bboxDrawn[2] - $bboxDrawn[0], 2) + pow($bboxDrawn[3] - $bboxDrawn[1], 2)); + imageline($g, $test['x'], $test['y'], + $test['x'] + $width * cos(deg2rad($test['angle'])), + $test['y'] - $width * sin(deg2rad($test['angle'])), $blue); +} + +imagepng($g, "$cwd/bug53504.png"); +?> +--CLEAN-- +<?php @unlink(dirname(__FILE__) . '/bug53504.png'); ?> +--EXPECTF-- +(2, 15), (208, 15), (208, -48), (2, -48) +(15, -1), (15, -208), (-48, -208), (-48, -2) +(11, 11), (169, -122), (129, -171), (-30, -39) +(8, 2), (385, 2), (385, -97), (8, -97) +(7, -37), (51, -37), (51, -46), (7, -46) +(7, 15), (21, 15), (21, -13), (7, -13) +(7, 1), (21, 1), (21, -13), (7, -13) +(8, 0), (17, 0), (17, -95), (8, -95) +(5, 29), (60, 29), (60, -72), (5, -72) +(2, 107), (80, 107), (80, -29), (2, -29) +(70, 81), (131, 31), (43, -74), (-18, -24) +(107, -1), (107, -80), (-29, -80), (-29, -2) +(0, -4), (0, -165), (-47, -165), (-47, -4) +(-19, -2), (-18, -167), (-29, -167), (-29, -2) +(3, -3), (107, -127), (70, -157), (-34, -33) +(-13, -13), (93, -141), (85, -147), (-21, -20) +(4, 0), (165, 0), (165, -47), (4, -47) +(2, -19), (167, -19), (167, -29), (2, -29) +(16, 59), (330, 59), (330, -190), (16, -190) |