summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/xsrc/t1_char.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/xsrc/t1_char.c')
-rw-r--r--Build/source/texk/dvipdfm-x/xsrc/t1_char.c1590
1 files changed, 0 insertions, 1590 deletions
diff --git a/Build/source/texk/dvipdfm-x/xsrc/t1_char.c b/Build/source/texk/dvipdfm-x/xsrc/t1_char.c
deleted file mode 100644
index 7b6788870bd..00000000000
--- a/Build/source/texk/dvipdfm-x/xsrc/t1_char.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/*
-
- This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
-
- Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
- the dvipdfmx project team.
-
- Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-*/
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <math.h>
-
-#include "system.h"
-#include "mem.h"
-#include "error.h"
-#include "numbers.h"
-
-#include "pdfobj.h"
-#include "pdffont.h"
-
-#include "pdfencoding.h"
-#include "unicode.h"
-
-#include "dpxutil.h"
-
-#include "pst_obj.h"
-#include "pst.h"
-
-#include "cff_limits.h"
-#include "cff_types.h"
-#include "cff_dict.h"
-#include "cff.h"
-
-#include "t1_char.h"
-
-/*
- * Type 1 -> Type 1C
- */
-
-/* Charstring decoder/encoder status codes */
-#define CS_OP_NOSUPPORT -4
-#define CS_BUFFER_ERROR -3
-#define CS_STACK_ERROR -2
-#define CS_PARSE_ERROR -1
-#define CS_PARSE_OK 0
-#define CS_PARSE_END 1
-#define CS_SUBR_RETURN 2
-#define CS_CHAR_END 3
-
-static int status = CS_PARSE_ERROR;
-
-#define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_ERROR ; return ; }}
-#define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_ERROR ; return ; }}
-#define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_ERROR ; return ; }}
-
-#define T1_CS_PHASE_INIT 0
-#define T1_CS_PHASE_HINT 1
-#define T1_CS_PHASE_PATH 2
-#define T1_CS_PHASE_FLEX 3
-
-static int phase = -1;
-static int nest = -1;
-
-#ifndef CS_STEM_ZONE_MAX
-#define CS_STEM_ZONE_MAX 96
-#endif
-#ifndef CS_STEM_GROUP_MAX
-#define CS_STEM_GROUP_MAX CS_STEM_ZONE_MAX
-#endif
-#ifndef CS_ARG_STACK_MAX
-#define CS_ARG_STACK_MAX 48
-#endif
-#ifndef PS_ARG_STACK_MAX
-/*
- * Counter control may have CS_STEM_ZONE_MAX*2+2 arguments.
- */
-#define PS_ARG_STACK_MAX (CS_STEM_ZONE_MAX*2+2)
-#endif
-
-typedef struct t1_cpath {
- int type;
- int num_args;
- double args[CS_ARG_STACK_MAX];
- struct t1_cpath *next;
-} t1_cpath;
-
-#define HSTEM 0
-#define VSTEM 1
-typedef struct {
- int id;
- int dir;
- double pos, del;
-} t1_stem;
-
-typedef struct {
- int num_stems;
- double stems[CS_STEM_ZONE_MAX]; /* int */
-} t1_stemgroup;
-
-#define T1_CS_FLAG_NONE 0
-#define T1_CS_FLAG_USE_HINTMASK (1 << 0)
-#define T1_CS_FLAG_USE_CNTRMASK (1 << 1)
-#define T1_CS_FLAG_USE_SEAC (1 << 2)
-
-typedef struct {
- int flags;
- struct {
- double sbx, sby, wx, wy;
- } sbw;
- struct {
- double llx, lly, urx, ury;
- } bbox;
- struct {
- double asb, adx, ady;
- card8 bchar, achar;
- } seac;
- int num_stems;
- t1_stem stems[CS_STEM_ZONE_MAX];
- t1_cpath *charpath;
- t1_cpath *lastpath;
-} t1_chardesc;
-
-static int cs_stack_top = 0;
-static int ps_stack_top = 0;
-
-/* [vh]stem support require one more stack size. */
-static double cs_arg_stack[CS_ARG_STACK_MAX+1];
-static double ps_arg_stack[PS_ARG_STACK_MAX];
-
-#define CS_HINT_DECL -1
-#define CS_FLEX_CTRL -2
-#define CS_CNTR_CTRL -3
-
-/*
- * Type 1/2 CharString encoding
- */
-
-/*
- * 1-byte CharString operaotrs:
- * cs_escape is first byte of two-byte operator
- */
-
-/* RESERVED 0 */
-#define cs_hstem 1
-/* RESERVED 2 */
-#define cs_vstem 3
-#define cs_vmoveto 4
-#define cs_rlineto 5
-#define cs_hlineto 6
-#define cs_vlineto 7
-#define cs_rrcurveto 8
-#define cs_closepath 9
-#define cs_callsubr 10
-#define cs_return 11
-#define cs_escape 12
-#define cs_hsbw 13
-#define cs_endchar 14
-/* RESERVED 15 */
-/* RESERVED 16 */
-/* RESERVED 17 */
-#define cs_hstemhm 18
-#define cs_hintmask 19
-#define cs_cntrmask 20
-#define cs_rmoveto 21
-#define cs_hmoveto 22
-#define cs_vstemhm 23
-#define cs_rcurveline 24
-#define cs_rlinecurve 25
-#define cs_vvcurveto 26
-#define cs_hhcurveto 27
-/* SHORTINT 28 : first byte of shortint*/
-#define cs_callgsubr 29
-#define cs_vhcurveto 30
-#define cs_hvcurveto 31
-
-/* 2-byte op. flex 34-37 used. */
-
-/*
- * 2-byte CharString operaotrs:
- * "dotsection" is obsoleted in Type 2 charstring.
- */
-
-#define cs_dotsection 0
-#define cs_vstem3 1
-#define cs_hstem3 2
-#define cs_and 3
-#define cs_or 4
-#define cs_not 5
-#define cs_seac 6
-#define cs_sbw 7
-/* RESERVED 8 */
-#define cs_abs 9
-#define cs_add 10
-#define cs_sub 11
-#define cs_div 12
-/* RESERVED 13 */
-#define cs_neg 14
-#define cs_eq 15
-#define cs_callothersubr 16
-#define cs_pop 17
-#define cs_drop 18
-/* RESERVED 19 */
-#define cs_put 20
-#define cs_get 21
-#define cs_ifelse 22
-#define cs_random 23
-#define cs_mul 24
-/* RESERVED 25 */
-#define cs_sqrt 26
-#define cs_dup 27
-#define cs_exch 28
-#define cs_index 29
-#define cs_roll 30
-/* RESERVED 31 */
-/* RESERVED 32 */
-#define cs_setcurrentpoint 33
-#define cs_hflex 34
-#define cs_flex 35
-#define cs_hflex1 36
-#define cs_flex1 37
-
-#define IS_PATH_OPERATOR(o) (((o) >= cs_vmoveto && (o) <= cs_closepath) || \
- ((o) >= cs_rmoveto && (o) <= cs_hvcurveto && \
- (o) != cs_vstemhm && (o) != cs_callgsubr && (o) != 28)\
- )
-
-/*
- * Stem:
- *
- * 1. Stems must be sorted in the increasing bottom/left edge order.
- * 2. The encoded values are all relative; The value x(y) of the first
- * stem is relative to 0 for Type 2 charstring and is relative to
- * the left(bottom) side-bearing for Type 1 charstring.
- * 3. A width of -20(-21) specifies the top/right(bottom/left) edge
- * of an edge hint in Type 2 charstring. But the width of 'ghost'
- * hint in Type 1 charstring is positive with value 20 or 21.
- * 4. The h(v)stemhm MUST be used instead of h(v)stem if charstring
- * contains hintmask operator.
- *
- * TODO:
- *
- * Convert ghost hint to edge hint, Counter control for hstem3/vstem3.
- */
-
-static int CDECL
-stem_compare (const void *v1, const void *v2)
-{
- int cmp = 0;
- const t1_stem *s1, *s2;
-
- s1 = (const t1_stem *) v1;
- s2 = (const t1_stem *) v2;
- if (s1->dir == s2->dir) {
- if (s1->pos == s2->pos) {
- if (s1->del == s2->del)
- cmp = 0;
- else
- cmp = (s1->del < s2->del) ? -1 : 1;
- } else {
- cmp = (s1->pos < s2->pos) ? -1 : 1;
- }
- } else {
- cmp = (s1->dir == HSTEM) ? -1 : 1;
- }
-
- return cmp;
-}
-
-#define SORT_STEMS(cd) qsort((cd)->stems,(cd)->num_stems,sizeof(t1_stem),stem_compare)
-
-static int
-get_stem (t1_chardesc *cd, int stem_id)
-{
- int i;
-
- for (i = 0; i < cd->num_stems; i++) {
- if (cd->stems[i].id == stem_id)
- break;
- }
-
- return ((i < cd->num_stems) ? i : -1);
-}
-
-static int
-add_stem (t1_chardesc *cd, double pos, double del, int dir)
-{
- int i;
-
- ASSERT(cd);
-
- pos += (dir == HSTEM) ? cd->sbw.sby : cd->sbw.sbx;
- for (i = 0; i < cd->num_stems; i++) {
- if (cd->stems[i].dir == dir &&
- cd->stems[i].pos == pos &&
- cd->stems[i].del == del)
- break;
- }
- if (i == cd->num_stems) {
- if (cd->num_stems == CS_STEM_ZONE_MAX)
- return -1;
- cd->stems[i].dir = dir;
- cd->stems[i].pos = pos;
- cd->stems[i].del = del;
- cd->stems[i].id = cd->num_stems;
- (cd->num_stems)++;
- }
-
- return cd->stems[i].id;
-}
-
-
-static void
-copy_args (double *args1, double *args2, int count)
-{
- while (count-- > 0) {
- *args1 = *args2;
- args1++; args2++;
- }
-}
-
-/*
- * Stack:
- */
-#define LIMITCHECK(n) do {\
- if (cs_stack_top+(n) > CS_ARG_STACK_MAX) {\
- status = CS_STACK_ERROR;\
- return;\
- }\
- } while (0)
-#define CHECKSTACK(n) do {\
- if (cs_stack_top < (n)) {\
- status = CS_STACK_ERROR;\
- return;\
- }\
- } while (0)
-#define CLEARSTACK() do {\
- cs_stack_top = 0;\
- } while (0)
-
-/*
- * Path construction:
- */
-/* Get operands from cs_arg_stack[] */
-static void
-add_charpath (t1_chardesc *cd, int type, double *argv, int argn)
-{
- t1_cpath *p;
-
- ASSERT(cd);
- ASSERT(argn <= CS_ARG_STACK_MAX);
-
- p = NEW(1, t1_cpath);
- p->type = type;
- p->num_args = argn;
- p->next = NULL;
-
- while (argn-- > 0)
- p->args[argn] = argv[argn];
-
- if (!cd->charpath)
- cd->charpath = p;
- if (cd->lastpath)
- cd->lastpath->next = p;
- cd->lastpath = p;
-
- if (type >= 0 &&
- phase != T1_CS_PHASE_FLEX && IS_PATH_OPERATOR(type))
- phase = T1_CS_PHASE_PATH;
-}
-
-static void
-init_charpath (t1_chardesc *cd)
-{
- cd->flags = T1_CS_FLAG_NONE;
- cd->num_stems = 0;
- cd->sbw.wx = cd->sbw.wy = 0.0;
- cd->sbw.sbx = cd->sbw.sby = 0.0;
- cd->bbox.llx = cd->bbox.lly = cd->bbox.urx = cd->bbox.ury = 0.0;
- cd->charpath = cd->lastpath = NULL;
-}
-
-static void
-release_charpath (t1_chardesc *cd)
-{
- t1_cpath *curr, *next;
-
- ASSERT(cd);
-
- curr = cd->charpath;
- while (curr != NULL) {
- next = curr->next;
- RELEASE(curr);
- curr = next;
- }
-
- cd->charpath = cd->lastpath = NULL;
-}
-
-/*
- * Type 1 charstring operators:
- */
-#define ADD_PATH(p,t,n) add_charpath((p),(t),&(cs_arg_stack[cs_stack_top-(n)]),(n))
-
-/*
- * Single byte operators:
- */
-static void
-do_operator1 (t1_chardesc *cd, card8 **data, card8 *endptr)
-{
- card8 op = **data;
-
- *data += 1;
-
- switch (op) {
- case cs_closepath:
- /*
- * From T1 spec.:
- * Note that, unlike the closepath command in the PostScript language,
- * this command does not reposition the current point. Any subsequent
- * rmoveto must be relative to the current point in force before the
- * Type 1 font format closepath command was given.
- */
- /* noop */
- CLEARSTACK();
- break;
- case cs_hsbw:
- CHECKSTACK(2);
- cd->sbw.wx = cs_arg_stack[--cs_stack_top];
- cd->sbw.wy = 0;
- cd->sbw.sbx = cs_arg_stack[--cs_stack_top];
- cd->sbw.sby = 0;
- CLEARSTACK();
- /* hsbw does NOT set currentpoint. */
- break;
- case cs_hstem:
- case cs_vstem:
- CHECKSTACK(2);
- {
- int stem_id;
- stem_id = add_stem(cd,
- cs_arg_stack[cs_stack_top-2],
- cs_arg_stack[cs_stack_top-1],
- ((op == cs_hstem) ? HSTEM : VSTEM));
- if (stem_id < 0) {
- WARN("Too many hints...");
- status = CS_PARSE_ERROR;
- return;
- }
- /* Put stem_id onto the stack... */
- cs_arg_stack[cs_stack_top++] = stem_id;
- ADD_PATH(cd, CS_HINT_DECL, 1);
- }
- CLEARSTACK();
- break;
- case cs_rmoveto:
- /*
- * Reference point is (0, 0) in Type 2 charstring.
- */
- CHECKSTACK(2);
- {
- if (phase < T1_CS_PHASE_PATH) {
- cs_arg_stack[cs_stack_top-2] += cd->sbw.sbx;
- cs_arg_stack[cs_stack_top-1] += cd->sbw.sby;
- }
- ADD_PATH(cd, op, 2);
- }
- CLEARSTACK();
- break;
- case cs_hmoveto:
- case cs_vmoveto:
- CHECKSTACK(1);
- {
- int argn = 1;
- if (phase < T1_CS_PHASE_PATH) {
- /*
- * The reference point for the first moveto operator is diferrent
- * between Type 1 charstring and Type 2 charstring. We compensate it.
- */
- if (op == cs_hmoveto) {
- cs_arg_stack[cs_stack_top-1] += cd->sbw.sbx;
- if (cd->sbw.sby != 0.0) {
- cs_arg_stack[cs_stack_top++] = cd->sbw.sby;
- argn = 2;
- op = cs_rmoveto;
- }
- } else {
- cs_arg_stack[cs_stack_top-1] += cd->sbw.sby;
- if (cd->sbw.sbx != 0.0) {
- cs_arg_stack[cs_stack_top] = cs_arg_stack[cs_stack_top-1];
- cs_arg_stack[cs_stack_top-1] = cd->sbw.sbx;
- cs_stack_top++;
- argn = 2;
- op = cs_rmoveto;
- }
- }
- }
- ADD_PATH(cd, op, argn);
- }
- CLEARSTACK();
- break;
- case cs_endchar:
- status = CS_CHAR_END;
- CLEARSTACK();
- break;
- /* above oprators are candidate for first stack-clearing operator */
- case cs_rlineto:
- CHECKSTACK(2);
- ADD_PATH(cd, op, 2);
- CLEARSTACK();
- break;
- case cs_hlineto:
- case cs_vlineto:
- CHECKSTACK(1);
- ADD_PATH(cd, op, 1);
- CLEARSTACK();
- break;
- case cs_rrcurveto:
- CHECKSTACK(6);
- ADD_PATH(cd, op, 6);
- CLEARSTACK();
- break;
- case cs_vhcurveto:
- case cs_hvcurveto:
- CHECKSTACK(4);
- ADD_PATH(cd, op, 4);
- CLEARSTACK();
- break;
- /* all operotors above are stack-clearing operator */
- /* no output */
- case cs_return:
- break;
- case cs_callsubr:
- ERROR("Unexpected callsubr.");
- break;
- default:
- /* no-op ? */
- WARN("Unknown charstring operator: 0x%02x", op);
- status = CS_PARSE_ERROR;
- break;
- }
-
- return;
-}
-
-/*
- * OtherSubrs:
- *
- * arg0 arg1 ... argn n othersubr# callothersubr
- *
- * 0: Build flex:
- * fd x y 3 0 callothersubr
- * Othersubr #0 pushes x and y to PostScript interpreter operand stack.
- * 1: Start flex
- * 0 1 callothersubr
- * 2: Mark flex control points
- * 0 2 callothersubr
- * 3: Discard hint
- * subr# 1 3 callothersubr pop callsubr
- * Subroutine subr# (only) contains stem declaration.
- * Othersubr #3 pushes subr# to PostScript interpreter operand stack.
- * 12: Counter control
- * A subr to avoid stack overflow.
- * 13: Counter control
- */
-
-/*
- * Convert six control points marked as CS_FLEX_CTRL to a flex path.
- */
-static void
-do_othersubr0 (t1_chardesc *cd)
-{
- t1_cpath *flex, *cur, *next;
-
- if (ps_stack_top < 1) {
- status = CS_PARSE_ERROR;
- return;
- }
-
- /* Seek first CS_FLEX_CTRL mark */
- for (cur = cd->charpath; cur != NULL && cur->type != CS_FLEX_CTRL; cur = cur->next);
- flex = cur;
- {
- int i;
- cur = cur->next;
- for (i = 1; i < 7; i++) {
- if (cur == NULL || cur->type != CS_FLEX_CTRL ||
- cur->num_args != 2) {
- status = CS_PARSE_ERROR;
- return;
- }
- if (i == 1) {
- flex->args[0] += cur->args[0];
- flex->args[1] += cur->args[1];
- } else {
- copy_args(&(flex->args[2*i-2]), cur->args, 2);
- }
- next = cur->next;
- RELEASE(cur);
- cur = next;
- }
- }
- if (cur != NULL) {
- status = CS_PARSE_ERROR;
- return;
- }
- /*
- * Now 'flex' have all six control points, the first pair is relative
- * from starting point.
- */
- flex->type = cs_flex;
- flex->args[12] = ps_arg_stack[--ps_stack_top]; /* flex depth */
- flex->num_args = 13;
- flex->next = NULL;
- cd->lastpath = flex;
-
- phase = T1_CS_PHASE_PATH;
-}
-
-/* Start flex */
-static void
-do_othersubr1 (t1_chardesc *cd)
-{
- phase = T1_CS_PHASE_FLEX;
-}
-
-/* Mark flex control point */
-static void
-do_othersubr2 (t1_chardesc *cd)
-{
- if (phase != T1_CS_PHASE_FLEX || !cd->lastpath) {
- status = CS_PARSE_ERROR;
- return;
- }
-
- switch (cd->lastpath->type) {
- case cs_rmoveto:
- break;
- case cs_hmoveto:
- cd->lastpath->num_args = 2;
- cd->lastpath->args[1] = 0.0;
- break;
- case cs_vmoveto:
- cd->lastpath->num_args = 2;
- cd->lastpath->args[1] = cd->lastpath->args[0];
- cd->lastpath->args[0] = 0.0;
- break;
- default:
- status = CS_PARSE_ERROR;
- return;
- }
- cd->lastpath->type = CS_FLEX_CTRL;
-}
-
-/*
- * Hint Replacement:
- * "Adobe Type 1 Font Format", Chapter 8.
- */
-static void
-do_othersubr3 (t1_chardesc *cd)
-{
- cd->flags |= T1_CS_FLAG_USE_HINTMASK;
-}
-
-static void
-do_othersubr12 (t1_chardesc *cd)
-{
- /* Othersubr12 call must immediately follow the hsbw or sbw. */
- if (phase != T1_CS_PHASE_INIT) {
- status = CS_PARSE_ERROR;
- return;
- }
- /* noop */
-}
-
-static void
-do_othersubr13 (t1_chardesc *cd)
-{
- t1_stemgroup stemgroups[CS_STEM_GROUP_MAX];
- int num_hgroups, num_vgroups, n, stem_id;
- double pos, del;
-
- /* After #12 callothersubr or hsbw or sbw. */
- if (phase != T1_CS_PHASE_INIT) {
- status = CS_PARSE_ERROR;
- return;
- }
- for (n = 0; n < CS_STEM_GROUP_MAX; n++) {
- stemgroups[n].num_stems = 0;
- }
-
- num_hgroups = (int) ps_arg_stack[--ps_stack_top];
- if (num_hgroups < 0 || num_hgroups > CS_STEM_GROUP_MAX) {
- status = CS_PARSE_ERROR;
- return;
- }
- n = 0; pos = 0.0;
- while (ps_stack_top >= 2 && n < num_hgroups) {
- /* add_stem() add sidebearing */
- pos += ps_arg_stack[--ps_stack_top];
- del = ps_arg_stack[--ps_stack_top];
- stem_id = add_stem(cd,
- (del < 0.0) ? pos + del : pos,
- (del < 0.0) ? -del : del,
- HSTEM);
- stemgroups[n].stems[stemgroups[n].num_stems] = stem_id;
- stemgroups[n].num_stems += 1;
- pos += del;
- if (del < 0.0) {
- pos = 0.0;
- n++;
- }
- }
- if (n != num_hgroups) {
- status = CS_STACK_ERROR;
- return;
- }
-
- num_vgroups = (int) ps_arg_stack[--ps_stack_top];
- if (num_vgroups < 0 || num_vgroups > CS_STEM_GROUP_MAX) {
- status = CS_PARSE_ERROR;
- return;
- }
- n = 0; pos = 0.0;
- while (ps_stack_top >= 2 && n < num_vgroups) {
- /* add_stem() add sidebearing */
- pos += ps_arg_stack[--ps_stack_top];
- del = ps_arg_stack[--ps_stack_top];
- stem_id = add_stem(cd,
- (del < 0.0) ? pos + del : pos,
- (del < 0.0) ? -del : del,
- VSTEM);
- stemgroups[n].stems[stemgroups[n].num_stems] = stem_id;
- stemgroups[n].num_stems += 1;
- pos += del;
- if (del < 0.0) {
- pos = 0.0;
- n++;
- }
- }
- if (n != num_vgroups) {
- status = CS_STACK_ERROR;
- return;
- }
-
- for (n = 0; n < MAX(num_hgroups, num_vgroups); n++) {
- add_charpath(cd, cs_cntrmask,
- stemgroups[n].stems, stemgroups[n].num_stems);
- }
-
- cd->flags |= T1_CS_FLAG_USE_CNTRMASK;
-}
-
-static void
-do_callothersubr (t1_chardesc *cd)
-{
- int argn, subrno;
-
- CHECKSTACK(2);
- subrno = (int) cs_arg_stack[--cs_stack_top];
- argn = (int) cs_arg_stack[--cs_stack_top];
-
- CHECKSTACK(argn);
- if (ps_stack_top+argn > PS_ARG_STACK_MAX) {
- status = CS_PARSE_ERROR;
- return;
- }
- while (argn-- > 0)
- ps_arg_stack[ps_stack_top++] = cs_arg_stack[--cs_stack_top];
-
- switch (subrno) {
- case 0: do_othersubr0(cd) ; break;
- case 1: do_othersubr1(cd) ; break;
- case 2: do_othersubr2(cd) ; break;
- case 3: do_othersubr3(cd) ; break;
- case 12: do_othersubr12(cd); break;
- case 13: do_othersubr13(cd); break;
- default:
- ERROR("Unknown othersubr #%ld.", subrno);
- break;
- }
-}
-
-/*
- * Double byte operators:
- */
-static void
-do_operator2 (t1_chardesc *cd, card8 **data, card8 *endptr)
-{
- card8 op;
-
- *data += 1;
-
- SRC_NEED(endptr, *data + 1);
-
- op = **data;
- *data += 1;
-
- switch(op) {
- case cs_sbw:
- CHECKSTACK(4);
- cd->sbw.wy = cs_arg_stack[--cs_stack_top];
- cd->sbw.wx = cs_arg_stack[--cs_stack_top];
- cd->sbw.sby = cs_arg_stack[--cs_stack_top];
- cd->sbw.sbx = cs_arg_stack[--cs_stack_top];
- CLEARSTACK();
- break;
- case cs_hstem3:
- case cs_vstem3:
- /*
- * TODO:
- * The counter control can be used for hstem3 and vstem3
- * operator if LanguageGroup is not equal to 1.
- */
- CHECKSTACK(6);
- {
- int i;
- for (i = 2; i >= 0; i--) {
- int stem_id;
- stem_id = add_stem(cd,
- cs_arg_stack[cs_stack_top-2*i-2],
- cs_arg_stack[cs_stack_top-2*i-1],
- ((op == cs_hstem3) ? HSTEM : VSTEM));
- if (stem_id < 0) {
- WARN("Too many hints...");
- status = CS_PARSE_ERROR;
- return;
- }
- /* Put stem_id onto the stack... */
- cs_arg_stack[cs_stack_top++] = stem_id;
- ADD_PATH(cd, CS_HINT_DECL, 1);
- cs_stack_top--;
- }
- }
- CLEARSTACK();
- break;
- case cs_setcurrentpoint:
- CHECKSTACK(2);
- /* noop */
- CLEARSTACK();
- break;
- /* all operator above are stack-clearing */
- case cs_pop:
- /*
- * Transfer a operand from PS interpreter operand stack to BuildChar
- * operand stack.
- */
- if (ps_stack_top < 1) {
- status = CS_PARSE_ERROR;
- return;
- }
- LIMITCHECK(1);
- cs_arg_stack[cs_stack_top++] = ps_arg_stack[--ps_stack_top];
- break;
- case cs_dotsection:
-#if 0
- /*
- * If the hint replacement feature is used in the font, the
- * "dotsection" operator exist only for compatibility to older
- * (more than 10 years old) Type 1 font rasterizer which can't
- * perform hint replacement. In this case, we silently ignore
- * the "dotsection" operator.
- *
- * The following code will wrongly warn about "dotsection" when
- * the charstring only contains dot (e.g., "bullet") where the
- * hint replacement is not necessary.
- *
- * Adobe ATM renderers always treat this operator as a no-op.
- * (See, Adobe Technical Note #5177, Appendix C)
- */
- if (!(cd->flags & T1_CS_FLAG_USE_HINTMASK)) {
- if (__verbose > 1)
- WARN("Obsolete Type 1 charstring operator \"dotsection\" not supported.");
- }
-#endif
- /* noop */
- break;
- case cs_div: /* TODO: check overflow */
- CHECKSTACK(2);
- cs_arg_stack[cs_stack_top-2] /= cs_arg_stack[cs_stack_top-1];
- cs_stack_top--;
- break;
- case cs_callothersubr:
- do_callothersubr(cd);
- break;
- case cs_seac:
- CHECKSTACK(5);
- cd->flags |= T1_CS_FLAG_USE_SEAC;
- cd->seac.achar = (card8) cs_arg_stack[--cs_stack_top];
- cd->seac.bchar = (card8) cs_arg_stack[--cs_stack_top];
- cd->seac.ady = cs_arg_stack[--cs_stack_top];
- cd->seac.adx = cs_arg_stack[--cs_stack_top];
- /* We must compensate the difference of the glyph origin. */
- cd->seac.ady += cd->sbw.sby;
- cd->seac.adx += cd->sbw.sbx - cs_arg_stack[--cs_stack_top];
- CLEARSTACK();
- break;
- default:
- /* no-op ? */
- WARN("Unknown charstring operator: 0x0c%02x", op);
- status = CS_PARSE_ERROR;
- break;
- }
-
- return;
-}
-
-/*
- * Charstring encoding:
- * Copied from cs_type2.c
- * Note:
- * The Type 2 interpretation of a number encoded in five-bytes (those with
- * an initial byte value of 255) differs from how it is interpreted in the
- * Type 1 format.
- */
-
-/* Type 2 5-bytes encoding used. */
-static void
-put_numbers (double *argv, int argn, card8 **dest, card8 *limit)
-{
- int i;
-
- for (i = 0; i < argn; i++) {
- double value;
- long ivalue;
- value = argv[i];
- /* Nearest integer value */
- ivalue = (long) floor(value+0.5);
- if (value >= 0x8000L || value <= (-0x8000L - 1)) {
- /*
- * This number cannot be represented as a single operand.
- * We must use `a b mul ...' or `a c div' to represent large values.
- */
- ERROR("Argument value too large. (This is bug)");
- } else if (fabs(value - ivalue) > 3.0e-5) {
- /* 16.16-bit signed fixed value */
- DST_NEED(limit, *dest + 5);
- *(*dest)++ = 255;
- ivalue = (long) floor(value); /* mantissa */
- *(*dest)++ = (ivalue >> 8) & 0xff;
- *(*dest)++ = ivalue & 0xff;
- ivalue = (long)((value - ivalue) * 0x10000l); /* fraction */
- *(*dest)++ = (ivalue >> 8) & 0xff;
- *(*dest)++ = ivalue & 0xff;
- /* Everything else are integers. */
- } else if (ivalue >= -107 && ivalue <= 107) {
- DST_NEED(limit, *dest + 1);
- *(*dest)++ = ivalue + 139;
- } else if (ivalue >= 108 && ivalue <= 1131) {
- DST_NEED(limit, *dest + 2);
- ivalue = 0xf700u + ivalue - 108;
- *(*dest)++ = (ivalue >> 8) & 0xff;
- *(*dest)++ = ivalue & 0xff;
- } else if (ivalue >= -1131 && ivalue <= -108) {
- DST_NEED(limit, *dest + 2);
- ivalue = 0xfb00u - ivalue - 108;
- *(*dest)++ = (ivalue >> 8) & 0xff;
- *(*dest)++ = ivalue & 0xff;
- } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */
- DST_NEED(limit, *dest + 3);
- *(*dest)++ = 28;
- *(*dest)++ = (ivalue >> 8) & 0xff;
- *(*dest)++ = (ivalue) & 0xff;
- } else { /* Shouldn't come here */
- ERROR("Unexpected error.");
- }
- }
-
- return;
-}
-
-static void
-get_integer (card8 **data, card8 *endptr)
-{
- long result = 0;
- card8 b0 = **data, b1, b2;
-
- *data += 1;
-
- if (b0 == 28) { /* shortint */
- SRC_NEED(endptr, *data + 2);
- b1 = **data;
- b2 = *(*data+1);
- result = b1*256+b2;
- if (result > 0x7fff)
- result -= 0x10000L;
- *data += 2;
- } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
- result = b0 - 139;
- } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
- SRC_NEED(endptr, *data + 1);
- b1 = **data;
- result = (b0-247)*256+b1+108;
- *data += 1;
- } else if (b0 >= 251 && b0 <= 254) {
- SRC_NEED(endptr, *data + 1);
- b1 = **data;
- result = -(b0-251)*256-b1-108;
- *data += 1;
- } else {
- status = CS_PARSE_ERROR;
- return;
- }
-
- LIMITCHECK(1);
- cs_arg_stack[cs_stack_top++] = (double) result;
-
- return;
-}
-
-/* Type 1 */
-static void
-get_longint (card8 **data, card8 *endptr)
-{
- long result = 0;
- int i;
-
- *data += 1;
- SRC_NEED(endptr, *data + 4);
- result = **data;
- if (result >= 0x80L)
- result -= 0x100L;
- *data += 1;
- for (i = 1; i < 4; i++) {
- result = result*256 + (**data);
- *data += 1;
- }
-
- LIMITCHECK(1);
- cs_arg_stack[cs_stack_top++] = (double) result;
-
- return;
-}
-
-/*
- * TODO:
- * Check "seac"
- * We cannot do backword parsing due to subroutine, div etc.
- */
-
-/* Parse charstring and build charpath. */
-static void
-t1char_build_charpath (t1_chardesc *cd,
- card8 **data, card8 *endptr, cff_index *subrs)
-{
- card8 b0 = 0, *subr;
- long len;
-
- if (nest > CS_SUBR_NEST_MAX)
- ERROR("Subroutine nested too deeply.");
-
- nest++;
- while (*data < endptr && status == CS_PARSE_OK) {
- b0 = **data;
- if (b0 == 255) {
- get_longint(data, endptr); /* Type 1 */
- } else if (b0 == cs_return) {
- status = CS_SUBR_RETURN;
- } else if (b0 == cs_callsubr) {
- if (cs_stack_top < 1) {
- status = CS_STACK_ERROR;
- } else {
- int idx;
-
- idx = cs_arg_stack[--cs_stack_top];
- if (!subrs || idx >= subrs->count)
- ERROR("Invalid Subr#.");
- subr = subrs->data + subrs->offset[idx] - 1;
- len = subrs->offset[idx+1] - subrs->offset[idx];
- t1char_build_charpath(cd, &subr, subr+len, subrs);
- *data += 1;
- }
- } else if (b0 == cs_escape) {
- do_operator2(cd, data, endptr);
- } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */
- do_operator1(cd, data, endptr);
- } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */
- status = CS_PARSE_ERROR; /* not an error ? */
- } else { /* integer */
- get_integer(data, endptr);
- }
- }
-
- if (status == CS_SUBR_RETURN) {
- status = CS_PARSE_OK;
- } else if (status == CS_CHAR_END && *data < endptr) {
- if (!(*data == endptr - 1 && **data == cs_return))
- WARN("Garbage after endchar. (%ld bytes)", (long) (endptr - *data));
- } else if (status < CS_PARSE_OK) { /* error */
- ERROR("Parsing charstring failed: (status=%d, stack=%d)", status, cs_stack_top);
- }
-
- nest--;
-
- return;
-}
-
-/*
- * Calculate BoundingBox and compress path.
- * The essentials of PDF size reduction is not Type 2 charstring compression
- * but Type 1 charstring encryption. Encryption makes lossless compression
- * useless. We will only do very simple charstring compression.
- */
-static void
-do_postproc (t1_chardesc *cd)
-{
- int i;
- t1_cpath *cur, *prev, *next;
- double x, y;
-
- if (!cd->charpath)
- return;
-
- /* Set dummy large value. */
- cd->bbox.llx = cd->bbox.lly = 100000.0;
- cd->bbox.urx = cd->bbox.ury = -100000.0;
-
- cur = cd->charpath;
- prev = NULL;
- x = y = 0.0;
-
-#define UPDATE_BBOX(b,x,y) do {\
- if ((b).llx > (x)) (b).llx = (x);\
- if ((b).urx < (x)) (b).urx = (x);\
- if ((b).lly > (y)) (b).lly = (y);\
- if ((b).ury < (y)) (b).ury = (y);\
-} while (0)
-#define TRY_COMPACT (prev && cur && ((prev->num_args + cur->num_args) <= CS_ARG_STACK_MAX))
-
- while (cur != NULL) {
- next = cur->next;
- switch (cur->type) {
- case cs_rmoveto:
- x += cur->args[0]; y += cur->args[1];
- UPDATE_BBOX(cd->bbox, x, y);
- break;
- case cs_rlineto:
- x += cur->args[0]; y += cur->args[1];
- UPDATE_BBOX(cd->bbox, x, y);
- if (TRY_COMPACT) {
- if (prev->type == cs_rlineto) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- } else if (prev->type == cs_rrcurveto) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->type = cs_rcurveline;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_hmoveto:
- x += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- break;
- case cs_hlineto:
- x += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- if (TRY_COMPACT) {
- if ((prev->type == cs_vlineto && (prev->num_args % 2) == 1) ||
- (prev->type == cs_hlineto && (prev->num_args % 2) == 0)) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_vmoveto:
- y += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- break;
- case cs_vlineto:
- y += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- if (TRY_COMPACT) {
- if ((prev->type == cs_hlineto && (prev->num_args % 2) == 1) ||
- (prev->type == cs_vlineto && (prev->num_args % 2) == 0)) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_rrcurveto:
- for (i = 0; i < 3; i++) {
- x += cur->args[2*i]; y += cur->args[2*i+1];
- UPDATE_BBOX(cd->bbox, x, y);
- }
- if (TRY_COMPACT) {
- if (prev->type == cs_rrcurveto) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- } else if (prev->type == cs_rlineto) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->type = cs_rlinecurve;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_vhcurveto:
- y += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- x += cur->args[1]; y += cur->args[2];
- UPDATE_BBOX(cd->bbox, x, y);
- x += cur->args[3];
- UPDATE_BBOX(cd->bbox, x, y);
- if (TRY_COMPACT) {
- if ((prev->type == cs_hvcurveto && ((prev->num_args / 4) % 2) == 1) ||
- (prev->type == cs_vhcurveto && ((prev->num_args / 4) % 2) == 0)) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_hvcurveto:
- x += cur->args[0];
- UPDATE_BBOX(cd->bbox, x, y);
- x += cur->args[1]; y += cur->args[2];
- UPDATE_BBOX(cd->bbox, x, y);
- y += cur->args[3];
- UPDATE_BBOX(cd->bbox, x, y);
- if (TRY_COMPACT) {
- if ((prev->type == cs_vhcurveto && ((prev->num_args / 4) % 2) == 1) ||
- (prev->type == cs_hvcurveto && ((prev->num_args / 4) % 2) == 0)) {
- copy_args(prev->args+prev->num_args, cur->args, cur->num_args);
- prev->num_args += cur->num_args;
- prev->next = next;
- RELEASE(cur); cur = NULL;
- }
- }
- break;
- case cs_flex:
- for (i = 0; i < 6; i++) {
- x += cur->args[2*i]; y += cur->args[2*1+1];
- UPDATE_BBOX(cd->bbox, x, y);
- }
- if (cur->args[12] == 50.0) {
- if (cur->args[1] == 0.0 && cur->args[11] == 0.0 &&
- cur->args[5] == 0.0 && cur->args[7] == 0.0 &&
- cur->args[3] + cur->args[9] == 0.0) {
- /* cur->args[0] = cur->args[0]; dx1 */
- cur->args[1] = cur->args[2]; /* dx2 */
- cur->args[2] = cur->args[3]; /* dy2 */
- cur->args[3] = cur->args[4]; /* dx3 */
- cur->args[4] = cur->args[6]; /* dx4 */
- cur->args[5] = cur->args[8]; /* dx5 */
- cur->args[6] = cur->args[10]; /* dx6 */
- cur->num_args = 7;
- cur->type = cs_hflex;
- } else if (cur->args[5] == 0.0 && cur->args[7] == 0.0 &&
- (cur->args[1] + cur->args[3] +
- cur->args[9] + cur->args[11]) == 0) {
- /* cur->args[0] = cur->args[0]; dx1 */
- /* cur->args[1] = cur->args[1]; dy1 */
- /* cur->args[2] = cur->args[2]; dx2 */
- /* cur->args[3] = cur->args[3]; dy2 */
- /* cur->args[4] = cur->args[4]; dx3 */
- cur->args[5] = cur->args[6]; /* dx4 */
- cur->args[6] = cur->args[8]; /* dx5 */
- cur->args[7] = cur->args[9]; /* dy5 */
- cur->args[8] = cur->args[10]; /* dx6 */
- cur->num_args = 9;
- cur->type = cs_hflex1;
- }
- }
- break;
- case CS_HINT_DECL:
- case cs_cntrmask:
- /* noop */
- break;
- default:
- ERROR("Unexpected Type 2 charstring command %d.", cur->type);
- break;
- }
- if (cur != NULL)
- prev = cur;
- cur = next;
- }
-
- /* Had no path. Fix lower-left point. */
- if (cd->bbox.llx > cd->bbox.urx)
- cd->bbox.llx = cd->bbox.urx = cd->sbw.wx;
- if (cd->bbox.lly > cd->bbox.ury)
- cd->bbox.lly = cd->bbox.ury = cd->sbw.wy;
-
- return;
-}
-
-#define RESET_STATE() do {\
- status = CS_PARSE_OK;\
- phase = T1_CS_PHASE_INIT;\
- nest = 0;\
- ps_stack_top = 0;\
-} while (0)
-
-int
-t1char_get_metrics (card8 *src, long srclen, cff_index *subrs, t1_ginfo *ginfo)
-{
- t1_chardesc t1char, *cd;
-
- cd = &t1char;
- init_charpath(cd);
- RESET_STATE();
- CLEARSTACK();
- t1char_build_charpath(cd, &src, src+srclen, subrs);
- if (cs_stack_top != 0 || ps_stack_top != 0)
- WARN("Stack not empty. (%d, %d)", cs_stack_top, ps_stack_top);
- do_postproc(cd);
- if (ginfo) {
- ginfo->wx = cd->sbw.wx;
- ginfo->wy = cd->sbw.wy;
- ginfo->bbox.llx = cd->bbox.llx;
- ginfo->bbox.lly = cd->bbox.lly;
- ginfo->bbox.urx = cd->bbox.urx;
- ginfo->bbox.ury = cd->bbox.ury;
- if (cd->flags & T1_CS_FLAG_USE_SEAC) {
- ginfo->use_seac = 1;
- ginfo->seac.adx = cd->seac.adx;
- ginfo->seac.ady = cd->seac.ady;
- ginfo->seac.bchar = cd->seac.bchar;
- ginfo->seac.achar = cd->seac.achar;
- } else {
- ginfo->use_seac = 0;
- }
- }
- release_charpath(cd);
-
- return 0;
-}
-
-#define CHECK_BUFFER(n) if (dst+(n) >= endptr) {\
- ERROR("Buffer overflow.");\
-}
-#define CHECK_STATUS() if (status != CS_PARSE_OK) {\
- ERROR("Charstring encoder error: %d", status);\
-}
-
-/*
- * Encode Charpath as a Type 2 Charstring
- */
-static long
-t1char_encode_charpath (t1_chardesc *cd,
- double default_width, double nominal_width,
- card8 *dst, card8 *endptr)
-{
- card8 *save;
- t1_cpath *curr;
-
- ASSERT(cd);
-
- save = dst;
- curr = cd->charpath;
-
- RESET_STATE();
- CLEARSTACK();
- /*
- * Advance Width
- */
- if (cd->sbw.wx != default_width) {
- double wx = cd->sbw.wx - nominal_width;
- put_numbers(&wx, 1, &dst, endptr);
- CHECK_STATUS();
- }
- /*
- * Hint Declaration
- */
- {
- int num_hstems = 0, num_vstems = 0;
- int i, reset = 1;
- double stem[2];
-
- for (i = 0; i < cd->num_stems && cd->stems[i].dir == HSTEM; i++) {
- num_hstems++;
- stem[0] = (reset ?
- (cd->stems[i].pos) :
- (cd->stems[i].pos - (cd->stems[i-1].pos + cd->stems[i-1].del)));
- stem[1] = cd->stems[i].del;
- put_numbers(stem, 2, &dst, endptr);
- CHECK_STATUS();
- reset = 0;
- if (2*num_hstems == CS_ARG_STACK_MAX) {
- CHECK_BUFFER(1);
- *dst++ = (card8) ((cd->flags & T1_CS_FLAG_USE_HINTMASK) ? cs_hstemhm : cs_hstem);
- reset = 1;
- }
- }
- if (reset == 0) {
- CHECK_BUFFER(1);
- *dst++ = (card8) ((cd->flags & T1_CS_FLAG_USE_HINTMASK) ? cs_hstemhm : cs_hstem);
- }
- reset = 1;
- if (cd->num_stems - num_hstems > 0) {
- for (i = num_hstems; i < cd->num_stems; i++) {
- num_vstems++;
- stem[0] = (reset ?
- (cd->stems[i].pos) :
- (cd->stems[i].pos - (cd->stems[i-1].pos + cd->stems[i-1].del)));
- stem[1] = cd->stems[i].del;
- put_numbers(stem, 2, &dst, endptr);
- CHECK_STATUS();
- reset = 0;
- if (2*num_vstems == CS_ARG_STACK_MAX) {
- CHECK_BUFFER(1);
- *dst++ = (card8) ((cd->flags & T1_CS_FLAG_USE_HINTMASK) ? cs_vstemhm : cs_vstem);
- reset = 1;
- }
- }
- if (reset == 0) {
- CHECK_BUFFER(1);
- if ((cd->flags & T1_CS_FLAG_USE_HINTMASK) ||
- (cd->flags & T1_CS_FLAG_USE_CNTRMASK)) {
- /*
- * The vstem hint operator can be ommited if hstem and vstem hints
- * are both declared at the beginning of a charstring, and is
- * followed directly by the hintmask or cntrmask operators.
- */
- if (curr->type != CS_HINT_DECL &&
- curr->type != cs_cntrmask) {
- *dst++ = (card8) cs_vstemhm;
- }
- } else {
- *dst++ = (card8) cs_vstem;
- }
- }
- }
- }
- /*
- * Path Construction and Hint Replacement
- */
- while (curr != NULL && curr->type != cs_endchar) {
- switch (curr->type) {
- case CS_HINT_DECL:
- {
- card8 hintmask[(CS_STEM_ZONE_MAX+7)/8];
-
- memset(hintmask, 0, (cd->num_stems+7)/8);
- while (curr != NULL && curr->type == CS_HINT_DECL) {
- int stem_idx;
-
- stem_idx = get_stem(cd, (int) curr->args[0]);
- ASSERT(stem_idx < cd->num_stems);
- hintmask[stem_idx/8] |= (1 << (7 - (stem_idx % 8)));
- curr = curr->next;
- }
- if (cd->flags & T1_CS_FLAG_USE_HINTMASK) {
- CHECK_BUFFER((cd->num_stems+7)/8 + 1);
- *dst++ = (card8) cs_hintmask;
- memcpy(dst, hintmask, (cd->num_stems+7)/8);
- dst += (cd->num_stems+7)/8;
- }
- }
- break;
- case cs_cntrmask:
- {
- card8 cntrmask[(CS_STEM_ZONE_MAX+7)/8];
- int stem_idx, i;
-
- memset(cntrmask, 0, (cd->num_stems+7)/8);
- for (i = 0; i < curr->num_args; i++) {
- stem_idx = get_stem(cd, (int) curr->args[i]);
- ASSERT(stem_idx < cd->num_stems);
- cntrmask[stem_idx/8] |= (1 << (7 - (stem_idx % 8)));
- }
- CHECK_BUFFER((cd->num_stems+7)/8 + 1);
- *dst++ = (card8) cs_cntrmask;
- memcpy(dst, cntrmask, (cd->num_stems+7)/8);
- dst += (cd->num_stems+7)/8;
- curr = curr->next;
- }
- break;
- case cs_rmoveto: case cs_hmoveto: case cs_vmoveto:
- case cs_rlineto: case cs_hlineto: case cs_vlineto:
- case cs_rrcurveto: case cs_hvcurveto: case cs_vhcurveto:
- case cs_rlinecurve: case cs_rcurveline:
- {
- put_numbers(curr->args, curr->num_args, &dst, endptr);
- CHECK_STATUS();
- CHECK_BUFFER(1);
- *dst++ = (card8) curr->type;
- curr = curr->next;
- }
- break;
- case cs_flex: case cs_hflex:
- case cs_hflex1:
- {
- put_numbers(curr->args, curr->num_args, &dst, endptr);
- CHECK_STATUS();
- CHECK_BUFFER(2);
- *dst++ = (card8) cs_escape;
- *dst++ = (card8) curr->type;
- curr = curr->next;
- }
- break;
- default:
- ERROR("Unknown Type 2 charstring command: %d", curr->type);
- break;
- }
- }
-
- /*
- * (adx ady bchar achar) endchar
- */
- if (cd->flags & T1_CS_FLAG_USE_SEAC) {
- double seac[4];
- seac[0] = cd->seac.adx;
- seac[1] = cd->seac.ady;
- seac[2] = cd->seac.bchar;
- seac[3] = cd->seac.achar;
- put_numbers(seac, 4, &dst, endptr);
- CHECK_STATUS();
- CHECK_BUFFER(2);
- WARN("Obsolete four arguments of \"endchar\" will be used for Type 1 \"seac\" operator.");
- }
- CHECK_BUFFER(1);
- *dst++ = (card8) cs_endchar;
-
- return (long) (dst - save);
-}
-
-long
-t1char_convert_charstring (card8 *dst, long dstlen,
- card8 *src, long srclen, cff_index *subrs,
- double default_width, double nominal_width,
- t1_ginfo *ginfo)
-{
- long length;
- t1_chardesc t1char, *cd;
-
- cd = &t1char;
- init_charpath(cd);
- RESET_STATE();
- CLEARSTACK();
- t1char_build_charpath(cd, &src, src+srclen, subrs);
- if (cs_stack_top != 0 || ps_stack_top != 0)
- WARN("Stack not empty. (%d, %d)", cs_stack_top, ps_stack_top);
- do_postproc(cd);
- SORT_STEMS(cd);
-
- length = t1char_encode_charpath(cd, default_width, nominal_width, dst, dst+dstlen);
-
- if (ginfo) {
- ginfo->wx = cd->sbw.wx;
- ginfo->wy = cd->sbw.wy;
- ginfo->bbox.llx = cd->bbox.llx;
- ginfo->bbox.lly = cd->bbox.lly;
- ginfo->bbox.urx = cd->bbox.urx;
- ginfo->bbox.ury = cd->bbox.ury;
- if (cd->flags & T1_CS_FLAG_USE_SEAC) {
- ginfo->use_seac = 1;
- ginfo->seac.adx = cd->seac.adx;
- ginfo->seac.ady = cd->seac.ady;
- ginfo->seac.bchar = cd->seac.bchar;
- ginfo->seac.achar = cd->seac.achar;
- } else {
- ginfo->use_seac = 0;
- }
- }
- release_charpath(cd);
-
- return length;
-}