diff options
author | Henry Stiles <henry.stiles@artifex.com> | 2007-02-02 18:51:41 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 2007-02-02 18:51:41 +0000 |
commit | 728d9d60b3a0e04e181af8afc757c512c5ab1dc9 (patch) | |
tree | 93bf8ffa3ec46e59625b72788c4da9e343eb2fc0 /pl | |
parent | 70d2e0dcb3e879a5d651f6d1ee5bc4313cc70180 (diff) |
Gets rid of substitute glyph which is no longer necessary since Tom's
work to reasonably render partially corrupt intellifont glyphs. We
don't have a specification and only a limited number of test cases so
we may need to reconsider this code if we receive new test cases.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@2751 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'pl')
-rw-r--r-- | pl/plchar.c | 437 |
1 files changed, 181 insertions, 256 deletions
diff --git a/pl/plchar.c b/pl/plchar.c index 95bcb3b0d..f41dea335 100644 --- a/pl/plchar.c +++ b/pl/plchar.c @@ -1,4 +1,4 @@ -/* Portions Copyright (C) 2001 artofcode LLC. + /* Portions Copyright (C) 2001 artofcode LLC. Portions Copyright (C) 1996, 2001 Artifex Software Inc. Portions Copyright (C) 1988, 2000 Aladdin Enterprises. This software is based in part on the work of the Independent JPEG Group. @@ -13,8 +13,6 @@ /* plchar.c */ /* PCL font handling library -- operations on individual characters */ -#include "assert.h" - #include "math_.h" #include "memory_.h" #include "stdio_.h" /* for gdebug.h */ @@ -496,8 +494,7 @@ pl_tt_lookup_char(const pl_font_t *plfont, gs_glyph glyph) /* Get a string from a TrueType font. */ private int -pl_tt_string_proc(gs_font_type42 *pfont, ulong offset, uint length, - const byte **pdata) +pl_tt_string_proc(gs_font_type42 *pfont, ulong offset, uint length, byte **pdata) { pl_font_t *plfont = pfont->client_data; *pdata = plfont->header + plfont->offsets.GT + @@ -1188,269 +1185,194 @@ pl_intelli_merge_box(float wbox[6], const pl_font_t *plfont, gs_glyph glyph) return true; } -#if 0 -#define DEBUG_INTELLIFONT_SHOW_CHAR /* debug print the points inside the bounding box */ -#define DEBUG_INTELLIFONT_SHOW_CHAR_ALL /* debug print all points */ -#endif - -/* render an Intellifont character. */ -/* The caller has called setcachedevice. */ +/* Do the work for rendering an Intellifont character. */ +/* The caller has done the setcachedevice. */ private int pl_intelli_show_char(gs_state *pgs, const pl_font_t *plfont, gs_glyph glyph) -{ - const byte *cdata; - pl_font_glyph_t *font_glyph; - const intelli_metrics_t *metrics; - client_name_t cname = (client_name_t)"pl_intelli_show_char"; - font_glyph = pl_font_lookup_glyph(plfont, glyph); - cdata = font_glyph->data; - - if ( cdata == 0 ) - { - if_debug1('1', "[1] no character data for glyph %i\n",glyph); - return 0; - } - - if ( cdata[3] == 4 ) /* Compound character */ - { - gs_matrix save_ctm; - int i; - gs_currentmatrix(pgs, &save_ctm); - for ( i = 0; i < cdata[6]; ++i ) - { - const byte *edata = cdata + 8 + i * 6; - floatp x_offset = pl_get_int16(edata + 2); - floatp y_offset = pl_get_int16(edata + 4); - int code; - - gs_translate(pgs, x_offset, y_offset); - code = pl_intelli_show_char(pgs, plfont, pl_get_uint16(edata)); - gs_setmatrix(pgs, &save_ctm); - if ( code < 0 ) - return code; - } - return 0; - } /* compound character */ - - else /* not compound character */ - { - const byte *outlines; - uint num_loops; - uint i; +{ int code; - - cdata += 4; /* skip PCL character header */ - outlines = cdata + pl_get_uint16(cdata + 6); - num_loops = pl_get_uint16(outlines); - -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf1("glyph: %i\n",glyph); - dprintf1("contour size: %i\n", pl_get_uint16(cdata + 0)); - dprintf1("metric offset: %i\n", pl_get_uint16(cdata + 2)); - dprintf1("intelli offset: %i\n", pl_get_uint16(cdata + 4)); - dprintf1("outlines offset: %i\n", pl_get_uint16(cdata + 6)); - dprintf1("xy data offset: %i\n", pl_get_uint16(cdata + 8)); - dprintf1("num_loops: %i\n",num_loops); -#endif - - if_debug2('1', "[1]ifont glyph %lu: loops=%u\n",(ulong)glyph, num_loops); - - for ( i = 0; i < num_loops; ++i ) + const byte *cdata; + pl_font_glyph_t *font_glyph; + const intelli_metrics_t *metrics; + int *xBuffer, *yBuffer; + client_name_t cname = (client_name_t)"pl_intelli_show_char"; + font_glyph = pl_font_lookup_glyph(plfont, glyph); + cdata = font_glyph->data; + + if ( cdata == 0 ) { + if_debug1('1', "[1] no character data for glyph %ld\n",glyph); + return 0; + } + if ( cdata[3] == 4 ) { /* Compound character */ + gs_matrix save_ctm; + int i; + gs_currentmatrix(pgs, &save_ctm); + for ( i = 0; i < cdata[6]; ++i ) { + const byte *edata = cdata + 8 + i * 6; + floatp x_offset = pl_get_int16(edata + 2); + floatp y_offset = pl_get_int16(edata + 4); + gs_translate(pgs, x_offset, y_offset); + code = pl_intelli_show_char(pgs, plfont, pl_get_uint16(edata)); + gs_setmatrix(pgs, &save_ctm); + if ( code < 0 ) + return code; + } + return 0; + } /* compound character */ + + /* not compound character */ { - int xyc_offset = pl_get_uint16(outlines + 4 + i * 8); - const byte *xyc = cdata + pl_get_uint16(outlines + 4 + i * 8); - uint num_points; - uint num_aux_points; - const byte *x_coords, *y_coords, *x_coords_last; - const byte *x_aux_coords, *y_aux_coords, *x_aux_coords_last; - int llx, lly, urx, ury; /* character bounding box */ - uint j; - int x, y; - int xAux, yAux; - int first_point_moved; - int *xBuffer, *yBuffer, *xLimit, *yLimit; - int *xScan, *yScan, *xLast; - int pointBufferSize; - - num_points = pl_get_uint16(xyc); - num_aux_points = pl_get_uint16(xyc + 2); - - x_coords = xyc + 4; - y_coords = x_coords + num_points * 2; - x_coords_last = y_coords; - - metrics = (const intelli_metrics_t *)(cdata + pl_get_uint16(cdata + 2)); - llx = pl_get_int16(metrics->charSymbolBox[0]); - lly = pl_get_int16(metrics->charSymbolBox[1]); - urx = pl_get_int16(metrics->charSymbolBox[2]); - ury = pl_get_int16(metrics->charSymbolBox[3]); - - pointBufferSize = num_points; /* allocate enough to hold all points */ - if ( num_aux_points != 0xffff ) - { - pointBufferSize += num_aux_points; - x_aux_coords = y_coords + num_points * 2; - y_aux_coords = x_aux_coords + num_aux_points; - x_aux_coords_last = y_coords; - } - else - { - x_aux_coords = NULL; - y_aux_coords = NULL; - x_aux_coords_last = NULL; - } - xBuffer = (int *)gs_alloc_byte_array(pgs->memory, pointBufferSize, sizeof(int), cname); - yBuffer = (int *)gs_alloc_byte_array(pgs->memory, pointBufferSize, sizeof(int), cname); - if (xBuffer == 0 || yBuffer == 0) - { - if_debug1('1', "[1]cannot allocate point buffers %i\n",pointBufferSize * sizeof(int)); - return_error(gs_error_VMerror); - } - xLimit = xBuffer + pointBufferSize; - yLimit = yBuffer + pointBufferSize; - xLast = NULL; - - if_debug2('1', "[1]num_points=%u num_aux_points=%u\n", num_points, num_aux_points); - -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf1("num_points: %i\n",num_points); - dprintf1("num_aux_points: %i\n",num_aux_points); - dprintf4("bounding box: (%05i,%05i), (%05i,%05i)\n", - llx,lly,urx,ury); - dprintf4("bounding box: (%03i,%03i), (%03i,%03i)\n", - (int)llx/100,(int)lly/100, (int)urx/100,(int)ury/100); -#endif - - /* collect the points in the buffers, since we need to clean them up later */ - /* only points inside the bounding box are allowed */ - /* aux points are points inserted between two points, making the outline smoother */ - /* the aux points could be used for curve fitting, but we add line segments */ - for ( xScan = xBuffer, yScan = yBuffer; x_coords < x_coords_last; x_coords += 2, y_coords += 2 ) - { - x = pl_get_uint16(x_coords) & 0x3fff; - y = pl_get_uint16(y_coords) & 0x3fff; - -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR_ALL - dprintf4("%s (%d,%d) %s\n", - (*x_coords & 0x80 ? " line" : "curve"), x, y, - (*y_coords & 0x80 ? " line" : "curve")); -#endif - if_debug4('1', "[1]%s (%d,%d) %s\n", - (*x_coords & 0x80 ? " line" : "curve"), x, y, - (*y_coords & 0x80 ? " line" : "curve")); - - if (xScan > xBuffer) /* not first point, therefore aux is possible */ - { - if ( x_coords < x_aux_coords_last &&!(*x_coords & 0x80) ) /* use an aux point */ - { - /* The auxiliary dx and dy values are signed. */ - int dx = (*x_aux_coords++ ^ 0x80) - 0x80; - int dy = (*y_aux_coords++ ^ 0x80) - 0x80; - - if_debug2('1', "[1]... aux (%d,%d)\n", dx, dy); - - xAux = (x + *(xScan-1)) / 2 + dx; - yAux = (y + *(yScan-1)) / 2 + dy; - if ((xAux >= llx && xAux <= urx) && (yAux >= lly && yAux <= ury)) /* aux point is inside bounding box */ - { - *xScan++ = xAux; - *yScan++ = yAux; - if ( !(xScan <= xLimit && yScan <= yLimit) ) - { - dprintf("limit exceeded\n"); - } - assert(xScan <= xLimit && yScan <= yLimit); -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf2("%05i, %05i",xAux,yAux); - dprintf("\n"); -#endif - } /* end point inside bounding box */ - /* what do points outside the bounding box mean? */ - - -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR_ALL -#ifndef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf2("[%05i,%05i]",xAux,yAux); - dprintf2(" delta {%05i,%05i}",dx,dy); - if ( !(xAux >= llx && xAux <= urx) || !(yAux >= lly && yAux <= ury) ) - dprintf(" ****** "); -#endif -#endif - } /* use an aux point */ - } /* not first point */ - - if ( (x >= llx && x <= urx) && (y >= lly && y <= ury) ) /* point inside bounding box */ - { -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf2("%05i, %05i",x,y); - dprintf("\n"); -#endif - *xScan++ = x; - *yScan++ = y; - if ( !(xScan <= xLimit && yScan <= yLimit) ) - { - dprintf("limit exceeded\n"); - } - assert(xScan <= xLimit && yScan <= yLimit); - - } /* point inside bounding box */ -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR_ALL -#ifndef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf2("(%05i,%05i)",x,y); - dprintf2(" (%03i,%03i)",(int)x/100,(int)y/100); - if ( !(x >= llx && x <= urx) || !(y >= lly && y <= ury)) - dprintf(" ****** "); -#endif -#endif - - } /* for num_points - first time through */ - -#ifdef DEBUG_INTELLIFONT_SHOW_CHAR - dprintf("\n"); - dprintf("\n"); -#endif - - if ( num_aux_points != 0xffff ) - xLast = xScan; - else - xLast = xScan - 1; /* discard the last point */ - - xScan = xBuffer; - yScan = yBuffer; - if (xLast > xBuffer) - { - code = gs_moveto(pgs, (floatp)*xScan++, (floatp)*yScan++); - if ( code < 0 ) - return code; - assert(xScan <= xLimit && yScan <= yLimit); - } - - for (; xScan < xLast; ) - { - code = gs_lineto(pgs, (floatp)*xScan++, (floatp)*yScan++); - if ( code < 0 ) - return code; - assert(xScan <= xLimit && yScan <= yLimit); - } - /* close the path of this loop */ - code = gs_closepath(pgs); - if ( code < 0 ) - return code; + const byte *outlines; + uint num_loops; + uint i; + cdata += 4; /* skip PCL character header */ + outlines = cdata + pl_get_uint16(cdata + 6); + num_loops = pl_get_uint16(outlines); + + if_debug2('1', "[1]ifont glyph %lu: loops=%u\n",(ulong)glyph, num_loops); + + if (num_loops == 0) + return -1; + + for ( i = 0; i < num_loops; ++i ) { + const byte *xyc = cdata + pl_get_uint16(outlines + 4 + i * 8); + uint num_points; + uint num_aux_points; + const byte *x_coords, *y_coords, *x_coords_last; + const byte *x_aux_coords, *y_aux_coords, *x_aux_coords_last; + int llx, lly, urx, ury; /* character bounding box */ + int x, y; + int xAux, yAux; + int *xLimit, *yLimit, *xScan, *yScan, *xLast; + int pointBufferSize; + uint sz; + + num_points = pl_get_uint16(xyc); + num_aux_points = pl_get_uint16(xyc + 2); + + x_coords = xyc + 4; + y_coords = x_coords + num_points * 2; + x_coords_last = y_coords; + + metrics = (const intelli_metrics_t *)(cdata + pl_get_uint16(cdata + 2)); + llx = pl_get_int16(metrics->charSymbolBox[0]); + lly = pl_get_int16(metrics->charSymbolBox[1]); + urx = pl_get_int16(metrics->charSymbolBox[2]); + ury = pl_get_int16(metrics->charSymbolBox[3]); + + pointBufferSize = num_points; /* allocate enough to hold all points */ + if ( num_aux_points != 0xffff ) { + pointBufferSize += num_aux_points; + x_aux_coords = y_coords + num_points * 2; + y_aux_coords = x_aux_coords + num_aux_points; + x_aux_coords_last = y_coords; + } + else { + x_aux_coords = NULL; + y_aux_coords = NULL; + x_aux_coords_last = NULL; + } + + sz = pointBufferSize * sizeof(int); + + if (i == 0) { + xBuffer = (int *)gs_alloc_bytes(pgs->memory, sz, cname); + yBuffer = (int *)gs_alloc_bytes(pgs->memory, sz, cname); + } else { + /* NB we don't have a font that tests this yet */ + xBuffer = (int *)gs_resize_object(pgs->memory, xBuffer, sz, cname); + yBuffer = (int *)gs_resize_object(pgs->memory, yBuffer, sz, cname); + } - gs_free_object(pgs->memory, xBuffer, "x point buffer"); - gs_free_object(pgs->memory, yBuffer, "y point buffer"); + if (xBuffer == NULL || yBuffer == NULL) { + if( xBuffer != NULL) + gs_free_object(pgs->memory, xBuffer, "x point buffer"); + if( yBuffer != NULL) + gs_free_object(pgs->memory, yBuffer, "y point buffer"); + if_debug1('1', "[1]cannot allocate point buffers %i\n",pointBufferSize * sizeof(int)); + return_error(gs_error_VMerror); + } + + xLimit = xBuffer + pointBufferSize; + yLimit = yBuffer + pointBufferSize; + xLast = NULL; + + if_debug2('1', "[1]num_points=%u num_aux_points=%u\n", num_points, num_aux_points); + + /* collect the points in the buffers, since we need to clean them up later */ + /* only points inside the bounding box are allowed */ + /* aux points are points inserted between two points, making the outline smoother */ + /* the aux points could be used for curve fitting, but we add line segments */ + for ( xScan = xBuffer, yScan = yBuffer; x_coords < x_coords_last; x_coords += 2, y_coords += 2 ) { + x = pl_get_uint16(x_coords) & 0x3fff; + y = pl_get_uint16(y_coords) & 0x3fff; + + if_debug4('1', "[1]%s (%d,%d) %s\n", + (*x_coords & 0x80 ? " line" : "curve"), x, y, + (*y_coords & 0x80 ? " line" : "curve")); + + if (xScan > xBuffer) { /* not first point, therefore aux is possible */ + if ( x_aux_coords < x_aux_coords_last &&!(*x_coords & 0x80) ) { /* use an aux point */ + /* The auxiliary dx and dy values are signed. */ + int dx = (*x_aux_coords++ ^ 0x80) - 0x80; + int dy = (*y_aux_coords++ ^ 0x80) - 0x80; + + if_debug2('1', "[1]... aux (%d,%d)\n", dx, dy); + + xAux = (x + *(xScan-1)) / 2 + dx; + yAux = (y + *(yScan-1)) / 2 + dy; + if ((xAux >= llx && xAux <= urx) && (yAux >= lly && yAux <= ury)) { /* aux point is inside bounding box */ + *xScan++ = xAux; + *yScan++ = yAux; + } /* end point inside bounding box */ + /* what do points outside the bounding box mean? */ + } /* use an aux point */ + } /* not first point */ + + if ( (x >= llx && x <= urx) && (y >= lly && y <= ury) ) { /* point inside bounding box */ + *xScan++ = x; + *yScan++ = y; + } /* point inside bounding box */ + } /* for num_points - first time through */ + + if ( num_aux_points != 0xffff ) + xLast = xScan; + else + xLast = xScan - 1; /* discard the last point */ + + xScan = xBuffer; + yScan = yBuffer; + if (xLast > xBuffer) { + code = gs_moveto(pgs, (floatp)*xScan++, (floatp)*yScan++); + if ( code < 0 ) + goto cleanup; + } + + for (; xScan < xLast; ) { + code = gs_lineto(pgs, (floatp)*xScan++, (floatp)*yScan++); + if ( code < 0 ) + goto cleanup; + } + /* close the path of this loop */ + code = gs_closepath(pgs); + if ( code < 0 ) + break; - } /* for num_loops */ + } /* for num_loops */ - } /* end not compound */ - - return 0; +cleanup: + gs_free_object(pgs->memory, xBuffer, "x point buffer"); + gs_free_object(pgs->memory, yBuffer, "y point buffer"); + } /* end not compound */ + return code; } /* Get character existence and escapement for an Intellifont. */ private int pl_intelli_char_width(const pl_font_t *plfont, const void *pgs, uint char_code, gs_point *pwidth) -{ const byte *cdata = pl_font_lookup_glyph(plfont, char_code)->data; +{ + pl_font_glyph_t *cglyph = pl_font_lookup_glyph(plfont, char_code); + const byte *cdata = pl_font_lookup_glyph(plfont, char_code)->data; int wx; if ( !pwidth ) @@ -1478,6 +1400,9 @@ pl_intelli_char_width(const pl_font_t *plfont, const void *pgs, uint char_code, return 0; } pwidth->x = (floatp)wx / 8782.0; + + if_debug1('1', "[1] glyph %ld\n", cglyph->glyph); + if_debug2('1', "[1] intelli width of %d %f\n", char_code, pwidth->x); return 0; } |