From efbce9328093370ec88c747a420e5bd751e348d7 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Mon, 27 Jul 2026 22:08:22 +0800 Subject: [PATCH 01/10] fix(cve): CVE-2010-1628 - Change the order of allocations because alloc_save_change_alloc() leaves CVE: CVE-2010-1628 (critical) - Ghostscript 8.64, 8.70, and possibly other versions allows context-dependent attackers to execute arbitrary code via a PostScript file containing unlimited recursive procedure invocations, which trigger memory corruption in the stack of the interpreter. Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/e833acd440c5ff694cec3237eeed45cef69eb02e Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 +++++ debian/patches/CVE-2010-1628.patch | 40 ++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 47 insertions(+) create mode 100644 debian/patches/CVE-2010-1628.patch diff --git a/debian/changelog b/debian/changelog index d611187..85982ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin2) unstable; urgency=medium + + * fix(cve): CVE-2010-1628 + + -- deepin-ci-robot Mon, 27 Jul 2026 22:08:22 +0800 + ghostscript (10.05.1~dfsg-3deepin1) unstable; urgency=medium * Add libgs9-common transitional package for smooth upgrading diff --git a/debian/patches/CVE-2010-1628.patch b/debian/patches/CVE-2010-1628.patch new file mode 100644 index 0000000..937df68 --- /dev/null +++ b/debian/patches/CVE-2010-1628.patch @@ -0,0 +1,40 @@ +Description: CVE-2010-1628 - 安全修复 +Author: Alex Cherepanov +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/e833acd440c5ff694cec3237eeed45cef69eb02e +Bug: https://nvd.nist.gov/vuln/detail/CVE-2010-1628 +Last-Update: 2007-02-12 +--- +diff --git a/psi/ialloc.c b/psi/ialloc.c +index 40216e4..708ddce 100644 +--- a/psi/ialloc.c ++++ b/psi/ialloc.c +@@ -218,11 +218,6 @@ gs_alloc_ref_array(gs_ref_memory_t * mem, ref * parr, uint attrs, + alloc_change_t *cp = 0; + int code = 0; + +- if ((gs_memory_t *)mem != mem->stable_memory) { +- code = alloc_save_change_alloc(mem, "gs_alloc_ref_array", &cp); +- if (code < 0) +- return code; +- } + obj = gs_alloc_struct_array((gs_memory_t *) mem, num_refs + 1, + ref, &st_refs, cname); + if (obj == 0) { +@@ -257,9 +252,14 @@ gs_alloc_ref_array(gs_ref_memory_t * mem, ref * parr, uint attrs, + gs_abort((gs_memory_t *) mem); + } + } +- if (cp) { +- mem->changes = cp; +- cp->where = (ref_packed *)obj; ++ if ((gs_memory_t *)mem != mem->stable_memory) { ++ code = alloc_save_change_alloc(mem, "gs_alloc_ref_array", &cp); ++ if (code < 0) ++ return code; ++ if (cp) { ++ mem->changes = cp; ++ cp->where = (ref_packed *)obj; ++ } + } + } + for (i = 0; i < num_refs; i++) { diff --git a/debian/patches/series b/debian/patches/series index 2d3f9ca..d693711 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -14,3 +14,4 @@ 2010_add_build_timestamp_setting.patch 2011_disable_google_analytics.patch 2012_additional_gcc_15_fixes.patch +CVE-2010-1628.patch From 50cde6887a0b2d0d7a6a5864121a818f928e2c82 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 00:28:47 +0800 Subject: [PATCH 02/10] fix(cve): CVE-2017-9619 - XPS interpreter - bounds check POST table parsing CVE: CVE-2017-9619 (high) - The xps_true_callback_glyph_name function in xps/xpsttf.c in Artifex Ghostscript GhostXPS 9.21 allows remote attackers to cause a denial of service (Segmentation Violation and application crash) via a crafted file. Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/690ac215a57039c7202fd1ffdae12f52829f625d Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 +++++ debian/patches/CVE-2017-9619.patch | 41 ++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 48 insertions(+) create mode 100644 debian/patches/CVE-2017-9619.patch diff --git a/debian/changelog b/debian/changelog index 85982ac..207777b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin3) unstable; urgency=medium + + * fix(cve): CVE-2017-9619 + + -- deepin-ci-robot Tue, 28 Jul 2026 00:28:47 +0800 + ghostscript (10.05.1~dfsg-3deepin2) unstable; urgency=medium * fix(cve): CVE-2010-1628 diff --git a/debian/patches/CVE-2017-9619.patch b/debian/patches/CVE-2017-9619.patch new file mode 100644 index 0000000..f058930 --- /dev/null +++ b/debian/patches/CVE-2017-9619.patch @@ -0,0 +1,41 @@ +Description: CVE-2017-9619 - 安全修复 +Author: Ken Sharp +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/690ac215a57039c7202fd1ffdae12f52829f625d +Bug: https://nvd.nist.gov/vuln/detail/CVE-2017-9619 +Last-Update: 2025-09-09 08:01:56 +0100 +--- +diff --git a/xps/xpsttf.c b/xps/xpsttf.c +index 70ae184..e8eb0de 100644 +--- a/xps/xpsttf.c ++++ b/xps/xpsttf.c +@@ -143,7 +143,7 @@ xps_true_callback_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string *ps + ulong format; + int numGlyphs; + uint glyph_name_index; +- const byte *postp; /* post table pointer */ ++ const byte *postp, *indexp; /* post table pointer */ + xps_font_t *font = pfont->client_data; + + if (glyph >= GS_MIN_GLYPH_INDEX) { +@@ -217,7 +217,11 @@ xps_true_callback_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string *ps + } + + /* glyph name index starts at post + 34 each entry is 2 bytes */ +- glyph_name_index = u16(postp + 34 + (glyph * 2)); ++ indexp = postp + 34 + (glyph * 2); ++ if (indexp > (postp + table_length - 2)) ++ return gs_throw(-1, "post table format error"); ++ ++ glyph_name_index = u16(indexp); + + /* this shouldn't happen */ + if ( glyph_name_index > 0x7fff ) +@@ -249,6 +253,8 @@ xps_true_callback_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string *ps + { + pascal_stringp += ((int)(*pascal_stringp)+1); + glyph_name_index--; ++ if (pascal_stringp >= postp + table_length) ++ return gs_throw(-1, "data out of range"); + } + + /* length byte */ diff --git a/debian/patches/series b/debian/patches/series index d693711..65d2752 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -15,3 +15,4 @@ 2011_disable_google_analytics.patch 2012_additional_gcc_15_fixes.patch CVE-2010-1628.patch +CVE-2017-9619.patch From 028e2e5633a463a8d23d5f41f87d2837e13bfa1b Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 00:59:46 +0800 Subject: [PATCH 03/10] fix(cve): CVE-2018-17183 - Bug 699708 (part 1): 'Hide' non-replaceable error handlers for SAFER CVE: CVE-2018-17183 (high) - CVE-2018-17183: Ghostscript error handler vulnerability - malicious input could trigger problems by using custom error handlers when running with -dSAFER Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/fb713b3818b52d8a6cf62c951eba2e1795ff9624 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 +++ debian/patches/CVE-2018-17183.patch | 66 +++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 73 insertions(+) create mode 100644 debian/patches/CVE-2018-17183.patch diff --git a/debian/changelog b/debian/changelog index 207777b..2576ed2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin4) unstable; urgency=medium + + * fix(cve): CVE-2018-17183 + + -- deepin-ci-robot Tue, 28 Jul 2026 00:59:46 +0800 + ghostscript (10.05.1~dfsg-3deepin3) unstable; urgency=medium * fix(cve): CVE-2017-9619 diff --git a/debian/patches/CVE-2018-17183.patch b/debian/patches/CVE-2018-17183.patch new file mode 100644 index 0000000..b3dad21 --- /dev/null +++ b/debian/patches/CVE-2018-17183.patch @@ -0,0 +1,66 @@ +Description: CVE-2018-17183 - 安全修复 +Author: Chris Liddell +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/fb713b3818b52d8a6cf62c951eba2e1795ff9624 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2018-17183 +Last-Update: 2018-09-06 +--- +diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps +index 239596f63..c7051622b 100644 +--- a/Resource/Init/gs_init.ps ++++ b/Resource/Init/gs_init.ps +@@ -1400,7 +1400,11 @@ errordict begin + } .internalbind def + end % errordict + +-gserrordict /unknownerror errordict /unknownerror get put ++% Put all the default handlers in gserrordict ++gserrordict ++errordict {2 index 3 1 roll put} forall ++noaccess pop ++% remove the non-standard errors from errordict + errordict /unknownerror .undef + + /.SAFERERRORLIST ErrorNames def +diff --git a/psi/interp.c b/psi/interp.c +index 187d3fbb4..3c0c25173 100644 +--- a/psi/interp.c ++++ b/psi/interp.c +@@ -683,18 +683,27 @@ again: + if (gs_errorname(i_ctx_p, code, &error_name) < 0) + return code; /* out-of-range error code! */ + +- /* We refer to gserrordict first, which is not accessible to Postcript jobs +- * If we're running with SAFERERRORS all the handlers are copied to gserrordict +- * so we'll always find the default one. If not SAFERERRORS, only gs specific +- * errors are in gserrordict. ++ /* If LockFilePermissions is true, we only refer to gserrordict, which ++ * is not accessible to Postcript jobs + */ +- if ((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || +- !r_has_type(perrordict, t_dictionary) || +- dict_find(perrordict, &error_name, &epref) <= 0) && +- (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || +- !r_has_type(perrordict, t_dictionary) || +- dict_find(perrordict, &error_name, &epref) <= 0)) +- return code; /* error name not in errordict??? */ ++ if (i_ctx_p->LockFilePermissions) { ++ if (((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || ++ dict_find(perrordict, &error_name, &epref) <= 0)) ++ ) ++ return code; /* error name not in errordict??? */ ++ } ++ else { ++ /* ++ * For greater Adobe compatibility, only the standard PostScript errors ++ * are defined in errordict; the rest are in gserrordict. ++ */ ++ if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 || ++ (dict_find(perrordict, &error_name, &epref) <= 0 && ++ (dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 || ++ dict_find(perrordict, &error_name, &epref) <= 0)) ++ ) ++ return code; /* error name not in errordict??? */ ++ } + + if (code == gs_error_execstackoverflow + && obj_eq(imemory, &doref, epref)) { diff --git a/debian/patches/series b/debian/patches/series index 65d2752..f2105d1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -16,3 +16,4 @@ 2012_additional_gcc_15_fixes.patch CVE-2010-1628.patch CVE-2017-9619.patch +CVE-2018-17183.patch From cb6dae2e4d300ebddc663f61715f9bb9b5022a63 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 03:05:30 +0800 Subject: [PATCH 04/10] fix(cve): CVE-2017-7948 - Bug 697762: Fix scan converter SEGVs. CVE: CVE-2017-7948 (high) - Integer overflow in the mark_curve function in Artifex Ghostscript 9.21 allows remote attackers to cause a denial of service (out-of-bounds write and application crash) or possibly have unspecified other impact via a crafted PostScript document. Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/8210a2864372723b49c526e2b102fdc00c9c4699 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 + debian/patches/CVE-2017-7948.patch | 2896 ++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 2903 insertions(+) create mode 100644 debian/patches/CVE-2017-7948.patch diff --git a/debian/changelog b/debian/changelog index 2576ed2..139e90a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin5) unstable; urgency=medium + + * fix(cve): CVE-2017-7948 + + -- deepin-ci-robot Tue, 28 Jul 2026 03:05:30 +0800 + ghostscript (10.05.1~dfsg-3deepin4) unstable; urgency=medium * fix(cve): CVE-2018-17183 diff --git a/debian/patches/CVE-2017-7948.patch b/debian/patches/CVE-2017-7948.patch new file mode 100644 index 0000000..82a3475 --- /dev/null +++ b/debian/patches/CVE-2017-7948.patch @@ -0,0 +1,2896 @@ +Description: CVE-2017-7948 - 安全修复 +Author: Robin Watts +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/8210a2864372723b49c526e2b102fdc00c9c4699 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2017-7948 +Last-Update: 2017-04-19 +--- +diff --git a/base/gxscanc.c b/base/gxscanc.c +index 2fbe2aaf0..13ece3afc 100644 +--- a/base/gxscanc.c ++++ b/base/gxscanc.c +@@ -1,16 +1,14 @@ +-/* Copyright (C) 2001-2023 Artifex Software, Inc. ++/* Copyright (C) 2001-2016 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + +- This software is distributed under license and may not be copied, +- modified or distributed except as expressly authorized under the terms +- of the license contained in the file LICENSE in this distribution. +- +- Refer to licensing information at http://www.artifex.com or contact +- Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, +- CA 94129, USA, for further information. ++ This software is distributed under license and may not be copied, modified ++ or distributed except as expressly authorized under the terms of that ++ license. Refer to licensing information at http://www.artifex.com/ ++ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, ++ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. + */ + + /* Path stroking procedures for Ghostscript library */ +@@ -39,7 +37,6 @@ + #include "gxdcolor.h" + #include "assert_.h" + #include /* for qsort */ +-#include /* For INT_MAX */ + + /* Overview of the scan conversion algorithm. + * +@@ -141,8 +138,6 @@ + #undef DEBUG_SCAN_CONVERTER + #undef DEBUG_OUTPUT_SC_AS_PS + +-typedef int64_t fixed64; +- + enum + { + DIRN_UNSET = -1, +@@ -197,130 +192,9 @@ static void coord(const char *str, fixed x, fixed y) + } + #endif + +-typedef void (zero_filler_fn)(int *, const fixed *); +- +-static void mark_line_zero(fixed sx, fixed ex, fixed *zf) +-{ +- if (sx < zf[0]) +- zf[0] = sx; +- if (ex < zf[0]) +- zf[0] = ex; +- if (sx > zf[1]) +- zf[1] = sx; +- if (ex > zf[1]) +- zf[1] = ex; +-} +- +-static void mark_curve_zero(fixed sx, fixed c1x, fixed c2x, fixed ex, int depth, fixed *zf) +-{ +- fixed ax = (sx + c1x)>>1; +- fixed bx = (c1x + c2x)>>1; +- fixed cx = (c2x + ex)>>1; +- fixed dx = (ax + bx)>>1; +- fixed fx = (bx + cx)>>1; +- fixed gx = (dx + fx)>>1; +- +- assert(depth >= 0); +- if (depth == 0) +- mark_line_zero(sx, ex, zf); +- else { +- depth--; +- mark_curve_zero(sx, ax, dx, gx, depth, zf); +- mark_curve_zero(gx, fx, cx, ex, depth, zf); +- } +-} +- +-static void mark_curve_big_zero(fixed64 sx, fixed64 c1x, fixed64 c2x, fixed64 ex, int depth, fixed *zf) +-{ +- fixed64 ax = (sx + c1x)>>1; +- fixed64 bx = (c1x + c2x)>>1; +- fixed64 cx = (c2x + ex)>>1; +- fixed64 dx = (ax + bx)>>1; +- fixed64 fx = (bx + cx)>>1; +- fixed64 gx = (dx + fx)>>1; +- +- assert(depth >= 0); +- if (depth == 0) +- mark_line_zero((fixed)sx, (fixed)ex, zf); +- else { +- depth--; +- mark_curve_big_zero(sx, ax, dx, gx, depth, zf); +- mark_curve_big_zero(gx, fx, cx, ex, depth, zf); +- } +-} +- +-static void mark_curve_top_zero(fixed sx, fixed c1x, fixed c2x, fixed ex, int depth, fixed *zf) +-{ +- fixed test = (sx^(sx<<1))|(c1x^(c1x<<1))|(c2x^(c2x<<1))|(ex^(ex<<1)); +- +- if (test < 0) +- mark_curve_big_zero(sx, c1x, c2x, ex, depth, zf); +- else +- mark_curve_zero(sx, c1x, c2x, ex, depth, zf); +-} +- +-static int +-zero_case(gx_device * gs_restrict pdev, +- gx_path * gs_restrict path, +- gs_fixed_rect * gs_restrict ibox, +- int * gs_restrict index, +- int * gs_restrict table, +- fixed fixed_flat, +- zero_filler_fn * fill) +-{ +- const subpath *psub; +- fixed zf[2]; +- +- /* Step 2 continued: Now we run through the path, filling in the real +- * values. */ +- for (psub = path->first_subpath; psub != 0;) { +- const segment *pseg = (const segment *)psub; +- fixed ex = pseg->pt.x; +- fixed sy = pseg->pt.y; +- fixed ix = ex; +- int iy = fixed2int(pseg->pt.y); +- +- zf[0] = ex; +- zf[1] = ex; +- +- while ((pseg = pseg->next) != 0 && +- pseg->type != s_start +- ) { +- fixed sx = ex; +- ex = pseg->pt.x; +- +- switch (pseg->type) { +- default: +- case s_start: /* Should never happen */ +- case s_dash: /* We should never be seeing a dash here */ +- assert("This should never happen" == NULL); +- break; +- case s_curve: { +- const curve_segment *const pcur = (const curve_segment *)pseg; +- int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat); +- +- mark_curve_top_zero(sx, pcur->p1.x, pcur->p2.x, ex, k, zf); +- break; +- } +- case s_gap: +- case s_line: +- case s_line_close: +- mark_line_zero(sx, ex, zf); +- break; +- } +- } +- /* And close any open segments */ +- mark_line_zero(ex, ix, zf); +- fill(&table[index[iy-ibox->p.y]], zf); +- psub = (const subpath *)pseg; +- } +- +- return 0; +-} +- + static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index) + { +- int64_t delta; ++ int delta; + int iy, ih; + fixed clip_sy, clip_ey; + int dirn = DIRN_UP; +@@ -360,26 +234,25 @@ static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int he + clip_ey = int2fixed(base_y + height - 1) + fixed_half; + if (sy > clip_ey) + return; +- delta = (int64_t)clip_sy - (int64_t)sy; ++ delta = clip_sy - sy; + if (delta > 0) + { +- int64_t dx = (int64_t)ex - (int64_t)sx; +- int64_t dy = (int64_t)ey - (int64_t)sy; +- int advance = (int)((dx * delta + (dy>>1)) / dy); ++ int dx = ex - sx; ++ int dy = ey - sy; ++ int advance = (int)(((int64_t)dx * delta + (dy>>1)) / dy); + sx += advance; + sy += delta; + } +- delta = (int64_t)ey - (int64_t)clip_ey; ++ ex -= sx; ++ ey -= sy; ++ clip_ey -= clip_sy; ++ delta = ey - clip_ey; + if (delta > 0) + { +- int64_t dx = (int64_t)ex - (int64_t)sx; +- int64_t dy = (int64_t)ey - (int64_t)sy; +- int advance = (int)((dx * delta + (dy>>1)) / dy); ++ int advance = (int)(((int64_t)ex * delta + (ey>>1)) / ey); + ex -= advance; + ey -= delta; + } +- ex -= sx; +- ey -= sy; + ih = fixed2int(ey); + assert(ih >= 0); + iy = fixed2int(sy) - base_y; +@@ -471,24 +344,24 @@ static void mark_curve(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixe + } + } + +-static void mark_curve_big(fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, fixed base_y, fixed height, int *table, int *index, int depth) ++static void mark_curve_big(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int depth) + { +- fixed64 ax = (sx + c1x)>>1; +- fixed64 ay = (sy + c1y)>>1; +- fixed64 bx = (c1x + c2x)>>1; +- fixed64 by = (c1y + c2y)>>1; +- fixed64 cx = (c2x + ex)>>1; +- fixed64 cy = (c2y + ey)>>1; +- fixed64 dx = (ax + bx)>>1; +- fixed64 dy = (ay + by)>>1; +- fixed64 fx = (bx + cx)>>1; +- fixed64 fy = (by + cy)>>1; +- fixed64 gx = (dx + fx)>>1; +- fixed64 gy = (dy + fy)>>1; ++ fixed ax = (sx>>1) + (c1x>>1); ++ fixed ay = (sy>>1) + (c1y>>1); ++ fixed bx = (c1x>>1) + (c2x>>1); ++ fixed by = (c1y>>1) + (c2y>>1); ++ fixed cx = (c2x>>1) + (ex>>1); ++ fixed cy = (c2y>>1) + (ey>>1); ++ fixed dx = (ax>>1) + (bx>>1); ++ fixed dy = (ay>>1) + (by>>1); ++ fixed fx = (bx>>1) + (cx>>1); ++ fixed fy = (by>>1) + (cy>>1); ++ fixed gx = (dx>>1) + (fx>>1); ++ fixed gy = (dy>>1) + (fy>>1); + + assert(depth >= 0); + if (depth == 0) +- mark_line((fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, base_y, height, table, index); ++ mark_line(sx, sy, ex, ey, base_y, height, table, index); + else { + depth--; + mark_curve_big(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, depth); +@@ -508,91 +381,60 @@ static void mark_curve_top(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, + + static int make_bbox(gx_path * path, + const gs_fixed_rect * clip, +- gs_fixed_rect * bbox, + gs_fixed_rect * ibox, + fixed adjust) + { ++ gs_fixed_rect bbox; + int code; +- int ret = 0; + + /* Find the bbox - fixed */ +- code = gx_path_bbox(path, bbox); ++ code = gx_path_bbox(path, &bbox); + if (code < 0) + return code; + +- if (bbox->p.y == bbox->q.y) { +- /* Zero height path */ +- if (!clip || +- (bbox->p.y >= clip->p.y && bbox->q.y <= clip->q.y)) { +- /* Either we're not clipping, or we are vertically inside the clip */ +- if (clip) { +- if (bbox->p.x < clip->p.x) +- bbox->p.x = clip->p.x; +- if (bbox->q.x > clip->q.x) +- bbox->q.x = clip->q.x; +- } +- if (bbox->p.x <= bbox->q.x) { +- /* Zero height rectangle, not clipped completely away */ +- ret = 1; +- } +- } +- } +- + if (clip) { +- if (bbox->p.y < clip->p.y) +- bbox->p.y = clip->p.y; +- if (bbox->q.y > clip->q.y) +- bbox->q.y = clip->q.y; ++ if (bbox.p.y < clip->p.y) ++ bbox.p.y = clip->p.y; ++ if (bbox.q.y > clip->q.y) ++ bbox.q.y = clip->q.y; + } + + /* Convert to bbox - int */ +- ibox->p.x = fixed2int(bbox->p.x+adjust-(adjust?1:0)); +- ibox->p.y = fixed2int(bbox->p.y+adjust-(adjust?1:0)); +- ibox->q.x = fixed2int(bbox->q.x-adjust+fixed_1); +- ibox->q.y = fixed2int(bbox->q.y-adjust+fixed_1); ++ ibox->p.x = fixed2int(bbox.p.x-adjust); ++ ibox->p.y = fixed2int(bbox.p.y-adjust); ++ ibox->q.x = fixed2int(bbox.q.x-adjust+fixed_1); ++ ibox->q.y = fixed2int(bbox.q.y-adjust+fixed_1); + +- return ret; ++ return 0; + } + + static inline int + make_table_template(gx_device * pdev, + gx_path * path, +- gs_fixed_rect * ibox, ++ const gs_fixed_rect * ibox, + int intersection_size, +- int adjust, ++ fixed adjust, + int * scanlinesp, + int ** indexp, + int ** tablep) + { + int scanlines; +- const subpath * gs_restrict psub; +- int * gs_restrict index; +- int * gs_restrict table; ++ const subpath * restrict psub; ++ int * restrict index; ++ int * restrict table; + int i; +- int64_t offset; +- int delta; +- fixed base_y; ++ int offset, delta; ++ fixed base_y = ibox->p.y; + + *scanlinesp = 0; + *indexp = NULL; + *tablep = NULL; + +- if (pdev->max_fill_band != 0) +- ibox->p.y &= ~(pdev->max_fill_band-1); +- base_y = ibox->p.y; +- +- /* Previously we took adjust as a fixed distance to add to miny/maxy +- * to allow for the expansion due to 'any part of a pixel'. This causes +- * problems with over/underflow near INT_MAX/INT_MIN, so instead we +- * take adjust as boolean telling us whether to expand y by 1 or not, and +- * then adjust the assignments into the index as appropriate. This +- * solves Bug 697970. */ +- + /* Step 1: Make us a table */ + scanlines = ibox->q.y-base_y; +- /* +1+adjust simplifies the loop below */ ++ /* +1 simplifies the loop below */ + index = (int *)gs_alloc_bytes(pdev->memory, +- (scanlines+1+adjust) * sizeof(*index), ++ (scanlines+1) * sizeof(*index), + "scanc index buffer"); + if (index == NULL) + return_error(gs_error_VMerror); +@@ -602,8 +444,8 @@ make_table_template(gx_device * pdev, + + /* Step 1 continued: Run through the path, filling in the index */ + for (psub = path->first_subpath; psub != 0;) { +- const segment * gs_restrict pseg = (const segment *)psub; +- fixed ey = pseg->pt.y; ++ const segment * restrict pseg = (const segment *)psub; ++ fixed ey = pseg->pt.y + adjust; + fixed iy = ey; + int iey = fixed2int(iy) - base_y; + +@@ -622,7 +464,7 @@ make_table_template(gx_device * pdev, + pseg->type != s_start + ) { + fixed sy = ey; +- ey = pseg->pt.y; ++ ey = pseg->pt.y + adjust; + + switch (pseg->type) { + default: +@@ -631,9 +473,9 @@ make_table_template(gx_device * pdev, + assert("This should never happen" == NULL); + break; + case s_curve: { +- const curve_segment *const gs_restrict pcur = (const curve_segment *)pseg; +- fixed c1y = pcur->p1.y; +- fixed c2y = pcur->p2.y; ++ const curve_segment *const restrict pcur = (const curve_segment *)pseg; ++ fixed c1y = pcur->p1.y + adjust; ++ fixed c2y = pcur->p2.y + adjust; + fixed maxy = sy, miny = sy; + int imaxy, iminy; + if (miny > c1y) +@@ -653,10 +495,8 @@ make_table_template(gx_device * pdev, + dlprintf2("Curve (%x->%x) ", miny, maxy); + #endif + iminy = fixed2int(miny) - base_y; +- if (iminy <= 0) ++ if (iminy < 0) + iminy = 0; +- else +- iminy -= adjust; + if (iminy < scanlines) { + imaxy = fixed2int(maxy) - base_y; + if (imaxy >= 0) { +@@ -665,13 +505,12 @@ make_table_template(gx_device * pdev, + dlprintf1("+%x ", iminy); + #endif + index[iminy]+=3; +- if (imaxy < scanlines) { ++ if (imaxy < scanlines) + #ifdef DEBUG_SCAN_CONVERTER + if (debugging_scan_converter) + dlprintf1("-%x ", imaxy+1); + #endif +- index[imaxy+1+adjust]-=3; +- } ++ index[imaxy+1]-=3; + } + } + #ifdef DEBUG_SCAN_CONVERTER +@@ -701,10 +540,8 @@ make_table_template(gx_device * pdev, + dlprintf2("Line (%x->%x) ", miny, maxy); + #endif + iminy = fixed2int(miny) - base_y; +- if (iminy <= 0) ++ if (iminy < 0) + iminy = 0; +- else +- iminy -= adjust; + if (iminy < scanlines) { + imaxy = fixed2int(maxy) - base_y; + if (imaxy >= 0) { +@@ -718,7 +555,7 @@ make_table_template(gx_device * pdev, + if (debugging_scan_converter) + dlprintf1("-%x ", imaxy+1); + #endif +- index[imaxy+1+adjust]--; ++ index[imaxy+1]--; + } + } + } +@@ -744,10 +581,8 @@ make_table_template(gx_device * pdev, + dlprintf2("Close (%x->%x) ", miny, maxy); + #endif + iminy = fixed2int(miny) - base_y; +- if (iminy <= 0) ++ if (iminy < 0) + iminy = 0; +- else +- iminy -= adjust; + if (iminy < scanlines) { + imaxy = fixed2int(maxy) - base_y; + if (imaxy >= 0) { +@@ -761,7 +596,7 @@ make_table_template(gx_device * pdev, + if (debugging_scan_converter) + dlprintf1("-%x ", imaxy+1); + #endif +- index[imaxy+1+adjust]--; ++ index[imaxy+1]--; + } + } + } +@@ -780,47 +615,26 @@ make_table_template(gx_device * pdev, + /* Step 1 continued: index now contains a list of deltas (how the + * number of intersects on line x differs from the number on line x-1). + * First convert them to be the real number of intersects on that line. +- * Sum these values to get us the total number of intersects. Then ++ * Sum these values to get us the total nunber of intersects. Then + * convert the table to be a list of offsets into the real intersect + * buffer. */ + offset = 0; + delta = 0; +- for (i=0; i < scanlines+adjust; i++) { ++ for (i=0; i < scanlines; i++) { + delta += intersection_size*index[i]; /* delta = Num ints on this scanline. */ + index[i] = offset; /* Offset into table for this lines data. */ + offset += delta+1; /* Adjust offset for next line. */ + } +- /* Ensure we always have enough room for our zero height rectangle hack. */ +- if (offset < 2*intersection_size) +- offset += 2*intersection_size; +- offset *= sizeof(*table); +- +- /* Try to keep the size to 1Meg. This is enough for the vast majority +- * of files. Allow us to grow above this if it would mean dropping +- * the height below a suitably small number (set to be larger than +- * any max_fill_band we might meet). */ +- if (scanlines > 16 && offset > 1024*1024) { /* Arbitrary */ +- gs_free_object(pdev->memory, index, "scanc index buffer"); +- return offset/(1024*1024) + 1; +- } +- +- /* In the case where we have let offset be large, at least make sure +- * it's not TOO large for us to malloc. */ +- if (offset != (int64_t)(uint)offset) +- { +- gs_free_object(pdev->memory, index, "scanc index buffer"); +- return_error(gs_error_VMerror); +- } + + /* End of step 1: index[i] = offset into table 2 for scanline i's + * intersection data. offset = Total number of int entries required for + * table. */ + + /* Step 2: Collect the real intersections */ +- table = (int *)gs_alloc_bytes(pdev->memory, offset, ++ table = (int *)gs_alloc_bytes(pdev->memory, offset * sizeof(*table), + "scanc intersects buffer"); + if (table == NULL) { +- gs_free_object(pdev->memory, index, "scanc index buffer"); ++ gs_free_object(pdev->memory, table, "scanc index buffer"); + return_error(gs_error_VMerror); + } + +@@ -840,37 +654,27 @@ make_table_template(gx_device * pdev, + + static int make_table(gx_device * pdev, + gx_path * path, +- gs_fixed_rect * ibox, ++ const gs_fixed_rect * ibox, + int * scanlines, + int ** index, + int ** table) + { +- return make_table_template(pdev, path, ibox, 1, 1, scanlines, index, table); +-} +- +-static void +-fill_zero(int *row, const fixed *x) +-{ +- int n = *row = (*row)+2; /* Increment the count */ +- row[n-1] = (x[0]&~1); +- row[n ] = (x[1]|1); ++ return make_table_template(pdev, path, ibox, 1, fixed_half-1, scanlines, index, table); + } + +-int gx_scan_convert(gx_device * gs_restrict pdev, +- gx_path * gs_restrict path, +- const gs_fixed_rect * gs_restrict clip, +- gx_edgebuffer * gs_restrict edgebuffer, +- fixed fixed_flat) ++int gx_scan_convert(gx_device * restrict pdev, ++ gx_path * restrict path, ++ const gs_fixed_rect * restrict clip, ++ gx_edgebuffer * restrict edgebuffer, ++ fixed fixed_flat) + { + gs_fixed_rect ibox; +- gs_fixed_rect bbox; + int scanlines; + const subpath *psub; + int *index; + int *table; + int i; + int code; +- int zero; + + edgebuffer->index = NULL; + edgebuffer->table = NULL; +@@ -879,24 +683,17 @@ int gx_scan_convert(gx_device * gs_restrict pdev, + if (path->first_subpath == NULL) + return 0; + +- zero = make_bbox(path, clip, &bbox, &ibox, fixed_half); +- if (zero < 0) +- return zero; ++ code = make_bbox(path, clip, &ibox, fixed_half); ++ if (code < 0) ++ return code; + + if (ibox.q.y <= ibox.p.y) + return 0; + + code = make_table(pdev, path, &ibox, &scanlines, &index, &table); +- if (code != 0) /* >0 means "retry with smaller height" */ ++ if (code < 0) + return code; + +- if (scanlines == 0) +- return 0; +- +- if (zero) { +- code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero); +- } else { +- + /* Step 2 continued: Now we run through the path, filling in the real + * values. */ + for (psub = path->first_subpath; psub != 0;) { +@@ -940,7 +737,6 @@ int gx_scan_convert(gx_device * gs_restrict pdev, + mark_line(ex, ey, ix, iy, ibox.p.y, scanlines, table, index); + psub = (const subpath *)pseg; + } +- } + + /* Step 2 complete: We now have a complete list of intersection data in + * table, indexed by index. */ +@@ -985,8 +781,8 @@ int gx_scan_convert(gx_device * gs_restrict pdev, + + /* Step 5: Filter the intersections according to the rules */ + int +-gx_filter_edgebuffer(gx_device * gs_restrict pdev, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_filter_edgebuffer(gx_device * restrict pdev, ++ gx_edgebuffer * restrict edgebuffer, + int rule) + { + int i; +@@ -1041,9 +837,9 @@ gx_filter_edgebuffer(gx_device * gs_restrict pdev, + + /* Step 6: Fill the edgebuffer */ + int +-gx_fill_edgebuffer(gx_device * gs_restrict pdev, +- const gx_device_color * gs_restrict pdevc, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_fill_edgebuffer(gx_device * restrict pdev, ++ const gx_device_color * restrict pdevc, ++ gx_edgebuffer * restrict edgebuffer, + int log_op) + { + int i, code; +@@ -1154,7 +950,7 @@ typedef struct + } cursor; + + static inline void +-cursor_output(cursor * gs_restrict cr, int iy) ++cursor_output(cursor * restrict cr, int iy) + { + int *row; + int count; +@@ -1167,21 +963,21 @@ cursor_output(cursor * gs_restrict cr, int iy) + cr->save_iy = iy; + cr->save_d = cr->d; + cr->saved = 1; +- } else if (cr->d != DIRN_UNSET) { ++ } else { + /* Enter it into the table */ ++ assert(cr->d != DIRN_UNSET); ++ + row = &cr->table[cr->index[iy]]; + *row = count = (*row)+1; /* Increment the count */ + row[2 * count - 1] = (cr->left&~1) | cr->d; + row[2 * count ] = cr->right; +- } else { +- assert(cr->left == max_fixed && cr->right == min_fixed); + } + } + cr->first = 0; + } + + static inline void +-cursor_output_inrange(cursor * gs_restrict cr, int iy) ++cursor_output_inrange(cursor * restrict cr, int iy) + { + int *row; + int count; +@@ -1208,7 +1004,7 @@ cursor_output_inrange(cursor * gs_restrict cr, int iy) + + /* Step the cursor in y, allowing for maybe crossing a scanline */ + static inline void +-cursor_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip) ++cursor_step(cursor * restrict cr, fixed dy, fixed x) + { + int new_iy; + int iy = fixed2int(cr->y) - cr->base; +@@ -1216,8 +1012,7 @@ cursor_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip) + cr->y += dy; + new_iy = fixed2int(cr->y) - cr->base; + if (new_iy != iy) { +- if (!skip) +- cursor_output(cr, iy); ++ cursor_output(cr, iy); + cr->left = x; + cr->right = x; + } else { +@@ -1230,7 +1025,7 @@ cursor_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip) + + /* Step the cursor in y, never by enough to cross a scanline. */ + static inline void +-cursor_never_step_vertical(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_never_step_vertical(cursor * restrict cr, fixed dy, fixed x) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -1241,7 +1036,7 @@ cursor_never_step_vertical(cursor * gs_restrict cr, fixed dy, fixed x) + * knowing that we are moving left, and that the right edge + * has already been accounted for. */ + static inline void +-cursor_never_step_left(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_never_step_left(cursor * restrict cr, fixed dy, fixed x) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -1254,7 +1049,7 @@ cursor_never_step_left(cursor * gs_restrict cr, fixed dy, fixed x) + * knowing that we are moving right, and that the left edge + * has already been accounted for. */ + static inline void +-cursor_never_step_right(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_never_step_right(cursor * restrict cr, fixed dy, fixed x) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -1265,12 +1060,11 @@ cursor_never_step_right(cursor * gs_restrict cr, fixed dy, fixed x) + + /* Step the cursor in y, always by enough to cross a scanline. */ + static inline void +-cursor_always_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip) ++cursor_always_step(cursor * restrict cr, fixed dy, fixed x) + { + int iy = fixed2int(cr->y) - cr->base; + +- if (!skip) +- cursor_output(cr, iy); ++ cursor_output(cr, iy); + cr->y += dy; + cr->left = x; + cr->right = x; +@@ -1280,7 +1074,7 @@ cursor_always_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip) + * part of a vertical line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_step_inrange_vertical(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_always_step_inrange_vertical(cursor * restrict cr, fixed dy, fixed x) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -1292,7 +1086,7 @@ cursor_always_step_inrange_vertical(cursor * gs_restrict cr, fixed dy, fixed x) + * part of a left moving line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_inrange_step_left(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_always_inrange_step_left(cursor * restrict cr, fixed dy, fixed x) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -1305,7 +1099,7 @@ cursor_always_inrange_step_left(cursor * gs_restrict cr, fixed dy, fixed x) + * part of a right moving line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_inrange_step_right(cursor * gs_restrict cr, fixed dy, fixed x) ++cursor_always_inrange_step_right(cursor * restrict cr, fixed dy, fixed x) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -1314,7 +1108,7 @@ cursor_always_inrange_step_right(cursor * gs_restrict cr, fixed dy, fixed x) + cr->left = x; + } + +-static inline void cursor_init(cursor * gs_restrict cr, fixed y, fixed x) ++static inline void cursor_init(cursor * restrict cr, fixed y, fixed x) + { + assert(y >= int2fixed(cr->base) && y <= int2fixed(cr->base + cr->scanlines)); + +@@ -1324,45 +1118,40 @@ static inline void cursor_init(cursor * gs_restrict cr, fixed y, fixed x) + cr->d = DIRN_UNSET; + } + +-static inline void cursor_left_merge(cursor * gs_restrict cr, fixed x) ++static inline void cursor_left_merge(cursor * restrict cr, fixed x) + { + if (x < cr->left) + cr->left = x; + } + +-static inline void cursor_left(cursor * gs_restrict cr, fixed x) ++static inline void cursor_left(cursor * restrict cr, fixed x) + { + cr->left = x; + } + +-static inline void cursor_right_merge(cursor * gs_restrict cr, fixed x) ++static inline void cursor_right_merge(cursor * restrict cr, fixed x) + { + if (x > cr->right) + cr->right = x; + } + +-static inline void cursor_right(cursor * gs_restrict cr, fixed x) ++static inline void cursor_right(cursor * restrict cr, fixed x) + { + cr->right = x; + } + +-static inline int cursor_down(cursor * gs_restrict cr, fixed x) ++static inline void cursor_down(cursor * restrict cr, fixed x) + { +- int skip = 0; +- if ((cr->y & 0xff) == 0) +- skip = 1; + if (cr->d == DIRN_UP) + { +- if (!skip) +- cursor_output(cr, fixed2int(cr->y) - cr->base); ++ cursor_output(cr, fixed2int(cr->y) - cr->base); + cr->left = x; + cr->right = x; + } + cr->d = DIRN_DOWN; +- return skip; + } + +-static inline void cursor_up(cursor * gs_restrict cr, fixed x) ++static inline void cursor_up(cursor * restrict cr, fixed x) + { + if (cr->d == DIRN_DOWN) + { +@@ -1374,7 +1163,7 @@ static inline void cursor_up(cursor * gs_restrict cr, fixed x) + } + + static inline void +-cursor_flush(cursor * gs_restrict cr, fixed x) ++cursor_flush(cursor * restrict cr, fixed x) + { + int iy; + +@@ -1383,11 +1172,6 @@ cursor_flush(cursor * gs_restrict cr, fixed x) + * rectangle from the start point. */ + if (cr->first) { + int iy = fixed2int(cr->y) - cr->base; +- /* Any zero height rectangle counts as filled, except +- * those on the baseline of a pixel. */ +- if (cr->d == DIRN_UNSET && (cr->y & 0xff) == 0) +- return; +- assert(cr->left != max_fixed && cr->right != min_fixed); + if (iy >= 0 && iy < cr->scanlines) { + int *row = &cr->table[cr->index[iy]]; + int count = *row = (*row)+2; /* Increment the count */ +@@ -1423,17 +1207,10 @@ cursor_flush(cursor * gs_restrict cr, fixed x) + } + } + +-static inline void +-cursor_null(cursor *cr) +-{ +- cr->right = min_fixed; +- cr->left = max_fixed; +- cr->d = DIRN_UNSET; +-} +- +-static void mark_line_app(cursor * gs_restrict cr, fixed sx, fixed sy, fixed ex, fixed ey) ++static void mark_line_app(cursor * restrict cr, fixed sx, fixed sy, fixed ex, fixed ey) + { + int isy, iey; ++ fixed y_steps; + fixed saved_sy = sy; + fixed saved_ex = ex; + fixed saved_ey = ey; +@@ -1455,45 +1232,34 @@ static void mark_line_app(cursor * gs_restrict cr, fixed sx, fixed sy, fixed ex, + dlprintf("stroke %%PS\n"); + #endif + +- /* Horizontal motion at the bottom of a pixel is ignored */ +- if (sy == ey && (sy & 0xff) == 0) +- return; +- +- assert(cr->y == sy && +- ((cr->left <= sx && cr->right >= sx) || ((sy & 0xff) == 0)) && +- cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN); ++ assert(cr->y == sy && cr->left <= sx && cr->right >= sx && cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN); + + if (isy < iey) { + /* Rising line */ + if (iey < 0 || isy >= cr->scanlines) { + /* All line is outside. */ +- if ((ey & 0xff) == 0) +- cursor_null(cr); +- else { +- cr->left = ex; +- cr->right = ex; +- } + cr->y = ey; ++ cr->left = ex; ++ cr->right = ex; + cr->first = 0; + return; + } + if (isy < 0) { + /* Move sy up */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_sy = int2fixed(cr->base); +- int64_t dy = (int64_t)new_sy - (int64_t)sy; ++ int y = ey - sy; ++ int new_sy = int2fixed(cr->base); ++ int dy = new_sy - sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; +- cursor_null(cr); +- cr->y = sy; ++ cursor_init(cr, sy, sx); + isy = 0; + } + truncated = iey > cr->scanlines; + if (truncated) { + /* Move ey down */ +- int64_t y = ey - sy; +- fixed new_ey = int2fixed(cr->base + cr->scanlines); +- int64_t dy = (int64_t)ey - (int64_t)new_ey; ++ int y = ey - sy; ++ int new_ey = int2fixed(cr->base + cr->scanlines); ++ int dy = ey - new_ey; + saved_ex = ex; + saved_ey = ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); +@@ -1504,42 +1270,34 @@ static void mark_line_app(cursor * gs_restrict cr, fixed sx, fixed sy, fixed ex, + /* Falling line */ + if (isy < 0 || iey >= cr->scanlines) { + /* All line is outside. */ +- if ((ey & 0xff) == 0) +- cursor_null(cr); +- else { +- cr->left = ex; +- cr->right = ex; +- } + cr->y = ey; ++ cr->left = ex; ++ cr->right = ex; + cr->first = 0; + return; + } + truncated = iey < 0; + if (truncated) { + /* Move ey up */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_ey = int2fixed(cr->base); +- int64_t dy = (int64_t)ey - (int64_t)new_ey; ++ int y = ey - sy; ++ int new_ey = int2fixed(cr->base); ++ int dy = ey - new_ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); + ey = new_ey; + iey = 0; + } + if (isy >= cr->scanlines) { + /* Move sy down */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_sy = int2fixed(cr->base + cr->scanlines); +- int64_t dy = (int64_t)new_sy - (int64_t)sy; ++ int y = ey - sy; ++ int new_sy = int2fixed(cr->base + cr->scanlines); ++ int dy = new_sy - sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; +- cursor_null(cr); +- cr->y = sy; ++ cursor_init(cr, sy, sx); + isy = cr->scanlines; + } + } + +- cursor_left_merge(cr, sx); +- cursor_right_merge(cr, sx); +- + assert(cr->left <= sx); + assert(cr->right >= sx); + assert(cr->y == sy); +@@ -1567,42 +1325,24 @@ static void mark_line_app(cursor * gs_restrict cr, fixed sx, fixed sy, fixed ex, + if (isy == iey) { + if (saved_sy == saved_ey) { + /* Horizontal line. Don't change cr->d, don't flush. */ +- if ((ey & 0xff) == 0) +- goto no_merge; + } else if (saved_sy > saved_ey) { + /* Falling line, flush if previous was rising */ +- int skip = cursor_down(cr, sx); +- if ((ey & 0xff) == 0) { +- /* We are falling to the baseline of a subpixel, so output +- * for the current pixel, and leave the cursor nulled. */ +- if (sx <= ex) { +- cursor_right_merge(cr, ex); +- } else { +- cursor_left_merge(cr, ex); +- } +- if (!skip) +- cursor_output(cr, fixed2int(cr->y) - cr->base); +- cursor_null(cr); +- goto no_merge; +- } ++ cursor_down(cr, sx); + } else { + /* Rising line, flush if previous was falling */ + cursor_up(cr, sx); +- if ((ey & 0xff) == 0) { +- cursor_null(cr); +- goto no_merge; +- } + } + if (sx <= ex) { ++ cursor_left_merge(cr, sx); + cursor_right_merge(cr, ex); + } else { + cursor_left_merge(cr, ex); ++ cursor_right_merge(cr, sx); + } +-no_merge: + cr->y = ey; + if (sy > saved_ey) + goto endFalling; +- } else if (iey > isy) { ++ } else if ((y_steps = ey - sy) > 0) { + /* We want to change from sy to ey, which are guaranteed to be on + * different scanlines. We do this in 3 phases. + * Phase 1 gets us from sy to the next scanline boundary. +@@ -1617,7 +1357,6 @@ no_merge: + */ + int phase1_y_steps = (-sy) & (fixed_1 - 1); + int phase3_y_steps = ey & (fixed_1 - 1); +- ufixed y_steps = (ufixed)ey - (ufixed)sy; + + cursor_up(cr, sx); + +@@ -1625,16 +1364,16 @@ no_merge: + /* Vertical line. (Rising) */ + + /* Phase 1: */ ++ cursor_left_merge(cr, sx); ++ cursor_right_merge(cr, sx); + if (phase1_y_steps) { + /* If phase 1 will move us into a new scanline, then we must + * flush it before we move. */ +- cursor_step(cr, phase1_y_steps, sx, 0); ++ cursor_step(cr, phase1_y_steps, sx); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -1644,7 +1383,7 @@ no_merge: + y_steps = fixed2int(y_steps); + assert(y_steps >= 0); + if (y_steps > 0) { +- cursor_always_step(cr, fixed_1, sx, 0); ++ cursor_always_step(cr, fixed_1, sx); + y_steps--; + while (y_steps) { + cursor_always_step_inrange_vertical(cr, fixed_1, sx); +@@ -1654,28 +1393,24 @@ no_merge: + + /* Phase 3 */ + assert(cr->left == sx && cr->right == sx); +- if (phase3_y_steps == 0) +- cursor_null(cr); +- else +- cr->y += phase3_y_steps; ++ cr->y += phase3_y_steps; + } else if (sx < ex) { + /* Lines increasing in x. (Rightwards, rising) */ + int phase1_x_steps, phase3_x_steps; + fixed x_steps = ex - sx; + + /* Phase 1: */ ++ cursor_left_merge(cr, sx); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + sx += phase1_x_steps; + cursor_right_merge(cr, sx); + x_steps -= phase1_x_steps; +- cursor_step(cr, phase1_y_steps, sx, 0); ++ cursor_step(cr, phase1_y_steps, sx); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -1702,7 +1437,7 @@ no_merge: + if (f < 0) + f += d, sx++; + cursor_right_merge(cr, sx); +- cursor_always_step(cr, fixed_1, sx, 0); ++ cursor_always_step(cr, fixed_1, sx); + y_steps--; + + while (y_steps) { +@@ -1718,30 +1453,25 @@ no_merge: + + /* Phase 3 */ + assert(cr->left <= ex && cr->right >= sx); +- if (phase3_y_steps == 0) +- cursor_null(cr); +- else { +- cursor_right(cr, ex); +- cr->y += phase3_y_steps; +- } ++ cursor_right(cr, ex); ++ cr->y += phase3_y_steps; + } else { + /* Lines decreasing in x. (Leftwards, rising) */ + int phase1_x_steps, phase3_x_steps; + fixed x_steps = sx - ex; + + /* Phase 1: */ ++ cursor_right_merge(cr, sx); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; + sx -= phase1_x_steps; + cursor_left_merge(cr, sx); +- cursor_step(cr, phase1_y_steps, sx, 0); ++ cursor_step(cr, phase1_y_steps, sx); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -1768,7 +1498,7 @@ no_merge: + if (f < 0) + f += d, sx--; + cursor_left_merge(cr, sx); +- cursor_always_step(cr, fixed_1, sx, 0); ++ cursor_always_step(cr, fixed_1, sx); + y_steps--; + + while (y_steps) { +@@ -1784,12 +1514,8 @@ no_merge: + + /* Phase 3 */ + assert(cr->right >= ex && cr->left <= sx); +- if (phase3_y_steps == 0) +- cursor_null(cr); +- else { +- cursor_left(cr, ex); +- cr->y += phase3_y_steps; +- } ++ cursor_left(cr, ex); ++ cr->y += phase3_y_steps; + } + } else { + /* So lines decreasing in y. */ +@@ -1801,21 +1527,34 @@ no_merge: + */ + int phase1_y_steps = sy & (fixed_1 - 1); + int phase3_y_steps = (-ey) & (fixed_1 - 1); +- ufixed y_steps = (ufixed)sy - (ufixed)ey; + +- int skip = cursor_down(cr, sx); ++ y_steps = -y_steps; ++ /* Cope with the awkward 0x80000000 case. */ ++ if (y_steps < 0) ++ { ++ int mx, my; ++ mx = sx + ((ex-sx)>>1); ++ my = sy + ((ey-sy)>>1); ++ mark_line_app(cr, sx, sy, mx, my); ++ mark_line_app(cr, mx, my, ex, ey); ++ return; ++ } ++ ++ cursor_down(cr, sx); + + if (sx == ex) { + /* Vertical line. (Falling) */ + + /* Phase 1: */ ++ cursor_left_merge(cr, sx); ++ cursor_right_merge(cr, sx); + if (phase1_y_steps) { + /* Phase 1 in a falling line never moves us into a new scanline. */ + cursor_never_step_vertical(cr, -phase1_y_steps, sx); + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingLeftOnEdgeOfPixel; ++ goto endFalling; + } + + /* Phase 3: precalculation */ +@@ -1826,8 +1565,7 @@ no_merge: + y_steps = fixed2int(y_steps); + assert(y_steps >= 0); + if (y_steps) { +- cursor_always_step(cr, -fixed_1, sx, skip); +- skip = 0; ++ cursor_always_step(cr, -fixed_1, sx); + y_steps--; + while (y_steps) { + cursor_always_step_inrange_vertical(cr, -fixed_1, sx); +@@ -1836,12 +1574,8 @@ no_merge: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingLeftOnEdgeOfPixel: +- cursor_always_step_inrange_vertical(cr, 0, sx); +- cursor_null(cr); +- } else { +- cursor_step(cr, -phase3_y_steps, sx, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step(cr, -phase3_y_steps, sx); + assert(cr->left == sx && cr->right == sx); + } + } else if (sx < ex) { +@@ -1850,6 +1584,7 @@ endFallingLeftOnEdgeOfPixel: + fixed x_steps = ex - sx; + + /* Phase 1: */ ++ cursor_left_merge(cr, sx); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; +@@ -1859,8 +1594,9 @@ endFallingLeftOnEdgeOfPixel: + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingRightOnEdgeOfPixel; +- } ++ goto endFalling; ++ } else ++ cursor_right_merge(cr, sx); + + /* Phase 3: precalculation */ + phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps); +@@ -1879,8 +1615,7 @@ endFallingLeftOnEdgeOfPixel: + int f = y_steps/2; + int d = y_steps; + +- cursor_always_step(cr, -fixed_1, sx, skip); +- skip = 0; ++ cursor_always_step(cr, -fixed_1, sx); + sx += x_inc; + f -= n_inc; + if (f < 0) +@@ -1900,12 +1635,8 @@ endFallingLeftOnEdgeOfPixel: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingRightOnEdgeOfPixel: +- cursor_always_step_inrange_vertical(cr, 0, sx); +- cursor_null(cr); +- } else { +- cursor_step(cr, -phase3_y_steps, sx, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step(cr, -phase3_y_steps, sx); + cursor_right(cr, ex); + assert(cr->left == sx && cr->right == ex); + } +@@ -1915,6 +1646,7 @@ endFallingRightOnEdgeOfPixel: + fixed x_steps = sx - ex; + + /* Phase 1: */ ++ cursor_right_merge(cr, sx); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; +@@ -1924,8 +1656,9 @@ endFallingRightOnEdgeOfPixel: + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingVerticalOnEdgeOfPixel; +- } ++ goto endFalling; ++ } else ++ cursor_left_merge(cr, sx); + + /* Phase 3: precalculation */ + phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps); +@@ -1944,8 +1677,7 @@ endFallingRightOnEdgeOfPixel: + int f = y_steps/2; + int d = y_steps; + +- cursor_always_step(cr, -fixed_1, sx, skip); +- skip = 0; ++ cursor_always_step(cr, -fixed_1, sx); + sx -= x_inc; + f -= n_inc; + if (f < 0) +@@ -1965,17 +1697,15 @@ endFallingRightOnEdgeOfPixel: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingVerticalOnEdgeOfPixel: +- cursor_always_step_inrange_vertical(cr, 0, sx); +- cursor_null(cr); +- } else { +- cursor_step(cr, -phase3_y_steps, sx, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step(cr, -phase3_y_steps, sx); + cursor_left(cr, ex); + assert(cr->left == ex && cr->right == sx); + } + } +-endFalling: {} ++endFalling: ++ if (truncated) ++ cursor_output(cr, fixed2int(cr->y) - cr->base); + } + + end: +@@ -2011,24 +1741,24 @@ static void mark_curve_app(cursor *cr, fixed sx, fixed sy, fixed c1x, fixed c1y, + } + } + +-static void mark_curve_big_app(cursor *cr, fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, int depth) ++static void mark_curve_big_app(cursor *cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth) + { +- fixed64 ax = (sx + c1x)>>1; +- fixed64 ay = (sy + c1y)>>1; +- fixed64 bx = (c1x + c2x)>>1; +- fixed64 by = (c1y + c2y)>>1; +- fixed64 cx = (c2x + ex)>>1; +- fixed64 cy = (c2y + ey)>>1; +- fixed64 dx = (ax + bx)>>1; +- fixed64 dy = (ay + by)>>1; +- fixed64 fx = (bx + cx)>>1; +- fixed64 fy = (by + cy)>>1; +- fixed64 gx = (dx + fx)>>1; +- fixed64 gy = (dy + fy)>>1; ++ fixed ax = (sx>>1) + (c1x>>1); ++ fixed ay = (sy>>1) + (c1y>>1); ++ fixed bx = (c1x>>1) + (c2x>>1); ++ fixed by = (c1y>>1) + (c2y>>1); ++ fixed cx = (c2x>>1) + (ex>>1); ++ fixed cy = (c2y>>1) + (ey>>1); ++ fixed dx = (ax>>1) + (bx>>1); ++ fixed dy = (ay>>1) + (by>>1); ++ fixed fx = (bx>>1) + (cx>>1); ++ fixed fy = (by>>1) + (cy>>1); ++ fixed gx = (dx>>1) + (fx>>1); ++ fixed gy = (dy>>1) + (fy>>1); + + assert(depth >= 0); + if (depth == 0) +- mark_line_app(cr, (fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey); ++ mark_line_app(cr, sx, sy, ex, ey); + else { + depth--; + mark_curve_big_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth); +@@ -2048,7 +1778,7 @@ static void mark_curve_top_app(cursor *cr, fixed sx, fixed sy, fixed c1x, fixed + + static int make_table_app(gx_device * pdev, + gx_path * path, +- gs_fixed_rect * ibox, ++ const gs_fixed_rect * ibox, + int * scanlines, + int ** index, + int ** table) +@@ -2056,24 +1786,13 @@ static int make_table_app(gx_device * pdev, + return make_table_template(pdev, path, ibox, 2, 0, scanlines, index, table); + } + +-static void +-fill_zero_app(int *row, const fixed *x) +-{ +- int n = *row = (*row)+2; /* Increment the count */ +- row[2*n-3] = (x[0]&~1); +- row[2*n-2] = (x[1]&~1); +- row[2*n-1] = (x[1]&~1)|1; +- row[2*n ] = x[1]; +-} +- +-int gx_scan_convert_app(gx_device * gs_restrict pdev, +- gx_path * gs_restrict path, +- const gs_fixed_rect * gs_restrict clip, +- gx_edgebuffer * gs_restrict edgebuffer, ++int gx_scan_convert_app(gx_device * restrict pdev, ++ gx_path * restrict path, ++ const gs_fixed_rect * restrict clip, ++ gx_edgebuffer * restrict edgebuffer, + fixed fixed_flat) + { + gs_fixed_rect ibox; +- gs_fixed_rect bbox; + int scanlines; + const subpath *psub; + int *index; +@@ -2081,7 +1800,6 @@ int gx_scan_convert_app(gx_device * gs_restrict pdev, + int i; + cursor cr; + int code; +- int zero; + + edgebuffer->index = NULL; + edgebuffer->table = NULL; +@@ -2090,24 +1808,17 @@ int gx_scan_convert_app(gx_device * gs_restrict pdev, + if (path->first_subpath == NULL) + return 0; + +- zero = make_bbox(path, clip, &bbox, &ibox, 0); +- if (zero < 0) +- return zero; ++ code = make_bbox(path, clip, &ibox, 0); ++ if (code < 0) ++ return code; + + if (ibox.q.y <= ibox.p.y) + return 0; + + code = make_table_app(pdev, path, &ibox, &scanlines, &index, &table); +- if (code != 0) /* > 0 means "retry with smaller height" */ ++ if (code < 0) + return code; + +- if (scanlines == 0) +- return 0; +- +- if (zero) { +- code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_app); +- } else { +- + /* Step 2 continued: Now we run through the path, filling in the real + * values. */ + cr.scanlines = scanlines; +@@ -2122,12 +1833,7 @@ int gx_scan_convert_app(gx_device * gs_restrict pdev, + fixed iy = ey; + fixed sx, sy; + +- if ((ey & 0xff) == 0) { +- cr.left = max_fixed; +- cr.right = min_fixed; +- } else { +- cr.left = cr.right = ex; +- } ++ cr.left = cr.right = ex; + cr.y = ey; + cr.d = DIRN_UNSET; + cr.first = 1; +@@ -2166,7 +1872,6 @@ int gx_scan_convert_app(gx_device * gs_restrict pdev, + cursor_flush(&cr, ex); + psub = (const subpath *)pseg; + } +- } + + /* Step 2 complete: We now have a complete list of intersection data in + * table, indexed by index. */ +@@ -2195,9 +1900,9 @@ int gx_scan_convert_app(gx_device * gs_restrict pdev, + if (rowlen <= 6) { + int j, k; + for (j = 0; j < rowlen-1; j++) { +- int * gs_restrict t = &row[j<<1]; ++ int * restrict t = &row[j<<1]; + for (k = j+1; k < rowlen; k++) { +- int * gs_restrict s = &row[k<<1]; ++ int * restrict s = &row[k<<1]; + int tmp; + if (t[0] < s[0]) + continue; +@@ -2221,8 +1926,8 @@ swap01: + + /* Step 5: Filter the intersections according to the rules */ + int +-gx_filter_edgebuffer_app(gx_device * gs_restrict pdev, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_filter_edgebuffer_app(gx_device * restrict pdev, ++ gx_edgebuffer * restrict edgebuffer, + int rule) + { + int i; +@@ -2242,7 +1947,7 @@ gx_filter_edgebuffer_app(gx_device * gs_restrict pdev, + int ll, lr, rl, rr, wind, marked_to; + + /* Avoid double setting pixels, by keeping where we have marked to. */ +- marked_to = INT_MIN; ++ marked_to = 0; + while (rowlen > 0) { + if (rule == gx_rule_even_odd) { + /* Even Odd */ +@@ -2293,7 +1998,7 @@ gx_filter_edgebuffer_app(gx_device * gs_restrict pdev, + } + } + +- if (lr >= ll) { ++ if (lr > ll) { + *rowout++ = ll; + *rowout++ = lr; + marked_to = lr; +@@ -2306,9 +2011,9 @@ gx_filter_edgebuffer_app(gx_device * gs_restrict pdev, + + /* Step 6: Fill */ + int +-gx_fill_edgebuffer_app(gx_device * gs_restrict pdev, +- const gx_device_color * gs_restrict pdevc, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_fill_edgebuffer_app(gx_device * restrict pdev, ++ const gx_device_color * restrict pdevc, ++ gx_edgebuffer * restrict edgebuffer, + int log_op) + { + int i, code; +@@ -2380,7 +2085,7 @@ gx_edgebuffer_print_tr(gx_edgebuffer * edgebuffer) + + static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index, int id) + { +- int64_t delta; ++ int delta; + int iy, ih; + fixed clip_sy, clip_ey; + int dirn = DIRN_UP; +@@ -2420,26 +2125,25 @@ static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int + clip_ey = int2fixed(base_y + height - 1) + fixed_half; + if (sy > clip_ey) + return; +- delta = (int64_t)clip_sy - (int64_t)sy; ++ delta = clip_sy - sy; + if (delta > 0) + { +- int64_t dx = (int64_t)ex - (int64_t)sx; +- int64_t dy = (int64_t)ey - (int64_t)sy; +- int advance = (int)((dx * delta + (dy>>1)) / dy); ++ int dx = ex - sx; ++ int dy = ey - sy; ++ int advance = (int)(((int64_t)dx * delta + (dy>>1)) / dy); + sx += advance; + sy += delta; + } +- delta = (int64_t)ey - (int64_t)clip_ey; ++ ex -= sx; ++ ey -= sy; ++ clip_ey -= clip_sy; ++ delta = ey - clip_ey; + if (delta > 0) + { +- int64_t dx = (int64_t)ex - (int64_t)sx; +- int64_t dy = (int64_t)ey - (int64_t)sy; +- int advance = (int)((dx * delta + (dy>>1)) / dy); ++ int advance = (int)(((int64_t)ex * delta + (ey>>1)) / ey); + ex -= advance; + ey -= delta; + } +- ex -= sx; +- ey -= sy; + ih = fixed2int(ey); + assert(ih >= 0); + iy = fixed2int(sy) - base_y; +@@ -2538,25 +2242,25 @@ static void mark_curve_tr(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, f + } + } + +-static void mark_curve_big_tr(fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, fixed base_y, fixed height, int *table, int *index, int *id, int depth) ++static void mark_curve_big_tr(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int *id, int depth) + { +- fixed64 ax = (sx + c1x)>>1; +- fixed64 ay = (sy + c1y)>>1; +- fixed64 bx = (c1x + c2x)>>1; +- fixed64 by = (c1y + c2y)>>1; +- fixed64 cx = (c2x + ex)>>1; +- fixed64 cy = (c2y + ey)>>1; +- fixed64 dx = (ax + bx)>>1; +- fixed64 dy = (ay + by)>>1; +- fixed64 fx = (bx + cx)>>1; +- fixed64 fy = (by + cy)>>1; +- fixed64 gx = (dx + fx)>>1; +- fixed64 gy = (dy + fy)>>1; ++ fixed ax = (sx>>1) + (c1x>>1); ++ fixed ay = (sy>>1) + (c1y>>1); ++ fixed bx = (c1x>>1) + (c2x>>1); ++ fixed by = (c1y>>1) + (c2y>>1); ++ fixed cx = (c2x>>1) + (ex>>1); ++ fixed cy = (c2y>>1) + (ey>>1); ++ fixed dx = (ax>>1) + (bx>>1); ++ fixed dy = (ay>>1) + (by>>1); ++ fixed fx = (bx>>1) + (cx>>1); ++ fixed fy = (by>>1) + (cy>>1); ++ fixed gx = (dx>>1) + (fx>>1); ++ fixed gy = (dy>>1) + (fy>>1); + + assert(depth >= 0); + if (depth == 0) { + *id += 1; +- mark_line_tr((fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, base_y, height, table, index, *id); ++ mark_line_tr(sx, sy, ex, ey, base_y, height, table, index, *id); + } else { + depth--; + mark_curve_big_tr(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, id, depth); +@@ -2576,32 +2280,21 @@ static void mark_curve_top_tr(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2 + + static int make_table_tr(gx_device * pdev, + gx_path * path, +- gs_fixed_rect * ibox, ++ const gs_fixed_rect * ibox, + int * scanlines, + int ** index, + int ** table) + { +- return make_table_template(pdev, path, ibox, 2, 1, scanlines, index, table); +-} +- +-static void +-fill_zero_tr(int *row, const fixed *x) +-{ +- int n = *row = (*row)+2; /* Increment the count */ +- row[2*n-3] = x[0]; +- row[2*n-2] = 0; +- row[2*n-1] = x[1]; +- row[2*n ] = 1; ++ return make_table_template(pdev, path, ibox, 2, fixed_half-1, scanlines, index, table); + } + +-int gx_scan_convert_tr(gx_device * gs_restrict pdev, +- gx_path * gs_restrict path, +- const gs_fixed_rect * gs_restrict clip, +- gx_edgebuffer * gs_restrict edgebuffer, ++int gx_scan_convert_tr(gx_device * restrict pdev, ++ gx_path * restrict path, ++ const gs_fixed_rect * restrict clip, ++ gx_edgebuffer * restrict edgebuffer, + fixed fixed_flat) + { + gs_fixed_rect ibox; +- gs_fixed_rect bbox; + int scanlines; + const subpath *psub; + int *index; +@@ -2609,7 +2302,6 @@ int gx_scan_convert_tr(gx_device * gs_restrict pdev, + int i; + int code; + int id = 0; +- int zero; + + edgebuffer->index = NULL; + edgebuffer->table = NULL; +@@ -2618,24 +2310,17 @@ int gx_scan_convert_tr(gx_device * gs_restrict pdev, + if (path->first_subpath == NULL) + return 0; + +- zero = make_bbox(path, clip, &bbox, &ibox, fixed_half); +- if (zero < 0) +- return zero; ++ code = make_bbox(path, clip, &ibox, fixed_half); ++ if (code < 0) ++ return code; + + if (ibox.q.y <= ibox.p.y) + return 0; + + code = make_table_tr(pdev, path, &ibox, &scanlines, &index, &table); +- if (code != 0) /* > 0 means "retry with smaller height" */ ++ if (code < 0) + return code; + +- if (scanlines == 0) +- return 0; +- +- if (zero) { +- code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_tr); +- } else { +- + /* Step 3: Now we run through the path, filling in the real + * values. */ + for (psub = path->first_subpath; psub != 0;) { +@@ -2679,18 +2364,6 @@ int gx_scan_convert_tr(gx_device * gs_restrict pdev, + mark_line_tr(ex, ey, ix, iy, ibox.p.y, scanlines, table, index, ++id); + psub = (const subpath *)pseg; + } +- } +- +- //if (zero) { +- // if (table[0] == 0) { +- // /* Zero height rectangle fills a span */ +- // table[0] = 2; +- // table[1] = int2fixed(fixed2int(bbox.p.x + fixed_half)); +- // table[2] = 0; +- // table[3] = int2fixed(fixed2int(bbox.q.x + fixed_half)); +- // table[4] = 1; +- // } +- //} + + /* Step 2 complete: We now have a complete list of intersection data in + * table, indexed by index. */ +@@ -2719,9 +2392,9 @@ int gx_scan_convert_tr(gx_device * gs_restrict pdev, + if (rowlen <= 6) { + int j, k; + for (j = 0; j < rowlen-1; j++) { +- int * gs_restrict t = &row[j<<1]; ++ int * restrict t = &row[j<<1]; + for (k = j+1; k < rowlen; k++) { +- int * gs_restrict s = &row[k<<1]; ++ int * restrict s = &row[k<<1]; + int tmp; + if (t[0] < s[0]) + continue; +@@ -2742,9 +2415,9 @@ int gx_scan_convert_tr(gx_device * gs_restrict pdev, + + /* Step 5: Filter the intersections according to the rules */ + int +-gx_filter_edgebuffer_tr(gx_device * gs_restrict pdev, +- gx_edgebuffer * gs_restrict edgebuffer, +- int rule) ++gx_filter_edgebuffer_tr(gx_device * restrict pdev, ++ gx_edgebuffer * restrict edgebuffer, ++ int rule) + { + int i; + +@@ -2801,13 +2474,12 @@ gx_filter_edgebuffer_tr(gx_device * gs_restrict pdev, + + /* Step 6: Fill the edgebuffer */ + int +-gx_fill_edgebuffer_tr(gx_device * gs_restrict pdev, +- const gx_device_color * gs_restrict pdevc, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_fill_edgebuffer_tr(gx_device * restrict pdev, ++ const gx_device_color * restrict pdevc, ++ gx_edgebuffer * restrict edgebuffer, + int log_op) + { + int i, j, code; +- int mfb = pdev->max_fill_band; + + #ifdef DEBUG_SCAN_CONVERTER + if (debugging_scan_converter) { +@@ -2822,18 +2494,9 @@ gx_fill_edgebuffer_tr(gx_device * gs_restrict pdev, + int *row2; + int *rowptr; + int *row2ptr; +- int y_band_max; +- +- if (mfb) { +- y_band_max = (i & ~(mfb-1)) + mfb; +- if (y_band_max > edgebuffer->height) +- y_band_max = edgebuffer->height; +- } else { +- y_band_max = edgebuffer->height; +- } + + /* See how many scanlines match i */ +- for (j = i+1; j < y_band_max; j++) { ++ for (j = i+1; j < edgebuffer->height; j++) { + int row2len; + + row2 = &edgebuffer->table[edgebuffer->index[j]]; +@@ -2931,6 +2594,8 @@ rowdifferent:{} + row2 += 4; + rowlen -= 2; + ++ assert(le.start.x >= 0); ++ assert(le.end.x >= 0); + assert(re.start.x >= le.start.x); + assert(re.end.x >= le.end.x); + +@@ -3074,7 +2739,7 @@ typedef struct + } cursor_tr; + + static inline void +-cursor_output_tr(cursor_tr * gs_restrict cr, int iy) ++cursor_output_tr(cursor_tr * restrict cr, int iy) + { + int *row; + int count; +@@ -3089,23 +2754,23 @@ cursor_output_tr(cursor_tr * gs_restrict cr, int iy) + cr->save_iy = iy; + cr->save_d = cr->d; + cr->saved = 1; +- } else if (cr->d != DIRN_UNSET) { ++ } else { + /* Enter it into the table */ ++ assert(cr->d != DIRN_UNSET); ++ + row = &cr->table[cr->index[iy]]; + *row = count = (*row)+1; /* Increment the count */ + row[4 * count - 3] = cr->left; + row[4 * count - 2] = cr->d | (cr->lid<<1); + row[4 * count - 1] = cr->right; + row[4 * count ] = cr->rid; +- } else { +- assert(cr->left == max_fixed && cr->right == min_fixed); + } + } + cr->first = 0; + } + + static inline void +-cursor_output_inrange_tr(cursor_tr * gs_restrict cr, int iy) ++cursor_output_inrange_tr(cursor_tr * restrict cr, int iy) + { + int *row; + int count; +@@ -3136,7 +2801,7 @@ cursor_output_inrange_tr(cursor_tr * gs_restrict cr, int iy) + + /* Step the cursor in y, allowing for maybe crossing a scanline */ + static inline void +-cursor_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip) ++cursor_step_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + int new_iy; + int iy = fixed2int(cr->y) - cr->base; +@@ -3144,18 +2809,19 @@ cursor_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip) + cr->y += dy; + new_iy = fixed2int(cr->y) - cr->base; + if (new_iy != iy) { +- if (!skip) +- cursor_output_tr(cr, iy); ++ cursor_output_tr(cr, iy); + cr->left = x; + cr->lid = id; + cr->right = x; + cr->rid = id; + } else { +- if (x < cr->left) { ++ if (x < cr->left) ++ { + cr->left = x; + cr->lid = id; + } +- if (x > cr->right) { ++ if (x > cr->right) ++ { + cr->right = x; + cr->rid = id; + } +@@ -3164,7 +2830,7 @@ cursor_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip) + + /* Step the cursor in y, never by enough to cross a scanline. */ + static inline void +-cursor_never_step_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_never_step_vertical_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -3175,7 +2841,7 @@ cursor_never_step_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int + * knowing that we are moving left, and that the right edge + * has already been accounted for. */ + static inline void +-cursor_never_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_never_step_left_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -3191,7 +2857,7 @@ cursor_never_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) + * knowing that we are moving right, and that the left edge + * has already been accounted for. */ + static inline void +-cursor_never_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_never_step_right_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + assert(fixed2int(cr->y+dy) == fixed2int(cr->y)); + +@@ -3205,12 +2871,11 @@ cursor_never_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id + + /* Step the cursor in y, always by enough to cross a scanline. */ + static inline void +-cursor_always_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip) ++cursor_always_step_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + int iy = fixed2int(cr->y) - cr->base; + +- if (!skip) +- cursor_output_tr(cr, iy); ++ cursor_output_tr(cr, iy); + cr->y += dy; + cr->left = x; + cr->lid = id; +@@ -3222,7 +2887,7 @@ cursor_always_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int + * part of a vertical line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_step_inrange_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_always_step_inrange_vertical_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -3234,7 +2899,7 @@ cursor_always_step_inrange_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fix + * part of a left moving line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_inrange_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_always_inrange_step_left_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -3248,7 +2913,7 @@ cursor_always_inrange_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x + * part of a right moving line, knowing that we are moving from a + * position guaranteed to be in the valid y range. */ + static inline void +-cursor_always_inrange_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id) ++cursor_always_inrange_step_right_tr(cursor_tr * restrict cr, fixed dy, fixed x, int id) + { + int iy = fixed2int(cr->y) - cr->base; + +@@ -3258,7 +2923,7 @@ cursor_always_inrange_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed + cr->lid = id; + } + +-static inline void cursor_init_tr(cursor_tr * gs_restrict cr, fixed y, fixed x, int id) ++static inline void cursor_init_tr(cursor_tr * restrict cr, fixed y, fixed x, int id) + { + assert(y >= int2fixed(cr->base) && y <= int2fixed(cr->base + cr->scanlines)); + +@@ -3270,7 +2935,7 @@ static inline void cursor_init_tr(cursor_tr * gs_restrict cr, fixed y, fixed x, + cr->d = DIRN_UNSET; + } + +-static inline void cursor_left_merge_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_left_merge_tr(cursor_tr * restrict cr, fixed x, int id) + { + if (x < cr->left) { + cr->left = x; +@@ -3278,13 +2943,13 @@ static inline void cursor_left_merge_tr(cursor_tr * gs_restrict cr, fixed x, int + } + } + +-static inline void cursor_left_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_left_tr(cursor_tr * restrict cr, fixed x, int id) + { + cr->left = x; + cr->lid = id; + } + +-static inline void cursor_right_merge_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_right_merge_tr(cursor_tr * restrict cr, fixed x, int id) + { + if (x > cr->right) { + cr->right = x; +@@ -3292,31 +2957,26 @@ static inline void cursor_right_merge_tr(cursor_tr * gs_restrict cr, fixed x, in + } + } + +-static inline void cursor_right_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_right_tr(cursor_tr * restrict cr, fixed x, int id) + { + cr->right = x; + cr->rid = id; + } + +-static inline int cursor_down_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_down_tr(cursor_tr * restrict cr, fixed x, int id) + { +- int skip = 0; +- if ((cr->y & 0xff) == 0) +- skip = 1; + if (cr->d == DIRN_UP) + { +- if (!skip) +- cursor_output_tr(cr, fixed2int(cr->y) - cr->base); ++ cursor_output_tr(cr, fixed2int(cr->y) - cr->base); + cr->left = x; + cr->lid = id; + cr->right = x; + cr->rid = id; + } + cr->d = DIRN_DOWN; +- return skip; + } + +-static inline void cursor_up_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++static inline void cursor_up_tr(cursor_tr * restrict cr, fixed x, int id) + { + if (cr->d == DIRN_DOWN) + { +@@ -3330,7 +2990,7 @@ static inline void cursor_up_tr(cursor_tr * gs_restrict cr, fixed x, int id) + } + + static inline void +-cursor_flush_tr(cursor_tr * gs_restrict cr, fixed x, int id) ++cursor_flush_tr(cursor_tr * restrict cr, fixed x, int id) + { + int iy; + +@@ -3339,11 +2999,6 @@ cursor_flush_tr(cursor_tr * gs_restrict cr, fixed x, int id) + * rectangle from the start point. */ + if (cr->first) { + int iy = fixed2int(cr->y) - cr->base; +- /* Any zero height rectangle counts as filled, except +- * those on the baseline of a pixel. */ +- if (cr->d == DIRN_UNSET && (cr->y & 0xff) == 0) +- return; +- assert(cr->left != max_fixed && cr->right != min_fixed); + if (iy >= 0 && iy < cr->scanlines) { + int *row = &cr->table[cr->index[iy]]; + int count = *row = (*row)+2; /* Increment the count */ +@@ -3389,23 +3044,16 @@ cursor_flush_tr(cursor_tr * gs_restrict cr, fixed x, int id) + } + } + +-static inline void +-cursor_null_tr(cursor_tr *cr) +-{ +- cr->right = min_fixed; +- cr->left = max_fixed; +- cr->d = DIRN_UNSET; +-} +- +-static void mark_line_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed ex, fixed ey, int id) ++static void mark_line_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed ex, fixed ey, int id) + { + int isy, iey; ++ fixed y_steps; + fixed saved_sy = sy; + fixed saved_ex = ex; + fixed saved_ey = ey; + int truncated; + +- if (sy == ey && sx == ex) ++ if (sx == ex && sy == ey) + return; + + isy = fixed2int(sy) - cr->base; +@@ -3422,50 +3070,39 @@ static void mark_line_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fix + dlprintf("stroke %%PS\n"); + #endif + +- /* Horizontal motion at the bottom of a pixel is ignored */ +- if (sy == ey && (sy & 0xff) == 0) +- return; +- +- assert(cr->y == sy && +- ((cr->left <= sx && cr->right >= sx) || ((sy & 0xff) == 0)) && +- cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN); ++ assert(cr->y == sy && cr->left <= sx && cr->right >= sx && cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN); + + if (isy < iey) { + /* Rising line */ + if (iey < 0 || isy >= cr->scanlines) { + /* All line is outside. */ +- if ((ey & 0xff) == 0) { +- cursor_null_tr(cr); +- } else { +- cr->left = ex; +- cr->lid = id; +- cr->right = ex; +- cr->rid = id; +- } + cr->y = ey; ++ cr->left = ex; ++ cr->lid = id; ++ cr->right = ex; ++ cr->rid = id; + cr->first = 0; + return; + } + if (isy < 0) { + /* Move sy up */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_sy = int2fixed(cr->base); +- int64_t dy = (int64_t)new_sy - (int64_t)sy; +- sx += (int)(((((int64_t)ex-sx))*dy + y/2)/y); ++ int y = ey - sy; ++ int new_sy = int2fixed(cr->base); ++ int dy = new_sy - sy; ++ sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; +- cursor_null_tr(cr); +- cr->y = sy; ++ cursor_init_tr(cr, sy, sx, id); + isy = 0; + } + truncated = iey > cr->scanlines; + if (truncated) { + /* Move ey down */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_ey = int2fixed(cr->base + cr->scanlines); +- int64_t dy = (int64_t)ey - (int64_t)new_ey; ++ int y = ey - sy; ++ int new_ey = int2fixed(cr->base + cr->scanlines); ++ int dy = ey - new_ey; + saved_ex = ex; + saved_ey = ey; +- ex -= (int)(((((int64_t)ex-sx))*dy + y/2)/y); ++ ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); + ey = new_ey; + iey = cr->scanlines; + } +@@ -3473,44 +3110,36 @@ static void mark_line_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fix + /* Falling line */ + if (isy < 0 || iey >= cr->scanlines) { + /* All line is outside. */ +- if ((ey & 0xff) == 0) { +- cursor_null_tr(cr); +- } else { +- cr->left = ex; +- cr->lid = id; +- cr->right = ex; +- cr->rid = id; +- } + cr->y = ey; ++ cr->left = ex; ++ cr->lid = id; ++ cr->right = ex; ++ cr->rid = id; + cr->first = 0; + return; + } + truncated = iey < 0; + if (truncated) { + /* Move ey up */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_ey = int2fixed(cr->base); +- int64_t dy = (int64_t)ey - (int64_t)new_ey; +- ex -= (int)(((((int64_t)ex-sx))*dy + y/2)/y); ++ int y = ey - sy; ++ int new_ey = int2fixed(cr->base); ++ int dy = ey - new_ey; ++ ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); + ey = new_ey; + iey = 0; + } + if (isy >= cr->scanlines) { + /* Move sy down */ +- int64_t y = (int64_t)ey - (int64_t)sy; +- fixed new_sy = int2fixed(cr->base + cr->scanlines); +- int64_t dy = (int64_t)new_sy - (int64_t)sy; +- sx += (int)(((((int64_t)ex-sx))*dy + y/2)/y); ++ int y = ey - sy; ++ int new_sy = int2fixed(cr->base + cr->scanlines); ++ int dy = new_sy - sy; ++ sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; +- cursor_null_tr(cr); +- cr->y = sy; ++ cursor_init_tr(cr, sy, sx, id); + isy = cr->scanlines; + } + } + +- cursor_left_merge_tr(cr, sx, id); +- cursor_right_merge_tr(cr, sx, id); +- + assert(cr->left <= sx); + assert(cr->right >= sx); + assert(cr->y == sy); +@@ -3538,44 +3167,24 @@ static void mark_line_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fix + if (isy == iey) { + if (saved_sy == saved_ey) { + /* Horizontal line. Don't change cr->d, don't flush. */ +- if ((ey & 0xff) == 0) { +- cursor_null_tr(cr); +- goto no_merge; +- } + } else if (saved_sy > saved_ey) { + /* Falling line, flush if previous was rising */ +- int skip = cursor_down_tr(cr, sx, id); +- if ((ey & 0xff) == 0) { +- /* We are falling to the baseline of a subpixel, so output +- * for the current pixel, and leave the cursor nulled. */ +- if (sx <= ex) { +- cursor_right_merge_tr(cr, ex, id); +- } else { +- cursor_left_merge_tr(cr, ex, id); +- } +- if (!skip) +- cursor_output_tr(cr, fixed2int(cr->y) - cr->base); +- cursor_null_tr(cr); +- goto no_merge; +- } ++ cursor_down_tr(cr, sx, id); + } else { + /* Rising line, flush if previous was falling */ + cursor_up_tr(cr, sx, id); +- if ((ey & 0xff) == 0) { +- cursor_null_tr(cr); +- goto no_merge; +- } + } + if (sx <= ex) { ++ cursor_left_merge_tr(cr, sx, id); + cursor_right_merge_tr(cr, ex, id); + } else { + cursor_left_merge_tr(cr, ex, id); ++ cursor_right_merge_tr(cr, sx, id); + } +-no_merge: + cr->y = ey; + if (sy > saved_ey) + goto endFalling; +- } else if (iey > isy) { ++ } else if ((y_steps = ey - sy) > 0) { + /* So lines increasing in y. */ + /* We want to change from sy to ey, which are guaranteed to be on + * different scanlines. We do this in 3 phases. +@@ -3585,7 +3194,6 @@ no_merge: + */ + int phase1_y_steps = (-sy) & (fixed_1 - 1); + int phase3_y_steps = ey & (fixed_1 - 1); +- ufixed y_steps = (ufixed)ey - (ufixed)sy; + + cursor_up_tr(cr, sx, id); + +@@ -3593,16 +3201,16 @@ no_merge: + /* Vertical line. (Rising) */ + + /* Phase 1: */ ++ cursor_left_merge_tr(cr, sx, id); ++ cursor_right_merge_tr(cr, sx, id); + if (phase1_y_steps) { + /* If phase 1 will move us into a new scanline, then we must + * flush it before we move. */ +- cursor_step_tr(cr, phase1_y_steps, sx, id, 0); ++ cursor_step_tr(cr, phase1_y_steps, sx, id); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null_tr(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -3612,7 +3220,7 @@ no_merge: + y_steps = fixed2int(y_steps); + assert(y_steps >= 0); + if (y_steps > 0) { +- cursor_always_step_tr(cr, fixed_1, sx, id, 0); ++ cursor_always_step_tr(cr, fixed_1, sx, id); + y_steps--; + while (y_steps) { + cursor_always_step_inrange_vertical_tr(cr, fixed_1, sx, id); +@@ -3622,30 +3230,24 @@ no_merge: + + /* Phase 3 */ + assert(cr->left == sx && cr->right == sx && cr->lid == id && cr->rid == id); +- if (phase3_y_steps == 0) +- cursor_null_tr(cr); +- else +- cr->y += phase3_y_steps; ++ cr->y += phase3_y_steps; + } else if (sx < ex) { + /* Lines increasing in x. (Rightwards, rising) */ + int phase1_x_steps, phase3_x_steps; +- /* Use unsigned int here, to allow for extreme cases like +- * ex = 0x7fffffff, sx = 0x80000000 */ +- unsigned int x_steps = ex - sx; ++ fixed x_steps = ex - sx; + + /* Phase 1: */ ++ cursor_left_merge_tr(cr, sx, id); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + sx += phase1_x_steps; + cursor_right_merge_tr(cr, sx, id); + x_steps -= phase1_x_steps; +- cursor_step_tr(cr, phase1_y_steps, sx, id, 0); ++ cursor_step_tr(cr, phase1_y_steps, sx, id); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null_tr(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -3672,7 +3274,7 @@ no_merge: + if (f < 0) + f += d, sx++; + cursor_right_merge_tr(cr, sx, id); +- cursor_always_step_tr(cr, fixed_1, sx, id, 0); ++ cursor_always_step_tr(cr, fixed_1, sx, id); + y_steps--; + + while (y_steps) { +@@ -3688,32 +3290,25 @@ no_merge: + + /* Phase 3 */ + assert(cr->left <= ex && cr->lid == id && cr->right >= sx); +- if (phase3_y_steps == 0) +- cursor_null_tr(cr); +- else { +- cursor_right_tr(cr, ex, id); +- cr->y += phase3_y_steps; +- } ++ cursor_right_tr(cr, ex, id); ++ cr->y += phase3_y_steps; + } else { + /* Lines decreasing in x. (Leftwards, rising) */ + int phase1_x_steps, phase3_x_steps; +- /* Use unsigned int here, to allow for extreme cases like +- * sx = 0x7fffffff, ex = 0x80000000 */ +- unsigned int x_steps = sx - ex; ++ fixed x_steps = sx - ex; + + /* Phase 1: */ ++ cursor_right_merge_tr(cr, sx, id); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; + sx -= phase1_x_steps; + cursor_left_merge_tr(cr, sx, id); +- cursor_step_tr(cr, phase1_y_steps, sx, id, 0); ++ cursor_step_tr(cr, phase1_y_steps, sx, id); + sy += phase1_y_steps; + y_steps -= phase1_y_steps; +- if (y_steps == 0) { +- cursor_null_tr(cr); ++ if (y_steps == 0) + goto end; +- } + } + + /* Phase 3: precalculation */ +@@ -3723,7 +3318,7 @@ no_merge: + assert((y_steps & (fixed_1 - 1)) == 0); + + /* Phase 2: */ +- y_steps = fixed2int((unsigned int)y_steps); ++ y_steps = fixed2int(y_steps); + assert(y_steps >= 0); + if (y_steps) { + /* We want to change sx by x_steps in y_steps steps. +@@ -3740,7 +3335,7 @@ no_merge: + if (f < 0) + f += d, sx--; + cursor_left_merge_tr(cr, sx, id); +- cursor_always_step_tr(cr, fixed_1, sx, id, 0); ++ cursor_always_step_tr(cr, fixed_1, sx, id); + y_steps--; + + while (y_steps) { +@@ -3756,12 +3351,8 @@ no_merge: + + /* Phase 3 */ + assert(cr->right >= ex && cr->rid == id && cr->left <= sx); +- if (phase3_y_steps == 0) +- cursor_null_tr(cr); +- else { +- cursor_left_tr(cr, ex, id); +- cr->y += phase3_y_steps; +- } ++ cursor_left_tr(cr, ex, id); ++ cr->y += phase3_y_steps; + } + } else { + /* So lines decreasing in y. */ +@@ -3773,21 +3364,34 @@ no_merge: + */ + int phase1_y_steps = sy & (fixed_1 - 1); + int phase3_y_steps = (-ey) & (fixed_1 - 1); +- ufixed y_steps = (ufixed)sy - (ufixed)ey; + +- int skip = cursor_down_tr(cr, sx, id); ++ y_steps = -y_steps; ++ /* Cope with the awkward 0x80000000 case. */ ++ if (y_steps < 0) ++ { ++ int mx, my; ++ mx = sx + ((ex-sx)>>1); ++ my = sy + ((ey-sy)>>1); ++ mark_line_tr_app(cr, sx, sy, mx, my, id); ++ mark_line_tr_app(cr, mx, my, ex, ey, id); ++ return; ++ } ++ ++ cursor_down_tr(cr, sx, id); + + if (sx == ex) { + /* Vertical line. (Falling) */ + + /* Phase 1: */ ++ cursor_left_merge_tr(cr, sx, id); ++ cursor_right_merge_tr(cr, sx, id); + if (phase1_y_steps) { + /* Phase 1 in a falling line never moves us into a new scanline. */ + cursor_never_step_vertical_tr(cr, -phase1_y_steps, sx, id); + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingLeftOnEdgeOfPixel; ++ goto endFalling; + } + + /* Phase 3: precalculation */ +@@ -3798,8 +3402,7 @@ no_merge: + y_steps = fixed2int(y_steps); + assert(y_steps >= 0); + if (y_steps) { +- cursor_always_step_tr(cr, -fixed_1, sx, id, skip); +- skip = 0; ++ cursor_always_step_tr(cr, -fixed_1, sx, id); + y_steps--; + while (y_steps) { + cursor_always_step_inrange_vertical_tr(cr, -fixed_1, sx, id); +@@ -3808,22 +3411,17 @@ no_merge: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingLeftOnEdgeOfPixel: +- cursor_always_step_inrange_vertical_tr(cr, 0, sx, id); +- cursor_null_tr(cr); +- } else { +- cursor_step_tr(cr, -phase3_y_steps, sx, id, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step_tr(cr, -phase3_y_steps, sx, id); + assert(cr->left == sx && cr->lid == id && cr->right == sx && cr->rid == id); + } + } else if (sx < ex) { + /* Lines increasing in x. (Rightwards, falling) */ + int phase1_x_steps, phase3_x_steps; +- /* Use unsigned int here, to allow for extreme cases like +- * ex = 0x7fffffff, sx = 0x80000000 */ +- unsigned int x_steps = ex - sx; ++ fixed x_steps = ex - sx; + + /* Phase 1: */ ++ cursor_left_merge_tr(cr, sx, id); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; +@@ -3833,8 +3431,9 @@ endFallingLeftOnEdgeOfPixel: + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingRightOnEdgeOfPixel; +- } ++ goto endFalling; ++ } else ++ cursor_right_merge_tr(cr, sx, id); + + /* Phase 3: precalculation */ + phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps); +@@ -3853,8 +3452,7 @@ endFallingLeftOnEdgeOfPixel: + int f = y_steps/2; + int d = y_steps; + +- cursor_always_step_tr(cr, -fixed_1, sx, id, skip); +- skip = 0; ++ cursor_always_step_tr(cr, -fixed_1, sx, id); + sx += x_inc; + f -= n_inc; + if (f < 0) +@@ -3874,23 +3472,18 @@ endFallingLeftOnEdgeOfPixel: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingRightOnEdgeOfPixel: +- cursor_always_step_inrange_vertical_tr(cr, 0, sx, id); +- cursor_null_tr(cr); +- } else { +- cursor_step_tr(cr, -phase3_y_steps, sx, id, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step_tr(cr, -phase3_y_steps, sx, id); + cursor_right_tr(cr, ex, id); + assert(cr->left == sx && cr->lid == id && cr->right == ex && cr->rid == id); + } + } else { + /* Lines decreasing in x. (Falling) */ + int phase1_x_steps, phase3_x_steps; +- /* Use unsigned int here, to allow for extreme cases like +- * sx = 0x7fffffff, ex = 0x80000000 */ +- unsigned int x_steps = sx - ex; ++ fixed x_steps = sx - ex; + + /* Phase 1: */ ++ cursor_right_merge_tr(cr, sx, id); + if (phase1_y_steps) { + phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps); + x_steps -= phase1_x_steps; +@@ -3900,8 +3493,9 @@ endFallingRightOnEdgeOfPixel: + sy -= phase1_y_steps; + y_steps -= phase1_y_steps; + if (y_steps == 0) +- goto endFallingVerticalOnEdgeOfPixel; +- } ++ goto endFalling; ++ } else ++ cursor_left_merge_tr(cr, sx, id); + + /* Phase 3: precalculation */ + phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps); +@@ -3920,8 +3514,7 @@ endFallingRightOnEdgeOfPixel: + int f = y_steps/2; + int d = y_steps; + +- cursor_always_step_tr(cr, -fixed_1, sx, id, skip); +- skip = 0; ++ cursor_always_step_tr(cr, -fixed_1, sx, id); + sx -= x_inc; + f -= n_inc; + if (f < 0) +@@ -3941,17 +3534,17 @@ endFallingRightOnEdgeOfPixel: + } + + /* Phase 3 */ +- if (phase3_y_steps == 0) { +-endFallingVerticalOnEdgeOfPixel: +- cursor_always_step_inrange_vertical_tr(cr, 0, sx, id); +- cursor_null_tr(cr); +- } else { +- cursor_step_tr(cr, -phase3_y_steps, sx, id, skip); ++ if (phase3_y_steps > 0) { ++ cursor_step_tr(cr, -phase3_y_steps, sx, id); + cursor_left_tr(cr, ex, id); + assert(cr->left == ex && cr->lid == id && cr->right == sx && cr->rid == id); + } + } +-endFalling: {} ++endFalling: ++ if (truncated) ++ { ++ cursor_output_tr(cr, fixed2int(cr->y) - cr->base); ++ } + } + + end: +@@ -3964,7 +3557,7 @@ end: + } + } + +-static void mark_curve_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * gs_restrict id) ++static void mark_curve_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * restrict id) + { + int ax = (sx + c1x)>>1; + int ay = (sy + c1y)>>1; +@@ -3990,25 +3583,25 @@ static void mark_curve_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fi + } + } + +-static void mark_curve_big_tr_app(cursor_tr * gs_restrict cr, fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, int depth, int * gs_restrict id) ++static void mark_curve_big_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * restrict id) + { +- fixed64 ax = (sx + c1x)>>1; +- fixed64 ay = (sy + c1y)>>1; +- fixed64 bx = (c1x + c2x)>>1; +- fixed64 by = (c1y + c2y)>>1; +- fixed64 cx = (c2x + ex)>>1; +- fixed64 cy = (c2y + ey)>>1; +- fixed64 dx = (ax + bx)>>1; +- fixed64 dy = (ay + by)>>1; +- fixed64 fx = (bx + cx)>>1; +- fixed64 fy = (by + cy)>>1; +- fixed64 gx = (dx + fx)>>1; +- fixed64 gy = (dy + fy)>>1; ++ fixed ax = (sx>>1) + (c1x>>1); ++ fixed ay = (sy>>1) + (c1y>>1); ++ fixed bx = (c1x>>1) + (c2x>>1); ++ fixed by = (c1y>>1) + (c2y>>1); ++ fixed cx = (c2x>>1) + (ex>>1); ++ fixed cy = (c2y>>1) + (ey>>1); ++ fixed dx = (ax>>1) + (bx>>1); ++ fixed dy = (ay>>1) + (by>>1); ++ fixed fx = (bx>>1) + (cx>>1); ++ fixed fy = (by>>1) + (cy>>1); ++ fixed gx = (dx>>1) + (fx>>1); ++ fixed gy = (dy>>1) + (fy>>1); + + assert(depth >= 0); + if (depth == 0) { + *id += 1; +- mark_line_tr_app(cr, (fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, *id); ++ mark_line_tr_app(cr, sx, sy, ex, ey, *id); + } else { + depth--; + mark_curve_big_tr_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth, id); +@@ -4016,7 +3609,7 @@ static void mark_curve_big_tr_app(cursor_tr * gs_restrict cr, fixed64 sx, fixed6 + } + } + +-static void mark_curve_top_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * gs_restrict id) ++static void mark_curve_top_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * restrict id) + { + fixed test = (sx^(sx<<1))|(sy^(sy<<1))|(c1x^(c1x<<1))|(c1y^(c1y<<1))|(c2x^(c2x<<1))|(c2y^(c2y<<1))|(ex^(ex<<1))|(ey^(ey<<1)); + +@@ -4028,7 +3621,7 @@ static void mark_curve_top_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy + + static int make_table_tr_app(gx_device * pdev, + gx_path * path, +- gs_fixed_rect * ibox, ++ const gs_fixed_rect * ibox, + int * scanlines, + int ** index, + int ** table) +@@ -4036,28 +3629,13 @@ static int make_table_tr_app(gx_device * pdev, + return make_table_template(pdev, path, ibox, 4, 0, scanlines, index, table); + } + +-static void +-fill_zero_app_tr(int *row, const fixed *x) +-{ +- int n = *row = (*row)+2; /* Increment the count */ +- row[4*n-7] = x[0]; +- row[4*n-6] = 0; +- row[4*n-5] = x[1]; +- row[4*n-4] = 0; +- row[4*n-3] = x[1]; +- row[4*n-2] = (1<<1)|1; +- row[4*n-1] = x[1]; +- row[4*n ] = 1; +-} +- +-int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, +- gx_path * gs_restrict path, +- const gs_fixed_rect * gs_restrict clip, +- gx_edgebuffer * gs_restrict edgebuffer, ++int gx_scan_convert_tr_app(gx_device * restrict pdev, ++ gx_path * restrict path, ++ const gs_fixed_rect * restrict clip, ++ gx_edgebuffer * restrict edgebuffer, + fixed fixed_flat) + { + gs_fixed_rect ibox; +- gs_fixed_rect bbox; + int scanlines; + const subpath *psub; + int *index; +@@ -4066,7 +3644,6 @@ int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, + cursor_tr cr; + int code; + int id = 0; +- int zero; + + edgebuffer->index = NULL; + edgebuffer->table = NULL; +@@ -4075,24 +3652,17 @@ int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, + if (path->first_subpath == NULL) + return 0; + +- zero = make_bbox(path, clip, &bbox, &ibox, 0); +- if (zero < 0) +- return zero; ++ code = make_bbox(path, clip, &ibox, 0); ++ if (code < 0) ++ return code; + + if (ibox.q.y <= ibox.p.y) + return 0; + + code = make_table_tr_app(pdev, path, &ibox, &scanlines, &index, &table); +- if (code != 0) /* > 0 means "retry with smaller height" */ ++ if (code < 0) + return code; + +- if (scanlines == 0) +- return 0; +- +- if (zero) { +- code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_app_tr); +- } else { +- + /* Step 2 continued: Now we run through the path, filling in the real + * values. */ + cr.scanlines = scanlines; +@@ -4107,12 +3677,7 @@ int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, + fixed iy = ey; + fixed sx, sy; + +- if ((ey & 0xff) == 0) { +- cr.left = max_fixed; +- cr.right = min_fixed; +- } else { +- cr.left = cr.right = ex; +- } ++ cr.left = cr.right = ex; + cr.lid = cr.rid = id+1; + cr.y = ey; + cr.d = DIRN_UNSET; +@@ -4152,7 +3717,6 @@ int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, + cursor_flush_tr(&cr, ex, id); + psub = (const subpath *)pseg; + } +- } + + /* Step 2 complete: We now have a complete list of intersection data in + * table, indexed by index. */ +@@ -4181,9 +3745,9 @@ int gx_scan_convert_tr_app(gx_device * gs_restrict pdev, + if (rowlen <= 6) { + int j, k; + for (j = 0; j < rowlen-1; j++) { +- int * gs_restrict t = &row[j<<2]; ++ int * restrict t = &row[j<<2]; + for (k = j+1; k < rowlen; k++) { +- int * gs_restrict s = &row[k<<2]; ++ int * restrict s = &row[k<<2]; + int tmp; + if (t[0] < s[0]) + continue; +@@ -4219,8 +3783,8 @@ swap13: + + /* Step 5: Filter the intersections according to the rules */ + int +-gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_filter_edgebuffer_tr_app(gx_device * restrict pdev, ++ gx_edgebuffer * restrict edgebuffer, + int rule) + { + int i; +@@ -4241,7 +3805,7 @@ gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, + int ll, llid, lr, lrid, rlid, rr, rrid, wind, marked_to; + + /* Avoid double setting pixels, by keeping where we have marked to. */ +- marked_to = INT_MIN; ++ marked_to = 0; + while (rowlen > 0) { + if (rule == gx_rule_even_odd) { + /* Even Odd */ +@@ -4250,18 +3814,24 @@ gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, + lr = *row++; + lrid = *row++; + rowlen--; ++ wind = 1; + + /* We will fill solidly from ll to at least lr, possibly further */ + assert(rowlen > 0); +- (void)row++; /* rl not needed here */ +- (void)row++; +- rr = *row++; +- rrid = *row++; +- rowlen--; +- if (rr > lr) { +- lr = rr; +- lrid = rrid; +- } ++ do { ++ (void)row++; /* rl not needed here */ ++ rlid = *row++>>1; ++ rr = *row++; ++ rrid = *row++; ++ rowlen--; ++ if (rr > lr) { ++ lr = rr; ++ lrid = rrid; ++ } ++ wind ^= 1; ++ if (wind == 0) ++ break; ++ } while (rowlen > 0); + } else { + /* Non-Zero */ + int w; +@@ -4296,7 +3866,7 @@ gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, + if (lr < marked_to) + continue; + +- if (marked_to >= ll) { ++ if (marked_to > ll) { + if (rowout == rowstart) { + ll = marked_to; + llid = --marked_id; +@@ -4307,7 +3877,7 @@ gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, + } + } + +- if (lr >= ll) { ++ if (lr > ll) { + *rowout++ = ll; + *rowout++ = llid; + *rowout++ = lr; +@@ -4322,13 +3892,12 @@ gx_filter_edgebuffer_tr_app(gx_device * gs_restrict pdev, + + /* Step 6: Fill */ + int +-gx_fill_edgebuffer_tr_app(gx_device * gs_restrict pdev, +- const gx_device_color * gs_restrict pdevc, +- gx_edgebuffer * gs_restrict edgebuffer, ++gx_fill_edgebuffer_tr_app(gx_device * restrict pdev, ++ const gx_device_color * restrict pdevc, ++ gx_edgebuffer * restrict edgebuffer, + int log_op) + { + int i, j, code; +- int mfb = pdev->max_fill_band; + + #ifdef DEBUG_SCAN_CONVERTER + if (debugging_scan_converter) { +@@ -4343,18 +3912,9 @@ gx_fill_edgebuffer_tr_app(gx_device * gs_restrict pdev, + int *row2; + int *rowptr; + int *row2ptr; +- int y_band_max; +- +- if (mfb) { +- y_band_max = (i & ~(mfb-1)) + mfb; +- if (y_band_max > edgebuffer->height) +- y_band_max = edgebuffer->height; +- } else { +- y_band_max = edgebuffer->height; +- } + + /* See how many scanlines match i */ +- for (j = i+1; j < y_band_max; j++) { ++ for (j = i+1; j < edgebuffer->height; j++) { + int row2len; + + row2 = &edgebuffer->table[edgebuffer->index[j]]; +@@ -4473,6 +4033,8 @@ rowdifferent:{} + offset += 4; + rowlen--; + ++ assert(le.start.x >= -fixed_half); ++ assert(le.end.x >= -fixed_half); + assert(re.start.x >= le.start.x); + assert(re.end.x >= le.end.x); + assert(le.start.y <= ybot + fixed_half); +@@ -4558,97 +4120,3 @@ gx_edgebuffer_fin(gx_device * pdev, + edgebuffer->index = NULL; + edgebuffer->table = NULL; + } +- +-gx_scan_converter_t gx_scan_converter = +-{ +- gx_scan_convert, +- gx_filter_edgebuffer, +- gx_fill_edgebuffer +-}; +- +-gx_scan_converter_t gx_scan_converter_app = +-{ +- gx_scan_convert_app, +- gx_filter_edgebuffer_app, +- gx_fill_edgebuffer_app +-}; +- +-gx_scan_converter_t gx_scan_converter_tr = +-{ +- gx_scan_convert_tr, +- gx_filter_edgebuffer_tr, +- gx_fill_edgebuffer_tr +-}; +- +-gx_scan_converter_t gx_scan_converter_tr_app = +-{ +- gx_scan_convert_tr_app, +- gx_filter_edgebuffer_tr_app, +- gx_fill_edgebuffer_tr_app +-}; +- +-int +-gx_scan_convert_and_fill(const gx_scan_converter_t *sc, +- gx_device *dev, +- gx_path *ppath, +- const gs_fixed_rect *ibox, +- fixed flat, +- int rule, +- const gx_device_color *pdevc, +- int lop) +-{ +- int code; +- gx_edgebuffer eb; +- gs_fixed_rect ibox2 = *ibox; +- int height; +- int mfb = dev->max_fill_band; +- +- if (mfb != 0) { +- ibox2.p.y &= ~(mfb-1); +- ibox2.q.y = (ibox2.q.y+mfb-1) & ~(mfb-1); +- } +- height = ibox2.q.y - ibox2.p.y; +- +- do { +- gx_edgebuffer_init(&eb); +- while (1) { +- ibox2.q.y = ibox2.p.y + height; +- if (ibox2.q.y > ibox->q.y) +- ibox2.q.y = ibox->q.y; +- code = sc->scan_convert(dev, +- ppath, +- &ibox2, +- &eb, +- flat); +- if (code <= 0) +- break; +- /* Let's shrink the ibox and try again */ +- if (mfb && height == mfb) { +- /* Can't shrink the height any more! */ +- code = gs_error_rangecheck; +- break; +- } +- height = height/code; +- if (mfb) +- height = (height + mfb-1) & ~(mfb-1); +- if (height < (mfb ? mfb : 1)) { +- code = gs_error_VMerror; +- break; +- } +- } +- if (code >= 0) +- code = sc->filter(dev, +- &eb, +- rule); +- if (code >= 0) +- code = sc->fill(dev, +- pdevc, +- &eb, +- lop); +- gx_edgebuffer_fin(dev,&eb); +- ibox2.p.y += height; +- } +- while (ibox2.p.y < ibox->q.y); +- +- return code; +-} diff --git a/debian/patches/series b/debian/patches/series index f2105d1..144a12a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -17,3 +17,4 @@ CVE-2010-1628.patch CVE-2017-9619.patch CVE-2018-17183.patch +CVE-2017-7948.patch From 7c2093d058198b73597e5c9b5577aee658f5f076 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 04:32:35 +0800 Subject: [PATCH 05/10] fix(cve): CVE-2025-59801 - XPS interpreter - check some TIFF values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE: CVE-2025-59801 (medium) - XPS 解释器在解析恶意 TIFF 文件时存在栈缓冲区溢出漏洞 Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/99727069197d548a8db69ba5d63f766bff40eaab Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 ++++++ debian/patches/CVE-2025-59801.patch | 26 ++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 33 insertions(+) create mode 100644 debian/patches/CVE-2025-59801.patch diff --git a/debian/changelog b/debian/changelog index 139e90a..b6d0333 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin6) unstable; urgency=medium + + * fix(cve): CVE-2025-59801 + + -- deepin-ci-robot Tue, 28 Jul 2026 04:32:35 +0800 + ghostscript (10.05.1~dfsg-3deepin5) unstable; urgency=medium * fix(cve): CVE-2017-7948 diff --git a/debian/patches/CVE-2025-59801.patch b/debian/patches/CVE-2025-59801.patch new file mode 100644 index 0000000..bd49abb --- /dev/null +++ b/debian/patches/CVE-2025-59801.patch @@ -0,0 +1,26 @@ +Description: CVE-2025-59801 - 安全修复 +Author: Ken Sharp +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/99727069197d548a8db69ba5d63f766bff40eaab +Bug: https://nvd.nist.gov/vuln/detail/CVE-2025-59801 +Last-Update: 2025-09-09 +--- +diff --git a/xps/xpstiff.c b/xps/xpstiff.c +index 484ed5b3a..83cb913d1 100644 +--- a/xps/xpstiff.c ++++ b/xps/xpstiff.c +@@ -1175,6 +1175,15 @@ xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image) + if (tiff->rowsperstrip > tiff->imagelength) + tiff->rowsperstrip = tiff->imagelength; + ++ if (tiff->bitspersample != 1 && tiff->bitspersample != 4 && tiff->bitspersample != 8 && tiff->bitspersample != 16) ++ return gs_rethrow(error, "Illegal BitsPerSample in TIFF header"); ++ ++ if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 3 && tiff->samplesperpixel != 4 && tiff->samplesperpixel != 5) ++ return gs_rethrow(error, "Illegal SamplesPerPixel in TIFF header"); ++ ++ if (tiff->compression < 1 || (tiff->compression > 5 && (tiff->compression != 7 && tiff->compression != 32773))) ++ return gs_rethrow(error, "Illegal Compression in TIFF header"); ++ + error = xps_decode_tiff_strips(ctx, tiff, image); + if (error) + return gs_rethrow(error, "could not decode image data"); diff --git a/debian/patches/series b/debian/patches/series index 144a12a..71d8107 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -18,3 +18,4 @@ CVE-2010-1628.patch CVE-2017-9619.patch CVE-2018-17183.patch CVE-2017-7948.patch +CVE-2025-59801.patch From b3662fd5a7d07030197bf191effd0c5ccde553c2 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 06:09:47 +0800 Subject: [PATCH 06/10] fix(cve): CVE-2025-59799 - pdfwrite - bounds check some strings CVE: CVE-2025-59799 (medium) - pdfwrite - bounds check some strings Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/6dab38fb211f15226c242ab7a83fa53e4b0ff781 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 ++++++ debian/patches/CVE-2025-59799.patch | 28 ++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 35 insertions(+) create mode 100644 debian/patches/CVE-2025-59799.patch diff --git a/debian/changelog b/debian/changelog index b6d0333..7ab2501 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin7) unstable; urgency=medium + + * fix(cve): CVE-2025-59799 + + -- deepin-ci-robot Tue, 28 Jul 2026 06:09:47 +0800 + ghostscript (10.05.1~dfsg-3deepin6) unstable; urgency=medium * fix(cve): CVE-2025-59801 diff --git a/debian/patches/CVE-2025-59799.patch b/debian/patches/CVE-2025-59799.patch new file mode 100644 index 0000000..3566ef0 --- /dev/null +++ b/debian/patches/CVE-2025-59799.patch @@ -0,0 +1,28 @@ +Description: CVE-2025-59799 - 安全修复 +Author: Piotr Kajda +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/6dab38fb211f15226c242ab7a83fa53e4b0ff781 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2025-59799 +Last-Update: 2025-05-08 +--- +diff --git a/devices/vector/gdevpdfm.c b/devices/vector/gdevpdfm.c +index d1237c91a..c120ba1ae 100644 +--- a/devices/vector/gdevpdfm.c ++++ b/devices/vector/gdevpdfm.c +@@ -199,6 +199,8 @@ pdfmark_coerce_dest(gs_param_string *dstr, char dest[MAX_DEST_STRING]) + { + const byte *data = dstr->data; + uint size = dstr->size; ++ if (size > MAX_DEST_STRING) ++ return_error(gs_error_limitcheck); + if (size == 0 || data[0] != '(') + return 0; + /****** HANDLE ESCAPES ******/ +@@ -859,6 +861,8 @@ pdfmark_put_ao_pairs(gx_device_pdf * pdev, cos_dict_t *pcd, + char buf[30]; + int d0, d1; + ++ if (Action[1].size > 29) ++ return_error(gs_error_rangecheck); + memcpy(buf, Action[1].data, Action[1].size); + buf[Action[1].size] = 0; + if (sscanf(buf, "%d %d R", &d0, &d1) == 2) diff --git a/debian/patches/series b/debian/patches/series index 71d8107..bb820a9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -19,3 +19,4 @@ CVE-2017-9619.patch CVE-2018-17183.patch CVE-2017-7948.patch CVE-2025-59801.patch +CVE-2025-59799.patch From d45920362394fe86b29a428ad50ed6b11b177b0c Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 06:29:20 +0800 Subject: [PATCH 07/10] fix(cve): CVE-2025-59798 - pdfwrite - avoid buffer overrun CVE: CVE-2025-59798 (medium) - pdfwrite - avoid buffer overrun in pdf_write_cmap and pdf_write_cid_system_info_to_stream functions Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/0cae41b23a9669e801211dd4cf97b6dadd6dbdd7 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 ++ debian/patches/CVE-2025-59798.patch | 106 ++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 113 insertions(+) create mode 100644 debian/patches/CVE-2025-59798.patch diff --git a/debian/changelog b/debian/changelog index 7ab2501..fd87a29 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin8) unstable; urgency=medium + + * fix(cve): CVE-2025-59798 + + -- deepin-ci-robot Tue, 28 Jul 2026 06:29:20 +0800 + ghostscript (10.05.1~dfsg-3deepin7) unstable; urgency=medium * fix(cve): CVE-2025-59799 diff --git a/debian/patches/CVE-2025-59798.patch b/debian/patches/CVE-2025-59798.patch new file mode 100644 index 0000000..3443af7 --- /dev/null +++ b/debian/patches/CVE-2025-59798.patch @@ -0,0 +1,106 @@ +Description: CVE-2025-59798 - 安全修复 +Author: Ken Sharp +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/0cae41b23a9669e801211dd4cf97b6dadd6dbdd7 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2025-59798 +Last-Update: 2025-05-22 +--- +diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c +index ced15c9b2..fe24dd73a 100644 +--- a/devices/vector/gdevpdtw.c ++++ b/devices/vector/gdevpdtw.c +@@ -703,7 +703,8 @@ static int + pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s, + const gs_cid_system_info_t *pcidsi, gs_id object_id) + { +- byte *Registry, *Ordering; ++ byte *Registry = NULL, *Ordering = NULL; ++ int code = 0; + + Registry = gs_alloc_bytes(pdev->pdf_memory, pcidsi->Registry.size, "temporary buffer for Registry"); + if (!Registry) +@@ -734,14 +735,19 @@ pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s, + } + s_arcfour_process_buffer(&sarc4, Ordering, pcidsi->Ordering.size); + } +- stream_puts(s, "<<\n/Registry"); ++ code = stream_puts(s, "<<\n/Registry"); ++ if (code < 0) ++ goto error; + s_write_ps_string(s, Registry, pcidsi->Registry.size, PRINT_HEX_NOT_OK); +- stream_puts(s, "\n/Ordering"); ++ code = stream_puts(s, "\n/Ordering"); ++ if(code < 0) ++ goto error; + s_write_ps_string(s, Ordering, pcidsi->Ordering.size, PRINT_HEX_NOT_OK); ++error: + pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement); + gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer"); + gs_free_object(pdev->pdf_memory, Ordering, "free temporary Ordering buffer"); +- return 0; ++ return code; + } + + int +@@ -786,31 +792,55 @@ pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap, + *ppres = writer.pres; + writer.pres->where_used = 0; /* CMap isn't a PDF resource. */ + if (!pcmap->ToUnicode) { +- byte buf[200]; ++ byte *buf = NULL; ++ uint64_t buflen = 0; + cos_dict_t *pcd = (cos_dict_t *)writer.pres->object; + stream s; + ++ /* We use 'buf' for the stream 's' below and that needs to have some extra ++ * space for the CIDSystemInfo. We also need an extra byte for the leading '/' ++ * 100 bytes is ample for the overhead. ++ */ ++ buflen = pcmap->CIDSystemInfo->Registry.size + pcmap->CIDSystemInfo->Ordering.size + pcmap->CMapName.size + 100; ++ if (buflen > max_uint) ++ return_error(gs_error_limitcheck); ++ ++ buf = gs_alloc_bytes(pdev->memory, buflen, "pdf_write_cmap"); ++ if (buf == NULL) ++ return_error(gs_error_VMerror); ++ + code = cos_dict_put_c_key_int(pcd, "/WMode", pcmap->WMode); +- if (code < 0) ++ if (code < 0) { ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + return code; ++ } + buf[0] = '/'; + memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size); + code = cos_dict_put_c_key_string(pcd, "/CMapName", + buf, pcmap->CMapName.size + 1); +- if (code < 0) ++ if (code < 0) { ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + return code; ++ } + s_init(&s, pdev->memory); +- swrite_string(&s, buf, sizeof(buf)); ++ swrite_string(&s, buf, buflen); + code = pdf_write_cid_system_info_to_stream(pdev, &s, pcmap->CIDSystemInfo, 0); +- if (code < 0) ++ if (code < 0) { ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + return code; ++ } + code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo", + buf, stell(&s)); +- if (code < 0) ++ if (code < 0) { ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + return code; ++ } + code = cos_dict_put_string_copy(pcd, "/Type", "/CMap"); +- if (code < 0) ++ if (code < 0) { ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + return code; ++ } ++ gs_free_object(pdev->memory, buf, "pdf_write_cmap"); + } + if (pcmap->CMapName.size == 0) { + /* Create an arbitrary name (for ToUnicode CMap). */ diff --git a/debian/patches/series b/debian/patches/series index bb820a9..80da50f 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -20,3 +20,4 @@ CVE-2018-17183.patch CVE-2017-7948.patch CVE-2025-59801.patch CVE-2025-59799.patch +CVE-2025-59798.patch From b861eeb5f8f38d072189e70a9b6f7cba17c6b6da Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 07:03:30 +0800 Subject: [PATCH 08/10] fix(cve): CVE-2018-16539 - Remove direct access to temp directories. CVE: CVE-2018-16539 (medium) - In Artifex Ghostscript before 9.24, attackers able to supply crafted PostScript files could use incorrect access checking in temp file handling to disclose contents of files on the system otherwise not readable. Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/e0174f4d743782e7cb949c90e955ff912c11d592 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 +++ debian/patches/CVE-2018-16539.patch | 84 +++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 91 insertions(+) create mode 100644 debian/patches/CVE-2018-16539.patch diff --git a/debian/changelog b/debian/changelog index fd87a29..4a050b2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin9) unstable; urgency=medium + + * fix(cve): CVE-2018-16539 + + -- deepin-ci-robot Tue, 28 Jul 2026 07:03:30 +0800 + ghostscript (10.05.1~dfsg-3deepin8) unstable; urgency=medium * fix(cve): CVE-2025-59798 diff --git a/debian/patches/CVE-2018-16539.patch b/debian/patches/CVE-2018-16539.patch new file mode 100644 index 0000000..90e3fea --- /dev/null +++ b/debian/patches/CVE-2018-16539.patch @@ -0,0 +1,84 @@ +Description: CVE-2018-16539 - 安全修复 +Author: Chris Liddell +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/e0174f4d743782e7cb949c90e955ff912c11d592 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2018-16539 +Last-Update: 2026-02-23 14:59:01 +0000 +--- +diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps +index c7051622b..4d6c9e828 100644 +--- a/Resource/Init/gs_init.ps ++++ b/Resource/Init/gs_init.ps +@@ -2369,20 +2369,6 @@ readonly def + //systemdict /SAFERUndefinePostScriptOperators .forceundef + } .forcebind def % must be bound and hidden for .forceundef + +-/tempfilepaths +-[ +- (TMPDIR) getenv not +- { +- (TEMP) getenv not +- { +- (TMP) getenv not +- { +- (/temp) (/tmp) +- } if +- } if +- } if +-] def +- + /.lockfileaccess { + .currentpathcontrolstate + { +@@ -2394,7 +2380,6 @@ readonly def + } + { + [ +- //tempfilepaths (*) .generate_dir_list_templates + /FONTPATH .systemvar (*) .generate_dir_list_templates + /level2dict where { + pop +@@ -2408,14 +2393,6 @@ readonly def + } if + ] {/PermitFileReading exch .addcontrolpath} forall + +- [ +- //tempfilepaths (*) .generate_dir_list_templates +- ] {/PermitFileWriting exch .addcontrolpath} forall +- +- [ +- //tempfilepaths (*) .generate_dir_list_templates +- ] {/PermitFileControl exch .addcontrolpath} forall +- + .activatepathcontrol + } ifelse + } .internalbind def +@@ -2425,7 +2402,6 @@ readonly def + << + /PermitFileReading [ + currentuserparams /PermitFileReading get aload pop +- //tempfilepaths (*) .generate_dir_list_templates + /FONTPATH .systemvar (*) .generate_dir_list_templates + % Library files : + /LIBPATH .systemvar (*) .generate_dir_list_templates +@@ -2445,21 +2421,12 @@ readonly def + .generate_dir_list_templates + } if + ] +- /PermitFileWriting [ +- currentuserparams /PermitFileWriting get aload pop +- //tempfilepaths (*) .generate_dir_list_templates +- ] +- /PermitFileControl [ +- currentuserparams /PermitFileControl get aload pop +- //tempfilepaths (*) .generate_dir_list_templates +- ] + /LockFilePermissions //true + >> setuserparams + } + if + } .forcebind def + +-currentdict /tempfilepaths undef + + %% --- These are documented extensions --- + /.locksafe { diff --git a/debian/patches/series b/debian/patches/series index 80da50f..d0ce5ff 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -21,3 +21,4 @@ CVE-2017-7948.patch CVE-2025-59801.patch CVE-2025-59799.patch CVE-2025-59798.patch +CVE-2018-16539.patch From f5819814c45fe5b2962018cb714159c27fae9567 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 07:30:01 +0800 Subject: [PATCH 09/10] fix(cve): CVE-2025-59800 - PDF OCR 8 bit device - avoid overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE: CVE-2025-59800 (medium) - PDF OCR 8 bit device - avoid overflow. 整数溢出漏洞,可能导致堆溢出 Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/176cf0188a2294bc307b8caec876f39412e58350 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 ++++++ debian/patches/CVE-2025-59800.patch | 25 +++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 32 insertions(+) create mode 100644 debian/patches/CVE-2025-59800.patch diff --git a/debian/changelog b/debian/changelog index 4a050b2..6f1afb6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin10) unstable; urgency=medium + + * fix(cve): CVE-2025-59800 + + -- deepin-ci-robot Tue, 28 Jul 2026 07:30:01 +0800 + ghostscript (10.05.1~dfsg-3deepin9) unstable; urgency=medium * fix(cve): CVE-2018-16539 diff --git a/debian/patches/CVE-2025-59800.patch b/debian/patches/CVE-2025-59800.patch new file mode 100644 index 0000000..202f281 --- /dev/null +++ b/debian/patches/CVE-2025-59800.patch @@ -0,0 +1,25 @@ +Description: CVE-2025-59800 - 安全修复 +Author: Ken Sharp +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/176cf0188a2294bc307b8caec876f39412e58350 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2025-59800 +Last-Update: 2025-07-01 +--- +diff --git a/devices/gdevpdfocr.c b/devices/gdevpdfocr.c +index 1c1e8eab8..7c9c12f8c 100644 +--- a/devices/gdevpdfocr.c ++++ b/devices/gdevpdfocr.c +@@ -521,9 +521,12 @@ ocr_line32(gx_device_pdf_image *dev, void *row) + static int + ocr_begin_page(gx_device_pdf_image *dev, int w, int h, int bpp) + { +- int raster = (w+3)&~3; ++ int64_t raster = (w + 3) & ~3; + +- dev->ocr.data = gs_alloc_bytes(dev->memory, raster * h, "ocr_begin_page"); ++ raster = raster * (int64_t)h; ++ if (raster < 0 || raster > max_size_t) ++ return gs_note_error(gs_error_VMerror); ++ dev->ocr.data = gs_alloc_bytes(dev->memory, raster, "ocr_begin_page"); + if (dev->ocr.data == NULL) + return_error(gs_error_VMerror); + dev->ocr.w = w; diff --git a/debian/patches/series b/debian/patches/series index d0ce5ff..4b349f1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -22,3 +22,4 @@ CVE-2025-59801.patch CVE-2025-59799.patch CVE-2025-59798.patch CVE-2018-16539.patch +CVE-2025-59800.patch From eff6fec96b66af82c5042b9a7307a4a8a993e319 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 28 Jul 2026 08:31:59 +0800 Subject: [PATCH 10/10] fix(cve): CVE-2017-8908 - Fix Bug 698969 SEGV caused by overflow in mark_line_*** functions CVE: CVE-2017-8908 (medium) - The mark_line_tr function in gxscanc.c in Artifex Ghostscript 9.21 allows remote attackers to cause a denial of service (out-of-bounds read) via a crafted PostScript document. Upstream: https://github.com/ArtifexSoftware/ghostpdl/commit/9f9daedfdf98bab590eba53e34fba76b96307ec0 Co-authored-by: hudeng Generated-By: qwen3.6-35b --- debian/changelog | 6 ++ debian/patches/CVE-2017-8908.patch | 166 +++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 173 insertions(+) create mode 100644 debian/patches/CVE-2017-8908.patch diff --git a/debian/changelog b/debian/changelog index 6f1afb6..6402268 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +ghostscript (10.05.1~dfsg-3deepin11) unstable; urgency=medium + + * fix(cve): CVE-2017-8908 + + -- deepin-ci-robot Tue, 28 Jul 2026 08:31:59 +0800 + ghostscript (10.05.1~dfsg-3deepin10) unstable; urgency=medium * fix(cve): CVE-2025-59800 diff --git a/debian/patches/CVE-2017-8908.patch b/debian/patches/CVE-2017-8908.patch new file mode 100644 index 0000000..1086fd4 --- /dev/null +++ b/debian/patches/CVE-2017-8908.patch @@ -0,0 +1,166 @@ +Description: CVE-2017-8908 - 安全修复 +Author: Ray Johnston +Origin: https://github.com/ArtifexSoftware/ghostpdl/commit/9f9daedfdf98bab590eba53e34fba76b96307ec0 +Bug: https://nvd.nist.gov/vuln/detail/CVE-2017-8908 +Last-Update: 2018-02-13 +--- +diff --git a/base/gxscanc.c b/base/gxscanc.c +index 13ece3afc..db8ab1213 100644 +--- a/base/gxscanc.c ++++ b/base/gxscanc.c +@@ -194,7 +194,7 @@ static void coord(const char *str, fixed x, fixed y) + + static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index) + { +- int delta; ++ int64_t delta; + int iy, ih; + fixed clip_sy, clip_ey; + int dirn = DIRN_UP; +@@ -234,7 +234,7 @@ static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int he + clip_ey = int2fixed(base_y + height - 1) + fixed_half; + if (sy > clip_ey) + return; +- delta = clip_sy - sy; ++ delta = (int64_t)clip_sy - (int64_t)sy; + if (delta > 0) + { + int dx = ex - sx; +@@ -246,7 +246,7 @@ static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int he + ex -= sx; + ey -= sy; + clip_ey -= clip_sy; +- delta = ey - clip_ey; ++ delta = (int64_t)ey - (int64_t)clip_ey; + if (delta > 0) + { + int advance = (int)(((int64_t)ex * delta + (ey>>1)) / ey); +@@ -1246,9 +1246,9 @@ static void mark_line_app(cursor * restrict cr, fixed sx, fixed sy, fixed ex, fi + } + if (isy < 0) { + /* Move sy up */ +- int y = ey - sy; +- int new_sy = int2fixed(cr->base); +- int dy = new_sy - sy; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_sy = int2fixed(cr->base); ++ int64_t dy = (int64_t)new_sy - (int64_t)sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; + cursor_init(cr, sy, sx); +@@ -1257,9 +1257,9 @@ static void mark_line_app(cursor * restrict cr, fixed sx, fixed sy, fixed ex, fi + truncated = iey > cr->scanlines; + if (truncated) { + /* Move ey down */ +- int y = ey - sy; +- int new_ey = int2fixed(cr->base + cr->scanlines); +- int dy = ey - new_ey; ++ int64_t y = ey - sy; ++ fixed new_ey = int2fixed(cr->base + cr->scanlines); ++ int64_t dy = (int64_t)ey - (int64_t)new_ey; + saved_ex = ex; + saved_ey = ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); +@@ -1279,18 +1279,18 @@ static void mark_line_app(cursor * restrict cr, fixed sx, fixed sy, fixed ex, fi + truncated = iey < 0; + if (truncated) { + /* Move ey up */ +- int y = ey - sy; +- int new_ey = int2fixed(cr->base); +- int dy = ey - new_ey; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_ey = int2fixed(cr->base); ++ int64_t dy = (int64_t)ey - (int64_t)new_ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); + ey = new_ey; + iey = 0; + } + if (isy >= cr->scanlines) { + /* Move sy down */ +- int y = ey - sy; +- int new_sy = int2fixed(cr->base + cr->scanlines); +- int dy = new_sy - sy; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_sy = int2fixed(cr->base + cr->scanlines); ++ int64_t dy = (int64_t)new_sy - (int64_t)sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; + cursor_init(cr, sy, sx); +@@ -2085,7 +2085,7 @@ gx_edgebuffer_print_tr(gx_edgebuffer * edgebuffer) + + static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index, int id) + { +- int delta; ++ int64_t delta; + int iy, ih; + fixed clip_sy, clip_ey; + int dirn = DIRN_UP; +@@ -2125,7 +2125,7 @@ static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int + clip_ey = int2fixed(base_y + height - 1) + fixed_half; + if (sy > clip_ey) + return; +- delta = clip_sy - sy; ++ delta = (int64_t)clip_sy - (int64_t)sy; + if (delta > 0) + { + int dx = ex - sx; +@@ -2137,7 +2137,7 @@ static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int + ex -= sx; + ey -= sy; + clip_ey -= clip_sy; +- delta = ey - clip_ey; ++ delta = (int64_t)ey - (int64_t)clip_ey; + if (delta > 0) + { + int advance = (int)(((int64_t)ex * delta + (ey>>1)) / ey); +@@ -3086,9 +3086,9 @@ static void mark_line_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed + } + if (isy < 0) { + /* Move sy up */ +- int y = ey - sy; +- int new_sy = int2fixed(cr->base); +- int dy = new_sy - sy; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_sy = int2fixed(cr->base); ++ int64_t dy = (int64_t)new_sy - (int64_t)sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; + cursor_init_tr(cr, sy, sx, id); +@@ -3097,9 +3097,9 @@ static void mark_line_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed + truncated = iey > cr->scanlines; + if (truncated) { + /* Move ey down */ +- int y = ey - sy; +- int new_ey = int2fixed(cr->base + cr->scanlines); +- int dy = ey - new_ey; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_ey = int2fixed(cr->base + cr->scanlines); ++ int64_t dy = (int64_t)ey - (int64_t)new_ey; + saved_ex = ex; + saved_ey = ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); +@@ -3121,18 +3121,18 @@ static void mark_line_tr_app(cursor_tr * restrict cr, fixed sx, fixed sy, fixed + truncated = iey < 0; + if (truncated) { + /* Move ey up */ +- int y = ey - sy; +- int new_ey = int2fixed(cr->base); +- int dy = ey - new_ey; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_ey = int2fixed(cr->base); ++ int64_t dy = (int64_t)ey - (int64_t)new_ey; + ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y); + ey = new_ey; + iey = 0; + } + if (isy >= cr->scanlines) { + /* Move sy down */ +- int y = ey - sy; +- int new_sy = int2fixed(cr->base + cr->scanlines); +- int dy = new_sy - sy; ++ int64_t y = (int64_t)ey - (int64_t)sy; ++ fixed new_sy = int2fixed(cr->base + cr->scanlines); ++ int64_t dy = (int64_t)new_sy - (int64_t)sy; + sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y); + sy = new_sy; + cursor_init_tr(cr, sy, sx, id); diff --git a/debian/patches/series b/debian/patches/series index 4b349f1..760d327 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -23,3 +23,4 @@ CVE-2025-59799.patch CVE-2025-59798.patch CVE-2018-16539.patch CVE-2025-59800.patch +CVE-2017-8908.patch