diff --git a/Tests/differ.py b/Tests/differ.py index 09dc960d1..c20cec546 100755 --- a/Tests/differ.py +++ b/Tests/differ.py @@ -18,7 +18,7 @@ from fontTools.misc.py23 import open -__version__ = '0.2.3' +__version__ = '0.2.4' logger = logging.getLogger('differ') @@ -82,26 +82,31 @@ def _read_txt_file(self, path): # Hard code a first line; this way the difflib results start # from 1 instead of zero, thus matching the file's line numbers lines = [''] - with open(path, "r", encoding=self.encoding) as f: - for i, line in enumerate(f.readlines(), 1): - # Skip lines that change, such as timestamps - if self._line_to_skip(line): - logger.debug("Matched begin of line. Skipped: {}" - "".format(line.rstrip())) - # Blank the line instead of actually skipping (via - # 'continue'); this way the difflib results show the - # correct line numbers - line = '' - # Skip specific lines, referenced by number - elif i in self.skip_lines: - logger.debug("Matched line #{}. Skipped: {}" - "".format(i, line.rstrip())) - # Blank the line instead of actually skipping (via - # 'continue'); this way the difflib results show the - # correct line numbers - line = '' - # Use os-native line separator to enable running difflib - lines.append(line.rstrip() + os.linesep) + try: + with open(path, "r", encoding=self.encoding) as f: + for i, line in enumerate(f.readlines(), 1): + # Skip lines that change, such as timestamps + if self._line_to_skip(line): + logger.debug("Matched begin of line. Skipped: {}" + "".format(line.rstrip())) + # Blank the line instead of actually skipping (via + # 'continue'); this way the difflib results show the + # correct line numbers + line = '' + # Skip specific lines, referenced by number + elif i in self.skip_lines: + logger.debug("Matched line #{}. Skipped: {}" + "".format(i, line.rstrip())) + # Blank the line instead of actually skipping (via + # 'continue'); this way the difflib results show the + # correct line numbers + line = '' + # Use os-native line separator to enable running difflib + lines.append(line.rstrip() + os.linesep) + except UnicodeDecodeError: + logger.error("Couldn't read text file using '{}' encoding.\n" + " File path: {}".format(self.encoding, path)) + sys.exit(1) return lines def _line_to_skip(self, line): diff --git a/Tests/tx_data/expected_output/trademark.pfa b/Tests/tx_data/expected_output/trademark.pfa new file mode 100644 index 000000000..12459593b --- /dev/null +++ b/Tests/tx_data/expected_output/trademark.pfa @@ -0,0 +1,69 @@ +%!FontType1-1.1: SourceSansPro-Regular 2.20 +%ADOt1write: (1.0.34) +%%BeginResource: font SourceSansPro-Regular +12 dict dup begin +/FontType 1 def +/FontName /SourceSansPro-Regular def +/FontInfo 8 dict dup begin +/version (2.20) def +/Notice (This trademark string contains a Copyright U+00A9 character that will be converted to 'Copyright') def +/Copyright (Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'.) def +/FamilyName (Source Sans Pro) def +/UnderlinePosition -75 def +end def +/PaintType 0 def +/FontMatrix [0.001 0 0 0.001 0 0] def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +def +/FontBBox {0 -22 565 660} def +end +currentfile eexec BAB431EA06BB0A1031E1AA11919E714AC69FC6474167B6 +17C8FF56014245E5C1290C81D5312994CDC47B07C655DDD53C35D530C44F953F +804152D5ED7591016D3D1968FC4A9F629E0ADB83B91691E8A0AB81C098760580 +FFC73B03E534FD00C1C69885C6151AADEBF9BBF7284F088A81EB0A35C6F197CE +C173C8CE58E9B3FCB9208ADF4EBF3C5EC25A74C97BDB35FA4F8BAF3D9D763102 +55C3E50F584FEB672E23505BBC67907CAC330D8610101B45E890175E814906C8 +5FF1D20B4CCDC66764F2FA912AD901262DCD7462798A6E1AD554991CD5E4435E +1C69900DCBF8976BCB8E40D2BAB384AA01173A71AC2604A39B608756AE648B0A +7C4F577FF3A7CD6F30E99C644ED00100238F9DE60D83AC5071FCA2C640EE25EA +06B8DA5305575F00B2E725082360DD11C32965A77DCB027BCA4D6A6C6472A1FD +40B1CBA50AFC4B418C9D7A00512F856598DC16039701FDA8AF67DCABB1672DC4 +4C87F47DD65AF1B053E9AE4DF25A15399E40B396E720FF473BE6D753B8431EED +BCA59FDD6827DFAFB75B6FA86ED3E68E5A7D66473657103E863BC577E7087DC1 +B0BB983EA24E43E75521BB5F1555F3A4E963DA5A942D4AC45DFB9375843000FD +4E1792007522ACEC58446732EEF48FE0C4180554E16D7F22FD503893DD0CEED7 +58311B45E4CECC68E5934BD37C88AAFA5BB40FAC8B9305D3B2F3070D221B51D9 +86EE88B097C227D419BBBF8643032623FB5768C671D687BB2350A97AB05D3FA4 +7C15A8DA2C93097AF86BD87A0BA465FC3536C3E5A17F5E5BBEFEB69BE83B737A +B6B5226CA2B9FEDDE2ABCD1457125D6B52EDAB200FFA76E4462DFFAC68E78EF3 +397E0FBF14883D2FDBB5C35E17A54757E8895A40404729535F8DDE809ED04C76 +03CC7D3C867985133A922DBE015225C533408091B5C9CD839A5BEBF7433E9DF2 +DBA0A35138B2E07C55D8030B3DBCF093C8A40081E6DA98A46286707F8083832E +1FFB4202F2361419F8B62BF7B33156F509BC850896B86686D396EC0854BE8CEF +5573B5DC6473A9C3DABEDA4DEC27D040053C35AF8F3CCBDCFE627499A1BAA3A3 +2722510021CD7624354C9DEE818B18C986BDFDF0DCA665BEF672B18B0E596ABF +4B934806C61442F9D6E3D0A3B2B9DE59BD6304E580E0DA3110FBDD70F67A9902 +8FEFF483265F47508E83FF2DA6669C79268D4E39C83F91025A3A872753CCC513 +A214B3DF4297EB9743E2992FC8569FF8AF7EB24B3485B7049C37F74995BAD994 +16564450400A11138748F829593A333FB414A6971CA64A65C319895761E014F5 +686C761CF26DCD8C730084D4EA407EC6075CE5178E5275B7CCF7C26B5DCE6DC6 +D0D47024979299998FCA0318D26C276AB4453289FF24B8D2840C7B36978520F1 +911392CDFCA615B9BDEC40EA997C182A9A2278EAED91C4B9326B8A578D73C549 +8C35B23F48E5C73549B3BF3D2E75A185FC0D4D8EB73DB300FED5C8F60B623FCD +DF364B566CC001D9A3CFBE141341DC18F7EF957B87A2992824995CEDF281D3EB +D4D0291795F84E8E0BBF2C3AC4B81DF5E4528ADED24BB7824C5A4DF38D533DED +FF89EDF57559ABFBB243625656DAB404B37305465C4D79A79EAF5ED9CD37B24A +E54CF01F3E427F0EFCEA8C5A789E60568A89F1A764D6004597309F24FF3835F2 +DAF8634317ADD97D76D50E1F80B8 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark +%%EndResource +%%EOF diff --git a/Tests/tx_data/input/trademark.ufo/fontinfo.plist b/Tests/tx_data/input/trademark.ufo/fontinfo.plist new file mode 100644 index 000000000..9223937aa --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/fontinfo.plist @@ -0,0 +1,166 @@ + + + + + ascender + 712 + capHeight + 656 + copyright + Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. + descender + -205 + familyName + Source Sans Pro + italicAngle + 0 + openTypeHheaAscender + 984 + openTypeHheaDescender + -273 + openTypeHheaLineGap + 0 + openTypeNameDesigner + Paul D. Hunt + openTypeNameLicense + This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFL. This Font Software is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software. + openTypeNameLicenseURL + http://scripts.sil.org/OFL + openTypeNameManufacturer + Adobe Systems Incorporated + openTypeNameManufacturerURL + http://www.adobe.com/type + openTypeOS2CodePageRanges + + 0 + 1 + 2 + 3 + 4 + 7 + 8 + 29 + + openTypeOS2Panose + + 2 + 11 + 5 + 3 + 3 + 4 + 3 + 2 + 2 + 4 + + openTypeOS2Type + + + openTypeOS2TypoAscender + 750 + openTypeOS2TypoDescender + -250 + openTypeOS2TypoLineGap + 0 + openTypeOS2UnicodeRanges + + 0 + 1 + 2 + 4 + 5 + 6 + 7 + 9 + 29 + 30 + 32 + 57 + + openTypeOS2VendorID + ADBO + openTypeOS2WinAscent + 984 + openTypeOS2WinDescent + 273 + postscriptBlueFuzz + 0 + postscriptBlueScale + 0.0625 + postscriptBlueValues + + -12 + 0 + 486 + 498 + 518 + 530 + 574 + 586 + 638 + 650 + 656 + 668 + 712 + 724 + + postscriptFamilyBlues + + -12 + 0 + 486 + 498 + 518 + 530 + 574 + 586 + 638 + 650 + 656 + 668 + 712 + 724 + + postscriptFamilyOtherBlues + + -217 + -205 + + postscriptFontName + SourceSansPro-Regular + postscriptForceBold + + postscriptOtherBlues + + -217 + -205 + + postscriptStemSnapH + + 67 + 78 + + postscriptStemSnapV + + 84 + 95 + + postscriptUnderlinePosition + -75 + postscriptUnderlineThickness + 50 + styleName + Regular + trademark + This trademark string contains a © U+00A9 character that will be converted to 'Copyright' + unitsPerEm + 1000 + versionMajor + 2 + versionMinor + 20 + xHeight + 486 + + diff --git a/Tests/tx_data/input/trademark.ufo/glyphs/_notdef.glif b/Tests/tx_data/input/trademark.ufo/glyphs/_notdef.glif new file mode 100644 index 000000000..209f5611b --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/glyphs/_notdef.glif @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/tx_data/input/trademark.ufo/glyphs/a.glif b/Tests/tx_data/input/trademark.ufo/glyphs/a.glif new file mode 100644 index 000000000..ad3b2592c --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/glyphs/a.glif @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/tx_data/input/trademark.ufo/glyphs/contents.plist b/Tests/tx_data/input/trademark.ufo/glyphs/contents.plist new file mode 100644 index 000000000..f7fa5dd46 --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/glyphs/contents.plist @@ -0,0 +1,10 @@ + + + + + .notdef + _notdef.glif + a + a.glif + + diff --git a/Tests/tx_data/input/trademark.ufo/lib.plist b/Tests/tx_data/input/trademark.ufo/lib.plist new file mode 100644 index 000000000..830d35e15 --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/lib.plist @@ -0,0 +1,11 @@ + + + + + public.glyphOrder + + .notdef + a + + + diff --git a/Tests/tx_data/input/trademark.ufo/metainfo.plist b/Tests/tx_data/input/trademark.ufo/metainfo.plist new file mode 100644 index 000000000..9c654d4c2 --- /dev/null +++ b/Tests/tx_data/input/trademark.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + org.robofab.ufoLib + formatVersion + 2 + + diff --git a/Tests/tx_test.py b/Tests/tx_test.py index 8a726a37a..176f4152a 100755 --- a/Tests/tx_test.py +++ b/Tests/tx_test.py @@ -156,3 +156,15 @@ def test_varread_pr355(): actual_path = runner(CMD + ['-o', 't1', '-f', 'cff2_vf.otf']) expected_path = _get_expected_path('cff2_vf.pfa') assert differ([expected_path, actual_path]) + + +# ----------- +# Other tests +# ----------- + +def test_trademark_string_pr425(): + # the copyright symbol used in the trademark field of a UFO is + # converted to 'Copyright' and stored in Notice field of a Type1 + actual_path = runner(CMD + ['-o', 't1', '-f', 'trademark.ufo']) + expected_path = _get_expected_path('trademark.pfa') + assert differ([expected_path, actual_path]) diff --git a/afdko/Tools/Programs/autohint/autohintlib/source/public/extras/pubtypes.h b/afdko/Tools/Programs/autohint/autohintlib/source/public/extras/pubtypes.h index 6eaf45c64..b9adaee29 100644 --- a/afdko/Tools/Programs/autohint/autohintlib/source/public/extras/pubtypes.h +++ b/afdko/Tools/Programs/autohint/autohintlib/source/public/extras/pubtypes.h @@ -172,9 +172,6 @@ typedef character *charptr; #endif #define NIL NULL -typedef void (*PVoidProc)(); - /* Pointer to procedure returning */ - /* no result */ #ifndef __MWERKS__ typedef Card32 GenericID; /* Generic ID for contexts, */ /* spaces, name cache, etc. */ diff --git a/afdko/Tools/Programs/public/lib/api/supportpublictypes.h b/afdko/Tools/Programs/public/lib/api/supportpublictypes.h index d3a5a3e66..89a56ba86 100644 --- a/afdko/Tools/Programs/public/lib/api/supportpublictypes.h +++ b/afdko/Tools/Programs/public/lib/api/supportpublictypes.h @@ -344,8 +344,6 @@ typedef unsigned char character, *string, *charptr; #define NIL NULL -typedef void (*PVoidProc)(); /* Pointer to procedure returning no result */ - #if 0 /* XXX */ /* Codes for exit system calls */ diff --git a/afdko/Tools/Programs/public/lib/source/uforead/uforead.c b/afdko/Tools/Programs/public/lib/source/uforead/uforead.c index a23c40988..df4db057f 100755 --- a/afdko/Tools/Programs/public/lib/source/uforead/uforead.c +++ b/afdko/Tools/Programs/public/lib/source/uforead/uforead.c @@ -3,26 +3,26 @@ This software is licensed as OpenSource, under the Apache License, Version 2.0. /* * Simple ufo file parser. - - If a glif file exists in the processed glyph layer, I trust that the data is up to date, and use it, + + If a glif file exists in the processed glyph layer, I trust that the data is up to date, and use it, else I use the glif from the default layer. I read both the hint and drawing operator list before calling any call backs, and I need to have both in hand to do so. - + - parse points into a list of operators - parse ADobe t1 hint data, if any, into a list of hint mask operators - play back the list of operators, calling the abf call backs. - - Hint processing. + + Hint processing. The hint data is stored as an separate XML element from the outline data, This is so that outline editors do not need to understand this info, and it can be private data. - + Read the hint data into list of hint mask pointers. The hint mask pointer list is expanded to include a pointer for each point index, up to the highest point referenced in any hintmask. Hint mask pointers not referenced by a hint mask are set to null. The list of hint mask pointers is passed into the point processing function, which checks to see if there is a non-null hintmask pointer for the current point. If so, the function plays back the current hint list through the call backs. - + The flex operator is also kept in the hint data. - + */ #include "absfont.h" @@ -40,10 +40,10 @@ This software is licensed as OpenSource, under the Apache License, Version 2.0. enum { - ufoUnknown, - ufoNumeric, - ufoOperator, - ufoNotSet, + ufoUnknown, + ufoNumeric, + ufoOperator, + ufoNotSet, }; #define kMaxToken 1024 @@ -54,15 +54,15 @@ const char * t1HintKeyV2 = "com.adobe.type.autohint.v2"; typedef struct { - int type; - char val[kMaxToken]; - size_t length; - size_t offset; /* into buffer */ + int type; + char val[kMaxToken]; + size_t length; + size_t offset; /* into buffer */ } token; -typedef unsigned short STI; /* String index */ -#define STI_UNDEF 0xffff /* Undefined string index */ -#define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) +typedef unsigned short STI; /* String index */ +#define STI_UNDEF 0xffff /* Undefined string index */ +#define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) #ifdef _WIN32 #define round round_int #endif @@ -73,29 +73,22 @@ enum #define DCL_KEY(key,index) index, #include "ufo_ops.h" #undef DCL_KEY - kKeyCount -}; - -static const char op_keys[] = -{ -#define DCL_KEY(key,index) key, -#include "ufo_ops.h" -#undef DCL_KEY + kKeyCount }; typedef struct { - float mtx[6]; /* Float matrix */ + float mtx[6]; /* Float matrix */ int isDefault; int isOffsetOnly; } Transform; typedef struct _floatRect { - float left; - float bottom; - float right; - float top; + float left; + float bottom; + float right; + float top; } floatRect; typedef struct @@ -106,9 +99,9 @@ typedef struct long int glyphOrder; // used to sort the glypfRecs by glyph order from lib.plist. } GLIF_Rec; -typedef struct +typedef struct { - int order; + long order; char* glyphName; } GlIFOrderRec; @@ -123,27 +116,27 @@ typedef enum typedef struct { OpType opType; - float coords[6]; /* Float matrix */ + float coords[6]; /* Float matrix */ char* pointName; } OpRec; enum { - outlineStart, - outlineInContour, - outlineInPoint, - outlineInComponent, - outlineInComment, - outlineInLib, - outlineInLibDict, - outlineInID, - outlineInHintData, - outlineInHintSetList, + outlineStart, + outlineInContour, + outlineInPoint, + outlineInComponent, + outlineInComment, + outlineInLib, + outlineInLibDict, + outlineInID, + outlineInHintData, + outlineInHintSetList, outlineInFlexList, - outlineInHintSet, - outlineInHintSetName, - outlineInHintSetStemList, - outlineInStemHint, + outlineInHintSet, + outlineInHintSetName, + outlineInHintSetStemList, + outlineInStemHint, otherDictKey, otherInElement, otherInTag, @@ -163,92 +156,92 @@ typedef struct { struct ufoCtx_ { - abfTopDict top; - abfFontDict fdict; - int flags; -#define SEEN_END 1 - struct - { - void *dbg; - void *src; + abfTopDict top; + abfFontDict fdict; + int flags; +#define SEEN_END 1 + struct + { + void *dbg; + void *src; } stm; - struct - { - long offset; - char *buf; - size_t length; - char *end; - char *next; - token tk; + struct + { + long offset; + char *buf; + size_t length; + char *end; + char *next; + token tk; } src; - struct + struct { - dnaDCL(GLIF_Rec, glifRecs); - dnaDCL(GlIFOrderRec, glifOrder); - dnaDCL(OpRec, opList); + dnaDCL(GLIF_Rec, glifRecs); + dnaDCL(GlIFOrderRec, glifOrder); + dnaDCL(OpRec, opList); } data; - struct + struct { StemHint stems[T2_MAX_STEMS]; - dnaDCL(HintMask, hintMasks); - dnaDCL(char*, flexOpList); + dnaDCL(HintMask, hintMasks); + dnaDCL(char*, flexOpList); char * pointName; /* used save the hint refernce from the first point of a curve, since it has to be used in trh last point of the curve. */ } hints; - - dnaDCL(char*, valueArray); /* used when parsing elements */ + + dnaDCL(char*, valueArray); /* used when parsing elements */ char *parseKeyName; /* used to keep track of current top element name. */ - dnaDCL(char, tmp); /* Temporary buffer */ - char *mark; /* Buffer position marker */ + dnaDCL(char, tmp); /* Temporary buffer */ + char *mark; /* Buffer position marker */ char *altLayerDir; char *defaultLayerDir; - struct + struct { - int cnt; - unsigned long flags; -#define PARSE_INIT (1<<0) -#define PARSE_PATH (1<<1) + int cnt; + unsigned long flags; +#define PARSE_INIT (1<<0) +#define PARSE_PATH (1<<1) #define PARSE_STARTHINT (1<<2) -#define PARSE_HINT (1<<3) -#define PARSE_ENDHINT (1<<4) +#define PARSE_HINT (1<<3) +#define PARSE_ENDHINT (1<<4) #define PARSE_SEEN_MOVETO (1<<6) // have seen an explicit a "move". IF there is no subsequent marking operator, we skip the operation. -#define PARSE_END (1<<7) - - int hintflags; +#define PARSE_END (1<<7) + + int hintflags; #define UFO_MAX_OP_STACK 18 - - float array[UFO_MAX_OP_STACK]; + + float array[UFO_MAX_OP_STACK]; } stack; - - floatRect aggregatebounds; - struct /* Metric data */ + + floatRect aggregatebounds; + struct /* Metric data */ { struct abfMetricsCtx_ ctx; - abfGlyphInfo gi; + abfGlyphInfo gi; abfGlyphCallbacks cb; - long defaultWidth; + long defaultWidth; } metrics; - - struct + + struct { - dnaDCL(abfGlyphInfo, index); - dnaDCL(long, byName); /* In glyph name order */ - dnaDCL(long, widths); /* In index order; [SRI]->width */ + dnaDCL(abfGlyphInfo, index); + dnaDCL(long, byName); /* In glyph name order */ + dnaDCL(long, widths); /* In index order; [SRI]->width */ } chars; - struct /* String pool */ + struct /* String pool */ { - dnaDCL(long, index); /* In index order; [SRI]->iBuf */ - dnaDCL(char, buf); /* String buffer */ + dnaDCL(long, index); /* In index order; [SRI]->iBuf */ + dnaDCL(char, buf); /* String buffer */ } strings; - struct + struct { - ctlMemoryCallbacks mem; - ctlStreamCallbacks stm; + ctlMemoryCallbacks mem; + ctlStreamCallbacks stm; } cb; - dnaCtx dna; - struct + dnaCtx dna; + struct { - _Exc_Buf env; - int code; + _Exc_Buf env; + int code; } err; }; @@ -258,7 +251,7 @@ typedef struct float array[14]; } BluesArray; -typedef abfGlyphInfo Char; /* Character record */ +typedef abfGlyphInfo Char; /* Character record */ static STI addString(ufoCtx h, size_t length, const char *value); @@ -270,58 +263,58 @@ static void setWidth(ufoCtx h, STI sti, long value); static long getWidth(ufoCtx h, STI sti); static int addChar(ufoCtx h, STI sti, Char **chr); static int CTL_CDECL postMatchChar(const void *key, const void *value, - void *ctx); + void *ctx); /* -------------------------- Error Support ------------------------ */ char *ufoErrStr(int err_code) { - static char *errstrs[] = + static char *errstrs[] = { #undef CTL_DCL_ERR -#define CTL_DCL_ERR(name,string) string, +#define CTL_DCL_ERR(name,string) string, #include "ufoerr.h" }; - return (err_code < 0 || err_code >= (int)ARRAY_LEN(errstrs))? + return (err_code < 0 || err_code >= (int)ARRAY_LEN(errstrs))? (char*)"unknown error": errstrs[err_code]; } /* Write message to debug stream from va_list. */ static void vmessage(ufoCtx h, char *fmt, va_list ap) { - char text[BUFSIZ]; - - if (h->stm.dbg == NULL) - return; /* Debug stream not available */ - - vsprintf(text, fmt, ap); - (void)h->cb.stm.write(&h->cb.stm, h->stm.dbg, strlen(text), text); + char text[BUFSIZ]; + + if (h->stm.dbg == NULL) + return; /* Debug stream not available */ + + vsprintf(text, fmt, ap); + (void)h->cb.stm.write(&h->cb.stm, h->stm.dbg, strlen(text), text); } /* Write message to debug stream from varargs. */ static void CTL_CDECL message(ufoCtx h, char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vmessage(h, fmt, ap); - va_end(ap); + va_list ap; + va_start(ap, fmt); + vmessage(h, fmt, ap); + va_end(ap); } static void CTL_CDECL fatal(ufoCtx h, int err_code, char *fmt, ...) { - if (fmt == NULL) + if (fmt == NULL) /* Write standard error message */ - message(h, "%s", ufoErrStr(err_code)); - else - { - /* Write font-specific error message */ - va_list ap; - va_start(ap, fmt); - vmessage(h, fmt, ap); - va_end(ap); + message(h, "%s", ufoErrStr(err_code)); + else + { + /* Write font-specific error message */ + va_list ap; + va_start(ap, fmt); + vmessage(h, fmt, ap); + va_end(ap); } - h->err.code = err_code; - RAISE(&h->err.env, err_code, NULL); + h->err.code = err_code; + RAISE(&h->err.env, err_code, NULL); } /* --------------------------- Memory Management --------------------------- */ @@ -329,16 +322,16 @@ static void CTL_CDECL fatal(ufoCtx h, int err_code, char *fmt, ...) /* Allocate memory. */ static void *memNew(ufoCtx h, size_t size) { - void *ptr = h->cb.mem.manage(&h->cb.mem, NULL, size); - if (ptr == NULL) - fatal(h, ufoErrNoMemory, NULL); - return ptr; + void *ptr = h->cb.mem.manage(&h->cb.mem, NULL, size); + if (ptr == NULL) + fatal(h, ufoErrNoMemory, NULL); + return ptr; } /* Free memory. */ static void memFree(ufoCtx h, void *ptr) { - (void)h->cb.mem.manage(&h->cb.mem, ptr, 0); + (void)h->cb.mem.manage(&h->cb.mem, ptr, 0); } /* -------------------------- Safe dynarr Callbacks ------------------------ */ @@ -346,20 +339,20 @@ static void memFree(ufoCtx h, void *ptr) /* Manage memory. */ static void *dna_manage(ctlMemoryCallbacks *cb, void *old, size_t size) { - ufoCtx h = (ufoCtx)cb->ctx; - void *ptr = h->cb.mem.manage(&h->cb.mem, old, size); - if (size > 0 && ptr == NULL) - fatal(h, ufoErrNoMemory, NULL); - return ptr; + ufoCtx h = (ufoCtx)cb->ctx; + void *ptr = h->cb.mem.manage(&h->cb.mem, old, size); + if (size > 0 && ptr == NULL) + fatal(h, ufoErrNoMemory, NULL); + return ptr; } /* Initialize error handling dynarr context. */ static void dna_init(ufoCtx h) { - ctlMemoryCallbacks cb; - cb.ctx = h; - cb.manage = dna_manage; - h->dna = dnaNew(&cb, DNA_CHECK_ARGS); + ctlMemoryCallbacks cb; + cb.ctx = h; + cb.manage = dna_manage; + h->dna = dnaNew(&cb, DNA_CHECK_ARGS); } /* ------------------------ Context handling ------------------------------ */ @@ -380,9 +373,9 @@ static void initHintMask(void *ctx, long cnt, HintMask *base) void ufoFree(ufoCtx h) { - if (h == NULL) - return; - + if (h == NULL) + return; + dnaFREE(h->valueArray); { int i = 0; @@ -396,56 +389,56 @@ void ufoFree(ufoCtx h) dnaFREE(h->hints.hintMasks); dnaFREE(h->hints.flexOpList); dnaFREE(h->chars.index); - dnaFREE(h->chars.byName); - dnaFREE(h->chars.widths); - dnaFREE(h->tmp); - dnaFREE(h->data.glifRecs); - dnaFREE(h->data.glifOrder); - dnaFREE(h->data.opList); - freeStrings(h); - dnaFree(h->dna); - - /* Close debug stream */ - if (h->stm.dbg != NULL) - (void)h->cb.stm.close(&h->cb.stm, h->stm.dbg); - - /* Free library context */ - memFree(h, h); + dnaFREE(h->chars.byName); + dnaFREE(h->chars.widths); + dnaFREE(h->tmp); + dnaFREE(h->data.glifRecs); + dnaFREE(h->data.glifOrder); + dnaFREE(h->data.opList); + freeStrings(h); + dnaFree(h->dna); + + /* Close debug stream */ + if (h->stm.dbg != NULL) + (void)h->cb.stm.close(&h->cb.stm, h->stm.dbg); + + /* Free library context */ + memFree(h, h); } /* Validate client and create context */ ufoCtx ufoNew(ctlMemoryCallbacks *mem_cb, ctlStreamCallbacks *stm_cb, CTL_CHECK_ARGS_DCL) { - ufoCtx h; - - /* Check client/library compatibility */ - if (CTL_CHECK_ARGS_TEST(UFO_VERSION)) - return NULL; - - /* Allocate context */ - h = (ufoCtx)mem_cb->manage(mem_cb, NULL, sizeof(struct ufoCtx_)); - if (h == NULL) - return NULL; + ufoCtx h; + + /* Check client/library compatibility */ + if (CTL_CHECK_ARGS_TEST(UFO_VERSION)) + return NULL; + + /* Allocate context */ + h = (ufoCtx)mem_cb->manage(mem_cb, NULL, sizeof(struct ufoCtx_)); + if (h == NULL) + return NULL; /* Safety initialization */ memset(h, 0, sizeof(*h)); - - h->metrics.defaultWidth = 1000; - h->altLayerDir = "glyphs.com.adobe.type.processedGlyphs"; - h->defaultLayerDir = "glyphs"; - - - /* Copy callbacks */ - h->cb.mem = *mem_cb; - h->cb.stm = *stm_cb; - - /* Set error handler */ + + h->metrics.defaultWidth = 1000; + h->altLayerDir = "glyphs.com.adobe.type.processedGlyphs"; + h->defaultLayerDir = "glyphs"; + + + /* Copy callbacks */ + h->cb.mem = *mem_cb; + h->cb.stm = *stm_cb; + + /* Set error handler */ DURING_EX(h->err.env) - + /* Initialize service library */ dna_init(h); - + dnaINIT(h->dna, h->valueArray, 256, 50); dnaINIT(h->dna, h->tmp, 100, 250); dnaINIT(h->dna, h->chars.index, 256, 1000); @@ -457,68 +450,68 @@ ufoCtx ufoNew(ctlMemoryCallbacks *mem_cb, ctlStreamCallbacks *stm_cb, dnaINIT(h->dna, h->hints.hintMasks, 10, 10); dnaINIT(h->dna, h->hints.flexOpList, 10, 10); h->hints.hintMasks.func = initHintMask; - + newStrings(h); - + /* Open debug stream */ h->stm.dbg = h->cb.stm.open(&h->cb.stm, UFO_DBG_STREAM_ID, 0); - HANDLER + HANDLER /* Initialization failed */ ufoFree(h); h = NULL; END_HANDLER - return h; + return h; } static void prepClientData(ufoCtx h) { - h->top.sup.nGlyphs = h->chars.index.cnt; - if (h->stm.dbg == NULL) - abfCheckAllDicts(NULL, &h->top); + h->top.sup.nGlyphs = h->chars.index.cnt; + if (h->stm.dbg == NULL) + abfCheckAllDicts(NULL, &h->top); } /* ---------------------- Buffer handling ---------------------------- */ static void fillbuf(ufoCtx h, long offset) { - h->src.length = h->cb.stm.read(&h->cb.stm, h->stm.src, &h->src.buf); - if (h->src.length == 0) - h->flags |= SEEN_END; - h->src.offset = offset; - h->src.next = h->src.buf; - h->src.end = h->src.buf + h->src.length; + h->src.length = h->cb.stm.read(&h->cb.stm, h->stm.src, &h->src.buf); + if (h->src.length == 0) + h->flags |= SEEN_END; + h->src.offset = offset; + h->src.next = h->src.buf; + h->src.end = h->src.buf + h->src.length; } static int nextbuf(ufoCtx h) { - if ( h->flags & SEEN_END) - return 0; - - /* buffer read must be able to contain a full token */ - if ( h->mark && h->mark != h->src.buf) - { - size_t new_offset = h->src.offset + ( h->mark - h->src.buf ); - h->cb.stm.seek(&h->cb.stm, h->stm.src, new_offset); - fillbuf(h, new_offset); - - /* make sure we are still pointing at the beginning of token */ - h->mark = h->src.buf; + if ( h->flags & SEEN_END) + return 0; + + /* buffer read must be able to contain a full token */ + if ( h->mark && h->mark != h->src.buf) + { + size_t new_offset = h->src.offset + ( h->mark - h->src.buf ); + h->cb.stm.seek(&h->cb.stm, h->stm.src, new_offset); + fillbuf(h, new_offset); + + /* make sure we are still pointing at the beginning of token */ + h->mark = h->src.buf; } - if ( h->src.next == h->src.end ) + if ( h->src.next == h->src.end ) { - fillbuf(h, h->src.offset + h->src.length); + fillbuf(h, h->src.offset + h->src.length); } - - return ((h->flags & SEEN_END) == 0); + + return ((h->flags & SEEN_END) == 0); } static int bufferReady(ufoCtx h) { - if ( h->src.next == h->src.end ) - return nextbuf(h); - - return 1; + if ( h->src.next == h->src.end ) + return nextbuf(h); + + return 1; } static char* getBufferContextPtr(ufoCtx h) @@ -534,27 +527,27 @@ static char* getBufferContextPtr(ufoCtx h) if (strlen(p) > 128) p[128] = 0; return p; - + } static token* setToken(ufoCtx h) { - size_t len; - if ( h->src.buf == NULL || h->mark == NULL) - return NULL; - - len = h->src.next - h->mark; - if ((len+1) > kMaxToken) - return NULL; - - if (len >0) + size_t len; + if ( h->src.buf == NULL || h->mark == NULL) + return NULL; + + len = h->src.next - h->mark; + if ((len+1) > kMaxToken) + return NULL; + + if (len >0) memcpy(h->src.tk.val, h->mark, len); - h->src.tk.val[len] = 0; - h->src.tk.length = len; - h->src.tk.offset = h->src.offset + (h->mark - h->src.buf); - h->src.tk.type = ufoUnknown; - - return &h->src.tk; + h->src.tk.val[len] = 0; + h->src.tk.length = len; + h->src.tk.offset = h->src.offset + (h->mark - h->src.buf); + h->src.tk.type = ufoUnknown; + + return &h->src.tk; } /* Tokens are separated by whitespace and '"' @@ -562,58 +555,58 @@ static token* setToken(ufoCtx h) */ static token* getToken(ufoCtx h, int state) { - char ch; + char ch = 0; token* tk = NULL; - h->mark = NULL; - - while (bufferReady(h)) + h->mark = NULL; + + while (bufferReady(h)) { - ch = *h->src.next; - if ( ch == 0 ) + ch = *h->src.next; + if ( ch == 0 ) { - break; + break; } - if ( isspace(ch) || (ch == '"')) - h->src.next++; - else - break; + if ( isspace(ch) || (ch == '"')) + h->src.next++; + else + break; } - - while (bufferReady(h)) + + while (bufferReady(h)) { - if ( ch == 0 ) + if ( ch == 0 ) { - break; + break; } - else if ( h->mark == NULL ) + else if ( h->mark == NULL ) { - h->mark = h->src.next++; - if (( ch == 0 ) || (!bufferReady(h))) - break; - ch = *h->src.next; + h->mark = h->src.next++; + if (( ch == 0 ) || (!bufferReady(h))) + break; + ch = *h->src.next; if ((ch == '<') && (h->mark != h->src.next)) break; - while ( (!isspace(ch)) && ( ch != '"')) + while ( (!isspace(ch)) && ( ch != '"')) { - h->src.next++; - if (( ch == 0 ) || ( ch == '>' )|| (!bufferReady(h))) - break; - ch = *h->src.next; + h->src.next++; + if (( ch == 0 ) || ( ch == '>' )|| (!bufferReady(h))) + break; + ch = *h->src.next; if ((ch == '<') && (h->mark != h->src.next)) break; } - break; + break; } - else + else { - break; + break; } } - + // Back up and remove any final whitespace. while ((h->mark != NULL) && (h->src.next != h->mark ) && (isspace(*(h->src.next-1)))) h->src.next--; - + tk = setToken(h); if (tk == NULL) { @@ -622,32 +615,32 @@ static token* getToken(ufoCtx h, int state) fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph.%s.", getBufferContextPtr(h)); } } - + return tk; } /* return actual tokens, ignores comments, preserves white space */ static token* getAttribute(ufoCtx h, int state) { - char ch; + char ch = 0; token* tk = NULL; int lastWasQuote = 0; - h->mark = NULL; - - while (bufferReady(h)) + h->mark = NULL; + + while (bufferReady(h)) { - ch = *h->src.next; - if ( ch == 0 ) + ch = *h->src.next; + if ( ch == 0 ) { - break; + break; } - if ( isspace(ch)) - { + if ( isspace(ch)) + { lastWasQuote = 0; h->src.next++; } - else if (ch == '"') - { + else if (ch == '"') + { if (lastWasQuote) { ch = 0; /* we have an empty attribute */ @@ -660,40 +653,40 @@ static token* getAttribute(ufoCtx h, int state) lastWasQuote = 1; } } - else - break; + else + break; } - - while (bufferReady(h)) + + while (bufferReady(h)) { - if ( ch == 0 ) + if ( ch == 0 ) { - break; + break; } - else if ( h->mark == NULL ) + else if ( h->mark == NULL ) { - h->mark = h->src.next++; - if (( ch == 0 ) || (!bufferReady(h))) - break; - ch = *h->src.next; - while (!( ch == '"')) + h->mark = h->src.next++; + if (( ch == 0 ) || (!bufferReady(h))) + break; + ch = *h->src.next; + while (!( ch == '"')) { - h->src.next++; - if (( ch == 0 ) || (!bufferReady(h))) - break; - ch = *h->src.next; + h->src.next++; + if (( ch == 0 ) || (!bufferReady(h))) + break; + ch = *h->src.next; } - break; + break; } - else + else { - break; + break; } } // Back up and remove any final whitespace. while ((h->mark != NULL) && (h->src.next != h->mark ) && (isspace(*(h->src.next-1)))) h->src.next--; - + tk = setToken(h); if (tk == NULL) { @@ -702,60 +695,60 @@ static token* getAttribute(ufoCtx h, int state) fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph.%s.", getBufferContextPtr(h)); } } - + return tk; } /* return value between begin/end element, skipping white space before and after. */ static token* getElementValue(ufoCtx h, int state) { - char ch; + char ch; token* tk = NULL; - h->mark = NULL; - - while (bufferReady(h)) + h->mark = NULL; + + while (bufferReady(h)) { - ch = *h->src.next; - if ( ch == 0 ) + ch = *h->src.next; + if ( ch == 0 ) { - break; + break; } - if (ch == '"') - h->src.next++; - else - break; + if (ch == '"') + h->src.next++; + else + break; } - - while (bufferReady(h)) + + while (bufferReady(h)) { - if ( ch == 0 ) + if ( ch == 0 ) { - break; + break; } - else if ( h->mark == NULL ) + else if ( h->mark == NULL ) { - h->mark = h->src.next++; - if (( ch == 0 ) || (!bufferReady(h))) - break; - ch = *h->src.next; - while (ch != '<') + h->mark = h->src.next++; + if (( ch == 0 ) || (!bufferReady(h))) + break; + ch = *h->src.next; + while (ch != '<') { - h->src.next++; - if (( ch == 0 ) || (!bufferReady(h))) - break; - ch = *h->src.next; + h->src.next++; + if (( ch == 0 ) || (!bufferReady(h))) + break; + ch = *h->src.next; } - break; + break; } - else + else { - break; + break; } } // Back up and remove any final whitespace. while ((h->mark != NULL) && (h->src.next != h->mark ) && (isspace(*(h->src.next-1)))) h->src.next--; - + tk = setToken(h); if (tk == NULL) { @@ -764,143 +757,8 @@ static token* getElementValue(ufoCtx h, int state) fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph.%s.",getBufferContextPtr(h)); } } - - return tk; -} - -static long getPathLength(ufoCtx h) -{ - char ch; - int startOffset = h->src.offset + (h->src.next - h->src.buf); - int endOffset; - while (bufferReady(h)) - { - ch = *h->src.next; - if ( ch == 0 ) - { - break; - } - if ( isspace(ch) || (ch == ',') || (ch == '"')) - h->src.next++; - else if (( ch == '%' ) || ( ch == '#' )) - { - ch = *h->src.next++; - if (!bufferReady(h)) - break; - while ( !(ch == '\n' || ch == '\r' || ch == '\f') ) - { - ch = *h->src.next++; - if (!bufferReady(h)) - break; - } - } - else if (ch == '/' || ch == '"' ) - break; - else - ch = *h->src.next++; - } - endOffset = h->src.offset + (h->src.next - h->src.buf); - return endOffset - startOffset; -} - - -static token* setPathToken(ufoCtx h, int tokenType) -{ - size_t len; - if ( h->src.buf == NULL || h->mark == NULL) - return NULL; - - len = h->src.next - h->mark; - if ((len+1) > kMaxToken) - return NULL; - - memcpy(h->src.tk.val, h->mark, len); - h->src.tk.val[len] = 0; - h->src.tk.length = len; - h->src.tk.offset = h->src.offset + (h->mark - h->src.buf); - h->src.tk.type = tokenType; - return &h->src.tk; -} - -/* return actual tokens, ignores comments as well */ -static token* getPathToken(ufoCtx h, long endOffset) -{ - char ch; - int tokenType = ufoUnknown; - h->mark = NULL; - - if (endOffset == 0) /* A non-marking glyph. */ - return NULL; - - while (bufferReady(h)) - { - ch = *h->src.next; - if ( ch == 0 ) - { - return NULL; - } - if ( isspace(ch) || (ch == ',') || (ch == '"')) - h->src.next++; - else - break; - } - - if ( (h->src.offset + (h->src.next - h->src.buf)) >=endOffset) - return NULL; - - h->mark = h->src.next; - /* If we reload the buffer while processing the token, h->mark is outdated. Make sure that we have - enough text to be able to deal with the entire token. */ - if ((h->src.end - h->src.next) < kMaxToken) - { - nextbuf(h); /* refills the buffer with h->mark as the first glyph, and resets h->mark to point to the start of the buffer. */ - } - - ch = *h->src.next; - if ( ch == 0 ) - { - return NULL; - } - else - { - if (isdigit(ch) || (ch == '-') || (ch == '.')) /* Possible chars for start of numeric coordinate */ - { - tokenType = ufoNumeric; - h->src.next++; /* This is safe, since we have at least kMaxToken bytes at this point.*/ - while (1) - { - ch = *h->src.next; - if ( ch == 0 ) - break; - else if (isdigit(ch) || (ch == '.')) - { - h->src.next++; - if (h->src.next >= h->src.end) - return NULL; - } - else - break; - } - } - else if (isalpha(ch)) - { - /* The non-digit, no whitespace values are assumed to be single-letter oparators */ - tokenType = ufoOperator; - h->src.next++; - } - else /* Found something other than digit or alphabetic.*/ - { - h->src.next++; - } - } - return setPathToken(h, tokenType); -} -static void copyToken(token *src, token* dst) -{ - *dst = *src; - memcpy(dst->val, src->val, src->length); - src->val[src->length] = 0; + return tk; } #if _WIN32 @@ -912,15 +770,15 @@ static int round_int( double r ) /* Construct matrix from args. */ static void setTransformMtx(Transform* transform, - float a, float b, float c, float d, float tx, float ty, int isDefault, int isOffsetOnly) + float a, float b, float c, float d, float tx, float ty, int isDefault, int isOffsetOnly) { float* val = transform->mtx; - val[0] = a; - val[1] = b; - val[2] = c; - val[3] = d; - val[4] = tx; - val[5] = ty; + val[0] = a; + val[1] = b; + val[2] = c; + val[3] = d; + val[4] = tx; + val[5] = ty; transform->isDefault = isDefault; transform->isOffsetOnly = isOffsetOnly; } @@ -928,12 +786,12 @@ static void setTransformMtx(Transform* transform, /* Multiple matices a and b giving result. */ static void matMult(float *result, float * a, float * b) { - result[0] = a[0]*b[0] + a[1]*b[2]; - result[1] = a[0]*b[1] + a[1]*b[3]; - result[2] = a[2]*b[0] + a[3]*b[2]; - result[3] = a[2]*b[1] + a[3]*b[3]; - result[4] = a[4]*b[0] + a[5]*b[2] + b[4]; - result[5] = a[4]*b[1] + a[5]*b[3] + b[5]; + result[0] = a[0]*b[0] + a[1]*b[2]; + result[1] = a[0]*b[1] + a[1]*b[3]; + result[2] = a[2]*b[0] + a[3]*b[2]; + result[3] = a[2]*b[1] + a[3]*b[3]; + result[4] = a[4]*b[0] + a[5]*b[2] + b[4]; + result[5] = a[4]*b[1] + a[5]*b[3] + b[5]; } static void setTransformValue(Transform* transform, float val, int valIndex) @@ -953,7 +811,7 @@ static void setTransformValue(Transform* transform, float val, int valIndex) if ((valIndex == 1) || (valIndex == 2)) transform->isOffsetOnly = 0; } - + } /* -------------------------- Parsing routines ------------------------ */ @@ -971,21 +829,16 @@ do if(h->stack.cnt+(n)>UFO_MAX_OP_STACK)fatal(h,ufoErrStackOverflow,"");while(0) #define POP() (h->stack.array[--h->stack.cnt]) #define PUSH(v) (h->stack.array[h->stack.cnt++]=(float)(v)) -static void EnsureState(ufoCtx h, int flags) -{ - if (!(h->stack.flags & flags)) - fatal(h, ufoErrParse, "Invalid token"); -} /* hints */ static void doOp_mt(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) { - float dy, dx; + float dy, dx; OpRec* opRec; - CHKUFLOW(2); - dy = POP(); - dx = POP(); - + CHKUFLOW(2); + dy = POP(); + dx = POP(); + opRec = dnaNEXT(h->data.opList); opRec->opType = movetoType; opRec->coords[0] = dx; @@ -993,20 +846,20 @@ static void doOp_mt(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) opRec->pointName = pointName; /* pointName may or may not be NULL */ h->stack.flags |= PARSE_SEEN_MOVETO; //printf("moveto %f %f. opIndex: %ld \n", dx, dy, h->data.opList.cnt-1); - h->metrics.cb.move(&h->metrics.cb, dx, dy); - + h->metrics.cb.move(&h->metrics.cb, dx, dy); + } static void doOp_dt(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) { - float dy, dx; + float dy, dx; OpRec* opRec; - CHKUFLOW(2); - - dy = POP(); - dx = POP(); - + CHKUFLOW(2); + + dy = POP(); + dx = POP(); + opRec = dnaNEXT(h->data.opList); opRec->opType = linetoType; opRec->coords[0] = dx; @@ -1022,12 +875,12 @@ static void doOp_dt(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) { h->metrics.cb.line(&h->metrics.cb, dx, dy); } - + } static void doOp_ct(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) { - float dy3, dx3, dy2, dx2, dy1, dx1; + float dy3, dx3, dy2, dx2, dy1, dx1; OpRec* opRec; opRec = dnaNEXT(h->data.opList); @@ -1050,14 +903,14 @@ static void doOp_ct(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) else { CHKUFLOW(6); - + dy3 = POP(); dx3 = POP(); dy2 = POP(); dx2 = POP(); dy1 = POP(); dx1 = POP(); - + opRec->coords[0] = dx1; opRec->coords[1] = dy1; opRec->coords[2] = dx2; @@ -1065,71 +918,59 @@ static void doOp_ct(ufoCtx h, abfGlyphCallbacks *glyph_cb, char * pointName) opRec->coords[4] = dx3; opRec->coords[5] = dy3; //printf("curveo %f %f. opIndex: %ld \n", dx3, dy3, h->data.opList.cnt-1); - + h->metrics.cb.curve(&h->metrics.cb, dx1, dy1, dx2, dy2, dx3, dy3); } - + } static void doOp_ed(ufoCtx h, abfGlyphCallbacks *glyph_cb) { - abfMetricsCtx g = &h->metrics.ctx; - - /* get the bounding box and compute the aggregate */ - if (h->aggregatebounds.left > g->real_mtx.left) - h->aggregatebounds.left = g->real_mtx.left; - if (h->aggregatebounds.bottom > g->real_mtx.bottom) - h->aggregatebounds.bottom = g->real_mtx.bottom; - if (h->aggregatebounds.right < g->real_mtx.right) - h->aggregatebounds.right = g->real_mtx.right; - if (h->aggregatebounds.top < g->real_mtx.top) - h->aggregatebounds.top = g->real_mtx.top; - + abfMetricsCtx g = &h->metrics.ctx; + + /* get the bounding box and compute the aggregate */ + if (h->aggregatebounds.left > g->real_mtx.left) + h->aggregatebounds.left = g->real_mtx.left; + if (h->aggregatebounds.bottom > g->real_mtx.bottom) + h->aggregatebounds.bottom = g->real_mtx.bottom; + if (h->aggregatebounds.right < g->real_mtx.right) + h->aggregatebounds.right = g->real_mtx.right; + if (h->aggregatebounds.top < g->real_mtx.top) + h->aggregatebounds.top = g->real_mtx.top; + glyph_cb->end(glyph_cb); /* I call glyph_cb->end directly, unlike the path operators, as the opList has already been played back. */ } static int tkncmp(token* tk, char* str) { size_t len = strlen(str); - int retVal; - if (len != tk->length) - retVal = 1; - else - retVal = strncmp(tk->val, str, tk->length); - return retVal; + int retVal = 1; + if ((tk != NULL) && (len == tk->length)) + retVal = strncmp(tk->val, str, tk->length); + return retVal; } static int tokenEqualStr(token* tk, char* str) { - return tkncmp(tk, str) == 0; + return tkncmp(tk, str) == 0; } static int tokenEqualStrN(token* tk, char* str, int n) { - return 0 == strncmp(tk->val, str, n); + return 0 == strncmp(tk->val, str, n); } static int isUnknownAttribute(token* tk) { - return tk->val[tk->length-1] == '='; -} - -static int matchOps(const void *l, const void *r) -{ - int retval; - token* tk = (token*)l; - char * c = (char*)r; - if ( tk->length != 1) - return -1; - - retval = strncmp( tk->val,c, 1); - return retval; + if (tk == NULL) + return true; + else + return tk->val[tk->length-1] == '='; } - /* --------------------- Glyph Processing ----------------------- */ static char* copyStr(ufoCtx h, char* oldString) { @@ -1143,7 +984,7 @@ static char* getKeyValue(ufoCtx h, char* endName, int state) { char *value = NULL; token* tk; - + tk = getElementValue(h, state); if (!tokenEqualStr(tk, endName)) { @@ -1156,7 +997,7 @@ static char* getKeyValue(ufoCtx h, char* endName, int state) fatal(h,ufoErrParse, "Encountered element '%s' when reading value for element '%s'.", tk->val, endName); } return value; - + } static void setBluesArrayValue(ufoCtx h, BluesArray* bluesArray, int numElements) @@ -1179,24 +1020,30 @@ static void setFontDictKey(ufoCtx h, char * keyValue) abfFontDict* fd0 = &h->top.FDArray.array[0]; abfPrivateDict* pd = &fd0->Private; BluesArray* bluesArray; - + /* If we do not use a keyValue, we need to dispose of it */ - if (!strcmp(keyName, "copyright")) + if (!strcmp(keyName, "copyright")) { top->Copyright.ptr = keyValue; } else if (!strcmp(keyName, "trademark")) { char * copySymbol; - top->Notice.ptr = keyValue; - copySymbol = strstr(keyValue, "\u00A9"); + top->Notice.ptr = keyValue; + /* look for the (c) symbol U+00A9, which is 0xC2, 0xA9 in UTF-8 */ + copySymbol = strstr(keyValue, "\xC2\xA9"); if (copySymbol != NULL) { + /* if there is a copyright symbol (U+00A9), + replace it with the word "Copyright" */ char* cpy = "Copyright"; char* newString = memNew(h, strlen(cpy) + strlen(keyValue) + 2); - copySymbol = '\0'; - sprintf(newString, "%s%s%s", keyValue, "Copyright", copySymbol + 5); + /* set the 0xC2 to NULL to terminate the left side of the string */ + *copySymbol = '\0'; + /* use copySymbol + 2 to skip the NULL and the 0xA9 + to get the right side of the string */ + sprintf(newString, "%s%s%s", keyValue, "Copyright", copySymbol + 2); top->Notice.ptr = newString; } } @@ -1297,7 +1144,7 @@ static void setFontDictKey(ufoCtx h, char * keyValue) { pd->ForceBold = atol(keyValue); } - + else if (!strcmp(keyName, "postscriptBlueValues")) { bluesArray = (BluesArray*)&pd->BlueValues; @@ -1338,13 +1185,13 @@ static void setFontDictKey(ufoCtx h, char * keyValue) bluesArray = (BluesArray*)&pd->StemSnapV; setBluesArrayValue(h, bluesArray, 12); } - + else { // if it isn't used, free the string. memFree(h, keyValue); } - + } @@ -1360,7 +1207,7 @@ static int doFontDictValue(ufoCtx h, char* keyName, char* endKeyName, int state) /* It is valid and common for styleName can be present and empty, when the style is "Regular".*/ } } - + if (state == 2) // we are processing a key value. { @@ -1384,7 +1231,6 @@ static int doFontDictValue(ufoCtx h, char* keyName, char* endKeyName, int state) static int CTL_CDECL cmpOrderRecs(const void *first, const void *second, void *ctx) { - ufoCtx h = ctx; GlIFOrderRec* orderRec1= (GlIFOrderRec *)first; GlIFOrderRec* orderRec2= (GlIFOrderRec *)second; int retVal = 0; @@ -1394,7 +1240,6 @@ static int CTL_CDECL cmpOrderRecs(const void *first, const void *second, void *c static int CTL_CDECL cmpGlifRecs(const void *first, const void *second, void *ctx) { - ufoCtx h = ctx; GLIF_Rec* glifRec1= (GLIF_Rec *)first; GLIF_Rec* glifRec2= (GLIF_Rec *)second; int retVal = 0; @@ -1412,7 +1257,7 @@ static int CTL_CDECL cmpGlifRecs(const void *first, const void *second, void *ct } else if (glifRec2->glyphOrder == ABF_UNSET_INT) { - + } else { if (glifRec1->glyphOrder > glifRec2->glyphOrder) @@ -1426,40 +1271,37 @@ static int CTL_CDECL cmpGlifRecs(const void *first, const void *second, void *ct static int matchGLIFOrderRec(const void *key, const void *value, void *ctx) { - ufoCtx h = ctx; GlIFOrderRec* orderRec= (GlIFOrderRec *)value; return strcmp((char *)key, orderRec->glyphName); } -static int getGlyphOrderIndex(ufoCtx h, char * glyphName) +static long getGlyphOrderIndex(ufoCtx h, char * glyphName) { - int orderIndex = ABF_UNSET_INT; + long orderIndex = ABF_UNSET_INT; int recIndex = 0; - - if (ctuLookup(glyphName, h->data.glifOrder.array, h->data.glifOrder.cnt, - sizeof(h->data.glifOrder.array[0]), matchGLIFOrderRec, (size_t*)&recIndex, h)) - { + + if (ctuLookup(glyphName, h->data.glifOrder.array, h->data.glifOrder.cnt, + sizeof(h->data.glifOrder.array[0]), matchGLIFOrderRec, (size_t*)&recIndex, h)) + { orderIndex = h->data.glifOrder.array[recIndex].order; } else { message(h, "Warning: glyph order does not contain glyph name '%s'.", glyphName); } - + return orderIndex; } static void addGLIFRec(ufoCtx h, int state) { - char* fileName; + char* fileName; GLIF_Rec* newGLIFRec; long int glyphOrder; - int k; glyphOrder = getGlyphOrderIndex(h, h->parseKeyName); newGLIFRec = dnaNEXT(h->data.glifRecs); - k = h->data.glifRecs.cnt-1; newGLIFRec->glyphName = h->parseKeyName; newGLIFRec->glyphOrder = glyphOrder; fileName = getKeyValue(h, "", state); @@ -1482,50 +1324,50 @@ static int parseGlyphOrder(ufoCtx h) int prevState = 0; token* tk; h->src.next = h->mark = NULL; - + h->cb.stm.clientFileName = "lib.plist"; - h->stm.src = h->cb.stm.open(&h->cb.stm, UFO_SRC_STREAM_ID, 0); - if (h->stm.src == NULL || h->cb.stm.seek(&h->cb.stm, h->stm.src, 0)) + h->stm.src = h->cb.stm.open(&h->cb.stm, UFO_SRC_STREAM_ID, 0); + if (h->stm.src == NULL || h->cb.stm.seek(&h->cb.stm, h->stm.src, 0)) { fprintf(stderr, "Failed to read lib.plist\n"); - return ufoErrSrcStream; + return ufoErrSrcStream; } - + dnaSET_CNT(h->valueArray,0); - fillbuf(h, 0); + fillbuf(h, 0); /* Read in file, then sort by glyph name */ - while (!(seenGO || (h->flags & SEEN_END))) + while (!(seenGO || (h->flags & SEEN_END))) { - tk = getToken(h, state); - + tk = getToken(h, state); + if (tk == NULL) break; - - if (tokenEqualStr(tk, "")) + + if (tokenEqualStr(tk, "")) { - continue; + if (state != IN_COMMENT) + fatal(h,ufoErrParse, "Encountered end comment token while not in comment."); + state = prevState; + } + else if (state == IN_COMMENT) + { + continue; } - else if (tokenEqualStrN(tk, "")) + else if (tokenEqualStr(tk, "")) { state--; } - else if (tokenEqualStrN(tk, "val[tk->length-2] == '/') && (tk->val[tk->length-1] == '>')) { @@ -1566,21 +1408,19 @@ static int parseGlyphOrder(ufoCtx h) } else if ((tokenEqualStr(tk, "")) && (state == IN_PUBLIC_ORDER)) { - state = prevState; - seenGO = 1; break; } else if ((tokenEqualStrN(tk, "val[tk->length-2] == '/') && (tk->val[tk->length-1] == '>')) { message(h, "Warning: Encountered empty in public.glyphOrder. Text: '%s'.", getBufferContextPtr(h)); } else { - + tk = getElementValue(h, state); if (tokenEqualStr(tk, "")) { @@ -1600,16 +1440,16 @@ static int parseGlyphOrder(ufoCtx h) } } } - + } /* end while more tokens */ - + if (h->data.glifOrder.cnt > 0) { /* Sort the array by glyph name. */ - - ctuQSort(h->data.glifOrder.array, h->data.glifOrder.cnt, - sizeof(h->data.glifOrder.array[0]), cmpOrderRecs, h); - + + ctuQSort(h->data.glifOrder.array, h->data.glifOrder.cnt, + sizeof(h->data.glifOrder.array[0]), cmpOrderRecs, h); + /* weed out duplicates - these casue sorting to work differently depending on whether we approach the pair from the top or bottom. */ { @@ -1627,11 +1467,11 @@ static int parseGlyphOrder(ufoCtx h) } } } - + h->cb.stm.close(&h->cb.stm, h->stm.src); h->stm.src = NULL; - - return ufoSuccess; + + return ufoSuccess; } static int parseGlyphList(ufoCtx h) @@ -1640,56 +1480,55 @@ static int parseGlyphList(ufoCtx h) int prevState = 0; token* tk; h->src.next = h->mark = NULL; - + h->cb.stm.clientFileName = "glyphs/contents.plist"; - h->stm.src = h->cb.stm.open(&h->cb.stm, UFO_SRC_STREAM_ID, 0); - if (h->stm.src == NULL || h->cb.stm.seek(&h->cb.stm, h->stm.src, 0)) + h->stm.src = h->cb.stm.open(&h->cb.stm, UFO_SRC_STREAM_ID, 0); + if (h->stm.src == NULL || h->cb.stm.seek(&h->cb.stm, h->stm.src, 0)) { fprintf(stderr, "Failed to read glyphs/contents.plist\n"); - return ufoErrSrcStream; + return ufoErrSrcStream; } - + dnaSET_CNT(h->valueArray,0); - fillbuf(h, 0); - - h->metrics.defaultWidth = 0; - h->flags &= ~SEEN_END; - - while (!(h->flags & SEEN_END)) - { - tk = getToken(h, state); - - if (tokenEqualStr(tk, "")) - { - if (state != 4) - fatal(h,ufoErrParse, "Encountered end comment token while not in comment."); - state = prevState; - } - else if (state == 4) - { - continue; - } - else if (tokenEqualStr(tk, "")) - { - if (state > 0) - fatal(h,ufoErrParse, "Encountered second metrics.defaultWidth = 0; + h->flags &= ~SEEN_END; + + while (!(h->flags & SEEN_END)) + { + tk = getToken(h, state); + + if (tokenEqualStr(tk, "")) + { + if (state != 4) + fatal(h,ufoErrParse, "Encountered end comment token while not in comment."); + state = prevState; + } + else if (state == 4) + { + continue; + } + else if (tokenEqualStr(tk, "")) + { + if (state > 0) + fatal(h,ufoErrParse, "Encountered second ")) + else if (tokenEqualStr(tk, "")) { - state = 0; h->flags |= SEEN_END; break; // end processing at end of first dict. } - else if (tokenEqualStr(tk, "")) + else if (tokenEqualStr(tk, "")) { - if (state != 1) - fatal(h,ufoErrParse, "Encountered while not in top level of first "); + if (state != 1) + fatal(h,ufoErrParse, "Encountered while not in top level of first "); // get key name tk = getElementValue(h, state); if (tokenEqualStr(tk, "")) @@ -1714,7 +1553,7 @@ static int parseGlyphList(ufoCtx h) addGLIFRec(h, state); state = 1; } - else if (state != 0) + else if (state != 0) { message(h, "Warning: discarding token '%s", tk->val); } @@ -1723,14 +1562,14 @@ static int parseGlyphList(ufoCtx h) if (h->data.glifRecs.cnt > 0) // If we have seen the glifs, then we are done with any additional parsing break; } - + } /* end while more tokens */ - + if (h->data.glifOrder.cnt > 0) { - ctuQSort(h->data.glifRecs.array, h->data.glifRecs.cnt, - sizeof(h->data.glifRecs.array[0]), cmpGlifRecs, h); - + ctuQSort(h->data.glifRecs.array, h->data.glifRecs.cnt, + sizeof(h->data.glifRecs.array[0]), cmpGlifRecs, h); + } if (h->data.glifRecs.cnt > 0) { @@ -1742,11 +1581,11 @@ static int parseGlyphList(ufoCtx h) addString(h, strlen(glifRec->glyphName), glifRec->glyphName); } } - + h->cb.stm.close(&h->cb.stm, h->stm.src); h->stm.src = NULL; - - return ufoSuccess; + + return ufoSuccess; } static int preParseGLIF(ufoCtx h, GLIF_Rec* newGLIFRec, int tag); @@ -1755,7 +1594,7 @@ static int preParseGLIFS(ufoCtx h) { int tag = 0; int retVal = ufoSuccess; - + h->metrics.defaultWidth = 0; while (tag < h->data.glifRecs.cnt) { @@ -1776,17 +1615,17 @@ static void addCharFromGLIF(ufoCtx h, int tag, char* glyphName, long char_begin, if (addChar(h, tag, &chr)) { - + message(h, "Warning: duplicate charstring <%s> (discarded)", getString(h, tag)); } else { - chr->flags = 0; - chr->tag = tag; - chr->gname.ptr = glyphName; - chr->gname.impl = tag; - chr->iFD = 0; + chr->flags = 0; + chr->tag = tag; + chr->gname.ptr = glyphName; + chr->gname.impl = tag; + chr->iFD = 0; if (unicode != ABF_GLYPH_UNENC) { chr->flags |= ABF_GLYPH_UNICODE; @@ -1802,9 +1641,9 @@ static void addCharFromGLIF(ufoCtx h, int tag, char* glyphName, long char_begin, chr->sup.begin = char_begin; chr->sup.end = char_end; //chr->width = width; - + } - + } static int preParseGLIF(ufoCtx h, GLIF_Rec* glifRec, int tag) @@ -1813,16 +1652,15 @@ static int preParseGLIF(ufoCtx h, GLIF_Rec* glifRec, int tag) int state = 0; /* 0 == start, 1= seen start of glyph, 4 in comment. */ int prevState = 0; long i; - long char_begin; - long char_end; - long defaultWidth = 1000; + long char_begin = 0; + long char_end = 0; long glyphWidth; unsigned long unicode = ABF_GLYPH_UNENC; char tempVal[kMaxName]; char tempName[kMaxName]; token* tk; h->src.next = h->mark = NULL; - + h->flags &= ~((unsigned long)SEEN_END); /* First, try the alt layer directory */ @@ -1837,7 +1675,7 @@ static int preParseGLIF(ufoCtx h, GLIF_Rec* glifRec, int tag) memFree(h, glifRec->glifFilePath); glifRec->glifFilePath = memNew(h, 2 + strlen(h->defaultLayerDir) + strlen(glifRec->glifFileName)); sprintf(glifRec->glifFilePath, "%s/%s", h->defaultLayerDir, glifRec->glifFileName); - + h->cb.stm.clientFileName = glifRec->glifFilePath; h->stm.src = h->cb.stm.open(&h->cb.stm, UFO_SRC_STREAM_ID, 0); } @@ -1853,8 +1691,8 @@ static int preParseGLIF(ufoCtx h, GLIF_Rec* glifRec, int tag) } fillbuf(h, 0); - - h->flags &= ~SEEN_END; + + h->flags &= ~SEEN_END; while (!(h->flags & SEEN_END)) { tk = getToken(h, state); @@ -1868,7 +1706,7 @@ static int preParseGLIF(ufoCtx h, GLIF_Rec* glifRec, int tag) else break; } - + if (tokenEqualStr(tk, "")) + + while (!(h->flags & SEEN_END)) + { + tk = getToken(h, state); + + if (tokenEqualStr(tk, "")) { if (state != 4) { @@ -2130,29 +1961,28 @@ static int parseFontInfo(ufoCtx h) } state = prevState; } - else if (state == 4) + else if (state == 4) { - continue; + continue; } - else if (tokenEqualStr(tk, "")) + else if (tokenEqualStr(tk, "")) { - if (state > 0) + if (state > 0) { skipToDictEnd(h); } else state = 1; } - else if (tokenEqualStr(tk, "")) + else if (tokenEqualStr(tk, "")) { - seenDict = 1; break; } - else if (state > 4) + else if (state > 4) continue; - else if (tokenEqualStr(tk, "")) + else if (tokenEqualStr(tk, "")) { - if (state != 1) + if (state != 1) { fatal(h,ufoErrParse, "Encountered '' while not in top level of first , in fontinfo.plist file. Context: '%s'.\n", getBufferContextPtr(h)); } @@ -2185,7 +2015,7 @@ static int parseFontInfo(ufoCtx h) state = 3; dnaSET_CNT(h->valueArray, 0); } - else if (tokenEqualStr(tk, "")) + else if (tokenEqualStr(tk, "")) { if (state != 3) { @@ -2227,7 +2057,7 @@ static int parseFontInfo(ufoCtx h) setFontDictKey(h, "1"); state--; } - else if (state != 0) + else if (state != 0) { tk->val[tk->length -1] = 0; message(h, "Warning: discarding token '%s', in fontinfo.plist file. Context: '%s'.", tk->val, getBufferContextPtr(h)); @@ -2235,36 +2065,35 @@ static int parseFontInfo(ufoCtx h) state = 1; else if (state == 3) state = 2; - + } else { if (seenDict) // If we have seen the , then we are done with any additional parsing break; } - + } /* end while more tokens */ - + /* Currently, proscriptStdHW and postscriptStdVW have to be hand-edited in. If they haven't been provided, use the first value of the stemsnap entries. */ fixUnsetDictValues(h); - + h->cb.stm.close(&h->cb.stm, h->stm.src); h->stm.src = NULL; - return ufoSuccess; + return ufoSuccess; } static int parseUFO(ufoCtx h) { - /* This does a first pass through the font, loading the glyph name/ID and the path to each glyph file. + /* This does a first pass through the font, loading the glyph name/ID and the path to each glyph file. Open the UFO fontinfo.plist, and extract the PS infop Open the glyphs/contents.plist file, and extract any glyphs that are not in the glyphs.ac/contents.plist file */ - int dummy; int retVal = parseFontInfo(h); if (retVal == ufoSuccess) - dummy = parseGlyphOrder(h); + retVal = parseGlyphOrder(h); /* return value was being ignored prior to 15 June 2018, not sure why -- CJC */ if (retVal == ufoSuccess) retVal = parseGlyphList(h); if (retVal == ufoSuccess) @@ -2281,9 +2110,9 @@ static int parsePoint(ufoCtx h, abfGlyphCallbacks *glyph_cb, GLIF_Rec* glifRec, int type = 0; char * end; char * pointName = NULL; - int prevState; + int prevState = outlineStart; int result = ufoSuccess; - + while (1) { tk = getToken(h, state); @@ -2291,7 +2120,7 @@ static int parsePoint(ufoCtx h, abfGlyphCallbacks *glyph_cb, GLIF_Rec* glifRec, { fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph.%s. Context: %s\n", glifRec->glifFilePath, getBufferContextPtr(h)); } - + else if (tokenEqualStr(tk, "")) - { + { if (state != outlineInComment) { fatal(h,ufoErrParse, "Encountered end comment token while not in comment. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); } state = prevState; - } + } else if (state == outlineInComment) - { + { continue; - } + } else if (tokenEqualStrN(tk, " token unexpectedly. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); @@ -4013,15 +3831,15 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr tk = getToken(h, state); while (tk->val[tk->length-1] != '>') tk = getToken(h, state); - + // advance to end token } contourStartOpIndex = h->data.opList.cnt; // This will be the index of the first op in the new contour. h->stack.flags |= PARSE_PATH; h->stack.flags &= ~((unsigned long)PARSE_SEEN_MOVETO); - } + } else if (tokenEqualStr(tk, "")) - { + { if (state != outlineInContour) { fatal(h,ufoErrParse, "Encountered token unexpectedly. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); @@ -4033,7 +3851,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr OpRec* firstOpRec = &h->data.opList.array[contourStartOpIndex]; /* Now we need to fix up the OpList. In GLIF, there is usually no explicit start point, as the format expresses the path segments as a complete closed path, with no explicit start point. - + I use the first path operator end point as the start point, and convert this first operator to move-to. If the first path operator was a line-to, then I do not add it to the end of the op-list, as it should become an implicit rather than explicit close path. If it is a curve, then I need to add it to the oplist as the final path segment. */ @@ -4054,20 +3872,20 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr PUSH(firstOpRec->coords[0]); PUSH(firstOpRec->coords[1]); doOp_ct(h, glyph_cb, h->hints.pointName); /* adds a new curve opRec to the op list, using the point name (if any) of the first point of the curve. */ - + /* doOp_ct can resize the opList array, invalidating the firstOpRec pointer */ firstOpRec = &h->data.opList.array[contourStartOpIndex]; firstOpRec->opType = movetoType; - + h->hints.pointName = NULL; } - + } h->stack.flags &= ~((unsigned long)(PARSE_PATH | PARSE_SEEN_MOVETO)); - } + } else if (tokenEqualStr(tk, "glyphName, getBufferContextPtr(h)); @@ -4077,9 +3895,9 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr state = outlineInContour; if (ufoSuccess != result) break; - } + } else if (tokenEqualStr(tk, "glyphName, getBufferContextPtr(h)); @@ -4089,7 +3907,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr state = outlineStart; if (ufoSuccess != result) break; - } + } else if (tokenEqualStr(tk, "")) { if (state == outlineStart) @@ -4134,7 +3952,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); h->stack.flags = PARSE_END; } - + if (0 == strcmp(valueString, t1HintKeyV1)) { tk = getToken(h, state); @@ -4143,7 +3961,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph when parsing t1 hint key. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); h->stack.flags = PARSE_END; } - + if (tokenEqualStr(tk, "")) { parseType1HintDataV1(h, glifRec, transform); @@ -4157,7 +3975,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr fatal(h,ufoErrParse, "Encountered end of buffer before end of glyph when parsing t1 hint key. Glyph: %s. Context: %s\n.", glifRec->glyphName, getBufferContextPtr(h)); h->stack.flags = PARSE_END; } - + if (tokenEqualStr(tk, "")) { parseType1HintDataV2(h, glifRec, transform); @@ -4168,7 +3986,7 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr /* We just saw a data<\key> for a third party . We want to skip tokens until we see the end of the data. */ skipData(h, glifRec); } - + } } else if (tokenEqualStr(tk, "")) @@ -4189,13 +4007,13 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr if ((state != outlineInLib) && (state != outlineInLibDict)) printf("parseGlyphOutline: unhandled token: %s. Glyph: %s. Context: %s.\n", tk->val, glifRec->glyphName, getBufferContextPtr(h)); } - - - + + + } } while (!(h->stack.flags & PARSE_END)); - + /* An odd exit - didn't see "" */ h->cb.stm.close(&h->cb.stm, h->stm.src); return result; @@ -4204,24 +4022,24 @@ static int parseGLIF(ufoCtx h, abfGlyphInfo* gi, abfGlyphCallbacks *glyph_cb, Tr static int readGlyph(ufoCtx h, unsigned short tag, abfGlyphCallbacks *glyph_cb) { - int result; - token op_tk; - abfGlyphInfo* gi; - long width; + int result; + token op_tk; + abfGlyphInfo* gi; + long width; int i; - - op_tk.type = ufoNotSet; - - gi = &h->chars.index.array[tag]; - - /* note that gname.ptr is not stable: it is a pointer into the h->string->buf array, which moves when it gets resized. */ - gi->gname.ptr = getString(h, (STI)gi->tag); - result = glyph_cb->beg(glyph_cb, gi); - gi->flags |= ABF_GLYPH_SEEN; - - - /* Check result */ - switch (result) + + op_tk.type = ufoNotSet; + + gi = &h->chars.index.array[tag]; + + /* note that gname.ptr is not stable: it is a pointer into the h->string->buf array, which moves when it gets resized. */ + gi->gname.ptr = getString(h, (STI)gi->tag); + result = glyph_cb->beg(glyph_cb, gi); + gi->flags |= ABF_GLYPH_SEEN; + + + /* Check result */ + switch (result) { case ABF_SKIP_RET: return ufoSuccess; @@ -4230,36 +4048,36 @@ static int readGlyph(ufoCtx h, unsigned short tag, abfGlyphCallbacks *glyph_cb) case ABF_FAIL_RET: fatal(h, ufoErrParseFail, NULL); } - result = h->metrics.cb.beg(&h->metrics.cb, &h->metrics.gi); + result = h->metrics.cb.beg(&h->metrics.cb, &h->metrics.gi); width = getWidth(h, (STI)gi->tag); glyph_cb->width(glyph_cb, (float)width ); if (result == ABF_WIDTH_RET) return ufoSuccess; - + parseGLIF(h, gi, glyph_cb, NULL); doOpList(h, gi, glyph_cb); h->stm.src = NULL; doOp_ed(h, glyph_cb); // we do this outside of parseGLIFOutline so that we can use parseGLIFOutline to process component glyphs. /* set the FontBBox field in the abfTopDict */ - h->top.FontBBox[0] = h->aggregatebounds.left; - h->top.FontBBox[1] = h->aggregatebounds.bottom; - h->top.FontBBox[2] = h->aggregatebounds.right; - h->top.FontBBox[3] = h->aggregatebounds.top; - + h->top.FontBBox[0] = h->aggregatebounds.left; + h->top.FontBBox[1] = h->aggregatebounds.bottom; + h->top.FontBBox[2] = h->aggregatebounds.right; + h->top.FontBBox[3] = h->aggregatebounds.top; + /* clear out any point names from the last run */ if (h->data.opList.cnt > 0) { for (i=0; i < h->data.opList.cnt; i++) { OpRec* opRec = &h->data.opList.array[i++]; - if (opRec->pointName != NULL) - { - memFree(h, opRec->pointName); + if (opRec->pointName != NULL) + { + memFree(h, opRec->pointName); opRec->pointName = NULL; - } + } } - h->data.opList.cnt = 0; /* zero the list of ops in the glyph */ + h->data.opList.cnt = 0; /* zero the list of ops in the glyph */ } /* reset all the hint masks */ if (h->hints.hintMasks.cnt > 0) @@ -4268,28 +4086,28 @@ static int readGlyph(ufoCtx h, unsigned short tag, abfGlyphCallbacks *glyph_cb) { HintMask* curMask = dnaINDEX(h->hints.hintMasks, i ); curMask->maskStems.cnt = 0; - if (curMask->pointName != NULL) + if (curMask->pointName != NULL) { memFree(h, curMask->pointName); curMask->pointName = NULL; } - + } - h->hints.hintMasks.cnt = 0; + h->hints.hintMasks.cnt = 0; } - /* clear the list of flex names */ - if (h->hints.flexOpList.cnt > 0) - { + /* clear the list of flex names */ + if (h->hints.flexOpList.cnt > 0) + { for (i=0; i < h->hints.flexOpList.cnt; i++) { - char* flexPointName = h->hints.flexOpList.array[i++]; - memFree(h, flexPointName); - } - h->hints.flexOpList.cnt = 0; - } - - return ufoSuccess; + char* flexPointName = h->hints.flexOpList.array[i++]; + memFree(h, flexPointName); + } + h->hints.flexOpList.cnt = 0; + } + + return ufoSuccess; } /* --------------------------- String Management --------------------------- */ @@ -4297,22 +4115,15 @@ static int readGlyph(ufoCtx h, unsigned short tag, abfGlyphCallbacks *glyph_cb) /* Initialize strings. */ static void newStrings(ufoCtx h) { - dnaINIT(h->dna, h->strings.index, 50, 200); - dnaINIT(h->dna, h->strings.buf, 32000, 6000); -} - -/* Reinitilize strings for new font. */ -static void initStrings(ufoCtx h) -{ - h->strings.index.cnt = 0; - h->strings.buf.cnt = 0; + dnaINIT(h->dna, h->strings.index, 50, 200); + dnaINIT(h->dna, h->strings.buf, 32000, 6000); } /* Free strings. */ static void freeStrings(ufoCtx h) { - dnaFREE(h->strings.index); - dnaFREE(h->strings.buf); + dnaFREE(h->strings.index); + dnaFREE(h->strings.buf); } /* Add string. */ @@ -4320,55 +4131,55 @@ static void freeStrings(ufoCtx h) /* static STI addString(ufoCtx h, unsigned length, const char *value) */ static STI addString(ufoCtx h, size_t length, const char *value) { - STI sti = (STI)h->strings.index.cnt; - - if (length == 0) + STI sti = (STI)h->strings.index.cnt; + + if (length == 0) { - /* A null name (/) is legal in PostScript but could lead to unexpected + /* A null name (/) is legal in PostScript but could lead to unexpected behaviour elsewhere in the coretype libraries so it is substituted for a name that is very likely to be unique in the font */ - const char subs_name[] = "_null_name_substitute_"; - value = subs_name; - length = sizeof(subs_name) - 1; - message(h, "null charstring name"); + const char subs_name[] = "_null_name_substitute_"; + value = subs_name; + length = sizeof(subs_name) - 1; + message(h, "null charstring name"); } - - /* Add new string index */ - *dnaNEXT(h->strings.index) = h->strings.buf.cnt; - - /* Add null-terminated string to buffer */ - /* 64-bit warning fixed by cast here HO */ - memcpy(dnaEXTEND(h->strings.buf, (long)(length + 1)), value, length); - h->strings.buf.array[h->strings.buf.cnt - 1] = '\0'; - - return sti; + + /* Add new string index */ + *dnaNEXT(h->strings.index) = h->strings.buf.cnt; + + /* Add null-terminated string to buffer */ + /* 64-bit warning fixed by cast here HO */ + memcpy(dnaEXTEND(h->strings.buf, (long)(length + 1)), value, length); + h->strings.buf.array[h->strings.buf.cnt - 1] = '\0'; + + return sti; } /* Get string from STI. */ static char *getString(ufoCtx h, STI sti) { - return &h->strings.buf.array[h->strings.index.array[sti]]; + return &h->strings.buf.array[h->strings.index.array[sti]]; } /* ----------------------Width management -----------------------*/ static void addWidth(ufoCtx h, STI sti, long value) { - if (sti != h->chars.widths.cnt) - { - fatal(h, ufoErrParse, "Width index does not match glyph name index. Glyph index %d.", sti); - } - *dnaNEXT(h->chars.widths) = value; - + if (sti != h->chars.widths.cnt) + { + fatal(h, ufoErrParse, "Width index does not match glyph name index. Glyph index %d.", sti); + } + *dnaNEXT(h->chars.widths) = value; + } static long getWidth(ufoCtx h, STI sti) { - return h->chars.widths.array[sti]; + return h->chars.widths.array[sti]; } static void setWidth(ufoCtx h, STI sti, long value) { - h->chars.widths.array[sti] = value; + h->chars.widths.array[sti] = value; } /* ----------------------Char management -----------------------*/ @@ -4376,205 +4187,191 @@ static void setWidth(ufoCtx h, STI sti, long value) /* Match glyph name. */ static int CTL_CDECL matchChar(const void *key, const void *value, void *ctx) { - ufoCtx h = ctx; - return strcmp((char *)key, getString(h, (STI)h->chars.index.array - [*(long *)value].tag) ); + ufoCtx h = ctx; + return strcmp((char *)key, getString(h, (STI)h->chars.index.array + [*(long *)value].tag) ); } /* Add char record. Return 1 if record exists else 0. Char record returned by "chr" parameter. */ static int addChar(ufoCtx h, STI sti, Char **chr) { - size_t index; - int found = + size_t index; + int found = ctuLookup(getString(h, sti), h->chars.byName.array, h->chars.byName.cnt, sizeof(h->chars.byName.array[0]), matchChar, &index, h); - - if (found) + + if (found) /* Match found; return existing record */ - *chr = &h->chars.index.array[h->chars.byName.array[index]]; - else - { - /* Not found; add to table and return new record */ - long *new = &dnaGROW(h->chars.byName, h->chars.byName.cnt)[index]; - - /* Make and fill hole */ - memmove(new + 1, new, (h->chars.byName.cnt++ - index) * - sizeof(h->chars.byName.array[0])); - *new = h->chars.index.cnt; - - *chr = dnaNEXT(h->chars.index); + *chr = &h->chars.index.array[h->chars.byName.array[index]]; + else + { + /* Not found; add to table and return new record */ + long *new = &dnaGROW(h->chars.byName, h->chars.byName.cnt)[index]; + + /* Make and fill hole */ + memmove(new + 1, new, (h->chars.byName.cnt++ - index) * + sizeof(h->chars.byName.array[0])); + *new = h->chars.index.cnt; + + *chr = dnaNEXT(h->chars.index); } - - return found; -} -/* Find char by name. NULL if not found else char record. */ -static Char *findChar(ufoCtx h, STI sti) -{ - size_t index; - if (ctuLookup(getString(h, sti), - h->chars.byName.array, h->chars.byName.cnt, - sizeof(h->chars.byName.array[0]), matchChar, &index, h)) - return &h->chars.index.array[h->chars.byName.array[index]]; - else - return NULL; + return found; } - /* ---------------------- Public API -----------------------*/ /* Parse files */ int ufoBegFont(ufoCtx h, long flags, abfTopDict **top, char *altLayerDir) { - int result; - char *dummy; - - /* Set error handler */ + int result; + + /* Set error handler */ DURING_EX(h->err.env) - + /* Initialize */ abfInitTopDict(&h->top); abfInitFontDict(&h->fdict); - + h->top.FDArray.cnt = 1; h->top.FDArray.array = &h->fdict; - + /* init glyph data structures used */ h->valueArray.cnt = 0; h->chars.index.cnt = 0; h->data.glifRecs.cnt = 0; h->data.opList.cnt = 0; h->hints.hintMasks.cnt = 0; - + h->aggregatebounds.left = 0.0; h->aggregatebounds.bottom = 0.0; h->aggregatebounds.right = 0.0; h->aggregatebounds.top = 0.0; - + h->metrics.cb = abfGlyphMetricsCallbacks; h->metrics.cb.direct_ctx = &h->metrics.ctx; h->metrics.ctx.flags = 0x0; - + if (altLayerDir != NULL) h->altLayerDir = altLayerDir; - - dummy = *dnaGROW(h->valueArray,14); - + + dnaGROW(h->valueArray,14); + result = parseUFO(h); if (result) fatal(h,result, NULL); - + prepClientData(h); *top = &h->top; - HANDLER - result = Exception.Code; + HANDLER + result = Exception.Code; END_HANDLER - - return result; + + return result; } int ufoEndFont(ufoCtx h) { - if ( h->stm.src ) - h->cb.stm.close(&h->cb.stm, h->stm.src); - memFree(h, h->top.FullName.ptr); - return ufoSuccess; + if ( h->stm.src ) + h->cb.stm.close(&h->cb.stm, h->stm.src); + memFree(h, h->top.FullName.ptr); + return ufoSuccess; } int ufoIterateGlyphs(ufoCtx h, abfGlyphCallbacks *glyph_cb) { - unsigned short i; - int res; - - /* Set error handler */ + unsigned short i; + int res; + + /* Set error handler */ DURING_EX(h->err.env) - + for (i = 0; i < h->chars.index.cnt; i++) { res = readGlyph(h, i, glyph_cb); if (res != ufoSuccess) return res; } - + HANDLER - return Exception.Code; + return Exception.Code; END_HANDLER - - return ufoSuccess; + + return ufoSuccess; } int ufoGetGlyphByTag(ufoCtx h, unsigned short tag, abfGlyphCallbacks *glyph_cb) { - int res = ufoSuccess; - - if (tag >= h->chars.index.cnt) - return ufoErrNoGlyph; - - /* Set error handler */ + int res = ufoSuccess; + + if (tag >= h->chars.index.cnt) + return ufoErrNoGlyph; + + /* Set error handler */ DURING_EX(h->err.env) - - res = readGlyph(h, tag, glyph_cb); - + + res = readGlyph(h, tag, glyph_cb); + HANDLER - res = Exception.Code; + res = Exception.Code; END_HANDLER - - return res; + + return res; } /* Match glyph name after font fully parsed. */ static int CTL_CDECL postMatchChar(const void *key, const void *value, - void *ctx) + void *ctx) { - ufoCtx h = ctx; + ufoCtx h = ctx; char * testKey = getString(h, (STI)h->chars.index.array [*(long *)value].tag); - return strcmp((char *)key, testKey ); + return strcmp((char *)key, testKey ); } int ufoGetGlyphByName(ufoCtx h, char *gname, abfGlyphCallbacks *glyph_cb) { - size_t index; - int result; - - if (!ctuLookup(gname, h->chars.byName.array, h->chars.byName.cnt, - sizeof(h->chars.byName.array[0]), postMatchChar, &index, h)) - return ufoErrNoGlyph; - - /* Set error handler */ + size_t index; + int result; + + if (!ctuLookup(gname, h->chars.byName.array, h->chars.byName.cnt, + sizeof(h->chars.byName.array[0]), postMatchChar, &index, h)) + return ufoErrNoGlyph; + + /* Set error handler */ DURING_EX(h->err.env) - - result = readGlyph(h, (unsigned short)h->chars.byName.array[index], glyph_cb); - HANDLER - result = Exception.Code; + result = readGlyph(h, (unsigned short)h->chars.byName.array[index], glyph_cb); + + HANDLER + result = Exception.Code; END_HANDLER - return result; -} + return result; +} int ufoResetGlyphs(ufoCtx h) -{ - long i; - - for (i = 0; i < h->chars.index.cnt; i++) - h->chars.index.array[i].flags &= ~((unsigned long)ABF_GLYPH_SEEN); - - return ufoSuccess; +{ + long i; + + for (i = 0; i < h->chars.index.cnt; i++) + h->chars.index.array[i].flags &= ~((unsigned long)ABF_GLYPH_SEEN); + + return ufoSuccess; } void ufoGetVersion(ctlVersionCallbacks *cb) { - if (cb->called & 1<getversion(cb, UFO_VERSION, "uforead"); - - cb->called |= 1<called & 1<getversion(cb, UFO_VERSION, "uforead"); + + cb->called |= 1<