diff options
Diffstat (limited to 'gs/base/gstype2.c')
-rw-r--r-- | gs/base/gstype2.c | 1282 |
1 files changed, 641 insertions, 641 deletions
diff --git a/gs/base/gstype2.c b/gs/base/gstype2.c index 21e3a335c..2c04e1b02 100644 --- a/gs/base/gstype2.c +++ b/gs/base/gstype2.c @@ -1,6 +1,6 @@ /* Copyright (C) 2001-2006 Artifex Software, Inc. All Rights Reserved. - + This software is provided AS-IS with no warranty, either express or implied. @@ -47,38 +47,38 @@ BEGIN\ if ( pcis->init_done < 0 )\ { ipsp->ip = cip, ipsp->dstate = state;\ - return type2_sbw(pcis, csp, cstack, ipsp, explicit_width);\ + return type2_sbw(pcis, csp, cstack, ipsp, explicit_width);\ }\ END static int type2_sbw(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack, ip_state_t * ipsp, - bool explicit_width) + bool explicit_width) { t1_hinter *h = &pcis->h; fixed sbx = fixed_0, sby = fixed_0, wx, wy = fixed_0; int code; if (explicit_width) { - wx = cstack[0] + pcis->pfont->data.nominalWidthX; - memmove(cstack, cstack + 1, (csp - cstack) * sizeof(*cstack)); - --csp; + wx = cstack[0] + pcis->pfont->data.nominalWidthX; + memmove(cstack, cstack + 1, (csp - cstack) * sizeof(*cstack)); + --csp; } else - wx = pcis->pfont->data.defaultWidthX; + wx = pcis->pfont->data.defaultWidthX; if (pcis->seac_accent < 0) { - if (pcis->sb_set) { - pcis->origin_offset.x = pcis->lsb.x - sbx; - pcis->origin_offset.y = pcis->lsb.y - sby; - sbx = pcis->lsb.x; - sby = pcis->lsb.y; - } - if (pcis->width_set) { - wx = pcis->width.x; - wy = pcis->width.y; - } + if (pcis->sb_set) { + pcis->origin_offset.x = pcis->lsb.x - sbx; + pcis->origin_offset.y = pcis->lsb.y - sby; + sbx = pcis->lsb.x; + sby = pcis->lsb.y; + } + if (pcis->width_set) { + wx = pcis->width.x; + wy = pcis->width.y; + } } code = t1_hinter__sbw(h, sbx, sby, wx, wy); if (code < 0) - return code; + return code; gs_type1_sbw(pcis, fixed_0, fixed_0, wx, fixed_0); /* Back up the interpretation pointer. */ ipsp->ip--; @@ -88,7 +88,7 @@ type2_sbw(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack, ip_state_t * ipsp, pcis->ips_count = ipsp - &pcis->ipstack[0] + 1; memcpy(pcis->ostack, cstack, pcis->os_count * sizeof(cstack[0])); if (pcis->init_done < 0) { /* Finish init when we return. */ - pcis->init_done = 0; + pcis->init_done = 0; } return type1_result_sbw; } @@ -102,8 +102,8 @@ type2_vstem(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack) for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) { code = t1_hinter__vstem(h, x += ap[0], ap[1]); - if (code < 0) - return code; + if (code < 0) + return code; } pcis->num_hints += (csp + 1 - cstack) >> 1; return 0; @@ -119,7 +119,7 @@ type2_vstem(gs_type1_state * pcis, cs_ptr csp, cs_ptr cstack) */ int gs_type2_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd, - int *ignore_pindex) + int *ignore_pindex) { gs_font_type1 *pfont = pcis->pfont; gs_type1_data *pdata = &pfont->data; @@ -138,659 +138,659 @@ gs_type2_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd, /****** FAKE THE REGISTRY ******/ struct { - float *values; - uint size; + float *values; + uint size; } Registry[1]; Registry[0].values = pcis->pfont->data.WeightVector.values; switch (pcis->init_done) { - case -1: - t1_hinter__init(h, pcis->path); - break; - case 0: - gs_type1_finish_init(pcis); /* sets origin */ + case -1: + t1_hinter__init(h, pcis->path); + break; + case 0: + gs_type1_finish_init(pcis); /* sets origin */ code = t1_hinter__set_mapping(h, &pcis->pis->ctm, - &pfont->FontMatrix, &pfont->base->FontMatrix, - pcis->scale.x.log2_unit, pcis->scale.x.log2_unit, - pcis->scale.x.log2_unit - pcis->log2_subpixels.x, - pcis->scale.y.log2_unit - pcis->log2_subpixels.y, - pcis->origin.x, pcis->origin.y, - gs_currentaligntopixels(pfont->dir)); - if (code < 0) - return code; - code = t1_hinter__set_font_data(h, 2, pdata, pcis->no_grid_fitting, - pcis->pfont->is_resource); - if (code < 0) - return code; - break; - default /*case 1 */ : - break; + &pfont->FontMatrix, &pfont->base->FontMatrix, + pcis->scale.x.log2_unit, pcis->scale.x.log2_unit, + pcis->scale.x.log2_unit - pcis->log2_subpixels.x, + pcis->scale.y.log2_unit - pcis->log2_subpixels.y, + pcis->origin.x, pcis->origin.y, + gs_currentaligntopixels(pfont->dir)); + if (code < 0) + return code; + code = t1_hinter__set_font_data(h, 2, pdata, pcis->no_grid_fitting, + pcis->pfont->is_resource); + if (code < 0) + return code; + break; + default /*case 1 */ : + break; } INIT_CSTACK(cstack, csp, pcis); if (pgd == 0) - goto cont; + goto cont; ipsp->cs_data = *pgd; cip = pgd->bits.data; if (cip == 0) - return (gs_note_error(gs_error_invalidfont)); + return (gs_note_error(gs_error_invalidfont)); call:state = crypt_charstring_seed; if (encrypted) { - int skip = pdata->lenIV; + int skip = pdata->lenIV; - /* Skip initial random bytes */ - for (; skip > 0; ++cip, --skip) - decrypt_skip_next(*cip, state); + /* Skip initial random bytes */ + for (; skip > 0; ++cip, --skip) + decrypt_skip_next(*cip, state); } goto top; cont:if (ipsp < pcis->ipstack || ipsp->ip == 0) - return (gs_note_error(gs_error_invalidfont)); + return (gs_note_error(gs_error_invalidfont)); cip = ipsp->ip; state = ipsp->dstate; top:for (;;) { - uint c0 = *cip++; - - charstring_next(c0, state, c, encrypted); - if (c >= c_num1) { - /* This is a number, decode it and push it on the stack. */ - - if (c < c_pos2_0) { /* 1-byte number */ - decode_push_num1(csp, cstack, c); - } else if (c < cx_num4) { /* 2-byte number */ - decode_push_num2(csp, cstack, c, cip, state, encrypted); - } else if (c == cx_num4) { /* 4-byte number */ - long lw; - - decode_num4(lw, cip, state, encrypted); - /* 32-bit numbers are 16:16. */ - CS_CHECK_PUSH(csp, cstack); - *++csp = arith_rshift(lw, 16 - _fixed_shift); - } else /* not possible */ - return_error(gs_error_invalidfont); - pushed:if_debug3('1', "[1]%d: (%d) %f\n", - (int)(csp - cstack), c, fixed2float(*csp)); - continue; - } + uint c0 = *cip++; + + charstring_next(c0, state, c, encrypted); + if (c >= c_num1) { + /* This is a number, decode it and push it on the stack. */ + + if (c < c_pos2_0) { /* 1-byte number */ + decode_push_num1(csp, cstack, c); + } else if (c < cx_num4) { /* 2-byte number */ + decode_push_num2(csp, cstack, c, cip, state, encrypted); + } else if (c == cx_num4) { /* 4-byte number */ + long lw; + + decode_num4(lw, cip, state, encrypted); + /* 32-bit numbers are 16:16. */ + CS_CHECK_PUSH(csp, cstack); + *++csp = arith_rshift(lw, 16 - _fixed_shift); + } else /* not possible */ + return_error(gs_error_invalidfont); + pushed:if_debug3('1', "[1]%d: (%d) %f\n", + (int)(csp - cstack), c, fixed2float(*csp)); + continue; + } #ifdef DEBUG - if (gs_debug['1']) { - static const char *const c2names[] = - {char2_command_names}; - - if (c2names[c] == 0) - dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c); - else - dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c, - c2names[c]); - } + if (gs_debug['1']) { + static const char *const c2names[] = + {char2_command_names}; + + if (c2names[c] == 0) + dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c); + else + dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c, + c2names[c]); + } #endif - switch ((char_command) c) { + switch ((char_command) c) { #define cnext clear; goto top - /* Commands with identical functions in Type 1 and Type 2, */ - /* except for 'escape'. */ - - case c_undef0: - case c_undef2: - case c_undef17: - return_error(gs_error_invalidfont); - case c_callsubr: - c = fixed2int_var(*csp) + pdata->subroutineNumberBias; - code = pdata->procs.subr_data - (pfont, c, false, &ipsp[1].cs_data); - subr:if (code < 0) { - /* Calling a Subr with an out-of-range index is clearly a error: - * the Adobe documentation says the results of doing this are - * undefined. However, we have seen a PDF file produced by Adobe - * PDF Library 4.16 that included a Type 2 font that called an - * out-of-range Subr, and Acrobat Reader did not signal an error. - * Therefore, we ignore such calls. - */ + /* Commands with identical functions in Type 1 and Type 2, */ + /* except for 'escape'. */ + + case c_undef0: + case c_undef2: + case c_undef17: + return_error(gs_error_invalidfont); + case c_callsubr: + c = fixed2int_var(*csp) + pdata->subroutineNumberBias; + code = pdata->procs.subr_data + (pfont, c, false, &ipsp[1].cs_data); + subr:if (code < 0) { + /* Calling a Subr with an out-of-range index is clearly a error: + * the Adobe documentation says the results of doing this are + * undefined. However, we have seen a PDF file produced by Adobe + * PDF Library 4.16 that included a Type 2 font that called an + * out-of-range Subr, and Acrobat Reader did not signal an error. + * Therefore, we ignore such calls. + */ cip++; goto top; } - --csp; - ipsp->ip = cip, ipsp->dstate = state; - ++ipsp; - cip = ipsp->cs_data.bits.data; - goto call; - case c_return: - gs_glyph_data_free(&ipsp->cs_data, "gs_type2_interpret"); - --ipsp; - goto cont; - case c_undoc15: - /* See gstype1.h for information on this opcode. */ - cnext; - - /* Commands with similar but not identical functions */ - /* in Type 1 and Type 2 charstrings. */ - - case cx_hstem: - goto hstem; - case cx_vstem: - goto vstem; - case cx_vmoveto: - check_first_operator(csp > cstack); + --csp; + ipsp->ip = cip, ipsp->dstate = state; + ++ipsp; + cip = ipsp->cs_data.bits.data; + goto call; + case c_return: + gs_glyph_data_free(&ipsp->cs_data, "gs_type2_interpret"); + --ipsp; + goto cont; + case c_undoc15: + /* See gstype1.h for information on this opcode. */ + cnext; + + /* Commands with similar but not identical functions */ + /* in Type 1 and Type 2 charstrings. */ + + case cx_hstem: + goto hstem; + case cx_vstem: + goto vstem; + case cx_vmoveto: + check_first_operator(csp > cstack); code = t1_hinter__rmoveto(h, 0, *csp); - move: - cc: - if (code < 0) - return code; - goto pp; - case cx_rlineto: - for (ap = cstack; ap + 1 <= csp; ap += 2) { - code = t1_hinter__rlineto(h, ap[0], ap[1]); - if (code < 0) - return code; - } - pp: - cnext; - case cx_hlineto: - vertical = false; - goto hvl; - case cx_vlineto: - vertical = true; - hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) { - if (vertical) { - code = t1_hinter__rlineto(h, 0, ap[0]); - } else { - code = t1_hinter__rlineto(h, ap[0], 0); - } - if (code < 0) - return code; - } - goto pp; - case cx_rrcurveto: - for (ap = cstack; ap + 5 <= csp; ap += 6) { - code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], - ap[3], ap[4], ap[5]); - if (code < 0) - return code; - } - goto pp; - case cx_endchar: - /* - * It is a feature of Type 2 CharStrings that if endchar is - * invoked with 4 or 5 operands, it is equivalent to the - * Type 1 seac operator. In this case, the asb operand of - * seac is missing: we assume it is the same as the - * l.s.b. of the accented character. This feature was - * undocumented until the 16 March 2000 version of the Type - * 2 Charstring Format specification, but, thankfully, is - * described in that revision. - */ - if (csp >= cstack + 3) { - check_first_operator(csp > cstack + 3); - code = gs_type1_seac(pcis, cstack, 0, ipsp); - if (code < 0) - return code; - clear; - cip = ipsp->cs_data.bits.data; - goto call; - } - /* - * This might be the only operator in the charstring. - * In this case, there might be a width on the stack. - */ - check_first_operator(csp >= cstack); - if (pcis->seac_accent < 0) { - code = t1_hinter__endglyph(h); - if (code < 0) - return code; - code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path); - if (code < 0) - return code; - } else { - t1_hinter__setcurrentpoint(h, pcis->save_adxy.x + pcis->origin_offset.x, - pcis->save_adxy.y + pcis->origin_offset.y); - code = t1_hinter__end_subglyph(h); - if (code < 0) - return code; - } - code = gs_type1_endchar(pcis); - if (code == 1) { - /* - * Reset the total hint count so that hintmask will - * parse its following data correctly. - * (gs_type1_endchar already reset the actual hint - * tables.) - */ - pcis->num_hints = 0; - /* do accent of seac */ - ipsp = &pcis->ipstack[pcis->ips_count - 1]; - cip = ipsp->cs_data.bits.data; - goto call; - } - return code; - case cx_rmoveto: - /* See vmoveto above re closing the subpath. */ - check_first_operator(!((csp - cstack) & 1)); - if (csp > cstack + 1) { - /* Some Type 2 charstrings omit the vstemhm operator before rmoveto, - even though this is only allowed before hintmask and cntrmask. - Thanks to Felix Pahl. - */ - type2_vstem(pcis, csp - 2, cstack); - cstack [0] = csp [-1]; - cstack [1] = csp [ 0]; - csp = cstack + 1; - } + move: + cc: + if (code < 0) + return code; + goto pp; + case cx_rlineto: + for (ap = cstack; ap + 1 <= csp; ap += 2) { + code = t1_hinter__rlineto(h, ap[0], ap[1]); + if (code < 0) + return code; + } + pp: + cnext; + case cx_hlineto: + vertical = false; + goto hvl; + case cx_vlineto: + vertical = true; + hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) { + if (vertical) { + code = t1_hinter__rlineto(h, 0, ap[0]); + } else { + code = t1_hinter__rlineto(h, ap[0], 0); + } + if (code < 0) + return code; + } + goto pp; + case cx_rrcurveto: + for (ap = cstack; ap + 5 <= csp; ap += 6) { + code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], + ap[3], ap[4], ap[5]); + if (code < 0) + return code; + } + goto pp; + case cx_endchar: + /* + * It is a feature of Type 2 CharStrings that if endchar is + * invoked with 4 or 5 operands, it is equivalent to the + * Type 1 seac operator. In this case, the asb operand of + * seac is missing: we assume it is the same as the + * l.s.b. of the accented character. This feature was + * undocumented until the 16 March 2000 version of the Type + * 2 Charstring Format specification, but, thankfully, is + * described in that revision. + */ + if (csp >= cstack + 3) { + check_first_operator(csp > cstack + 3); + code = gs_type1_seac(pcis, cstack, 0, ipsp); + if (code < 0) + return code; + clear; + cip = ipsp->cs_data.bits.data; + goto call; + } + /* + * This might be the only operator in the charstring. + * In this case, there might be a width on the stack. + */ + check_first_operator(csp >= cstack); + if (pcis->seac_accent < 0) { + code = t1_hinter__endglyph(h); + if (code < 0) + return code; + code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path); + if (code < 0) + return code; + } else { + t1_hinter__setcurrentpoint(h, pcis->save_adxy.x + pcis->origin_offset.x, + pcis->save_adxy.y + pcis->origin_offset.y); + code = t1_hinter__end_subglyph(h); + if (code < 0) + return code; + } + code = gs_type1_endchar(pcis); + if (code == 1) { + /* + * Reset the total hint count so that hintmask will + * parse its following data correctly. + * (gs_type1_endchar already reset the actual hint + * tables.) + */ + pcis->num_hints = 0; + /* do accent of seac */ + ipsp = &pcis->ipstack[pcis->ips_count - 1]; + cip = ipsp->cs_data.bits.data; + goto call; + } + return code; + case cx_rmoveto: + /* See vmoveto above re closing the subpath. */ + check_first_operator(!((csp - cstack) & 1)); + if (csp > cstack + 1) { + /* Some Type 2 charstrings omit the vstemhm operator before rmoveto, + even though this is only allowed before hintmask and cntrmask. + Thanks to Felix Pahl. + */ + type2_vstem(pcis, csp - 2, cstack); + cstack [0] = csp [-1]; + cstack [1] = csp [ 0]; + csp = cstack + 1; + } code = t1_hinter__rmoveto(h, csp[-1], *csp); - goto move; - case cx_hmoveto: - /* See vmoveto above re closing the subpath. */ - check_first_operator(csp > cstack); + goto move; + case cx_hmoveto: + /* See vmoveto above re closing the subpath. */ + check_first_operator(csp > cstack); code = t1_hinter__rmoveto(h, *csp, 0); - goto move; - case cx_vhcurveto: - vertical = true; - goto hvc; - case cx_hvcurveto: - vertical = false; - hvc:for (ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4) { - gs_fixed_point pt[2] = {{0, 0}, {0, 0}}; - if (vertical) { - pt[0].y = ap[0]; - pt[1].x = ap[3]; - if (ap + 4 == csp) - pt[1].y = ap[4]; - } else { - pt[0].x = ap[0]; - if (ap + 4 == csp) - pt[1].x = ap[4]; - pt[1].y = ap[3]; - } - code = t1_hinter__rcurveto(h, pt[0].x, pt[0].y, ap[1], ap[2], pt[1].x, pt[1].y); - if (code < 0) - return code; - } - goto pp; - - /*********************** - * New Type 2 commands * - ***********************/ - - case c2_blend: - { - int n = fixed2int_var(*csp); - int num_values = csp - cstack; - gs_font_type1 *pfont = pcis->pfont; - int k = pfont->data.WeightVector.count; - int i, j; - cs_ptr base, deltas; - - base = csp - 1 - num_values; - deltas = base + n - 1; - for (j = 0; j < n; j++, base++, deltas += k - 1) - for (i = 1; i < k; i++) - *base += (fixed)(deltas[i] * - pfont->data.WeightVector.values[i]); - } - cnext; - case c2_hstemhm: - hstem:check_first_operator(!((csp - cstack) & 1)); - { - fixed x = 0; - - for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) { - code = t1_hinter__hstem(h, x += ap[0], ap[1]); - if (code < 0) - return code; - } - } - pcis->num_hints += (csp + 1 - cstack) >> 1; - cnext; - case c2_hintmask: - /* - * A hintmask at the beginning of the CharString is - * equivalent to vstemhm + hintmask. For simplicity, we use - * this interpretation everywhere. - */ - case c2_cntrmask: - check_first_operator(!((csp - cstack) & 1)); - type2_vstem(pcis, csp, cstack); - /* - * We should clear the stack here only if this is the - * initial mask operator that includes the implicit - * vstemhm, but currently this is too much trouble to - * detect. - */ - clear; - { - byte mask[max_total_stem_hints / 8]; - int i; - - for (i = 0; i < pcis->num_hints; ++cip, i += 8) { - charstring_next(*cip, state, mask[i >> 3], encrypted); - if_debug1('1', " 0x%02x", mask[i >> 3]); - } - if_debug0('1', "\n"); - ipsp->ip = cip; - ipsp->dstate = state; - if (c == c2_cntrmask) { - /****** NYI ******/ - } else { /* hintmask or equivalent */ - if_debug0('1', "[1]hstem hints:\n"); - if_debug0('1', "[1]vstem hints:\n"); - code = t1_hinter__hint_mask(h, mask); - if (code < 0) - return code; - } - } - break; - case c2_vstemhm: - vstem:check_first_operator(!((csp - cstack) & 1)); - type2_vstem(pcis, csp, cstack); - cnext; - case c2_rcurveline: - for (ap = cstack; ap + 5 <= csp; ap += 6) { - code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3], - ap[4], ap[5]); - if (code < 0) - return code; - } - code = t1_hinter__rlineto(h, ap[0], ap[1]); - goto cc; - case c2_rlinecurve: - for (ap = cstack; ap + 7 <= csp; ap += 2) { - code = t1_hinter__rlineto(h, ap[0], ap[1]); - if (code < 0) - return code; - } - code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3], - ap[4], ap[5]); - goto cc; - case c2_vvcurveto: - ap = cstack; - { - int n = csp + 1 - cstack; - fixed dxa = (n & 1 ? *ap++ : 0); - - for (; ap + 3 <= csp; ap += 4) { - code = t1_hinter__rcurveto(h, dxa, ap[0], ap[1], ap[2], - fixed_0, ap[3]); - if (code < 0) - return code; - dxa = 0; - } - } - goto pp; - case c2_hhcurveto: - ap = cstack; - { - int n = csp + 1 - cstack; - fixed dya = (n & 1 ? *ap++ : 0); - - for (; ap + 3 <= csp; ap += 4) { - code = t1_hinter__rcurveto(h, ap[0], dya, ap[1], ap[2], - ap[3], fixed_0); - if (code < 0) - return code; - dya = 0; - } - } - goto pp; - case c2_shortint: - { - int c1, c2; - - charstring_next(*cip, state, c1, encrypted); - ++cip; - charstring_next(*cip, state, c2, encrypted); - ++cip; - CS_CHECK_PUSH(csp, cstack); - *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2); - } - goto pushed; - case c2_callgsubr: - c = fixed2int_var(*csp) + pdata->gsubrNumberBias; - code = pdata->procs.subr_data - (pfont, c, true, &ipsp[1].cs_data); - goto subr; - case cx_escape: - charstring_next(*cip, state, c, encrypted); - ++cip; + goto move; + case cx_vhcurveto: + vertical = true; + goto hvc; + case cx_hvcurveto: + vertical = false; + hvc:for (ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4) { + gs_fixed_point pt[2] = {{0, 0}, {0, 0}}; + if (vertical) { + pt[0].y = ap[0]; + pt[1].x = ap[3]; + if (ap + 4 == csp) + pt[1].y = ap[4]; + } else { + pt[0].x = ap[0]; + if (ap + 4 == csp) + pt[1].x = ap[4]; + pt[1].y = ap[3]; + } + code = t1_hinter__rcurveto(h, pt[0].x, pt[0].y, ap[1], ap[2], pt[1].x, pt[1].y); + if (code < 0) + return code; + } + goto pp; + + /*********************** + * New Type 2 commands * + ***********************/ + + case c2_blend: + { + int n = fixed2int_var(*csp); + int num_values = csp - cstack; + gs_font_type1 *pfont = pcis->pfont; + int k = pfont->data.WeightVector.count; + int i, j; + cs_ptr base, deltas; + + base = csp - 1 - num_values; + deltas = base + n - 1; + for (j = 0; j < n; j++, base++, deltas += k - 1) + for (i = 1; i < k; i++) + *base += (fixed)(deltas[i] * + pfont->data.WeightVector.values[i]); + } + cnext; + case c2_hstemhm: + hstem:check_first_operator(!((csp - cstack) & 1)); + { + fixed x = 0; + + for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) { + code = t1_hinter__hstem(h, x += ap[0], ap[1]); + if (code < 0) + return code; + } + } + pcis->num_hints += (csp + 1 - cstack) >> 1; + cnext; + case c2_hintmask: + /* + * A hintmask at the beginning of the CharString is + * equivalent to vstemhm + hintmask. For simplicity, we use + * this interpretation everywhere. + */ + case c2_cntrmask: + check_first_operator(!((csp - cstack) & 1)); + type2_vstem(pcis, csp, cstack); + /* + * We should clear the stack here only if this is the + * initial mask operator that includes the implicit + * vstemhm, but currently this is too much trouble to + * detect. + */ + clear; + { + byte mask[max_total_stem_hints / 8]; + int i; + + for (i = 0; i < pcis->num_hints; ++cip, i += 8) { + charstring_next(*cip, state, mask[i >> 3], encrypted); + if_debug1('1', " 0x%02x", mask[i >> 3]); + } + if_debug0('1', "\n"); + ipsp->ip = cip; + ipsp->dstate = state; + if (c == c2_cntrmask) { + /****** NYI ******/ + } else { /* hintmask or equivalent */ + if_debug0('1', "[1]hstem hints:\n"); + if_debug0('1', "[1]vstem hints:\n"); + code = t1_hinter__hint_mask(h, mask); + if (code < 0) + return code; + } + } + break; + case c2_vstemhm: + vstem:check_first_operator(!((csp - cstack) & 1)); + type2_vstem(pcis, csp, cstack); + cnext; + case c2_rcurveline: + for (ap = cstack; ap + 5 <= csp; ap += 6) { + code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3], + ap[4], ap[5]); + if (code < 0) + return code; + } + code = t1_hinter__rlineto(h, ap[0], ap[1]); + goto cc; + case c2_rlinecurve: + for (ap = cstack; ap + 7 <= csp; ap += 2) { + code = t1_hinter__rlineto(h, ap[0], ap[1]); + if (code < 0) + return code; + } + code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3], + ap[4], ap[5]); + goto cc; + case c2_vvcurveto: + ap = cstack; + { + int n = csp + 1 - cstack; + fixed dxa = (n & 1 ? *ap++ : 0); + + for (; ap + 3 <= csp; ap += 4) { + code = t1_hinter__rcurveto(h, dxa, ap[0], ap[1], ap[2], + fixed_0, ap[3]); + if (code < 0) + return code; + dxa = 0; + } + } + goto pp; + case c2_hhcurveto: + ap = cstack; + { + int n = csp + 1 - cstack; + fixed dya = (n & 1 ? *ap++ : 0); + + for (; ap + 3 <= csp; ap += 4) { + code = t1_hinter__rcurveto(h, ap[0], dya, ap[1], ap[2], + ap[3], fixed_0); + if (code < 0) + return code; + dya = 0; + } + } + goto pp; + case c2_shortint: + { + int c1, c2; + + charstring_next(*cip, state, c1, encrypted); + ++cip; + charstring_next(*cip, state, c2, encrypted); + ++cip; + CS_CHECK_PUSH(csp, cstack); + *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2); + } + goto pushed; + case c2_callgsubr: + c = fixed2int_var(*csp) + pdata->gsubrNumberBias; + code = pdata->procs.subr_data + (pfont, c, true, &ipsp[1].cs_data); + goto subr; + case cx_escape: + charstring_next(*cip, state, c, encrypted); + ++cip; #ifdef DEBUG - if (gs_debug['1'] && c < char2_extended_command_count) { - static const char *const ce2names[] = - {char2_extended_command_names}; - - if (ce2names[c] == 0) - dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c); - else - dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c, - ce2names[c]); - } + if (gs_debug['1'] && c < char2_extended_command_count) { + static const char *const ce2names[] = + {char2_extended_command_names}; + + if (ce2names[c] == 0) + dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c); + else + dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c, + ce2names[c]); + } #endif - switch ((char2_extended_command) c) { - case ce2_and: - csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0); - --csp; - break; - case ce2_or: - csp[-1] = (csp[-1] | *csp ? fixed_1 : 0); - --csp; - break; - case ce2_not: - *csp = (*csp ? 0 : fixed_1); - break; - case ce2_store: - { - int i, n = fixed2int_var(*csp); - float *to = Registry[fixed2int_var(csp[-3])].values + - fixed2int_var(csp[-2]); - const fixed *from = - pcis->transient_array + fixed2int_var(csp[-1]); - - for (i = 0; i < n; ++i) - to[i] = fixed2float(from[i]); - } - csp -= 4; - break; - case ce2_abs: - if (*csp < 0) - *csp = -*csp; - break; - case ce2_add: - csp[-1] += *csp; - --csp; - break; - case ce2_sub: - csp[-1] -= *csp; - --csp; - break; - case ce2_div: - csp[-1] = float2fixed((double)csp[-1] / *csp); - --csp; - break; - case ce2_load: - /* The specification says there is no j (starting index */ - /* in registry array) argument.... */ - { - int i, n = fixed2int_var(*csp); - const float *from = Registry[fixed2int_var(csp[-2])].values; - fixed *to = - pcis->transient_array + fixed2int_var(csp[-1]); - - for (i = 0; i < n; ++i) - to[i] = float2fixed(from[i]); - } - csp -= 3; - break; - case ce2_neg: - *csp = -*csp; - break; - case ce2_eq: - csp[-1] = (csp[-1] == *csp ? fixed_1 : 0); - --csp; - break; - case ce2_drop: - --csp; - break; - case ce2_put: - pcis->transient_array[fixed2int_var(*csp)] = csp[-1]; - csp -= 2; - break; - case ce2_get: - *csp = pcis->transient_array[fixed2int_var(*csp)]; - break; - case ce2_ifelse: - if (csp[-1] > *csp) - csp[-3] = csp[-2]; - csp -= 3; - break; - case ce2_random: - CS_CHECK_PUSH(csp, cstack); - ++csp; - /****** NYI ******/ - break; - case ce2_mul: - { - double prod = fixed2float(csp[-1]) * *csp; - - csp[-1] = - (prod > max_fixed ? max_fixed : - prod < min_fixed ? min_fixed : (fixed)prod); - } - --csp; - break; - case ce2_sqrt: - if (*csp >= 0) - *csp = float2fixed(sqrt(fixed2float(*csp))); - break; - case ce2_dup: - CS_CHECK_PUSH(csp, cstack); - csp[1] = *csp; - ++csp; - break; - case ce2_exch: - { - fixed top = *csp; - - *csp = csp[-1], csp[-1] = top; - } - break; - case ce2_index: - *csp = - (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]); - break; - case ce2_roll: - { - int distance = fixed2int_var(*csp); - int count = fixed2int_var(csp[-1]); - cs_ptr bot; - - csp -= 2; - if (count < 0 || count > csp + 1 - cstack) - return_error(gs_error_invalidfont); - if (count == 0) - break; - if (distance < 0) - distance = count - (-distance % count); - bot = csp + 1 - count; - while (--distance >= 0) { - fixed top = *csp; - - memmove(bot + 1, bot, - (count - 1) * sizeof(fixed)); - *bot = top; - } - } - break; - case ce2_hflex: - csp[6] = fixed_half; /* fd/100 */ - csp[4] = *csp, csp[5] = 0; /* dx6, dy6 */ - csp[2] = csp[-1], csp[3] = -csp[-4]; /* dx5, dy5 */ - *csp = csp[-2], csp[1] = 0; /* dx4, dy4 */ - csp[-2] = csp[-3], csp[-1] = 0; /* dx3, dy3 */ - csp[-3] = csp[-4], csp[-4] = csp[-5]; /* dx2, dy2 */ - csp[-5] = 0; /* dy1 */ - csp += 6; - goto flex; - case ce2_flex: - *csp /= 100; /* fd/100 */ + switch ((char2_extended_command) c) { + case ce2_and: + csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0); + --csp; + break; + case ce2_or: + csp[-1] = (csp[-1] | *csp ? fixed_1 : 0); + --csp; + break; + case ce2_not: + *csp = (*csp ? 0 : fixed_1); + break; + case ce2_store: + { + int i, n = fixed2int_var(*csp); + float *to = Registry[fixed2int_var(csp[-3])].values + + fixed2int_var(csp[-2]); + const fixed *from = + pcis->transient_array + fixed2int_var(csp[-1]); + + for (i = 0; i < n; ++i) + to[i] = fixed2float(from[i]); + } + csp -= 4; + break; + case ce2_abs: + if (*csp < 0) + *csp = -*csp; + break; + case ce2_add: + csp[-1] += *csp; + --csp; + break; + case ce2_sub: + csp[-1] -= *csp; + --csp; + break; + case ce2_div: + csp[-1] = float2fixed((double)csp[-1] / *csp); + --csp; + break; + case ce2_load: + /* The specification says there is no j (starting index */ + /* in registry array) argument.... */ + { + int i, n = fixed2int_var(*csp); + const float *from = Registry[fixed2int_var(csp[-2])].values; + fixed *to = + pcis->transient_array + fixed2int_var(csp[-1]); + + for (i = 0; i < n; ++i) + to[i] = float2fixed(from[i]); + } + csp -= 3; + break; + case ce2_neg: + *csp = -*csp; + break; + case ce2_eq: + csp[-1] = (csp[-1] == *csp ? fixed_1 : 0); + --csp; + break; + case ce2_drop: + --csp; + break; + case ce2_put: + pcis->transient_array[fixed2int_var(*csp)] = csp[-1]; + csp -= 2; + break; + case ce2_get: + *csp = pcis->transient_array[fixed2int_var(*csp)]; + break; + case ce2_ifelse: + if (csp[-1] > *csp) + csp[-3] = csp[-2]; + csp -= 3; + break; + case ce2_random: + CS_CHECK_PUSH(csp, cstack); + ++csp; + /****** NYI ******/ + break; + case ce2_mul: + { + double prod = fixed2float(csp[-1]) * *csp; + + csp[-1] = + (prod > max_fixed ? max_fixed : + prod < min_fixed ? min_fixed : (fixed)prod); + } + --csp; + break; + case ce2_sqrt: + if (*csp >= 0) + *csp = float2fixed(sqrt(fixed2float(*csp))); + break; + case ce2_dup: + CS_CHECK_PUSH(csp, cstack); + csp[1] = *csp; + ++csp; + break; + case ce2_exch: + { + fixed top = *csp; + + *csp = csp[-1], csp[-1] = top; + } + break; + case ce2_index: + *csp = + (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]); + break; + case ce2_roll: + { + int distance = fixed2int_var(*csp); + int count = fixed2int_var(csp[-1]); + cs_ptr bot; + + csp -= 2; + if (count < 0 || count > csp + 1 - cstack) + return_error(gs_error_invalidfont); + if (count == 0) + break; + if (distance < 0) + distance = count - (-distance % count); + bot = csp + 1 - count; + while (--distance >= 0) { + fixed top = *csp; + + memmove(bot + 1, bot, + (count - 1) * sizeof(fixed)); + *bot = top; + } + } + break; + case ce2_hflex: + csp[6] = fixed_half; /* fd/100 */ + csp[4] = *csp, csp[5] = 0; /* dx6, dy6 */ + csp[2] = csp[-1], csp[3] = -csp[-4]; /* dx5, dy5 */ + *csp = csp[-2], csp[1] = 0; /* dx4, dy4 */ + csp[-2] = csp[-3], csp[-1] = 0; /* dx3, dy3 */ + csp[-3] = csp[-4], csp[-4] = csp[-5]; /* dx2, dy2 */ + csp[-5] = 0; /* dy1 */ + csp += 6; + goto flex; + case ce2_flex: + *csp /= 100; /* fd/100 */ flex: { - fixed x_join = csp[-12] + csp[-10] + csp[-8]; - fixed y_join = csp[-11] + csp[-9] + csp[-7]; - fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2]; - fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1]; - gs_point join, end; - double flex_depth; - - if ((code = - gs_distance_transform(fixed2float(x_join), - fixed2float(y_join), - &ctm_only(pcis->pis), - &join)) < 0 || - (code = - gs_distance_transform(fixed2float(x_end), - fixed2float(y_end), - &ctm_only(pcis->pis), - &end)) < 0 - ) - return code; - /* - * Use the X or Y distance depending on whether - * the curve is more horizontal or more - * vertical. - */ - if (any_abs(end.y) > any_abs(end.x)) - flex_depth = join.x; - else - flex_depth = join.y; - if (fabs(flex_depth) < fixed2float(*csp)) { - /* Do flex as line. */ - code = t1_hinter__rlineto(h, x_end, y_end); - } else { - /* - * Do flex as curve. We can't jump to rrc, - * because the flex operators don't clear - * the stack (!). - */ - code = t1_hinter__rcurveto(h, - csp[-12], csp[-11], csp[-10], - csp[-9], csp[-8], csp[-7]); - if (code < 0) - return code; - code = t1_hinter__rcurveto(h, - csp[-6], csp[-5], csp[-4], - csp[-3], csp[-2], csp[-1]); - } - if (code < 0) - return code; - csp -= 13; - } - cnext; - case ce2_hflex1: - csp[4] = fixed_half; /* fd/100 */ - csp[2] = *csp; /* dx6 */ - csp[3] = -(csp[-7] + csp[-5] + csp[-1]); /* dy6 */ - *csp = csp[-2], csp[1] = csp[-1]; /* dx5, dy5 */ - csp[-2] = csp[-3], csp[-1] = 0; /* dx4, dy4 */ - csp[-3] = 0; /* dy3 */ - csp += 4; - goto flex; - case ce2_flex1: - { - fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2]; - fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1]; - - if (any_abs(dx) > any_abs(dy)) - csp[1] = -dy; /* d6 is dx6 */ - else - csp[1] = *csp, *csp = -dx; /* d6 is dy6 */ - } - csp[2] = fixed_half; /* fd/100 */ - csp += 2; - goto flex; - } - break; - - /* Fill up the dispatch up to 32. */ - - case_c2_undefs: - default: /* pacify compiler */ - return_error(gs_error_invalidfont); - } + fixed x_join = csp[-12] + csp[-10] + csp[-8]; + fixed y_join = csp[-11] + csp[-9] + csp[-7]; + fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2]; + fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1]; + gs_point join, end; + double flex_depth; + + if ((code = + gs_distance_transform(fixed2float(x_join), + fixed2float(y_join), + &ctm_only(pcis->pis), + &join)) < 0 || + (code = + gs_distance_transform(fixed2float(x_end), + fixed2float(y_end), + &ctm_only(pcis->pis), + &end)) < 0 + ) + return code; + /* + * Use the X or Y distance depending on whether + * the curve is more horizontal or more + * vertical. + */ + if (any_abs(end.y) > any_abs(end.x)) + flex_depth = join.x; + else + flex_depth = join.y; + if (fabs(flex_depth) < fixed2float(*csp)) { + /* Do flex as line. */ + code = t1_hinter__rlineto(h, x_end, y_end); + } else { + /* + * Do flex as curve. We can't jump to rrc, + * because the flex operators don't clear + * the stack (!). + */ + code = t1_hinter__rcurveto(h, + csp[-12], csp[-11], csp[-10], + csp[-9], csp[-8], csp[-7]); + if (code < 0) + return code; + code = t1_hinter__rcurveto(h, + csp[-6], csp[-5], csp[-4], + csp[-3], csp[-2], csp[-1]); + } + if (code < 0) + return code; + csp -= 13; + } + cnext; + case ce2_hflex1: + csp[4] = fixed_half; /* fd/100 */ + csp[2] = *csp; /* dx6 */ + csp[3] = -(csp[-7] + csp[-5] + csp[-1]); /* dy6 */ + *csp = csp[-2], csp[1] = csp[-1]; /* dx5, dy5 */ + csp[-2] = csp[-3], csp[-1] = 0; /* dx4, dy4 */ + csp[-3] = 0; /* dy3 */ + csp += 4; + goto flex; + case ce2_flex1: + { + fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2]; + fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1]; + + if (any_abs(dx) > any_abs(dy)) + csp[1] = -dy; /* d6 is dx6 */ + else + csp[1] = *csp, *csp = -dx; /* d6 is dy6 */ + } + csp[2] = fixed_half; /* fd/100 */ + csp += 2; + goto flex; + } + break; + + /* Fill up the dispatch up to 32. */ + + case_c2_undefs: + default: /* pacify compiler */ + return_error(gs_error_invalidfont); + } } } |