1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* cffgload.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* OpenType Glyph Loader (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Copyright 1996-2013 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h" 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h" 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftstream.h" 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/sfnt.h" 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftoutln.h" 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftcffdrv.h" 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cffobjs.h" 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cffload.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cffgload.h" 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfferrs.h" 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_cffgload 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CFF_CONFIG_OPTION_OLD_ENGINE 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef enum CFF_Operator_ 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_unknown = 0, 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_rmoveto, 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hmoveto, 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vmoveto, 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_rlineto, 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hlineto, 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vlineto, 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_rrcurveto, 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hhcurveto, 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hvcurveto, 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_rcurveline, 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_rlinecurve, 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vhcurveto, 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vvcurveto, 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_flex, 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hflex, 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hflex1, 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_flex1, 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_endchar, 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hstem, 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vstem, 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hstemhm, 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_vstemhm, 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hintmask, 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_cntrmask, 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_dotsection, /* deprecated, acts as no-op */ 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_abs, 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_add, 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_sub, 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_div, 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_neg, 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_random, 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_mul, 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_sqrt, 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_blend, 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_drop, 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_exch, 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_index, 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_roll, 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_dup, 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_put, 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_get, 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_store, 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_load, 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_and, 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_or, 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_not, 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_eq, 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_ifelse, 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_callsubr, 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_callgsubr, 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_return, 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 opcodes: invalid but seen in real life */ 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_hsbw, 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_closepath, 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_callothersubr, 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_pop, 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_seac, 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_sbw, 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_setcurrentpoint, 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* do not remove */ 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_op_max 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } CFF_Operator; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_COUNT_CHECK_WIDTH 0x80 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_COUNT_EXACT 0x40 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_COUNT_CLEAR_STACK 0x20 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* used for checking the width and requested numbers of arguments */ 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* only; they are set to zero afterwards */ 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the other two flags are informative only and unused currently */ 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Byte cff_argument_counts[] = 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* unknown */ 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CLEAR_STACK, 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 13, /* flex */ 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 7, 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 9, 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 11, 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 | CFF_COUNT_CHECK_WIDTH, 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 | CFF_COUNT_CHECK_WIDTH, 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 | CFF_COUNT_CHECK_WIDTH, 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, /* dotsection */ 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, /* abs */ 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, /* blend */ 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, /* drop */ 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, /* put */ 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4, 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3, 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, /* and */ 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4, 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, /* callsubr */ 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1, 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2, /* hsbw */ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 5, /* seac */ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 4, /* sbw */ 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2 /* setcurrentpoint */ 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** GENERIC CHARSTRING PARSING *********/ 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cff_builder_init */ 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initializes a given glyph builder. */ 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* builder :: A pointer to the glyph builder to initialize. */ 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The current face object. */ 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* size :: The current size object. */ 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyph :: The current glyph object. */ 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* hinting :: Whether hinting is active. */ 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_init( CFF_Builder* builder, 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face, 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Size size, 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_GlyphSlot glyph, 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool hinting ) 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 0; 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->load_points = 1; 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->face = face; 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->glyph = glyph; 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->memory = face->root.memory; 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph ) 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader loader = glyph->root.internal->loader; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->loader = loader; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->base = &loader->base.outline; 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->current = &loader->current.outline; 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader_Rewind( loader ); 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->hints_globals = 0; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->hints_funcs = 0; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinting && size ) 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Internal internal = (CFF_Internal)size->root.internal; 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->hints_globals = (void *)internal->topfont; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->hints_funcs = glyph->root.internal->glyph_hints; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_x = 0; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_y = 0; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->left_bearing.x = 0; 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->left_bearing.y = 0; 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->advance.x = 0; 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->advance.y = 0; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cff_builder_done */ 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Finalizes a given glyph builder. Its contents can still be used */ 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* after the call, but the function saves important information */ 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* within the corresponding glyph slot. */ 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* builder :: A pointer to the glyph builder to finalize. */ 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_done( CFF_Builder* builder ) 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_GlyphSlot glyph = builder->glyph; 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph ) 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline = *builder->base; 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cff_compute_bias */ 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Computes the bias value in dependence of the number of glyph */ 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subroutines. */ 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in_charstring_type :: The `CharstringType' value of the top DICT */ 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* dictionary. */ 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* num_subrs :: The number of glyph subroutines. */ 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The bias value. */ 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Int 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_compute_bias( FT_Int in_charstring_type, 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_subrs ) 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int result; 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( in_charstring_type == 1 ) 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = 0; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( num_subrs < 1240 ) 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = 107; 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( num_subrs < 33900U ) 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = 1131; 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result = 32768U; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return result; 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cff_decoder_init */ 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initializes a given glyph decoder. */ 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decoder :: A pointer to the glyph builder to initialize. */ 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The current face object. */ 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* size :: The current size object. */ 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* slot :: The current glyph object. */ 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* hinting :: Whether hinting is active. */ 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* hint_mode :: The hinting mode. */ 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( void ) 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_decoder_init( CFF_Decoder* decoder, 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face, 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Size size, 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_GlyphSlot slot, 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool hinting, 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Render_Mode hint_mode ) 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)face->extra.data; 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* clear everything */ 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* initialize builder */ 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_init( &decoder->builder, face, size, slot, hinting ); 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* initialize Type2 decoder */ 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->cff = cff; 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_globals = cff->global_subrs_index.count; 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->globals = cff->global_subrs; 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->globals_bias = cff_compute_bias( 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff->top_font.font_dict.charstring_type, 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_globals ); 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->hint_mode = hint_mode; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this function is used to select the subfont */ 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and the locals subrs array */ 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_decoder_prepare( CFF_Decoder* decoder, 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Size size, 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index ) 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Builder *builder = &decoder->builder; 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)builder->face->extra.data; 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_SubFont sub = &cff->top_font; 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* manage CID fonts */ 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff->num_subfonts ) 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( fd_index >= cff->num_subfonts ) 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_File_Format ); 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub = cff->subfonts[fd_index]; 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( builder->hints_funcs && size ) 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Internal internal = (CFF_Internal)size->root.internal; 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for CFFs without subfonts, this value has already been set */ 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->hints_globals = (void *)internal->subfonts[fd_index]; 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE3(( "glyph index %d:\n", glyph_index )); 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_locals = sub->local_subrs_index.count; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->locals = sub->local_subrs; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->locals_bias = cff_compute_bias( 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->cff->top_font.font_dict.charstring_type, 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_locals ); 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = sub->private_dict.default_width; 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->nominal_width = sub->private_dict.nominal_width; 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->current_subfont = sub; /* for Adobe's CFF handler */ 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check that there is enough space for `count' more points */ 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( CFF_Builder* builder, 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int count ) 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* add a new point, do not check space */ 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( void ) 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( CFF_Builder* builder, 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos y, 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte flag ) 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline = builder->current; 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( builder->load_points ) 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* point = outline->points + outline->n_points; 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CFF_CONFIG_OPTION_OLD_ENGINE 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point->x = x >> 16; 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point->y = y >> 16; 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point->x = x >> 10; 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point->y = y >> 10; 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_points++; 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check space for a new on-curve point, then add it */ 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point1( CFF_Builder* builder, 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos y ) 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_check_points( builder, 1 ); 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check space for a new contour, then add it */ 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_contour( CFF_Builder* builder ) 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline = builder->current; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !builder->load_points ) 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_contours++; 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_contours > 0 ) 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->contours[outline->n_contours - 1] = 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (short)( outline->n_points - 1 ); 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_contours++; 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if a path was begun, add its first on-curve point */ 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_start_point( CFF_Builder* builder, 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos y ) 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* test whether we are building a new contour */ 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !builder->path_begun ) 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 1; 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_builder_add_contour( builder ); 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_builder_add_point1( builder, x, y ); 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* close the current contour */ 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( void ) 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_close_contour( CFF_Builder* builder ) 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline = builder->current; 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int first; 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline ) 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = outline->n_contours <= 1 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ? 0 : outline->contours[outline->n_contours - 2] + 1; 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We must not include the last point in the path if it */ 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is located on the first point. */ 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_points > 1 ) 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* p1 = outline->points + first; 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* p2 = outline->points + outline->n_points - 1; 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `delete' last point only if it coincides with the first */ 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* point and if it is not a control point (which can happen). */ 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( p1->x == p2->x && p1->y == p2->y ) 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *control == FT_CURVE_TAG_ON ) 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_points--; 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_contours > 0 ) 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Don't add contours only consisting of one point, i.e., */ 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check whether begin point and last point are the same. */ 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( first == outline->n_points - 1 ) 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_contours--; 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->n_points--; 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->contours[outline->n_contours - 1] = 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (short)( outline->n_points - 1 ); 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Int ) 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_lookup_glyph_by_stdcharcode( CFF_Font cff, 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int charcode ) 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n; 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort glyph_sid; 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* CID-keyed fonts don't have glyph names */ 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !cff->charset.sids ) 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check range of standard char code */ 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charcode < 0 || charcode > 255 ) 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Get code to SID mapping from `cff_standard_encoding'. */ 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < cff->num_glyphs; n++ ) 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff->charset.sids[n] == glyph_sid ) 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return n; 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_get_glyph_data( TT_Face face, 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index, 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte** pointer, 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong* length ) 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For incremental fonts get the character data using the */ 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* callback function. */ 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->root.internal->incremental_interface ) 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Data data; 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->funcs->get_glyph_data( 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->object, 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, &data ); 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pointer = (FT_Byte*)data.pointer; 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *length = data.length; 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)(face->extra.data); 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cff_index_access_element( &cff->charstrings_index, glyph_index, 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pointer, length ); 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( void ) 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_free_glyph_data( TT_Face face, 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte** pointer, 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong length ) 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_CONFIG_OPTION_INCREMENTAL 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( length ); 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For incremental fonts get the character data using the */ 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* callback function. */ 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->root.internal->incremental_interface ) 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Data data; 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data.pointer = *pointer; 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data.length = length; 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->funcs->free_glyph_data( 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->object, &data ); 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)(face->extra.data); 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_index_forget_element( &cff->charstrings_index, pointer ); 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CFF_CONFIG_OPTION_OLD_ENGINE 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_operator_seac( CFF_Decoder* decoder, 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos asb, 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos adx, 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos ady, 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int bchar, 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int achar ) 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Builder* builder = &decoder->builder; 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int bchar_index, achar_index; 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face = decoder->builder.face; 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector left_bearing, advance; 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* charstring; 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong charstring_len; 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos glyph_width; 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->seac ) 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Syntax_Error ); 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov adx += decoder->builder.left_bearing.x; 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ady += decoder->builder.left_bearing.y; 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Incremental fonts don't necessarily have valid charsets. */ 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* They use the character code, not the glyph index, in this case. */ 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->root.internal->incremental_interface ) 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bchar_index = bchar; 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov achar_index = achar; 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)(face->extra.data); 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( bchar_index < 0 || achar_index < 0 ) 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_operator_seac:" 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " invalid seac character code arguments\n" )); 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Syntax_Error ); 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If we are trying to load a composite glyph, do not load the */ 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* accent character and return the array of subglyphs. */ 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( builder->no_recurse ) 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader loader = glyph->internal->loader; 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_SubGlyph subg; 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reallocate subglyph array if necessary */ 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg = loader->current.subglyphs; 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subglyph 0 = base character */ 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->index = bchar_index; 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_SUBGLYPH_FLAG_USE_MY_METRICS; 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->arg1 = 0; 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->arg2 = 0; 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg++; 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subglyph 1 = accent character */ 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->index = achar_index; 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->arg1 = (FT_Int)( adx >> 16 ); 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subg->arg2 = (FT_Int)( ady >> 16 ); 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set up remaining glyph fields */ 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->num_subglyphs = 2; 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->subglyphs = loader->base.subglyphs; 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov loader->current.num_subglyphs = 2; 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader_Prepare( builder->loader ); 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* First load `bchar' in builder */ 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_get_glyph_data( face, bchar_index, 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &charstring, &charstring_len ); 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the seac operator must not be nested */ 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->seac = TRUE; 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_parse_charstrings( decoder, charstring, 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->seac = FALSE; 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_free_glyph_data( face, &charstring, charstring_len ); 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Save the left bearing, advance and glyph width of the base */ 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* character as they will be erased by the next load. */ 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left_bearing = builder->left_bearing; 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov advance = builder->advance; 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_width = decoder->glyph_width; 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->left_bearing.x = 0; 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->left_bearing.y = 0; 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_x = adx - asb; 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_y = ady; 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Now load `achar' on top of the base outline. */ 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_get_glyph_data( face, achar_index, 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &charstring, &charstring_len ); 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the seac operator must not be nested */ 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->seac = TRUE; 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_parse_charstrings( decoder, charstring, 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->seac = FALSE; 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_free_glyph_data( face, &charstring, charstring_len ); 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Restore the left side bearing, advance and glyph width */ 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* of the base character. */ 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->left_bearing = left_bearing; 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->advance = advance; 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = glyph_width; 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_x = 0; 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->pos_y = 0; 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cff_decoder_parse_charstrings */ 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Parses a given Type 2 charstrings program. */ 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decoder :: The current Type 1 decoder. */ 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* charstring_base :: The base of the charstring stream. */ 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* charstring_len :: The length in bytes of the charstring stream. */ 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_decoder_parse_charstrings( CFF_Decoder* decoder, 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* charstring_base, 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong charstring_len ) 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Decoder_Zone* zone; 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* ip; 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit; 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Builder* builder = &decoder->builder; 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, y; 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed seed; 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* stack; 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int charstring_type = 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->cff->top_font.font_dict.charstring_type; 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T2_Hints_Funcs hinter; 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set default width */ 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_hints = 0; 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->read_width = 1; 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute random seed from stack address of parameter */ 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_PtrDist)(char*)&decoder ^ 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_PtrDist)(char*)&charstring_base ) & 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULONG_MAX ) ; 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( seed == 0 ) 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov seed = 0x7384; 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* initialize the decoder */ 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->top = decoder->stack; 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->zone = decoder->zones; 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone = decoder->zones; 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov stack = decoder->top; 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter = (T2_Hints_Funcs)builder->hints_funcs; 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 0; 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->base = charstring_base; 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = zone->limit = charstring_base + charstring_len; 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip = zone->cursor = zone->base; 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = builder->pos_x; 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = builder->pos_y; 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* begin hints recording session, if any */ 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter ) 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->open( hinter->hints ); 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now execute loop */ 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ip < limit ) 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Operator op; 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte v; 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********************************************************************/ 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Decode operator or operand */ 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = *ip++; 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( v >= 32 || v == 28 ) 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift = 16; 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int32 val; 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an operand, push it on the stack */ 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if we use shifts, all computations are done with unsigned */ 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* values; the conversion to a signed value is the last step */ 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( v == 28 ) 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip + 1 >= limit ) 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip += 2; 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( v < 247 ) 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Int32)v - 139; 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( v < 251 ) 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip >= limit ) 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( v < 255 ) 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip >= limit ) 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip + 3 >= limit ) 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (FT_UInt32)ip[1] << 16 ) | 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (FT_UInt32)ip[2] << 8 ) | 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_UInt32)ip[3] ); 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip += 4; 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( charstring_type == 2 ) 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = 0; 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Overflow; 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Int32)( (FT_UInt32)val << shift ); 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *decoder->top++ = val; 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( val & 0xFFFFL ) ) 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " %.2f", val / 65536.0 )); 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The specification says that normally arguments are to be taken */ 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* from the bottom of the stack. However, this seems not to be */ 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* arguments similar to a PS interpreter. */ 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* args = decoder->top; 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int num_args = (FT_Int)( args - decoder->stack ); 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int req_args; 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* find operator */ 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_unknown; 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( v ) 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hstem; 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vstem; 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vmoveto; 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 5: 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_rlineto; 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 6: 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hlineto; 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 7: 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vlineto; 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 8: 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_rrcurveto; 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 9: 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_closepath; 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 10: 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_callsubr; 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 11: 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_return; 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 12: 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip >= limit ) 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = *ip++; 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( v ) 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 0: 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_dotsection; 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: /* this is actually the Type1 vstem3 operator */ 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vstem; 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 2: /* this is actually the Type1 hstem3 operator */ 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hstem; 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_and; 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_or; 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 5: 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_not; 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 6: 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_seac; 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 7: 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_sbw; 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 8: 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_store; 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 9: 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_abs; 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 10: 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_add; 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 11: 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_sub; 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 12: 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_div; 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 13: 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_load; 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 14: 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_neg; 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 15: 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_eq; 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 16: 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_callothersubr; 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 17: 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_pop; 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 18: 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_drop; 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 20: 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_put; 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 21: 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_get; 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 22: 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_ifelse; 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 23: 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_random; 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 24: 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_mul; 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 26: 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_sqrt; 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 27: 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_dup; 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 28: 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_exch; 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 29: 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_index; 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 30: 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_roll; 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 33: 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_setcurrentpoint; 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 34: 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hflex; 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 35: 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_flex; 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 36: 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hflex1; 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 37: 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_flex1; 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*default: */ /* XYQ 2007-9-6: we can't just quit if we see some reserved op */ 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decrement ip for syntax error message */ 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ip--;*/ 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 13: 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hsbw; 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 14: 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_endchar; 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 16: 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_blend; 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 18: 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hstemhm; 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 19: 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hintmask; 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 20: 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_cntrmask; 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 21: 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_rmoveto; 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 22: 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hmoveto; 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 23: 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vstemhm; 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 24: 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_rcurveline; 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 25: 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_rlinecurve; 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 26: 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vvcurveto; 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 27: 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hhcurveto; 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 29: 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_callgsubr; 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 30: 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_vhcurveto; 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 31: 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op = cff_op_hvcurveto; 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " unknown op (%d)\n", v )); 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( op == cff_op_unknown ) 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check arguments */ 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov req_args = cff_argument_counts[op]; 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( req_args & CFF_COUNT_CHECK_WIDTH ) 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args > 0 && decoder->read_width ) 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If `nominal_width' is non-zero, the number is really a */ 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* difference against `nominal_width'. Else, the number here */ 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is truly a width, not a difference against `nominal_width'. */ 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If the font does not set `nominal_width', then */ 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `nominal_width' defaults to zero, and so we can set */ 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `glyph_width' to `nominal_width' plus number on the stack */ 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -- for either case. */ 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int set_width_ok; 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( op ) 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hmoveto: 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vmoveto: 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov set_width_ok = num_args & 2; 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hstem: 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vstem: 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hstemhm: 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vstemhm: 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rmoveto: 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hintmask: 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_cntrmask: 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov set_width_ok = num_args & 1; 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_endchar: 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If there is a width specified for endchar, we either have */ 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 1 argument or 5 arguments. We like to argue. */ 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov set_width_ok = ( num_args == 5 ) || ( num_args == 1 ); 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov set_width_ok = 0; 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( set_width_ok ) 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = decoder->nominal_width + 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( stack[0] >> 16 ); 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->width_only ) 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we only want the advance width; stop here */ 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Consumed an argument. */ 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_args--; 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->read_width = 0; 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov req_args = 0; 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov req_args &= 0x000F; 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < req_args ) 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= req_args; 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_args -= req_args; 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Sunliang.Liu sync 221's revison. */ 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (args > decoder->stack + CFF_MAX_OPERANDS) 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Overflow; 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* At this point, `args' points to the first argument of the */ 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* operand in case `req_args' isn't zero. Otherwise, we have */ 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to adjust `args' manually. */ 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Note that we only pop arguments from the stack which we */ 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* really need and can digest so that we can continue in case */ 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* of superfluous stack elements. */ 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( op ) 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hstem: 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vstem: 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hstemhm: 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vstemhm: 1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the number of arguments is always even here */ 1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov op == cff_op_hstem ? " hstem\n" : 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( op == cff_op_vstem ? " vstem\n" : 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter ) 1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->stems( hinter->hints, 1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( op == cff_op_hstem || op == cff_op_hstemhm ), 1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_args / 2, 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args - ( num_args & ~1 ) ); 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_hints += num_args / 2; 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hintmask: 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_cntrmask: 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* implement vstem when needed -- */ 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the specification doesn't say it, but this also works */ 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* with the 'cntrmask' operator */ 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args > 0 ) 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter ) 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->stems( hinter->hints, 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_args / 2, 1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args - ( num_args & ~1 ) ); 1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_hints += num_args / 2; 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* In a valid charstring there must be at least one byte */ 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* after `hintmask' or `cntrmask' (e.g., for a `return' */ 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* instruction). Additionally, there must be space for */ 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `num_hints' bits. */ 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) 1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter ) 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( op == cff_op_hintmask ) 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->hintmask( hinter->hints, 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->current->n_points, 1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_hints, 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip ); 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->counter( hinter->hints, 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->num_hints, 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip ); 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt maskbyte; 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " (maskbytes:" )); 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( maskbyte = 0; 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maskbyte++, ip++ ) 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " 0x%02X", *ip )); 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( ")\n" )); 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip += ( decoder->num_hints + 7 ) >> 3; 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rmoveto: 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rmoveto\n" )); 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_close_contour( builder ); 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 0; 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[-2]; 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[-1]; 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vmoveto: 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " vmoveto\n" )); 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_close_contour( builder ); 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 0; 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[-1]; 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hmoveto: 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " hmoveto\n" )); 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_close_contour( builder ); 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->path_begun = 0; 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[-1]; 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rlineto: 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rlineto\n" )); 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, num_args / 2 ) ) 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 2 ) 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= num_args & ~1; 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( args < decoder->top ) 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hlineto: 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vlineto: 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int phase = ( op == cff_op_hlineto ); 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : " vlineto\n" )); 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 0 ) 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* there exist subsetted fonts (found in PDFs) */ 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* which call `hlineto' without arguments */ 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args == 0 ) 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, num_args ) ) 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( args < decoder->top ) 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( phase ) 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[0]; 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_add_point1( builder, x, y ) ) 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov phase ^= 1; 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rrcurveto: 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rrcurveto\n" )); 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 6 ) 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args - num_args % 6; 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, nargs / 2 ) ) 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( args < decoder->top ) 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[2]; 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[5]; 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 6; 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vvcurveto: 1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " vvcurveto\n" )); 1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 4 ) 1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if num_args isn't of the form 4n or 4n+1, */ 1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we enforce it by clearing the second bit */ 1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args & ~2; 1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) ) 1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nargs & 1 ) 1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs--; 1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) 1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( args < decoder->top ) 1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[0]; 1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[1]; 1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[2]; 1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 4; 1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hhcurveto: 1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " hhcurveto\n" )); 1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 4 ) 1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if num_args isn't of the form 4n or 4n+1, */ 1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we enforce it by clearing the second bit */ 1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args & ~2; 1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) ) 1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nargs & 1 ) 1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[0]; 1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs--; 1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) 1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( args < decoder->top ) 1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[1]; 1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[2]; 1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[3]; 1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 4; 1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_vhcurveto: 1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hvcurveto: 1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int phase; 1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" 1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : " hvcurveto\n" )); 1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) ) 1635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 4 ) 1638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ 1641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we enforce it by clearing the second bit */ 1642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args & ~2; 1644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) 1647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov phase = ( op == cff_op_hvcurveto ); 1650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( nargs >= 4 ) 1652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs -= 4; 1654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( phase ) 1655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[1]; 1659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[2]; 1660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nargs == 1 ) 1663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[0]; 1669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[1]; 1671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[2]; 1672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[3]; 1674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( nargs == 1 ) 1675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[4]; 1676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 4; 1679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov phase ^= 1; 1680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rlinecurve: 1686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int num_lines; 1688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rlinecurve\n" )); 1692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 8 ) 1694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args & ~1; 1697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_lines = ( nargs - 6 ) / 2; 1698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, num_lines + 3 ) ) 1701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first, add the line segments */ 1706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( num_lines > 0 ) 1707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 1712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_lines--; 1713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* then the curve */ 1716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[2]; 1720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[5]; 1724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_rcurveline: 1730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int num_curves; 1732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int nargs; 1733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rcurveline\n" )); 1736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args < 8 ) 1738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 1739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = num_args - 2; 1741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nargs = nargs - nargs % 6 + 2; 1742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_curves = ( nargs - 2 ) / 6; 1743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, num_curves * 3 + 2 ) ) 1746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= nargs; 1749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first, add the curves */ 1751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( num_curves > 0 ) 1752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[2]; 1757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[5]; 1761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 6; 1763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_curves--; 1764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* then the final line */ 1767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hflex1: 1775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos start_y; 1777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " hflex1\n" )); 1780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* adding five more points: 4 control points, 1 on-curve point */ 1782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* -- make sure we have enough space for the start point if it */ 1783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* needs to be added */ 1784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, 6 ) ) 1786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* record the starting point's y position for later use */ 1789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_y = y; 1790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first control point */ 1792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* second control point */ 1797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[2]; 1798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[3]; 1799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* join point; on curve, with y-value the same as the last */ 1802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* control point's y-value */ 1803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* third control point, with y-value the same as the join */ 1807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* point's y-value */ 1808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[5]; 1809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* fourth control point */ 1812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[6]; 1813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[7]; 1814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ending point, with y-value the same as the start */ 1817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[8]; 1818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = start_y; 1819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hflex: 1826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos start_y; 1828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " hflex\n" )); 1831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* adding six more points; 4 control points, 2 on-curve points */ 1833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, 6 ) ) 1835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* record the starting point's y-position for later use */ 1838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_y = y; 1839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first control point */ 1841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* second control point */ 1845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[1]; 1846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[2]; 1847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* join point; on curve, with y-value the same as the last */ 1850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* control point's y-value */ 1851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[3]; 1852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* third control point, with y-value the same as the join */ 1855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* point's y-value */ 1856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[4]; 1857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* fourth control point */ 1860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[5]; 1861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = start_y; 1862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 0 ); 1863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ending point, with y-value the same as the start point's */ 1865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* y-value -- we don't add this point, though */ 1866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[6]; 1867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_flex1: 1874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos start_x, start_y; /* record start x, y values for */ 1876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* alter use */ 1877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ 1878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* algorithm below */ 1879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int horizontal, count; 1880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* temp; 1881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " flex1\n" )); 1884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* adding six more points; 4 control points, 2 on-curve points */ 1886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, 6 ) ) 1888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* record the starting point's x, y position for later use */ 1891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_x = x; 1892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov start_y = y; 1893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: figure out whether this is supposed to be a horizontal */ 1895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* or vertical flex; the Type 2 specification is vague... */ 1896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp = args; 1898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* grab up to the last argument */ 1900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 5; count > 0; count-- ) 1901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx += temp[0]; 1903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy += temp[1]; 1904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp += 2; 1905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx < 0 ) 1908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = -dx; 1909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dy < 0 ) 1910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy = -dy; 1911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* strange test, but here it is... */ 1913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov horizontal = ( dx > dy ); 1914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 5; count > 0; count-- ) 1916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Bool)( count == 3 ) ); 1921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 1922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is last operand an x- or y-delta? */ 1925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( horizontal ) 1926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = start_y; 1929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = start_x; 1933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[0]; 1934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1 ); 1937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_flex: 1943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt count; 1945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " flex\n" )); 1948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff_builder_start_point( builder, x, y ) || 1950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_check_points( builder, 6 ) ) 1951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 1952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 6; count > 0; count-- ) 1954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += args[0]; 1956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += args[1]; 1957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_add_point( builder, x, y, 1958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Bool)( count == 4 || count == 1 ) ); 1959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 1960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 1963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_seac: 1967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " seac\n" )); 1968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_operator_seac( decoder, 1970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0], args[1], args[2], 1971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Int)( args[3] >> 16 ), 1972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Int)( args[4] >> 16 ) ); 1973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* add current outline to the glyph slot */ 1975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader_Add( builder->loader ); 1976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return now! */ 1978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "\n" )); 1979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_endchar: 1982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " endchar\n" )); 1983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We are going to emulate the seac operator. */ 1985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_args >= 4 ) 1986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Save glyph width so that the subglyphs don't overwrite it. */ 1988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos glyph_width = decoder->glyph_width; 1989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_operator_seac( decoder, 1992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0L, args[-4], args[-3], 1993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Int)( args[-2] >> 16 ), 1994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Int)( args[-1] >> 16 ) ); 1995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = glyph_width; 1997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 2002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_close_contour( builder ); 2004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* close hints recording session */ 2006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter ) 2007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( hinter->close( hinter->hints, 2009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->current->n_points ) ) 2010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* apply hints to the loaded glyph outline now */ 2013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinter->apply( hinter->hints, 2014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov builder->current, 2015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (PSH_Globals)builder->hints_globals, 2016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->hint_mode ); 2017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* add current outline to the glyph slot */ 2020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GlyphLoader_Add( builder->loader ); 2021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return now! */ 2024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "\n" )); 2025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_abs: 2028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " abs\n" )); 2029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( args[0] < 0 ) 2031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = -args[0]; 2032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_add: 2036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " add\n" )); 2037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] += args[1]; 2039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_sub: 2043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " sub\n" )); 2044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] -= args[1]; 2046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_div: 2050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " div\n" )); 2051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = FT_DivFix( args[0], args[1] ); 2053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_neg: 2057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " neg\n" )); 2058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = -args[0]; 2060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_random: 2064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed Rand; 2066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " rand\n" )); 2069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Rand = seed; 2071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( Rand >= 0x8000L ) 2072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Rand++; 2073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = Rand; 2075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov seed = FT_MulFix( seed, 0x10000L - seed ); 2076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( seed == 0 ) 2077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov seed += 0x2873; 2078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_mul: 2083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " mul\n" )); 2084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = FT_MulFix( args[0], args[1] ); 2086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_sqrt: 2090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " sqrt\n" )); 2091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( args[0] > 0 ) 2093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int count = 9; 2095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed root = args[0]; 2096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed new_root; 2097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (;;) 2100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; 2102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( new_root == root || count <= 0 ) 2103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov root = new_root; 2105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = new_root; 2107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = 0; 2110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_drop: 2114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nothing */ 2115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " drop\n" )); 2116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_exch: 2120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed tmp; 2122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " exch\n" )); 2125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tmp = args[0]; 2127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = args[1]; 2128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[1] = tmp; 2129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 2130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_index: 2134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int idx = (FT_Int)( args[0] >> 16 ); 2136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " index\n" )); 2139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx < 0 ) 2141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = 0; 2142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( idx > num_args - 2 ) 2143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx = num_args - 2; 2144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = args[-( idx + 1 )]; 2145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_roll: 2150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int count = (FT_Int)( args[0] >> 16 ); 2152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int idx = (FT_Int)( args[1] >> 16 ); 2153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " roll\n" )); 2156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( count <= 0 ) 2158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = 1; 2159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= count; 2161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( args < stack ) 2162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 2163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= 0 ) 2165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( idx > 0 ) 2167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed tmp = args[count - 1]; 2169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 2170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = count - 2; i >= 0; i-- ) 2173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[i + 1] = args[i]; 2174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = tmp; 2175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx--; 2176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( idx < 0 ) 2181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed tmp = args[0]; 2183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 2184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < count - 1; i++ ) 2187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[i] = args[i + 1]; 2188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[count - 1] = tmp; 2189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov idx++; 2190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += count; 2193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_dup: 2197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " dup\n" )); 2198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[1] = args[0]; 2200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args += 2; 2201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_put: 2204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed val = args[0]; 2206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int idx = (FT_Int)( args[1] >> 16 ); 2207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " put\n" )); 2210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) 2212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->buildchar[idx] = val; 2213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_get: 2217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int idx = (FT_Int)( args[0] >> 16 ); 2219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed val = 0; 2220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " get\n" )); 2223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) 2225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = decoder->buildchar[idx]; 2226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = val; 2228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_store: 2233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " store\n")); 2234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Unimplemented; 2236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_load: 2238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " load\n" )); 2239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Unimplemented; 2241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_dotsection: 2243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this operator is deprecated and ignored by the parser */ 2244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " dotsection\n" )); 2245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_closepath: 2248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " closepath (invalid op)\n" )); 2253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 2255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_hsbw: 2258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " hsbw (invalid op)\n" )); 2263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 ); 2265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.left_bearing.x = args[0]; 2267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.left_bearing.y = 0; 2268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = decoder->builder.pos_x + args[0]; 2270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = decoder->builder.pos_y; 2271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 2272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_sbw: 2275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " sbw (invalid op)\n" )); 2280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 ); 2282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.left_bearing.x = args[0]; 2284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->builder.left_bearing.y = args[1]; 2285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = decoder->builder.pos_x + args[0]; 2287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = decoder->builder.pos_y + args[1]; 2288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 2289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_setcurrentpoint: 2292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); 2297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = decoder->builder.pos_x + args[0]; 2299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = decoder->builder.pos_y + args[1]; 2300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args = stack; 2301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_callothersubr: 2304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " callothersubr (invalid op)\n" )); 2309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subsequent `pop' operands should add the arguments, */ 2311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is the implementation described for `unknown' other */ 2312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subroutines in the Type1 spec. */ 2313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX Fix return arguments (see discussion below). */ 2315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args -= 2 + ( args[-2] >> 16 ); 2316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( args < stack ) 2317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Underflow; 2318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_pop: 2321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this is an invalid Type 2 operator; however, there */ 2322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* exist fonts which are incorrectly converted from probably */ 2323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Type 1 to CFF, and some parsers seem to accept it */ 2324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " pop (invalid op)\n" )); 2326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX Increasing `args' is wrong: After a certain number of */ 2328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `pop's we get a stack overflow. Reason for doing it is */ 2329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* code like this (actually found in a CFF font): */ 2330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 17 1 3 callothersubr */ 2332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* pop */ 2333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* callsubr */ 2334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Since we handle `callothersubr' as a no-op, and */ 2336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `callsubr' needs at least one argument, `pop' can't be a */ 2337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no-op too as it basically should be. */ 2338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The right solution would be to provide real support for */ 2340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `callothersubr' as done in `t1decode.c', however, given */ 2341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the fact that CFF fonts with `pop' are invalid, it is */ 2342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* questionable whether it is worth the time. */ 2343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_and: 2347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed cond = args[0] && args[1]; 2349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " and\n" )); 2352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = cond ? 0x10000L : 0; 2354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_or: 2359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed cond = args[0] || args[1]; 2361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " or\n" )); 2364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = cond ? 0x10000L : 0; 2366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_eq: 2371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed cond = !args[0]; 2373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " eq\n" )); 2376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = cond ? 0x10000L : 0; 2378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_ifelse: 2383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed cond = ( args[2] <= args[3] ); 2385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " ifelse\n" )); 2388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !cond ) 2390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args[0] = args[1]; 2391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov args++; 2392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_callsubr: 2396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->locals_bias ); 2399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " callsubr(%d)\n", idx )); 2402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= decoder->num_locals ) 2404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " invalid local subr index\n" )); 2407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " too many nested subrs\n" )); 2414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->cursor = ip; /* save current instruction pointer */ 2418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone++; 2420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->base = decoder->locals[idx]; 2421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->limit = decoder->locals[idx + 1]; 2422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->cursor = zone->base; 2423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !zone->base || zone->limit == zone->base ) 2425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " invoking empty subrs\n" )); 2428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->zone = zone; 2432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip = zone->base; 2433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = zone->limit; 2434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_callgsubr: 2438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->globals_bias ); 2441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " callgsubr(%d)\n", idx )); 2444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( idx >= decoder->num_globals ) 2446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " invalid global subr index\n" )); 2449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " too many nested subrs\n" )); 2456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->cursor = ip; /* save current instruction pointer */ 2460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone++; 2462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->base = decoder->globals[idx]; 2463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->limit = decoder->globals[idx + 1]; 2464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone->cursor = zone->base; 2465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !zone->base || zone->limit == zone->base ) 2467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " invoking empty subrs\n" )); 2470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->zone = zone; 2474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip = zone->base; 2475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = zone->limit; 2476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case cff_op_return: 2480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( " return\n" )); 2481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->zone <= decoder->zones ) 2483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cff_decoder_parse_charstrings:" 2485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " unexpected return\n" )); 2486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Syntax_Error; 2487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->zone--; 2490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov zone = decoder->zone; 2491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ip = zone->cursor; 2492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = zone->limit; 2493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 2494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 2496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Unimplemented: 2497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); 2498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ip[-1] == 12 ) 2500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( " %d", ip[0] )); 2501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "\n" )); 2502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Unimplemented_Feature ); 2504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder->top = args; 2507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 2509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Stack_Overflow; 2510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } /* general operator processing */ 2512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } /* while ip < limit */ 2514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "..end..\n\n" )); 2516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 2518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Syntax_Error: 2521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); 2522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_File_Format ); 2523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Stack_Underflow: 2525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); 2526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Too_Few_Arguments ); 2527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Stack_Overflow: 2529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); 2530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Stack_Overflow ); 2531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ 2534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 2540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 2541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 2542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 2543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** The following code is in charge of computing *********/ 2544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** the maximum advance width of the font. It *********/ 2545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** quickly processes each glyph charstring to *********/ 2546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** extract the value from either a `sbw' or `seac' *********/ 2547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** operator. *********/ 2548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /********** *********/ 2549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 2552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if 0 /* unused until we support pure CFF fonts */ 2555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 2558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_compute_max_advance( TT_Face face, 2559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int* max_advance ) 2560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 2562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Decoder decoder; 2563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int glyph_index; 2564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)face->other; 2565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *max_advance = 0; 2568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initialize load decoder */ 2570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); 2571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.metrics_only = 1; 2573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.load_points = 0; 2574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For each glyph, parse the glyph charstring and extract */ 2576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the advance width. */ 2577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 2578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index++ ) 2579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* charstring; 2581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong charstring_len; 2582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now get load the unscaled outline */ 2585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_get_glyph_data( face, glyph_index, 2586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &charstring, &charstring_len ); 2587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_prepare( &decoder, size, glyph_index ); 2590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_parse_charstrings( &decoder, 2592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring, 2593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 2594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_free_glyph_data( face, &charstring, &charstring_len ); 2596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ignore the error if one has occurred -- skip to next glyph */ 2599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 2600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *max_advance = decoder.builder.advance.x; 2603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 2605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */ 2609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 2612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_slot_load( CFF_GlyphSlot glyph, 2613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Size size, 2614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index, 2615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int32 load_flags ) 2616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 2618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Decoder decoder; 2619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Face face = (TT_Face)glyph->root.face; 2620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool hinting, scaled, force_scaling; 2621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Font cff = (CFF_Font)face->extra.data; 2622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Matrix font_matrix; 2624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector font_offset; 2625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov force_scaling = FALSE; 2628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in a CID-keyed font, consider `glyph_index' as a CID and map */ 2630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* it immediately to the real glyph_index -- if it isn't a */ 2631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* subsetted font, glyph_indices and CIDs are identical, though */ 2632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && 2633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff->charset.cids ) 2634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ 2636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_index != 0 ) 2637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index = cff_charset_cid_to_gindex( &cff->charset, 2639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index ); 2640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_index == 0 ) 2641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 2642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( glyph_index >= cff->num_glyphs ) 2645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 2646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_NO_RECURSE ) 2648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 2649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->x_scale = 0x10000L; 2651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->y_scale = 0x10000L; 2652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( size ) 2653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->x_scale = size->root.metrics.x_scale; 2655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->y_scale = size->root.metrics.y_scale; 2656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* try to load embedded bitmap if any */ 2661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 2662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: The convention should be emphasized in */ 2663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the documents because it can be confusing. */ 2664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( size ) 2665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Face cff_face = (CFF_Face)size->root.face; 2667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; 2668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = cff_face->root.stream; 2669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( size->strike_index != 0xFFFFFFFFUL && 2672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sfnt->load_eblc && 2673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 2674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_SBit_MetricsRec metrics; 2676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = sfnt->load_sbit_image( face, 2679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov size->strike_index, 2680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, 2681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Int)load_flags, 2682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov stream, 2683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &glyph->root.bitmap, 2684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &metrics ); 2685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool has_vertical_info; 2689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort advance; 2690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short dummy; 2691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.n_points = 0; 2694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.n_contours = 0; 2695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.width = (FT_Pos)metrics.width << 6; 2697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.height = (FT_Pos)metrics.height << 6; 2698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 2700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 2701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 2702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 2704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 2705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 2706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.format = FT_GLYPH_FORMAT_BITMAP; 2708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 2710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.bitmap_left = metrics.vertBearingX; 2712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.bitmap_top = metrics.vertBearingY; 2713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.bitmap_left = metrics.horiBearingX; 2717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.bitmap_top = metrics.horiBearingY; 2718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute linear advance widths */ 2721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, 2723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, 2724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &dummy, 2725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &advance ); 2726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearHoriAdvance = advance; 2727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov has_vertical_info = FT_BOOL( 2729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->vertical_info && 2730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->vertical.number_Of_VMetrics > 0 ); 2731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get the vertical metrics from the vtmx table if we have one */ 2733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( has_vertical_info ) 2734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, 2736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, 2737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &dummy, 2738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &advance ); 2739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearVertAdvance = advance; 2740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make up vertical ones */ 2744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->os2.version != 0xFFFFU ) 2745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearVertAdvance = (FT_Pos) 2746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( face->os2.sTypoAscender - face->os2.sTypoDescender ); 2747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearVertAdvance = (FT_Pos) 2749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( face->horizontal.Ascender - face->horizontal.Descender ); 2750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return immediately if we only want the embedded bitmaps */ 2760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_SBITS_ONLY ) 2761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 2762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if we have a CID subfont, use its matrix (which has already */ 2764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* been multiplied with the root matrix) */ 2765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this scaling is only relevant if the PS hinter isn't active */ 2767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cff->num_subfonts ) 2768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong top_upm, sub_upm; 2770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, 2771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index ); 2772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( fd_index >= cff->num_subfonts ) 2775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fd_index = (FT_Byte)( cff->num_subfonts - 1 ); 2776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov top_upm = cff->top_font.font_dict.units_per_em; 2778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; 2779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; 2782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_offset = cff->subfonts[fd_index]->font_dict.font_offset; 2783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( top_upm != sub_upm ) 2785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); 2787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); 2788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov force_scaling = TRUE; 2790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix = cff->top_font.font_dict.font_matrix; 2795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_offset = cff->top_font.font_dict.font_offset; 2796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.n_points = 0; 2799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.n_contours = 0; 2800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* top-level code ensures that FT_LOAD_NO_HINTING is set */ 2802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if FT_LOAD_NO_SCALE is active */ 2803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 2804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); 2805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->hint = hinting; 2807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->scaled = scaled; 2808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ 2809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CFF_CONFIG_OPTION_OLD_ENGINE 2812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); 2813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 2814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* charstring; 2817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong charstring_len; 2818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_decoder_init( &decoder, face, size, glyph, hinting, 2821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOAD_TARGET_MODE( load_flags ) ); 2822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_ADVANCE_ONLY ) 2824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.width_only = TRUE; 2825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.no_recurse = 2827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); 2828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now load the unscaled outline */ 2830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_get_glyph_data( face, glyph_index, 2831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &charstring, &charstring_len ); 2832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 2833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Glyph_Build_Finished; 2834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_prepare( &decoder, size, glyph_index ); 2836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 2837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Glyph_Build_Finished; 2838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CFF_CONFIG_OPTION_OLD_ENGINE 2840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* choose which CFF renderer to use */ 2841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) 2842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cff_decoder_parse_charstrings( &decoder, 2843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring, 2844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 2845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 2847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cf2_decoder_parse_charstrings( &decoder, 2849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring, 2850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 2851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Adobe's engine uses 16.16 numbers everywhere; */ 2853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* as a consequence, glyphs larger than 2000ppem get rejected */ 2854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) 2855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this time, we retry unhinted and scale up the glyph later on */ 2857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ 2858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 0x400 for both `x_scale' and `y_scale' in this case) */ 2859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hinting = FALSE; 2860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov force_scaling = TRUE; 2861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->hint = hinting; 2862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cf2_decoder_parse_charstrings( &decoder, 2864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring, 2865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov charstring_len ); 2866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_free_glyph_data( face, &charstring, charstring_len ); 2870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 2872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Glyph_Build_Finished; 2873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 2875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Control data and length may not be available for incremental */ 2876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* fonts. */ 2877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->root.internal->incremental_interface ) 2878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.control_data = 0; 2880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.control_len = 0; 2881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We set control_data and control_len if charstrings is loaded. */ 2886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* See how charstring loads at cff_index_access_element() in */ 2887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cffload.c. */ 2888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFF_Index csindex = &cff->charstrings_index; 2890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( csindex->offsets ) 2893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.control_data = csindex->bytes + 2895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov csindex->offsets[glyph_index] - 1; 2896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.control_len = charstring_len; 2897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Glyph_Build_Finished: 2901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* save new glyph tables, if no error */ 2902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cff_builder_done( &decoder.builder ); 2904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: anything to do for broken glyph entry? */ 2905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_INCREMENTAL 2908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Incremental fonts can optionally override the metrics. */ 2910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error && 2911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface && 2912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 2913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Incremental_MetricsRec metrics; 2915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.bearing_x = decoder.builder.left_bearing.x; 2918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.bearing_y = 0; 2919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.advance = decoder.builder.advance.x; 2920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics.advance_v = decoder.builder.advance.y; 2921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 2923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->root.internal->incremental_interface->object, 2924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, FALSE, &metrics ); 2925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.left_bearing.x = metrics.bearing_x; 2927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.advance.x = metrics.advance; 2928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decoder.builder.advance.y = metrics.advance_v; 2929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 2934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Now, set the metrics -- this is rather simple, as */ 2936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the left side bearing is the xMin, and the top side */ 2937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* bearing the yMax. */ 2938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For composite glyphs, return only left side bearing and */ 2940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* advance width. */ 2941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_NO_RECURSE ) 2942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Slot_Internal internal = glyph->root.internal; 2944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; 2947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.metrics.horiAdvance = decoder.glyph_width; 2948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_matrix = font_matrix; 2949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_delta = font_offset; 2950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov internal->glyph_transformed = 1; 2951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox cbox; 2955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Glyph_Metrics* metrics = &glyph->root.metrics; 2956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector advance; 2957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool has_vertical_info; 2958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* copy the _unscaled_ advance width */ 2961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance = decoder.glyph_width; 2962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearHoriAdvance = decoder.glyph_width; 2963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.internal->glyph_transformed = 0; 2964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov has_vertical_info = FT_BOOL( face->vertical_info && 2966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->vertical.number_Of_VMetrics > 0 ); 2967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* get the vertical metrics from the vtmx table if we have one */ 2969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( has_vertical_info ) 2970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short vertBearingY = 0; 2972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort vertAdvance = 0; 2973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, 2976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_index, 2977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &vertBearingY, 2978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &vertAdvance ); 2979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertBearingY = vertBearingY; 2980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = vertAdvance; 2981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* make up vertical ones */ 2985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->os2.version != 0xFFFFU ) 2986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - 2987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->os2.sTypoDescender ); 2988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - 2990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->horizontal.Descender ); 2991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.linearVertAdvance = metrics->vertAdvance; 2994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 2996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.flags = 0; 2998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( size && size->root.metrics.y_ppem < 24 ) 2999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; 3000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; 3002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( font_matrix.xx == 0x10000L && 3004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix.yy == 0x10000L && 3005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix.xy == 0 && 3006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_matrix.yx == 0 ) ) 3007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Transform( &glyph->root.outline, &font_matrix ); 3008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( font_offset.x == 0 && 3010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_offset.y == 0 ) ) 3011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Translate( &glyph->root.outline, 3012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov font_offset.x, font_offset.y ); 3013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov advance.x = metrics->horiAdvance; 3015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov advance.y = 0; 3016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Transform( &advance, &font_matrix ); 3017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance = advance.x + font_offset.x; 3018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov advance.x = 0; 3020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov advance.y = metrics->vertAdvance; 3021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Transform( &advance, &font_matrix ); 3022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = advance.y + font_offset.y; 3023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) 3025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* scale the outline and the metrics */ 3027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 3028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* cur = &glyph->root.outline; 3029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec = cur->points; 3030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed x_scale = glyph->x_scale; 3031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed y_scale = glyph->y_scale; 3032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* First of all, scale the points */ 3035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !hinting || !decoder.builder.hints_funcs ) 3036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = cur->n_points; n > 0; n--, vec++ ) 3037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = FT_MulFix( vec->x, x_scale ); 3039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = FT_MulFix( vec->y, y_scale ); 3040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Then scale the metrics */ 3043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 3044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 3045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute the other metrics */ 3048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 3049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->width = cbox.xMax - cbox.xMin; 3051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->height = cbox.yMax - cbox.yMin; 3052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiBearingX = cbox.xMin; 3054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiBearingY = cbox.yMax; 3055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( has_vertical_info ) 3057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertBearingX = metrics->horiBearingX - 3058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->horiAdvance / 2; 3059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 3060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 3061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 3062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_synthesize_vertical_metrics( metrics, 3063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov metrics->vertAdvance ); 3064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 3069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 3070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 3072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 3073