1*9f62ea84SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*9f62ea84SAndrew Rist * distributed with this work for additional information 6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an 15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 17*9f62ea84SAndrew Rist * specific language governing permissions and limitations 18*9f62ea84SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*9f62ea84SAndrew Rist *************************************************************/ 21*9f62ea84SAndrew Rist 22*9f62ea84SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir /* 28cdf0e10cSrcweir * Sun Font Tools 29cdf0e10cSrcweir * 30cdf0e10cSrcweir * Author: Alexander Gelfenbain 31cdf0e10cSrcweir * 32cdf0e10cSrcweir */ 33cdf0e10cSrcweir 34cdf0e10cSrcweir #if OSL_DEBUG_LEVEL == 0 35cdf0e10cSrcweir # ifndef NDEBUG 36cdf0e10cSrcweir # define NDEBUG 37cdf0e10cSrcweir # endif 38cdf0e10cSrcweir #endif 39cdf0e10cSrcweir #include <assert.h> 40cdf0e10cSrcweir 41cdf0e10cSrcweir #include <stdlib.h> 42cdf0e10cSrcweir #include <string.h> 43cdf0e10cSrcweir #include <fcntl.h> 44cdf0e10cSrcweir #ifdef UNX 45cdf0e10cSrcweir #include <sys/mman.h> 46cdf0e10cSrcweir #include <sys/stat.h> 47cdf0e10cSrcweir #endif 48cdf0e10cSrcweir #include "sft.hxx" 49cdf0e10cSrcweir #include "gsub.h" 50cdf0e10cSrcweir #if ! (defined(NO_TTCR) && defined(NO_TYPE42)) 51cdf0e10cSrcweir #include "ttcr.hxx" 52cdf0e10cSrcweir #endif 53cdf0e10cSrcweir #ifndef NO_MAPPERS /* include MapChar() and MapString() */ 54cdf0e10cSrcweir #include "xlat.hxx" 55cdf0e10cSrcweir #endif 56cdf0e10cSrcweir #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */ 57cdf0e10cSrcweir #include <rtl/crc.h> 58cdf0e10cSrcweir #endif 59cdf0e10cSrcweir 60cdf0e10cSrcweir #include <osl/endian.h> 61cdf0e10cSrcweir #include <algorithm> 62cdf0e10cSrcweir 63cdf0e10cSrcweir #ifdef TEST7 64cdf0e10cSrcweir #include <ctype.h> 65cdf0e10cSrcweir #endif 66cdf0e10cSrcweir 67cdf0e10cSrcweir namespace vcl 68cdf0e10cSrcweir { 69cdf0e10cSrcweir 70cdf0e10cSrcweir /*- module identification */ 71cdf0e10cSrcweir 72cdf0e10cSrcweir static const char *modname = "SunTypeTools-TT"; 73cdf0e10cSrcweir static const char *modver = "1.0"; 74cdf0e10cSrcweir static const char *modextra = "gelf"; 75cdf0e10cSrcweir 76cdf0e10cSrcweir /*- private functions, constants and data types */ /*FOLD00*/ 77cdf0e10cSrcweir 78cdf0e10cSrcweir enum PathSegmentType { 79cdf0e10cSrcweir PS_NOOP = 0, 80cdf0e10cSrcweir PS_MOVETO = 1, 81cdf0e10cSrcweir PS_LINETO = 2, 82cdf0e10cSrcweir PS_CURVETO = 3, 83cdf0e10cSrcweir PS_CLOSEPATH = 4 84cdf0e10cSrcweir }; 85cdf0e10cSrcweir 86cdf0e10cSrcweir struct PSPathElement 87cdf0e10cSrcweir { 88cdf0e10cSrcweir PathSegmentType type; 89cdf0e10cSrcweir int x1, y1; 90cdf0e10cSrcweir int x2, y2; 91cdf0e10cSrcweir int x3, y3; 92cdf0e10cSrcweir 93cdf0e10cSrcweir PSPathElement( PathSegmentType i_eType ) : type( i_eType ), 94cdf0e10cSrcweir x1( 0 ), y1( 0 ), 95cdf0e10cSrcweir x2( 0 ), y2( 0 ), 96cdf0e10cSrcweir x3( 0 ), y3( 0 ) 97cdf0e10cSrcweir { 98cdf0e10cSrcweir } 99cdf0e10cSrcweir }; 100cdf0e10cSrcweir 101cdf0e10cSrcweir /*- In horisontal writing mode right sidebearing is calculated using this formula 102cdf0e10cSrcweir *- rsb = aw - (lsb + xMax - xMin) -*/ 103cdf0e10cSrcweir typedef struct { 104cdf0e10cSrcweir sal_Int16 xMin; 105cdf0e10cSrcweir sal_Int16 yMin; 106cdf0e10cSrcweir sal_Int16 xMax; 107cdf0e10cSrcweir sal_Int16 yMax; 108cdf0e10cSrcweir sal_uInt16 aw; /*- Advance Width (horisontal writing mode) */ 109cdf0e10cSrcweir sal_Int16 lsb; /*- Left sidebearing (horisontal writing mode) */ 110cdf0e10cSrcweir sal_uInt16 ah; /*- advance height (vertical writing mode) */ 111cdf0e10cSrcweir sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */ 112cdf0e10cSrcweir } TTGlyphMetrics; 113cdf0e10cSrcweir 114cdf0e10cSrcweir #define HFORMAT_LINELEN 64 115cdf0e10cSrcweir 116cdf0e10cSrcweir typedef struct { 117cdf0e10cSrcweir FILE *o; 118cdf0e10cSrcweir char buffer[HFORMAT_LINELEN]; 119cdf0e10cSrcweir int bufpos; 120cdf0e10cSrcweir int total; 121cdf0e10cSrcweir } HexFmt; 122cdf0e10cSrcweir 123cdf0e10cSrcweir typedef struct { 124cdf0e10cSrcweir sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */ 125cdf0e10cSrcweir sal_uInt32 *offs; /* array of nGlyphs offsets */ 126cdf0e10cSrcweir } GlyphOffsets; 127cdf0e10cSrcweir 128cdf0e10cSrcweir /* private tags */ 129cdf0e10cSrcweir static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */ 130cdf0e10cSrcweir 131cdf0e10cSrcweir static const sal_uInt32 T_true = 0x74727565; /* 'true' */ 132cdf0e10cSrcweir static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */ 133cdf0e10cSrcweir static const sal_uInt32 T_otto = 0x4f54544f; /* 'OTTO' */ 134cdf0e10cSrcweir 135cdf0e10cSrcweir /* standard TrueType table tags */ 136cdf0e10cSrcweir #define T_maxp 0x6D617870 137cdf0e10cSrcweir #define T_glyf 0x676C7966 138cdf0e10cSrcweir #define T_head 0x68656164 139cdf0e10cSrcweir #define T_loca 0x6C6F6361 140cdf0e10cSrcweir #define T_name 0x6E616D65 141cdf0e10cSrcweir #define T_hhea 0x68686561 142cdf0e10cSrcweir #define T_hmtx 0x686D7478 143cdf0e10cSrcweir #define T_cmap 0x636D6170 144cdf0e10cSrcweir #define T_vhea 0x76686561 145cdf0e10cSrcweir #define T_vmtx 0x766D7478 146cdf0e10cSrcweir #define T_OS2 0x4F532F32 147cdf0e10cSrcweir #define T_post 0x706F7374 148cdf0e10cSrcweir #define T_kern 0x6B65726E 149cdf0e10cSrcweir #define T_cvt 0x63767420 150cdf0e10cSrcweir #define T_prep 0x70726570 151cdf0e10cSrcweir #define T_fpgm 0x6670676D 152cdf0e10cSrcweir #define T_gsub 0x47535542 153cdf0e10cSrcweir #define T_CFF 0x43464620 154cdf0e10cSrcweir 155cdf0e10cSrcweir #define LAST_URANGE_BIT 69 156cdf0e10cSrcweir const char *ulcodes[LAST_URANGE_BIT+2] = { 157cdf0e10cSrcweir /* 0 */ "Basic Latin", 158cdf0e10cSrcweir /* 1 */ "Latin-1 Supplement", 159cdf0e10cSrcweir /* 2 */ "Latin Extended-A", 160cdf0e10cSrcweir /* 3 */ "Latin Extended-B", 161cdf0e10cSrcweir /* 4 */ "IPA Extensions", 162cdf0e10cSrcweir /* 5 */ "Spacing Modifier Letters", 163cdf0e10cSrcweir /* 6 */ "Combining Diacritical Marks", 164cdf0e10cSrcweir /* 7 */ "Basic Greek", 165cdf0e10cSrcweir /* 8 */ "Greek Symbols And Coptic", 166cdf0e10cSrcweir /* 9 */ "Cyrillic", 167cdf0e10cSrcweir /* 10 */ "Armenian", 168cdf0e10cSrcweir /* 11 */ "Basic Hebrew", 169cdf0e10cSrcweir /* 12 */ "Hebrew Extended (A and B blocks combined)", 170cdf0e10cSrcweir /* 13 */ "Basic Arabic", 171cdf0e10cSrcweir /* 14 */ "Arabic Extended", 172cdf0e10cSrcweir /* 15 */ "Devanagari", 173cdf0e10cSrcweir /* 16 */ "Bengali", 174cdf0e10cSrcweir /* 17 */ "Gurmukhi", 175cdf0e10cSrcweir /* 18 */ "Gujarati", 176cdf0e10cSrcweir /* 19 */ "Oriya", 177cdf0e10cSrcweir /* 20 */ "Tamil", 178cdf0e10cSrcweir /* 21 */ "Telugu", 179cdf0e10cSrcweir /* 22 */ "Kannada", 180cdf0e10cSrcweir /* 23 */ "Malayalam", 181cdf0e10cSrcweir /* 24 */ "Thai", 182cdf0e10cSrcweir /* 25 */ "Lao", 183cdf0e10cSrcweir /* 26 */ "Basic Georgian", 184cdf0e10cSrcweir /* 27 */ "Georgian Extended", 185cdf0e10cSrcweir /* 28 */ "Hangul Jamo", 186cdf0e10cSrcweir /* 29 */ "Latin Extended Additional", 187cdf0e10cSrcweir /* 30 */ "Greek Extended", 188cdf0e10cSrcweir /* 31 */ "General Punctuation", 189cdf0e10cSrcweir /* 32 */ "Superscripts And Subscripts", 190cdf0e10cSrcweir /* 33 */ "Currency Symbols", 191cdf0e10cSrcweir /* 34 */ "Combining Diacritical Marks For Symbols", 192cdf0e10cSrcweir /* 35 */ "Letterlike Symbols", 193cdf0e10cSrcweir /* 36 */ "Number Forms", 194cdf0e10cSrcweir /* 37 */ "Arrows", 195cdf0e10cSrcweir /* 38 */ "Mathematical Operators", 196cdf0e10cSrcweir /* 39 */ "Miscellaneous Technical", 197cdf0e10cSrcweir /* 40 */ "Control Pictures", 198cdf0e10cSrcweir /* 41 */ "Optical Character Recognition", 199cdf0e10cSrcweir /* 42 */ "Enclosed Alphanumerics", 200cdf0e10cSrcweir /* 43 */ "Box Drawing", 201cdf0e10cSrcweir /* 44 */ "Block Elements", 202cdf0e10cSrcweir /* 45 */ "Geometric Shapes", 203cdf0e10cSrcweir /* 46 */ "Miscellaneous Symbols", 204cdf0e10cSrcweir /* 47 */ "Dingbats", 205cdf0e10cSrcweir /* 48 */ "CJK Symbols And Punctuation", 206cdf0e10cSrcweir /* 49 */ "Hiragana", 207cdf0e10cSrcweir /* 50 */ "Katakana", 208cdf0e10cSrcweir /* 51 */ "Bopomofo", 209cdf0e10cSrcweir /* 52 */ "Hangul Compatibility Jamo", 210cdf0e10cSrcweir /* 53 */ "CJK Miscellaneous", 211cdf0e10cSrcweir /* 54 */ "Enclosed CJK Letters And Months", 212cdf0e10cSrcweir /* 55 */ "CJK Compatibility", 213cdf0e10cSrcweir /* 56 */ "Hangul", 214cdf0e10cSrcweir /* 57 */ "Reserved for Unicode SubRanges", 215cdf0e10cSrcweir /* 58 */ "Reserved for Unicode SubRanges", 216cdf0e10cSrcweir /* 59 */ "CJK Unified Ideographs", 217cdf0e10cSrcweir /* 60 */ "Private Use Area", 218cdf0e10cSrcweir /* 61 */ "CJK Compatibility Ideographs", 219cdf0e10cSrcweir /* 62 */ "Alphabetic Presentation Forms", 220cdf0e10cSrcweir /* 63 */ "Arabic Presentation Forms-A", 221cdf0e10cSrcweir /* 64 */ "Combining Half Marks", 222cdf0e10cSrcweir /* 65 */ "CJK Compatibility Forms", 223cdf0e10cSrcweir /* 66 */ "Small Form Variants", 224cdf0e10cSrcweir /* 67 */ "Arabic Presentation Forms-B", 225cdf0e10cSrcweir /* 68 */ "Halfwidth And Fullwidth Forms", 226cdf0e10cSrcweir /* 69 */ "Specials", 227cdf0e10cSrcweir /*70-127*/ "Reserved for Unicode SubRanges" 228cdf0e10cSrcweir }; 229cdf0e10cSrcweir 230cdf0e10cSrcweir 231cdf0e10cSrcweir 232cdf0e10cSrcweir /*- inline functions */ /*FOLD01*/ 233cdf0e10cSrcweir #ifdef __GNUC__ 234cdf0e10cSrcweir #define _inline static __inline__ 235cdf0e10cSrcweir #else 236cdf0e10cSrcweir #define _inline static 237cdf0e10cSrcweir #endif 238cdf0e10cSrcweir 239cdf0e10cSrcweir _inline void *smalloc(size_t size) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir void *res = malloc(size); 242cdf0e10cSrcweir assert(res != 0); 243cdf0e10cSrcweir return res; 244cdf0e10cSrcweir } 245cdf0e10cSrcweir 246cdf0e10cSrcweir _inline void *scalloc(size_t n, size_t size) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir void *res = calloc(n, size); 249cdf0e10cSrcweir assert(res != 0); 250cdf0e10cSrcweir return res; 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) { 254cdf0e10cSrcweir return (a << 24) | (b << 16) | (c << 8) | d; 255cdf0e10cSrcweir } 256cdf0e10cSrcweir 257cdf0e10cSrcweir /*- Data access macros for data stored in big-endian or little-endian format */ 258cdf0e10cSrcweir _inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir sal_Int16 t; 261cdf0e10cSrcweir assert(ptr != 0); 262cdf0e10cSrcweir 263cdf0e10cSrcweir if (bigendian) { 264cdf0e10cSrcweir t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 265cdf0e10cSrcweir } else { 266cdf0e10cSrcweir t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 267cdf0e10cSrcweir } 268cdf0e10cSrcweir 269cdf0e10cSrcweir return t; 270cdf0e10cSrcweir } 271cdf0e10cSrcweir 272cdf0e10cSrcweir _inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir sal_uInt16 t; 275cdf0e10cSrcweir assert(ptr != 0); 276cdf0e10cSrcweir 277cdf0e10cSrcweir if (bigendian) { 278cdf0e10cSrcweir t = (ptr+offset)[0] << 8 | (ptr+offset)[1]; 279cdf0e10cSrcweir } else { 280cdf0e10cSrcweir t = (ptr+offset)[1] << 8 | (ptr+offset)[0]; 281cdf0e10cSrcweir } 282cdf0e10cSrcweir 283cdf0e10cSrcweir return t; 284cdf0e10cSrcweir } 285cdf0e10cSrcweir 286cdf0e10cSrcweir _inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir sal_Int32 t; 289cdf0e10cSrcweir assert(ptr != 0); 290cdf0e10cSrcweir 291cdf0e10cSrcweir if (bigendian) { 292cdf0e10cSrcweir t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 293cdf0e10cSrcweir (ptr+offset)[2] << 8 | (ptr+offset)[3]; 294cdf0e10cSrcweir } else { 295cdf0e10cSrcweir t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 296cdf0e10cSrcweir (ptr+offset)[1] << 8 | (ptr+offset)[0]; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir 299cdf0e10cSrcweir return t; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir _inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian) 303cdf0e10cSrcweir { 304cdf0e10cSrcweir sal_uInt32 t; 305cdf0e10cSrcweir assert(ptr != 0); 306cdf0e10cSrcweir 307cdf0e10cSrcweir 308cdf0e10cSrcweir if (bigendian) { 309cdf0e10cSrcweir t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 | 310cdf0e10cSrcweir (ptr+offset)[2] << 8 | (ptr+offset)[3]; 311cdf0e10cSrcweir } else { 312cdf0e10cSrcweir t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 | 313cdf0e10cSrcweir (ptr+offset)[1] << 8 | (ptr+offset)[0]; 314cdf0e10cSrcweir } 315cdf0e10cSrcweir 316cdf0e10cSrcweir return t; 317cdf0e10cSrcweir } 318cdf0e10cSrcweir 319cdf0e10cSrcweir _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian) 320cdf0e10cSrcweir { 321cdf0e10cSrcweir assert(ptr != 0); 322cdf0e10cSrcweir 323cdf0e10cSrcweir if (bigendian) { 324cdf0e10cSrcweir ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF); 325cdf0e10cSrcweir ptr[offset+1] = (sal_uInt8)(val & 0xFF); 326cdf0e10cSrcweir } else { 327cdf0e10cSrcweir ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF); 328cdf0e10cSrcweir ptr[offset] = (sal_uInt8)(val & 0xFF); 329cdf0e10cSrcweir } 330cdf0e10cSrcweir 331cdf0e10cSrcweir } 332cdf0e10cSrcweir 333cdf0e10cSrcweir #if defined(OSL_BIGENDIAN) 334cdf0e10cSrcweir #define Int16FromMOTA(a) (a) 335cdf0e10cSrcweir #define Int32FromMOTA(a) (a) 336cdf0e10cSrcweir #else 337cdf0e10cSrcweir static sal_uInt16 Int16FromMOTA(sal_uInt16 a) { 338cdf0e10cSrcweir return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8)); 339cdf0e10cSrcweir } 340cdf0e10cSrcweir static sal_uInt32 Int32FromMOTA(sal_uInt32 a) { 341cdf0e10cSrcweir return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24)); 342cdf0e10cSrcweir } 343cdf0e10cSrcweir #endif 344cdf0e10cSrcweir 345cdf0e10cSrcweir _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir unsigned int a1, b1; 348cdf0e10cSrcweir unsigned int a2, b2; 349cdf0e10cSrcweir F16Dot16 res; 350cdf0e10cSrcweir int sign; 351cdf0e10cSrcweir 352cdf0e10cSrcweir sign = (a & 0x80000000) ^ (b & 0x80000000); 353cdf0e10cSrcweir if (a < 0) a = -a; 354cdf0e10cSrcweir if (b < 0) b = -b; 355cdf0e10cSrcweir 356cdf0e10cSrcweir a1 = a >> 16; 357cdf0e10cSrcweir b1 = a & 0xFFFF; 358cdf0e10cSrcweir a2 = b >> 16; 359cdf0e10cSrcweir b2 = b & 0xFFFF; 360cdf0e10cSrcweir 361cdf0e10cSrcweir res = a1 * a2; 362cdf0e10cSrcweir 363cdf0e10cSrcweir /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */ 364cdf0e10cSrcweir 365cdf0e10cSrcweir res <<= 16; 366cdf0e10cSrcweir res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16); 367cdf0e10cSrcweir 368cdf0e10cSrcweir return sign ? -res : res; 369cdf0e10cSrcweir } 370cdf0e10cSrcweir 371cdf0e10cSrcweir 372cdf0e10cSrcweir _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b) 373cdf0e10cSrcweir { 374cdf0e10cSrcweir unsigned int f, r; 375cdf0e10cSrcweir F16Dot16 res; 376cdf0e10cSrcweir int sign; 377cdf0e10cSrcweir 378cdf0e10cSrcweir sign = (a & 0x80000000) ^ (b & 0x80000000); 379cdf0e10cSrcweir if (a < 0) a = -a; 380cdf0e10cSrcweir if (b < 0) b = -b; 381cdf0e10cSrcweir 382cdf0e10cSrcweir f = a / b; 383cdf0e10cSrcweir r = a % b; 384cdf0e10cSrcweir 385cdf0e10cSrcweir /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */ 386cdf0e10cSrcweir 387cdf0e10cSrcweir while (r > 0xFFFF) { 388cdf0e10cSrcweir r >>= 1; 389cdf0e10cSrcweir b >>= 1; 390cdf0e10cSrcweir } 391cdf0e10cSrcweir 392cdf0e10cSrcweir res = (f << 16) + (r << 16) / b; 393cdf0e10cSrcweir 394cdf0e10cSrcweir return sign ? -res : res; 395cdf0e10cSrcweir } 396cdf0e10cSrcweir 397cdf0e10cSrcweir /*- returns a * b / c -*/ 398cdf0e10cSrcweir /* XXX provide a real implementation that preserves accuracy */ 399cdf0e10cSrcweir _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c) 400cdf0e10cSrcweir { 401cdf0e10cSrcweir F16Dot16 res; 402cdf0e10cSrcweir 403cdf0e10cSrcweir res = fixedMul(a, b); 404cdf0e10cSrcweir return fixedDiv(res, c); 405cdf0e10cSrcweir } 406cdf0e10cSrcweir 407cdf0e10cSrcweir /*- Translate units from TT to PS (standard 1/1000) -*/ 408cdf0e10cSrcweir _inline int XUnits(int unitsPerEm, int n) 409cdf0e10cSrcweir { 410cdf0e10cSrcweir return (n * 1000) / unitsPerEm; 411cdf0e10cSrcweir } 412cdf0e10cSrcweir 413cdf0e10cSrcweir _inline const char *UnicodeRangeName(sal_uInt16 bit) 414cdf0e10cSrcweir { 415cdf0e10cSrcweir if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1; 416cdf0e10cSrcweir 417cdf0e10cSrcweir return ulcodes[bit]; 418cdf0e10cSrcweir } 419cdf0e10cSrcweir 420cdf0e10cSrcweir _inline const sal_uInt8* getTable( TrueTypeFont *ttf, sal_uInt32 ord) 421cdf0e10cSrcweir { 422cdf0e10cSrcweir return (sal_uInt8*)ttf->tables[ord]; 423cdf0e10cSrcweir } 424cdf0e10cSrcweir 425cdf0e10cSrcweir _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord) 426cdf0e10cSrcweir { 427cdf0e10cSrcweir return ttf->tlens[ord]; 428cdf0e10cSrcweir } 429cdf0e10cSrcweir 430cdf0e10cSrcweir #ifndef NO_TYPE42 431cdf0e10cSrcweir /* Hex Formatter functions */ 432cdf0e10cSrcweir static char HexChars[] = "0123456789ABCDEF"; 433cdf0e10cSrcweir 434cdf0e10cSrcweir static HexFmt *HexFmtNew(FILE *outf) 435cdf0e10cSrcweir { 436cdf0e10cSrcweir HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt)); 437cdf0e10cSrcweir res->bufpos = res->total = 0; 438cdf0e10cSrcweir res->o = outf; 439cdf0e10cSrcweir return res; 440cdf0e10cSrcweir } 441cdf0e10cSrcweir 442cdf0e10cSrcweir static void HexFmtFlush(HexFmt *_this) 443cdf0e10cSrcweir { 444cdf0e10cSrcweir if (_this->bufpos) { 445cdf0e10cSrcweir fwrite(_this->buffer, 1, _this->bufpos, _this->o); 446cdf0e10cSrcweir _this->bufpos = 0; 447cdf0e10cSrcweir } 448cdf0e10cSrcweir } 449cdf0e10cSrcweir 450cdf0e10cSrcweir 451cdf0e10cSrcweir _inline void HexFmtOpenString(HexFmt *_this) 452cdf0e10cSrcweir { 453cdf0e10cSrcweir fputs("<\n", _this->o); 454cdf0e10cSrcweir } 455cdf0e10cSrcweir 456cdf0e10cSrcweir _inline void HexFmtCloseString(HexFmt *_this) 457cdf0e10cSrcweir { 458cdf0e10cSrcweir HexFmtFlush(_this); 459cdf0e10cSrcweir fputs("00\n>\n", _this->o); 460cdf0e10cSrcweir } 461cdf0e10cSrcweir 462cdf0e10cSrcweir _inline void HexFmtDispose(HexFmt *_this) 463cdf0e10cSrcweir { 464cdf0e10cSrcweir HexFmtFlush(_this); 465cdf0e10cSrcweir free(_this); 466cdf0e10cSrcweir } 467cdf0e10cSrcweir 468cdf0e10cSrcweir static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size) 469cdf0e10cSrcweir { 470cdf0e10cSrcweir sal_uInt8 Ch; 471cdf0e10cSrcweir sal_uInt32 i; 472cdf0e10cSrcweir 473cdf0e10cSrcweir if (_this->total + size > 65534) { 474cdf0e10cSrcweir HexFmtFlush(_this); 475cdf0e10cSrcweir HexFmtCloseString(_this); 476cdf0e10cSrcweir _this->total = 0; 477cdf0e10cSrcweir HexFmtOpenString(_this); 478cdf0e10cSrcweir } 479cdf0e10cSrcweir for (i=0; i<size; i++) { 480cdf0e10cSrcweir Ch = ((sal_uInt8 *) ptr)[i]; 481cdf0e10cSrcweir _this->buffer[_this->bufpos++] = HexChars[Ch >> 4]; 482cdf0e10cSrcweir _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF]; 483cdf0e10cSrcweir if (_this->bufpos == HFORMAT_LINELEN) { 484cdf0e10cSrcweir HexFmtFlush(_this); 485cdf0e10cSrcweir fputc('\n', _this->o); 486cdf0e10cSrcweir } 487cdf0e10cSrcweir 488cdf0e10cSrcweir } 489cdf0e10cSrcweir _this->total += size; 490cdf0e10cSrcweir } 491cdf0e10cSrcweir #endif 492cdf0e10cSrcweir 493cdf0e10cSrcweir 494cdf0e10cSrcweir 495cdf0e10cSrcweir /* Outline Extraction functions */ /*FOLD01*/ 496cdf0e10cSrcweir 497cdf0e10cSrcweir /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/ 498cdf0e10cSrcweir static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir const sal_uInt8* table = getTable( ttf, O_hmtx ); 501cdf0e10cSrcweir 502cdf0e10cSrcweir metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0; 503cdf0e10cSrcweir if (!table || !ttf->numberOfHMetrics) return; 504cdf0e10cSrcweir 505cdf0e10cSrcweir if (glyphID < ttf->numberOfHMetrics) { 506cdf0e10cSrcweir metrics->aw = GetUInt16(table, 4 * glyphID, 1); 507cdf0e10cSrcweir metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1); 508cdf0e10cSrcweir } else { 509cdf0e10cSrcweir metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1); 510cdf0e10cSrcweir metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); 511cdf0e10cSrcweir } 512cdf0e10cSrcweir 513cdf0e10cSrcweir table = getTable(ttf, O_vmtx); 514cdf0e10cSrcweir if( !table || !ttf->numOfLongVerMetrics ) 515cdf0e10cSrcweir return; 516cdf0e10cSrcweir 517cdf0e10cSrcweir if (glyphID < ttf->numOfLongVerMetrics) { 518cdf0e10cSrcweir metrics->ah = GetUInt16(table, 4 * glyphID, 1); 519cdf0e10cSrcweir metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1); 520cdf0e10cSrcweir } else { 521cdf0e10cSrcweir metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1); 522cdf0e10cSrcweir metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir } 525cdf0e10cSrcweir 526cdf0e10cSrcweir static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* ); 527cdf0e10cSrcweir 528cdf0e10cSrcweir /* returns the number of control points, allocates the pointArray */ 529cdf0e10cSrcweir static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/ 530cdf0e10cSrcweir { 531cdf0e10cSrcweir const sal_uInt8* table = getTable( ttf, O_glyf ); 532cdf0e10cSrcweir sal_uInt8 flag, n; 533cdf0e10cSrcweir sal_uInt16 t, lastPoint=0; 534cdf0e10cSrcweir int i, j, z; 535cdf0e10cSrcweir 536cdf0e10cSrcweir *pointArray = 0; 537cdf0e10cSrcweir 538cdf0e10cSrcweir /* printf("GetSimpleTTOutline(%d)\n", glyphID); */ 539cdf0e10cSrcweir 540cdf0e10cSrcweir if( glyphID >= ttf->nglyphs ) /*- glyph is not present in the font */ 541cdf0e10cSrcweir return 0; 542cdf0e10cSrcweir const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 543cdf0e10cSrcweir const sal_Int16 numberOfContours = GetInt16(ptr, 0, 1); 544cdf0e10cSrcweir if( numberOfContours <= 0 ) /*- glyph is not simple */ 545cdf0e10cSrcweir return 0; 546cdf0e10cSrcweir 547cdf0e10cSrcweir if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/ 548cdf0e10cSrcweir metrics->xMin = GetInt16(ptr, 2, 1); 549cdf0e10cSrcweir metrics->yMin = GetInt16(ptr, 4, 1); 550cdf0e10cSrcweir metrics->xMax = GetInt16(ptr, 6, 1); 551cdf0e10cSrcweir metrics->yMax = GetInt16(ptr, 8, 1); 552cdf0e10cSrcweir GetMetrics(ttf, glyphID, metrics); 553cdf0e10cSrcweir } 554cdf0e10cSrcweir 555cdf0e10cSrcweir /* determine the last point and be extra safe about it. But probably this code is not needed */ 556cdf0e10cSrcweir 557cdf0e10cSrcweir for (i=0; i<numberOfContours; i++) { 558cdf0e10cSrcweir if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t; 559cdf0e10cSrcweir } 560cdf0e10cSrcweir 561cdf0e10cSrcweir sal_uInt16 instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1); 562cdf0e10cSrcweir const sal_uInt8* p = ptr + 10 + 2 * numberOfContours + 2 + instLen; 563cdf0e10cSrcweir ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint)); 564cdf0e10cSrcweir 565cdf0e10cSrcweir i = 0; 566cdf0e10cSrcweir while (i <= lastPoint) { 567cdf0e10cSrcweir pa[i++].flags = (sal_uInt32) (flag = *p++); 568cdf0e10cSrcweir if (flag & 8) { /*- repeat flag */ 569cdf0e10cSrcweir n = *p++; 570cdf0e10cSrcweir for (j=0; j<n; j++) { 571cdf0e10cSrcweir if (i > lastPoint) { /*- if the font is really broken */ 572cdf0e10cSrcweir free(pa); 573cdf0e10cSrcweir return 0; 574cdf0e10cSrcweir } 575cdf0e10cSrcweir pa[i++].flags = flag; 576cdf0e10cSrcweir } 577cdf0e10cSrcweir } 578cdf0e10cSrcweir } 579cdf0e10cSrcweir 580cdf0e10cSrcweir /*- Process the X coordinate */ 581cdf0e10cSrcweir z = 0; 582cdf0e10cSrcweir for (i = 0; i <= lastPoint; i++) { 583cdf0e10cSrcweir if (pa[i].flags & 0x02) { 584cdf0e10cSrcweir if (pa[i].flags & 0x10) { 585cdf0e10cSrcweir z += (int) (*p++); 586cdf0e10cSrcweir } else { 587cdf0e10cSrcweir z -= (int) (*p++); 588cdf0e10cSrcweir } 589cdf0e10cSrcweir } else if ( !(pa[i].flags & 0x10)) { 590cdf0e10cSrcweir z += GetInt16(p, 0, 1); 591cdf0e10cSrcweir p += 2; 592cdf0e10cSrcweir } 593cdf0e10cSrcweir pa[i].x = (sal_Int16)z; 594cdf0e10cSrcweir } 595cdf0e10cSrcweir 596cdf0e10cSrcweir /*- Process the Y coordinate */ 597cdf0e10cSrcweir z = 0; 598cdf0e10cSrcweir for (i = 0; i <= lastPoint; i++) { 599cdf0e10cSrcweir if (pa[i].flags & 0x04) { 600cdf0e10cSrcweir if (pa[i].flags & 0x20) { 601cdf0e10cSrcweir z += *p++; 602cdf0e10cSrcweir } else { 603cdf0e10cSrcweir z -= *p++; 604cdf0e10cSrcweir } 605cdf0e10cSrcweir } else if ( !(pa[i].flags & 0x20)) { 606cdf0e10cSrcweir z += GetInt16(p, 0, 1); 607cdf0e10cSrcweir p += 2; 608cdf0e10cSrcweir } 609cdf0e10cSrcweir pa[i].y = (sal_Int16)z; 610cdf0e10cSrcweir } 611cdf0e10cSrcweir 612cdf0e10cSrcweir for (i=0; i<numberOfContours; i++) { 613cdf0e10cSrcweir pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */ 614cdf0e10cSrcweir } 615cdf0e10cSrcweir 616cdf0e10cSrcweir *pointArray = pa; 617cdf0e10cSrcweir return lastPoint + 1; 618cdf0e10cSrcweir } 619cdf0e10cSrcweir 620cdf0e10cSrcweir static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/ 621cdf0e10cSrcweir { 622cdf0e10cSrcweir sal_uInt16 flags, index; 623cdf0e10cSrcweir sal_Int16 e, f, numberOfContours; 624cdf0e10cSrcweir const sal_uInt8* table = getTable( ttf, O_glyf ); 625cdf0e10cSrcweir std::vector<ControlPoint> myPoints; 626cdf0e10cSrcweir ControlPoint *nextComponent, *pa; 627cdf0e10cSrcweir int i, np; 628cdf0e10cSrcweir F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3; 629cdf0e10cSrcweir 630cdf0e10cSrcweir *pointArray = 0; 631cdf0e10cSrcweir /* printf("GetCompoundTTOutline(%d)\n", glyphID); */ 632cdf0e10cSrcweir 633cdf0e10cSrcweir if (glyphID >= ttf->nglyphs) /*- incorrect glyphID */ 634cdf0e10cSrcweir return 0; 635cdf0e10cSrcweir 636cdf0e10cSrcweir const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 637cdf0e10cSrcweir if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) /*- glyph is not compound */ 638cdf0e10cSrcweir return 0; 639cdf0e10cSrcweir 640cdf0e10cSrcweir if (metrics) { 641cdf0e10cSrcweir metrics->xMin = GetInt16(ptr, 2, 1); 642cdf0e10cSrcweir metrics->yMin = GetInt16(ptr, 4, 1); 643cdf0e10cSrcweir metrics->xMax = GetInt16(ptr, 6, 1); 644cdf0e10cSrcweir metrics->yMax = GetInt16(ptr, 8, 1); 645cdf0e10cSrcweir GetMetrics(ttf, glyphID, metrics); 646cdf0e10cSrcweir } 647cdf0e10cSrcweir 648cdf0e10cSrcweir ptr += 10; 649cdf0e10cSrcweir 650cdf0e10cSrcweir do { 651cdf0e10cSrcweir flags = GetUInt16(ptr, 0, 1); 652cdf0e10cSrcweir /* printf("flags: 0x%X\n", flags); */ 653cdf0e10cSrcweir index = GetUInt16(ptr, 2, 1); 654cdf0e10cSrcweir ptr += 4; 655cdf0e10cSrcweir 656cdf0e10cSrcweir if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() ) 657cdf0e10cSrcweir { 658cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 659cdf0e10cSrcweir fprintf(stderr, "Endless loop found in a compound glyph.\n"); 660cdf0e10cSrcweir fprintf(stderr, "%d -> ", index); 661cdf0e10cSrcweir fprintf(stderr," ["); 662cdf0e10cSrcweir for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); 663cdf0e10cSrcweir it != glyphlist.end(); ++it ) 664cdf0e10cSrcweir { 665cdf0e10cSrcweir fprintf( stderr,"%d ", (int) *it ); 666cdf0e10cSrcweir } 667cdf0e10cSrcweir fprintf(stderr,"]\n"); 668cdf0e10cSrcweir /**/ 669cdf0e10cSrcweir #endif 670cdf0e10cSrcweir } 671cdf0e10cSrcweir 672cdf0e10cSrcweir glyphlist.push_back( index ); 673cdf0e10cSrcweir 674cdf0e10cSrcweir #ifdef DEBUG2 675cdf0e10cSrcweir fprintf(stderr,"glyphlist: += %d\n", index); 676cdf0e10cSrcweir #endif 677cdf0e10cSrcweir 678cdf0e10cSrcweir if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0) 679cdf0e10cSrcweir { 680cdf0e10cSrcweir /* XXX that probably indicates a corrupted font */ 681cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 682cdf0e10cSrcweir fprintf(stderr, "An empty compound!\n"); 683cdf0e10cSrcweir /* assert(!"An empty compound"); */ 684cdf0e10cSrcweir #endif 685cdf0e10cSrcweir } 686cdf0e10cSrcweir 687cdf0e10cSrcweir #ifdef DEBUG2 688cdf0e10cSrcweir fprintf(stderr,"%d [", (int)glyphlist.size() ); 689cdf0e10cSrcweir for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin(); 690cdf0e10cSrcweir it != glyphlist.end(); ++it ) 691cdf0e10cSrcweir { 692cdf0e10cSrcweir fprintf( stderr,"%d ", (int) *it ); 693cdf0e10cSrcweir } 694cdf0e10cSrcweir fprintf(stderr, "]\n"); 695cdf0e10cSrcweir if( ! glyphlist.empty() ) 696cdf0e10cSrcweir fprintf(stderr, "glyphlist: -= %d\n", (int) glyphlist.back()); 697cdf0e10cSrcweir 698cdf0e10cSrcweir #endif 699cdf0e10cSrcweir if( ! glyphlist.empty() ) 700cdf0e10cSrcweir glyphlist.pop_back(); 701cdf0e10cSrcweir 702cdf0e10cSrcweir if (flags & USE_MY_METRICS) { 703cdf0e10cSrcweir if (metrics) GetMetrics(ttf, index, metrics); 704cdf0e10cSrcweir } 705cdf0e10cSrcweir 706cdf0e10cSrcweir if (flags & ARG_1_AND_2_ARE_WORDS) { 707cdf0e10cSrcweir e = GetInt16(ptr, 0, 1); 708cdf0e10cSrcweir f = GetInt16(ptr, 2, 1); 709cdf0e10cSrcweir /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */ 710cdf0e10cSrcweir ptr += 4; 711cdf0e10cSrcweir } else { 712cdf0e10cSrcweir if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */ 713cdf0e10cSrcweir e = (sal_Int8) *ptr++; 714cdf0e10cSrcweir f = (sal_Int8) *ptr++; 715cdf0e10cSrcweir /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */ 716cdf0e10cSrcweir } else { /* args are unsigned */ 717cdf0e10cSrcweir /* printf("!ARGS_ARE_XY_VALUES\n"); */ 718cdf0e10cSrcweir e = *ptr++; 719cdf0e10cSrcweir f = *ptr++; 720cdf0e10cSrcweir } 721cdf0e10cSrcweir 722cdf0e10cSrcweir } 723cdf0e10cSrcweir 724cdf0e10cSrcweir a = d = 0x10000; 725cdf0e10cSrcweir b = c = 0; 726cdf0e10cSrcweir 727cdf0e10cSrcweir if (flags & WE_HAVE_A_SCALE) { 728cdf0e10cSrcweir #ifdef DEBUG2 729cdf0e10cSrcweir fprintf(stderr, "WE_HAVE_A_SCALE\n"); 730cdf0e10cSrcweir #endif 731cdf0e10cSrcweir a = GetInt16(ptr, 0, 1) << 2; 732cdf0e10cSrcweir d = a; 733cdf0e10cSrcweir ptr += 2; 734cdf0e10cSrcweir } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 735cdf0e10cSrcweir #ifdef DEBUG2 736cdf0e10cSrcweir fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n"); 737cdf0e10cSrcweir #endif 738cdf0e10cSrcweir a = GetInt16(ptr, 0, 1) << 2; 739cdf0e10cSrcweir d = GetInt16(ptr, 2, 1) << 2; 740cdf0e10cSrcweir ptr += 4; 741cdf0e10cSrcweir } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 742cdf0e10cSrcweir #ifdef DEBUG2 743cdf0e10cSrcweir fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n"); 744cdf0e10cSrcweir #endif 745cdf0e10cSrcweir a = GetInt16(ptr, 0, 1) << 2; 746cdf0e10cSrcweir b = GetInt16(ptr, 2, 1) << 2; 747cdf0e10cSrcweir c = GetInt16(ptr, 4, 1) << 2; 748cdf0e10cSrcweir d = GetInt16(ptr, 6, 1) << 2; 749cdf0e10cSrcweir ptr += 8; 750cdf0e10cSrcweir } 751cdf0e10cSrcweir 752cdf0e10cSrcweir abs1 = (a < 0) ? -a : a; 753cdf0e10cSrcweir abs2 = (b < 0) ? -b : b; 754cdf0e10cSrcweir m = (abs1 > abs2) ? abs1 : abs2; 755cdf0e10cSrcweir abs3 = abs1 - abs2; 756cdf0e10cSrcweir if (abs3 < 0) abs3 = -abs3; 757cdf0e10cSrcweir if (abs3 <= 33) m *= 2; 758cdf0e10cSrcweir 759cdf0e10cSrcweir abs1 = (c < 0) ? -c : c; 760cdf0e10cSrcweir abs2 = (d < 0) ? -d : d; 761cdf0e10cSrcweir n = (abs1 > abs2) ? abs1 : abs2; 762cdf0e10cSrcweir abs3 = abs1 - abs2; 763cdf0e10cSrcweir if (abs3 < 0) abs3 = -abs3; 764cdf0e10cSrcweir if (abs3 <= 33) n *= 2; 765cdf0e10cSrcweir 766cdf0e10cSrcweir if (!ARGS_ARE_XY_VALUES) { /* match the points */ 767cdf0e10cSrcweir assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n"); 768cdf0e10cSrcweir } 769cdf0e10cSrcweir 770cdf0e10cSrcweir #ifdef DEBUG2 771cdf0e10cSrcweir fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n", 772cdf0e10cSrcweir ((double) a) / 65536, 773cdf0e10cSrcweir ((double) b) / 65536, 774cdf0e10cSrcweir ((double) c) / 65536, 775cdf0e10cSrcweir ((double) d) / 65536, 776cdf0e10cSrcweir ((double) e) / 65536, 777cdf0e10cSrcweir ((double) f) / 65536, 778cdf0e10cSrcweir ((double) m) / 65536, 779cdf0e10cSrcweir ((double) n) / 65536); 780cdf0e10cSrcweir #endif 781cdf0e10cSrcweir 782cdf0e10cSrcweir for (i=0; i<np; i++) { 783cdf0e10cSrcweir F16Dot16 t; 784cdf0e10cSrcweir ControlPoint cp; 785cdf0e10cSrcweir cp.flags = nextComponent[i].flags; 786cdf0e10cSrcweir t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16); 787cdf0e10cSrcweir cp.x = (sal_Int16)(fixedMul(t, m) >> 16); 788cdf0e10cSrcweir t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16); 789cdf0e10cSrcweir cp.y = (sal_Int16)(fixedMul(t, n) >> 16); 790cdf0e10cSrcweir 791cdf0e10cSrcweir #ifdef DEBUG2 792cdf0e10cSrcweir fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp.x, cp.y); 793cdf0e10cSrcweir #endif 794cdf0e10cSrcweir 795cdf0e10cSrcweir myPoints.push_back( cp ); 796cdf0e10cSrcweir } 797cdf0e10cSrcweir 798cdf0e10cSrcweir free(nextComponent); 799cdf0e10cSrcweir 800cdf0e10cSrcweir } while (flags & MORE_COMPONENTS); 801cdf0e10cSrcweir 802cdf0e10cSrcweir 803cdf0e10cSrcweir 804cdf0e10cSrcweir np = myPoints.size(); 805cdf0e10cSrcweir 806cdf0e10cSrcweir pa = (ControlPoint*)calloc(np, sizeof(ControlPoint)); 807cdf0e10cSrcweir assert(pa != 0); 808cdf0e10cSrcweir 809cdf0e10cSrcweir memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) ); 810cdf0e10cSrcweir 811cdf0e10cSrcweir *pointArray = pa; 812cdf0e10cSrcweir return np; 813cdf0e10cSrcweir } 814cdf0e10cSrcweir 815cdf0e10cSrcweir /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, 816cdf0e10cSrcweir * but Get{Simple|Compound}GlyphOutline returns 0 in such a case. 817cdf0e10cSrcweir * 818cdf0e10cSrcweir * NOTE: glyphlist is the stack of glyphs traversed while constructing 819cdf0e10cSrcweir * a composite glyph. This is a safequard against endless recursion 820cdf0e10cSrcweir * in corrupted fonts. 821cdf0e10cSrcweir */ 822cdf0e10cSrcweir static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist) 823cdf0e10cSrcweir { 824cdf0e10cSrcweir const sal_uInt8 *table = getTable( ttf, O_glyf ); 825cdf0e10cSrcweir sal_Int16 numberOfContours; 826cdf0e10cSrcweir int res; 827cdf0e10cSrcweir *pointArray = 0; 828cdf0e10cSrcweir 829cdf0e10cSrcweir if (metrics) { 830cdf0e10cSrcweir memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */ 831cdf0e10cSrcweir } 832cdf0e10cSrcweir 833cdf0e10cSrcweir if (glyphID >= ttf->nglyphs) return -1; /**/ 834cdf0e10cSrcweir 835cdf0e10cSrcweir const sal_uInt8* ptr = table + ttf->goffsets[glyphID]; 836cdf0e10cSrcweir int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 837cdf0e10cSrcweir 838cdf0e10cSrcweir if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */ 839cdf0e10cSrcweir if (metrics) GetMetrics(ttf, glyphID, metrics); 840cdf0e10cSrcweir return 0; 841cdf0e10cSrcweir } 842cdf0e10cSrcweir 843cdf0e10cSrcweir numberOfContours = GetInt16(ptr, 0, 1); 844cdf0e10cSrcweir 845cdf0e10cSrcweir if (numberOfContours >= 0) 846cdf0e10cSrcweir { 847cdf0e10cSrcweir res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics); 848cdf0e10cSrcweir } 849cdf0e10cSrcweir else 850cdf0e10cSrcweir { 851cdf0e10cSrcweir std::vector< sal_uInt32 > aPrivList; 852cdf0e10cSrcweir aPrivList.push_back( glyphID ); 853cdf0e10cSrcweir res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList ); 854cdf0e10cSrcweir } 855cdf0e10cSrcweir 856cdf0e10cSrcweir #ifdef DEBUG3 857cdf0e10cSrcweir { 858cdf0e10cSrcweir int i; 859cdf0e10cSrcweir FILE *out = fopen("points.dat", "a"); 860cdf0e10cSrcweir assert(out != 0); 861cdf0e10cSrcweir fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res); 862cdf0e10cSrcweir for (i=0; i<res; i++) { 863cdf0e10cSrcweir fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.'); 864cdf0e10cSrcweir fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-'); 865cdf0e10cSrcweir fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y); 866cdf0e10cSrcweir } 867cdf0e10cSrcweir fclose(out); 868cdf0e10cSrcweir } 869cdf0e10cSrcweir #endif 870cdf0e10cSrcweir 871cdf0e10cSrcweir return res; 872cdf0e10cSrcweir } 873cdf0e10cSrcweir 874cdf0e10cSrcweir #ifndef NO_TYPE3 875cdf0e10cSrcweir 876cdf0e10cSrcweir /*- returns the number of items in the path -*/ 877cdf0e10cSrcweir 878cdf0e10cSrcweir static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path) 879cdf0e10cSrcweir { 880cdf0e10cSrcweir std::vector< PSPathElement > aPathList; 881cdf0e10cSrcweir int nPathCount = 0; 882cdf0e10cSrcweir PSPathElement p( PS_NOOP ); 883cdf0e10cSrcweir 884cdf0e10cSrcweir int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury; 885cdf0e10cSrcweir int lastOff = 0; /*- last point was off-contour */ 886cdf0e10cSrcweir int scflag = 1; /*- start contour flag */ 887cdf0e10cSrcweir int ecflag = 0; /*- end contour flag */ 888cdf0e10cSrcweir int cp = 0; /*- current point */ 889cdf0e10cSrcweir int StartContour = 0, EndContour = 1; 890cdf0e10cSrcweir 891cdf0e10cSrcweir *path = 0; 892cdf0e10cSrcweir 893cdf0e10cSrcweir /* if (srcCount > 0) for(;;) */ 894cdf0e10cSrcweir while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */ 895cdf0e10cSrcweir if (scflag) { 896cdf0e10cSrcweir int l = cp; 897cdf0e10cSrcweir StartContour = cp; 898cdf0e10cSrcweir while (!(srcA[l].flags & 0x8000)) l++; 899cdf0e10cSrcweir EndContour = l; 900cdf0e10cSrcweir if (StartContour == EndContour) { 901cdf0e10cSrcweir if (cp + 1 < srcCount) { 902cdf0e10cSrcweir cp++; 903cdf0e10cSrcweir continue; 904cdf0e10cSrcweir } else { 905cdf0e10cSrcweir break; 906cdf0e10cSrcweir } 907cdf0e10cSrcweir } 908cdf0e10cSrcweir p = PSPathElement(PS_MOVETO); 909cdf0e10cSrcweir if (!(srcA[cp].flags & 1)) { 910cdf0e10cSrcweir if (!(srcA[EndContour].flags & 1)) { 911cdf0e10cSrcweir p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2; 912cdf0e10cSrcweir p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2; 913cdf0e10cSrcweir } else { 914cdf0e10cSrcweir p.x1 = x0 = srcA[EndContour].x; 915cdf0e10cSrcweir p.y1 = y0 = srcA[EndContour].y; 916cdf0e10cSrcweir } 917cdf0e10cSrcweir } else { 918cdf0e10cSrcweir p.x1 = x0 = srcA[cp].x; 919cdf0e10cSrcweir p.y1 = y0 = srcA[cp].y; 920cdf0e10cSrcweir cp++; 921cdf0e10cSrcweir } 922cdf0e10cSrcweir aPathList.push_back( p ); 923cdf0e10cSrcweir lastOff = 0; 924cdf0e10cSrcweir scflag = 0; 925cdf0e10cSrcweir } 926cdf0e10cSrcweir 927cdf0e10cSrcweir curx = srcA[cp].x; 928cdf0e10cSrcweir cury = srcA[cp].y; 929cdf0e10cSrcweir 930cdf0e10cSrcweir if (srcA[cp].flags & 1) 931cdf0e10cSrcweir { 932cdf0e10cSrcweir if (lastOff) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir p = PSPathElement(PS_CURVETO); 935cdf0e10cSrcweir p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 936cdf0e10cSrcweir p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 937cdf0e10cSrcweir p.x2 = x1 + (curx - x1 + 1) / 3; 938cdf0e10cSrcweir p.y2 = y1 + (cury - y1 + 1) / 3; 939cdf0e10cSrcweir p.x3 = curx; 940cdf0e10cSrcweir p.y3 = cury; 941cdf0e10cSrcweir aPathList.push_back( p ); 942cdf0e10cSrcweir } 943cdf0e10cSrcweir else 944cdf0e10cSrcweir { 945cdf0e10cSrcweir if (!(x0 == curx && y0 == cury)) 946cdf0e10cSrcweir { /* eliminate empty lines */ 947cdf0e10cSrcweir p = PSPathElement(PS_LINETO); 948cdf0e10cSrcweir p.x1 = curx; 949cdf0e10cSrcweir p.y1 = cury; 950cdf0e10cSrcweir aPathList.push_back( p ); 951cdf0e10cSrcweir } 952cdf0e10cSrcweir } 953cdf0e10cSrcweir x0 = curx; y0 = cury; lastOff = 0; 954cdf0e10cSrcweir } 955cdf0e10cSrcweir else 956cdf0e10cSrcweir { 957cdf0e10cSrcweir if (lastOff) 958cdf0e10cSrcweir { 959cdf0e10cSrcweir x2 = (x1 + curx + 1) / 2; 960cdf0e10cSrcweir y2 = (y1 + cury + 1) / 2; 961cdf0e10cSrcweir p = PSPathElement(PS_CURVETO); 962cdf0e10cSrcweir p.x1 = x0 + (2 * (x1 - x0) + 1) / 3; 963cdf0e10cSrcweir p.y1 = y0 + (2 * (y1 - y0) + 1) / 3; 964cdf0e10cSrcweir p.x2 = x1 + (x2 - x1 + 1) / 3; 965cdf0e10cSrcweir p.y2 = y1 + (y2 - y1 + 1) / 3; 966cdf0e10cSrcweir p.x3 = x2; 967cdf0e10cSrcweir p.y3 = y2; 968cdf0e10cSrcweir aPathList.push_back( p ); 969cdf0e10cSrcweir x0 = x2; y0 = y2; 970cdf0e10cSrcweir x1 = curx; y1 = cury; 971cdf0e10cSrcweir } else { 972cdf0e10cSrcweir x1 = curx; y1 = cury; 973cdf0e10cSrcweir } 974cdf0e10cSrcweir lastOff = true; 975cdf0e10cSrcweir } 976cdf0e10cSrcweir 977cdf0e10cSrcweir if (ecflag) { 978cdf0e10cSrcweir aPathList.push_back( PSPathElement(PS_CLOSEPATH) ); 979cdf0e10cSrcweir scflag = 1; 980cdf0e10cSrcweir ecflag = 0; 981cdf0e10cSrcweir cp = EndContour + 1; 982cdf0e10cSrcweir if (cp >= srcCount) break; 983cdf0e10cSrcweir continue; 984cdf0e10cSrcweir } 985cdf0e10cSrcweir 986cdf0e10cSrcweir 987cdf0e10cSrcweir if (cp == EndContour) { 988cdf0e10cSrcweir cp = StartContour; 989cdf0e10cSrcweir ecflag = true; 990cdf0e10cSrcweir } else { 991cdf0e10cSrcweir cp++; 992cdf0e10cSrcweir } 993cdf0e10cSrcweir } 994cdf0e10cSrcweir 995cdf0e10cSrcweir if( (nPathCount = (int)aPathList.size()) > 0) 996cdf0e10cSrcweir { 997cdf0e10cSrcweir *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement)); 998cdf0e10cSrcweir assert(*path != 0); 999cdf0e10cSrcweir memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) ); 1000cdf0e10cSrcweir } 1001cdf0e10cSrcweir 1002cdf0e10cSrcweir return nPathCount; 1003cdf0e10cSrcweir } 1004cdf0e10cSrcweir 1005cdf0e10cSrcweir #endif 1006cdf0e10cSrcweir 1007cdf0e10cSrcweir /*- Extracts a string from the name table and allocates memory for it -*/ 1008cdf0e10cSrcweir 1009cdf0e10cSrcweir static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result ) 1010cdf0e10cSrcweir { 1011cdf0e10cSrcweir int i; 1012cdf0e10cSrcweir char *res; 1013cdf0e10cSrcweir const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1); 1014cdf0e10cSrcweir int len = GetUInt16(name+6, 12 * n + 8, 1); 1015cdf0e10cSrcweir 1016cdf0e10cSrcweir // sanity check 1017cdf0e10cSrcweir if( (len <= 0) || ((ptr+len) > (name+nTableSize)) ) 1018cdf0e10cSrcweir { 1019cdf0e10cSrcweir if( ucs2result ) 1020cdf0e10cSrcweir *ucs2result = NULL; 1021cdf0e10cSrcweir return NULL; 1022cdf0e10cSrcweir } 1023cdf0e10cSrcweir 1024cdf0e10cSrcweir if( ucs2result ) 1025cdf0e10cSrcweir *ucs2result = NULL; 1026cdf0e10cSrcweir if (dbFlag) { 1027cdf0e10cSrcweir res = (char*)malloc(1 + len/2); 1028cdf0e10cSrcweir assert(res != 0); 1029cdf0e10cSrcweir for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1); 1030cdf0e10cSrcweir res[len/2] = 0; 1031cdf0e10cSrcweir if( ucs2result ) 1032cdf0e10cSrcweir { 1033cdf0e10cSrcweir *ucs2result = (sal_uInt16*)malloc( len+2 ); 1034cdf0e10cSrcweir for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 ); 1035cdf0e10cSrcweir (*ucs2result)[len/2] = 0; 1036cdf0e10cSrcweir } 1037cdf0e10cSrcweir } else { 1038cdf0e10cSrcweir res = (char*)malloc(1 + len); 1039cdf0e10cSrcweir assert(res != 0); 1040cdf0e10cSrcweir memcpy(res, ptr, len); 1041cdf0e10cSrcweir res[len] = 0; 1042cdf0e10cSrcweir } 1043cdf0e10cSrcweir 1044cdf0e10cSrcweir return res; 1045cdf0e10cSrcweir } 1046cdf0e10cSrcweir 1047cdf0e10cSrcweir static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID, 1048cdf0e10cSrcweir sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID ) 1049cdf0e10cSrcweir { 1050cdf0e10cSrcweir int l = 0, r = n-1, i; 1051cdf0e10cSrcweir sal_uInt32 t1, t2; 1052cdf0e10cSrcweir sal_uInt32 m1, m2; 1053cdf0e10cSrcweir 1054cdf0e10cSrcweir if (n == 0) return -1; 1055cdf0e10cSrcweir 1056cdf0e10cSrcweir m1 = (platformID << 16) | encodingID; 1057cdf0e10cSrcweir m2 = (languageID << 16) | nameID; 1058cdf0e10cSrcweir 1059cdf0e10cSrcweir do { 1060cdf0e10cSrcweir i = (l + r) >> 1; 1061cdf0e10cSrcweir t1 = GetUInt32(name + 6, i * 12 + 0, 1); 1062cdf0e10cSrcweir t2 = GetUInt32(name + 6, i * 12 + 4, 1); 1063cdf0e10cSrcweir 1064cdf0e10cSrcweir if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1; 1065cdf0e10cSrcweir if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1; 1066cdf0e10cSrcweir } while (l <= r); 1067cdf0e10cSrcweir 1068cdf0e10cSrcweir if (l - r == 2) { 1069cdf0e10cSrcweir return l - 1; 1070cdf0e10cSrcweir } 1071cdf0e10cSrcweir 1072cdf0e10cSrcweir return -1; 1073cdf0e10cSrcweir } 1074cdf0e10cSrcweir 1075cdf0e10cSrcweir /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. 1076cdf0e10cSrcweir * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033) 1077cdf0e10cSrcweir * 1078cdf0e10cSrcweir * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0) 1079cdf0e10cSrcweir * and does not have (3, 1, 1033) 1080cdf0e10cSrcweir * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will 1081cdf0e10cSrcweir * require a change in algorithm 1082cdf0e10cSrcweir * 1083cdf0e10cSrcweir * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID, 1084cdf0e10cSrcweir * but (1, 0, 1042) strings usable 1085cdf0e10cSrcweir * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found 1086cdf0e10cSrcweir */ 1087cdf0e10cSrcweir 1088cdf0e10cSrcweir static void GetNames(TrueTypeFont *t) 1089cdf0e10cSrcweir { 1090cdf0e10cSrcweir const sal_uInt8* table = getTable( t, O_name ); 1091cdf0e10cSrcweir int nTableSize = getTableSize(t, O_name); 1092cdf0e10cSrcweir 1093cdf0e10cSrcweir if (nTableSize < 4) 1094cdf0e10cSrcweir { 1095cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1096cdf0e10cSrcweir fprintf(stderr, "O_name table too small\n"); 1097cdf0e10cSrcweir #endif 1098cdf0e10cSrcweir return; 1099cdf0e10cSrcweir } 1100cdf0e10cSrcweir 1101cdf0e10cSrcweir sal_uInt16 n = GetUInt16(table, 2, 1); 1102cdf0e10cSrcweir int i, r; 1103cdf0e10cSrcweir sal_Bool bPSNameOK = sal_True; 1104cdf0e10cSrcweir 1105cdf0e10cSrcweir /* #129743# simple sanity check for name table entry count */ 1106cdf0e10cSrcweir if( nTableSize <= n * 12 + 6 ) 1107cdf0e10cSrcweir n = 0; 1108cdf0e10cSrcweir 1109cdf0e10cSrcweir /* PostScript name: preferred Microsoft */ 1110cdf0e10cSrcweir t->psname = NULL; 1111cdf0e10cSrcweir if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) 1112cdf0e10cSrcweir t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1113cdf0e10cSrcweir if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1) 1114cdf0e10cSrcweir t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1115cdf0e10cSrcweir if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1) 1116cdf0e10cSrcweir { 1117cdf0e10cSrcweir // some symbol fonts like Marlett have a 3,0 name! 1118cdf0e10cSrcweir t->psname = nameExtract(table, nTableSize, r, 1, NULL); 1119cdf0e10cSrcweir } 1120cdf0e10cSrcweir // for embedded font in Ghostscript PDFs 1121cdf0e10cSrcweir if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1) 1122cdf0e10cSrcweir { 1123cdf0e10cSrcweir t->psname = nameExtract(table, nTableSize, r, 0, NULL); 1124cdf0e10cSrcweir } 1125cdf0e10cSrcweir if ( ! t->psname ) 1126cdf0e10cSrcweir { 1127cdf0e10cSrcweir if ( t->fname ) 1128cdf0e10cSrcweir { 1129cdf0e10cSrcweir char* pReverse = t->fname + strlen(t->fname); 1130cdf0e10cSrcweir /* take only last token of filename */ 1131cdf0e10cSrcweir while(pReverse != t->fname && *pReverse != '/') pReverse--; 1132cdf0e10cSrcweir if(*pReverse == '/') pReverse++; 1133cdf0e10cSrcweir t->psname = strdup(pReverse); 1134cdf0e10cSrcweir assert(t->psname != 0); 1135cdf0e10cSrcweir for (i=strlen(t->psname) - 1; i > 0; i--) 1136cdf0e10cSrcweir { 1137cdf0e10cSrcweir /*- Remove the suffix -*/ 1138cdf0e10cSrcweir if (t->psname[i] == '.' ) { 1139cdf0e10cSrcweir t->psname[i] = 0; 1140cdf0e10cSrcweir break; 1141cdf0e10cSrcweir } 1142cdf0e10cSrcweir } 1143cdf0e10cSrcweir } 1144cdf0e10cSrcweir else 1145cdf0e10cSrcweir t->psname = strdup( "Unknown" ); 1146cdf0e10cSrcweir } 1147cdf0e10cSrcweir 1148cdf0e10cSrcweir /* Font family and subfamily names: preferred Apple */ 1149cdf0e10cSrcweir t->family = NULL; 1150cdf0e10cSrcweir if ((r = findname(table, n, 0, 0, 0, 1)) != -1) 1151cdf0e10cSrcweir t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1152cdf0e10cSrcweir if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1) 1153cdf0e10cSrcweir t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1154cdf0e10cSrcweir if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1) 1155cdf0e10cSrcweir t->family = nameExtract(table, nTableSize, r, 0, NULL); 1156cdf0e10cSrcweir if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1) 1157cdf0e10cSrcweir t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1158cdf0e10cSrcweir if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1) 1159cdf0e10cSrcweir t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily); 1160cdf0e10cSrcweir if ( ! t->family ) 1161cdf0e10cSrcweir { 1162cdf0e10cSrcweir t->family = strdup(t->psname); 1163cdf0e10cSrcweir assert(t->family != 0); 1164cdf0e10cSrcweir } 1165cdf0e10cSrcweir 1166cdf0e10cSrcweir t->subfamily = NULL; 1167cdf0e10cSrcweir t->usubfamily = NULL; 1168cdf0e10cSrcweir if ((r = findname(table, n, 1, 0, 0, 2)) != -1) 1169cdf0e10cSrcweir t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily); 1170cdf0e10cSrcweir if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1) 1171cdf0e10cSrcweir t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily); 1172cdf0e10cSrcweir if ( ! t->subfamily ) 1173cdf0e10cSrcweir { 1174cdf0e10cSrcweir t->subfamily = strdup(""); 1175cdf0e10cSrcweir } 1176cdf0e10cSrcweir 1177cdf0e10cSrcweir /* #i60349# sanity check psname 1178cdf0e10cSrcweir * psname parctically has to be 7bit ascii and should not contains spaces 1179cdf0e10cSrcweir * there is a class of broken fonts which do not fullfill that at all, so let's try 1180cdf0e10cSrcweir * if the family name is 7bit ascii and take it instead if so 1181cdf0e10cSrcweir */ 1182cdf0e10cSrcweir /* check psname */ 1183cdf0e10cSrcweir for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ ) 1184cdf0e10cSrcweir if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) ) 1185cdf0e10cSrcweir bPSNameOK = sal_False; 1186cdf0e10cSrcweir if( bPSNameOK == sal_False ) 1187cdf0e10cSrcweir { 1188cdf0e10cSrcweir sal_Bool bReplace = sal_True; 1189cdf0e10cSrcweir /* check if family is a suitable replacement */ 1190cdf0e10cSrcweir if( t->ufamily && t->family ) 1191cdf0e10cSrcweir { 1192cdf0e10cSrcweir for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ ) 1193cdf0e10cSrcweir if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 ) 1194cdf0e10cSrcweir bReplace = sal_False; 1195cdf0e10cSrcweir if( bReplace ) 1196cdf0e10cSrcweir { 1197cdf0e10cSrcweir free( t->psname ); 1198cdf0e10cSrcweir t->psname = strdup( t->family ); 1199cdf0e10cSrcweir } 1200cdf0e10cSrcweir } 1201cdf0e10cSrcweir } 1202cdf0e10cSrcweir } 1203cdf0e10cSrcweir 1204cdf0e10cSrcweir enum cmapType { 1205cdf0e10cSrcweir CMAP_NOT_USABLE = -1, 1206cdf0e10cSrcweir CMAP_MS_Symbol = 10, 1207cdf0e10cSrcweir CMAP_MS_Unicode = 11, 1208cdf0e10cSrcweir CMAP_MS_ShiftJIS = 12, 1209cdf0e10cSrcweir CMAP_MS_Big5 = 13, 1210cdf0e10cSrcweir CMAP_MS_PRC = 14, 1211cdf0e10cSrcweir CMAP_MS_Wansung = 15, 1212cdf0e10cSrcweir CMAP_MS_Johab = 16 1213cdf0e10cSrcweir }; 1214cdf0e10cSrcweir 1215cdf0e10cSrcweir #define MISSING_GLYPH_INDEX 0 1216cdf0e10cSrcweir 1217cdf0e10cSrcweir /* 1218cdf0e10cSrcweir * getGlyph[0246]() functions and freinds are implemented by: 1219cdf0e10cSrcweir * @author Manpreet Singh 1220cdf0e10cSrcweir * getGlyph12() function and friends by: 1221cdf0e10cSrcweir * @author HDU 1222cdf0e10cSrcweir */ 1223cdf0e10cSrcweir static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) { 1224cdf0e10cSrcweir if (c <= 255) { 1225cdf0e10cSrcweir return *(cmap + 6 + c); 1226cdf0e10cSrcweir } else { 1227cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1228cdf0e10cSrcweir } 1229cdf0e10cSrcweir } 1230cdf0e10cSrcweir 1231cdf0e10cSrcweir typedef struct _subHeader2 { 1232cdf0e10cSrcweir sal_uInt16 firstCode; 1233cdf0e10cSrcweir sal_uInt16 entryCount; 1234cdf0e10cSrcweir sal_uInt16 idDelta; 1235cdf0e10cSrcweir sal_uInt16 idRangeOffset; 1236cdf0e10cSrcweir } subHeader2; 1237cdf0e10cSrcweir 1238cdf0e10cSrcweir static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) { 1239cdf0e10cSrcweir sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap; 1240cdf0e10cSrcweir sal_uInt8 theHighByte; 1241cdf0e10cSrcweir 1242cdf0e10cSrcweir sal_uInt8 theLowByte; 1243cdf0e10cSrcweir subHeader2* subHeader2s; 1244cdf0e10cSrcweir sal_uInt16* subHeader2Keys; 1245cdf0e10cSrcweir sal_uInt16 firstCode; 1246cdf0e10cSrcweir int k; 1247cdf0e10cSrcweir sal_uInt32 ToReturn; 1248cdf0e10cSrcweir 1249cdf0e10cSrcweir theHighByte = (sal_uInt8)((c >> 8) & 0x00ff); 1250cdf0e10cSrcweir theLowByte = (sal_uInt8)(c & 0x00ff); 1251cdf0e10cSrcweir subHeader2Keys = CMAP2 + 3; 1252cdf0e10cSrcweir subHeader2s = (subHeader2 *)(subHeader2Keys + 256); 1253cdf0e10cSrcweir k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8; 1254cdf0e10cSrcweir 1255cdf0e10cSrcweir if(k == 0) { 1256cdf0e10cSrcweir firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1257cdf0e10cSrcweir if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1258cdf0e10cSrcweir return *((&(subHeader2s[0].idRangeOffset)) 1259cdf0e10cSrcweir + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */ 1260cdf0e10cSrcweir + theLowByte /* + to_look */ 1261cdf0e10cSrcweir - Int16FromMOTA(subHeader2s[0].firstCode) 1262cdf0e10cSrcweir ); 1263cdf0e10cSrcweir } else { 1264cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1265cdf0e10cSrcweir } 1266cdf0e10cSrcweir } else if (k > 0) { 1267cdf0e10cSrcweir firstCode = Int16FromMOTA(subHeader2s[k].firstCode); 1268cdf0e10cSrcweir if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { 1269cdf0e10cSrcweir ToReturn = *((&(subHeader2s[k].idRangeOffset)) 1270cdf0e10cSrcweir + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2) 1271cdf0e10cSrcweir + theLowByte - firstCode); 1272cdf0e10cSrcweir if(ToReturn == 0) { 1273cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1274cdf0e10cSrcweir } else { 1275cdf0e10cSrcweir ToReturn += Int16FromMOTA(subHeader2s[k].idDelta); 1276cdf0e10cSrcweir return (ToReturn & 0xFFFF); 1277cdf0e10cSrcweir } 1278cdf0e10cSrcweir } else { 1279cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1280cdf0e10cSrcweir } 1281cdf0e10cSrcweir } else { 1282cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1283cdf0e10cSrcweir } 1284cdf0e10cSrcweir } 1285cdf0e10cSrcweir 1286cdf0e10cSrcweir static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) { 1287cdf0e10cSrcweir sal_uInt16 firstCode, lastCode, count; 1288cdf0e10cSrcweir sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap; 1289cdf0e10cSrcweir 1290cdf0e10cSrcweir firstCode = Int16FromMOTA(*(CMAP6 + 3)); 1291cdf0e10cSrcweir count = Int16FromMOTA(*(CMAP6 + 4)); 1292cdf0e10cSrcweir lastCode = firstCode + count - 1; 1293cdf0e10cSrcweir if (c < firstCode || c > lastCode) { 1294cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1295cdf0e10cSrcweir } else { 1296cdf0e10cSrcweir return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode)); 1297cdf0e10cSrcweir } 1298cdf0e10cSrcweir } 1299cdf0e10cSrcweir 1300cdf0e10cSrcweir static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) { 1301cdf0e10cSrcweir signed int low, mid, high, lastfound = 0xffff; 1302cdf0e10cSrcweir sal_uInt16 res; 1303cdf0e10cSrcweir if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) { 1304cdf0e10cSrcweir return (sal_uInt16)0xFFFF; 1305cdf0e10cSrcweir } 1306cdf0e10cSrcweir low = 0; 1307cdf0e10cSrcweir high = length - 1; 1308cdf0e10cSrcweir while(high >= low) { 1309cdf0e10cSrcweir mid = (high + low)/2; 1310cdf0e10cSrcweir res = Int16FromMOTA(*(ar+mid)); 1311cdf0e10cSrcweir if(res >= toSearch) { 1312cdf0e10cSrcweir lastfound = mid; 1313cdf0e10cSrcweir high = --mid; 1314cdf0e10cSrcweir } else { 1315cdf0e10cSrcweir low = ++mid; 1316cdf0e10cSrcweir } 1317cdf0e10cSrcweir } 1318cdf0e10cSrcweir return (sal_uInt16)lastfound; 1319cdf0e10cSrcweir } 1320cdf0e10cSrcweir 1321cdf0e10cSrcweir 1322cdf0e10cSrcweir static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) { 1323cdf0e10cSrcweir sal_uInt16 i; 1324cdf0e10cSrcweir int ToReturn; 1325cdf0e10cSrcweir sal_uInt16 segCount; 1326cdf0e10cSrcweir sal_uInt16 * startCode; 1327cdf0e10cSrcweir sal_uInt16 * endCode; 1328cdf0e10cSrcweir sal_uInt16 * idDelta; 1329cdf0e10cSrcweir /* sal_uInt16 * glyphIdArray; */ 1330cdf0e10cSrcweir sal_uInt16 * idRangeOffset; 1331cdf0e10cSrcweir sal_uInt16 * glyphIndexArray; 1332cdf0e10cSrcweir sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap; 1333cdf0e10cSrcweir /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */ 1334cdf0e10cSrcweir 1335cdf0e10cSrcweir segCount = Int16FromMOTA(*(CMAP4 + 3))/2; 1336cdf0e10cSrcweir endCode = CMAP4 + 7; 1337cdf0e10cSrcweir i = GEbinsearch(endCode, segCount, (sal_uInt16)c); 1338cdf0e10cSrcweir 1339cdf0e10cSrcweir if (i == (sal_uInt16) 0xFFFF) { 1340cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1341cdf0e10cSrcweir } 1342cdf0e10cSrcweir startCode = endCode + segCount + 1; 1343cdf0e10cSrcweir 1344cdf0e10cSrcweir if(Int16FromMOTA(startCode[i]) > c) { 1345cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1346cdf0e10cSrcweir } 1347cdf0e10cSrcweir idDelta = startCode + segCount; 1348cdf0e10cSrcweir idRangeOffset = idDelta + segCount; 1349cdf0e10cSrcweir glyphIndexArray = idRangeOffset + segCount; 1350cdf0e10cSrcweir 1351cdf0e10cSrcweir if(Int16FromMOTA(idRangeOffset[i]) != 0) { 1352cdf0e10cSrcweir c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i]))))); 1353cdf0e10cSrcweir } 1354cdf0e10cSrcweir 1355cdf0e10cSrcweir ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF; 1356cdf0e10cSrcweir return ToReturn; 1357cdf0e10cSrcweir } 1358cdf0e10cSrcweir 1359cdf0e10cSrcweir static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) { 1360cdf0e10cSrcweir const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap; 1361cdf0e10cSrcweir int nLength = Int32FromMOTA( pCMAP12[1] ); 1362cdf0e10cSrcweir int nGroups = Int32FromMOTA( pCMAP12[3] ); 1363cdf0e10cSrcweir int nLower = 0; 1364cdf0e10cSrcweir int nUpper = nGroups; 1365cdf0e10cSrcweir 1366cdf0e10cSrcweir if( nUpper > (nLength-16)/12 ) 1367cdf0e10cSrcweir nUpper = (nLength-16)/12; 1368cdf0e10cSrcweir 1369cdf0e10cSrcweir /* binary search in "segmented coverage" subtable */ 1370cdf0e10cSrcweir while( nLower < nUpper ) { 1371cdf0e10cSrcweir int nIndex = (nLower + nUpper) / 2; 1372cdf0e10cSrcweir const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ]; 1373cdf0e10cSrcweir sal_uInt32 cStart = Int32FromMOTA( pEntry[0] ); 1374cdf0e10cSrcweir sal_uInt32 cLast = Int32FromMOTA( pEntry[1] ); 1375cdf0e10cSrcweir if( cChar < cStart ) 1376cdf0e10cSrcweir nUpper = nIndex; 1377cdf0e10cSrcweir else if( cChar > cLast ) 1378cdf0e10cSrcweir nLower = nIndex + 1; 1379cdf0e10cSrcweir else { /* found matching entry! */ 1380cdf0e10cSrcweir sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] ); 1381cdf0e10cSrcweir nGlyph += cChar - cStart; 1382cdf0e10cSrcweir return nGlyph; 1383cdf0e10cSrcweir } 1384cdf0e10cSrcweir } 1385cdf0e10cSrcweir 1386cdf0e10cSrcweir return MISSING_GLYPH_INDEX; 1387cdf0e10cSrcweir } 1388cdf0e10cSrcweir 1389cdf0e10cSrcweir 1390cdf0e10cSrcweir static void FindCmap(TrueTypeFont *ttf) 1391cdf0e10cSrcweir { 1392cdf0e10cSrcweir const sal_uInt8* table = getTable(ttf, O_cmap); 1393cdf0e10cSrcweir sal_uInt32 table_size = getTableSize(ttf, O_cmap); 1394cdf0e10cSrcweir sal_uInt16 ncmaps = GetUInt16(table, 2, 1); 1395cdf0e10cSrcweir unsigned int i; 1396cdf0e10cSrcweir sal_uInt32 AppleUni = 0; // Apple Unicode 1397cdf0e10cSrcweir sal_uInt32 ThreeZero = 0; /* MS Symbol */ 1398cdf0e10cSrcweir sal_uInt32 ThreeOne = 0; /* MS UCS-2 */ 1399cdf0e10cSrcweir sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */ 1400cdf0e10cSrcweir sal_uInt32 ThreeThree = 0; /* MS Big5 */ 1401cdf0e10cSrcweir sal_uInt32 ThreeFour = 0; /* MS PRC */ 1402cdf0e10cSrcweir sal_uInt32 ThreeFive = 0; /* MS Wansung */ 1403cdf0e10cSrcweir sal_uInt32 ThreeSix = 0; /* MS Johab */ 1404cdf0e10cSrcweir 1405cdf0e10cSrcweir for (i = 0; i < ncmaps; i++) { 1406cdf0e10cSrcweir sal_uInt32 offset; 1407cdf0e10cSrcweir sal_uInt16 pID, eID; 1408cdf0e10cSrcweir 1409cdf0e10cSrcweir /* sanity check, cmap entry must lie within table */ 1410cdf0e10cSrcweir if( i*8+4 > table_size ) 1411cdf0e10cSrcweir break; 1412cdf0e10cSrcweir 1413cdf0e10cSrcweir pID = GetUInt16(table, 4 + i * 8, 1); 1414cdf0e10cSrcweir eID = GetUInt16(table, 6 + i * 8, 1); 1415cdf0e10cSrcweir offset = GetUInt32(table, 8 + i * 8, 1); 1416cdf0e10cSrcweir 1417cdf0e10cSrcweir /* sanity check, cmap must lie within file */ 1418cdf0e10cSrcweir if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize ) 1419cdf0e10cSrcweir continue; 1420cdf0e10cSrcweir 1421cdf0e10cSrcweir /* Unicode tables in Apple fonts */ 1422cdf0e10cSrcweir if (pID == 0) { 1423cdf0e10cSrcweir AppleUni = offset; 1424cdf0e10cSrcweir } 1425cdf0e10cSrcweir 1426cdf0e10cSrcweir if (pID == 3) { 1427cdf0e10cSrcweir switch (eID) { 1428cdf0e10cSrcweir case 0: ThreeZero = offset; break; 1429cdf0e10cSrcweir case 10: // UCS-4 1430cdf0e10cSrcweir case 1: ThreeOne = offset; break; 1431cdf0e10cSrcweir case 2: ThreeTwo = offset; break; 1432cdf0e10cSrcweir case 3: ThreeThree = offset; break; 1433cdf0e10cSrcweir case 4: ThreeFour = offset; break; 1434cdf0e10cSrcweir case 5: ThreeFive = offset; break; 1435cdf0e10cSrcweir case 6: ThreeSix = offset; break; 1436cdf0e10cSrcweir } 1437cdf0e10cSrcweir } 1438cdf0e10cSrcweir } 1439cdf0e10cSrcweir 1440cdf0e10cSrcweir // fall back to AppleUnicode if there are no ThreeOne/Threezero tables 1441cdf0e10cSrcweir if( AppleUni && !ThreeZero && !ThreeOne) 1442cdf0e10cSrcweir ThreeOne = AppleUni; 1443cdf0e10cSrcweir 1444cdf0e10cSrcweir if (ThreeOne) { 1445cdf0e10cSrcweir ttf->cmapType = CMAP_MS_Unicode; 1446cdf0e10cSrcweir ttf->cmap = table + ThreeOne; 1447cdf0e10cSrcweir } else if (ThreeTwo) { 1448cdf0e10cSrcweir ttf->cmapType = CMAP_MS_ShiftJIS; 1449cdf0e10cSrcweir ttf->cmap = table + ThreeTwo; 1450cdf0e10cSrcweir } else if (ThreeThree) { 1451cdf0e10cSrcweir ttf->cmapType = CMAP_MS_Big5; 1452cdf0e10cSrcweir ttf->cmap = table + ThreeThree; 1453cdf0e10cSrcweir } else if (ThreeFour) { 1454cdf0e10cSrcweir ttf->cmapType = CMAP_MS_PRC; 1455cdf0e10cSrcweir ttf->cmap = table + ThreeFour; 1456cdf0e10cSrcweir } else if (ThreeFive) { 1457cdf0e10cSrcweir ttf->cmapType = CMAP_MS_Wansung; 1458cdf0e10cSrcweir ttf->cmap = table + ThreeFive; 1459cdf0e10cSrcweir } else if (ThreeSix) { 1460cdf0e10cSrcweir ttf->cmapType = CMAP_MS_Johab; 1461cdf0e10cSrcweir ttf->cmap = table + ThreeSix; 1462cdf0e10cSrcweir } else if (ThreeZero) { 1463cdf0e10cSrcweir ttf->cmapType = CMAP_MS_Symbol; 1464cdf0e10cSrcweir ttf->cmap = table + ThreeZero; 1465cdf0e10cSrcweir } else { 1466cdf0e10cSrcweir ttf->cmapType = CMAP_NOT_USABLE; 1467cdf0e10cSrcweir ttf->cmap = 0; 1468cdf0e10cSrcweir } 1469cdf0e10cSrcweir 1470cdf0e10cSrcweir if (ttf->cmapType != CMAP_NOT_USABLE) { 1471cdf0e10cSrcweir switch (GetUInt16(ttf->cmap, 0, 1)) { 1472cdf0e10cSrcweir case 0: ttf->mapper = getGlyph0; break; 1473cdf0e10cSrcweir case 2: ttf->mapper = getGlyph2; break; 1474cdf0e10cSrcweir case 4: ttf->mapper = getGlyph4; break; 1475cdf0e10cSrcweir case 6: ttf->mapper = getGlyph6; break; 1476cdf0e10cSrcweir case 12: ttf->mapper= getGlyph12; break; 1477cdf0e10cSrcweir default: 1478cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1479cdf0e10cSrcweir /*- if the cmap table is really broken */ 1480cdf0e10cSrcweir printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1)); 1481cdf0e10cSrcweir #endif 1482cdf0e10cSrcweir ttf->cmapType = CMAP_NOT_USABLE; 1483cdf0e10cSrcweir ttf->cmap = 0; 1484cdf0e10cSrcweir ttf->mapper = 0; 1485cdf0e10cSrcweir } 1486cdf0e10cSrcweir } 1487cdf0e10cSrcweir } 1488cdf0e10cSrcweir 1489cdf0e10cSrcweir static void GetKern(TrueTypeFont *ttf) 1490cdf0e10cSrcweir { 1491cdf0e10cSrcweir const sal_uInt8* table = getTable(ttf, O_kern); 1492cdf0e10cSrcweir const sal_uInt8 *ptr; 1493cdf0e10cSrcweir 1494cdf0e10cSrcweir if( !table ) 1495cdf0e10cSrcweir goto badtable; 1496cdf0e10cSrcweir 1497cdf0e10cSrcweir if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */ 1498cdf0e10cSrcweir ttf->nkern = GetUInt16(table, 2, 1); 1499cdf0e10cSrcweir ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *)); 1500cdf0e10cSrcweir assert(ttf->kerntables != 0); 1501cdf0e10cSrcweir memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1502cdf0e10cSrcweir ttf->kerntype = KT_MICROSOFT; 1503cdf0e10cSrcweir ptr = table + 4; 1504cdf0e10cSrcweir for( unsigned i = 0; i < ttf->nkern; ++i) { 1505cdf0e10cSrcweir ttf->kerntables[i] = ptr; 1506cdf0e10cSrcweir ptr += GetUInt16(ptr, 2, 1); 1507cdf0e10cSrcweir /* sanity check */ 1508cdf0e10cSrcweir if( ptr > ttf->ptr+ttf->fsize ) 1509cdf0e10cSrcweir { 1510cdf0e10cSrcweir free( ttf->kerntables ); 1511cdf0e10cSrcweir goto badtable; 1512cdf0e10cSrcweir } 1513cdf0e10cSrcweir } 1514cdf0e10cSrcweir return; 1515cdf0e10cSrcweir } 1516cdf0e10cSrcweir 1517cdf0e10cSrcweir if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */ 1518cdf0e10cSrcweir ttf->nkern = GetUInt32(table, 4, 1); 1519cdf0e10cSrcweir ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*)); 1520cdf0e10cSrcweir assert(ttf->kerntables != 0); 1521cdf0e10cSrcweir memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *)); 1522cdf0e10cSrcweir ttf->kerntype = KT_APPLE_NEW; 1523cdf0e10cSrcweir ptr = table + 8; 1524cdf0e10cSrcweir for( unsigned i = 0; i < ttf->nkern; ++i) { 1525cdf0e10cSrcweir ttf->kerntables[i] = ptr; 1526cdf0e10cSrcweir ptr += GetUInt32(ptr, 0, 1); 1527cdf0e10cSrcweir /* sanity check; there are some fonts that are broken in this regard */ 1528cdf0e10cSrcweir if( ptr > ttf->ptr+ttf->fsize ) 1529cdf0e10cSrcweir { 1530cdf0e10cSrcweir free( ttf->kerntables ); 1531cdf0e10cSrcweir goto badtable; 1532cdf0e10cSrcweir } 1533cdf0e10cSrcweir } 1534cdf0e10cSrcweir return; 1535cdf0e10cSrcweir } 1536cdf0e10cSrcweir 1537cdf0e10cSrcweir badtable: 1538cdf0e10cSrcweir ttf->kerntype = KT_NONE; 1539cdf0e10cSrcweir ttf->kerntables = 0; 1540cdf0e10cSrcweir 1541cdf0e10cSrcweir return; 1542cdf0e10cSrcweir } 1543cdf0e10cSrcweir 1544cdf0e10cSrcweir #ifdef TEST5 1545cdf0e10cSrcweir /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and 1546cdf0e10cSrcweir * that x and y elements of the kern array are initialized to zeroes 1547cdf0e10cSrcweir */ 1548cdf0e10cSrcweir static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1549cdf0e10cSrcweir { 1550cdf0e10cSrcweir (void)ttf; /* avoid warning */ 1551cdf0e10cSrcweir (void)glyphs; /* avoid warning */ 1552cdf0e10cSrcweir (void)nglyphs; /* avoid warning */ 1553cdf0e10cSrcweir (void)wmode; /* avoid warning */ 1554cdf0e10cSrcweir (void)nglyphs; /* avoid warning */ 1555cdf0e10cSrcweir (void)kern; /* avoid warning */ 1556cdf0e10cSrcweir fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n"); 1557cdf0e10cSrcweir } 1558cdf0e10cSrcweir 1559cdf0e10cSrcweir static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 1560cdf0e10cSrcweir { 1561cdf0e10cSrcweir sal_uInt32 i, j; 1562cdf0e10cSrcweir sal_uInt32 gpair; 1563cdf0e10cSrcweir 1564cdf0e10cSrcweir if( ! nglyphs ) 1565cdf0e10cSrcweir return; 1566cdf0e10cSrcweir 1567cdf0e10cSrcweir for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) { 1568cdf0e10cSrcweir gpair = (glyphs[i] << 16) | glyphs[i+1]; 1569cdf0e10cSrcweir #ifdef DEBUG2 1570cdf0e10cSrcweir /* All fonts with MS kern table that I've seen so far contain just one kern subtable. 1571cdf0e10cSrcweir * MS kern documentation is very poor and I doubt that font developers will be using 1572cdf0e10cSrcweir * several subtables. I expect them to be using OpenType tables instead. 1573cdf0e10cSrcweir * According to MS documention, format 2 subtables are not supported by Windows and OS/2. 1574cdf0e10cSrcweir */ 1575cdf0e10cSrcweir if (ttf->nkern > 1) { 1576cdf0e10cSrcweir fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern); 1577cdf0e10cSrcweir } 1578cdf0e10cSrcweir #endif 1579cdf0e10cSrcweir for (j = 0; j < ttf->nkern; j++) { 1580cdf0e10cSrcweir sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1); 1581cdf0e10cSrcweir sal_uInt8 *ptr; 1582cdf0e10cSrcweir int npairs; 1583cdf0e10cSrcweir sal_uInt32 t; 1584cdf0e10cSrcweir int l, r, k; 1585cdf0e10cSrcweir 1586cdf0e10cSrcweir if (! ((coverage & 1) ^ wmode)) continue; 1587cdf0e10cSrcweir if ((coverage & 0xFFFE) != 0) { 1588cdf0e10cSrcweir #ifdef DEBUG2 1589cdf0e10cSrcweir fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage); 1590cdf0e10cSrcweir #endif 1591cdf0e10cSrcweir continue; 1592cdf0e10cSrcweir } 1593cdf0e10cSrcweir ptr = ttf->kerntables[j]; 1594cdf0e10cSrcweir npairs = GetUInt16(ptr, 6, 1); 1595cdf0e10cSrcweir ptr += 14; 1596cdf0e10cSrcweir l = 0; 1597cdf0e10cSrcweir r = npairs; 1598cdf0e10cSrcweir do { 1599cdf0e10cSrcweir k = (l + r) >> 1; 1600cdf0e10cSrcweir t = GetUInt32(ptr, k * 6, 1); 1601cdf0e10cSrcweir if (gpair >= t) l = k + 1; 1602cdf0e10cSrcweir if (gpair <= t) r = k - 1; 1603cdf0e10cSrcweir } while (l <= r); 1604cdf0e10cSrcweir if (l - r == 2) { 1605cdf0e10cSrcweir if (!wmode) { 1606cdf0e10cSrcweir kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1607cdf0e10cSrcweir } else { 1608cdf0e10cSrcweir kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1)); 1609cdf0e10cSrcweir } 1610cdf0e10cSrcweir /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */ 1611cdf0e10cSrcweir } 1612cdf0e10cSrcweir } 1613cdf0e10cSrcweir } 1614cdf0e10cSrcweir } 1615cdf0e10cSrcweir #endif 1616cdf0e10cSrcweir 1617cdf0e10cSrcweir /*- Public functions */ /*FOLD00*/ 1618cdf0e10cSrcweir 1619cdf0e10cSrcweir int CountTTCFonts(const char* fname) 1620cdf0e10cSrcweir { 1621cdf0e10cSrcweir int nFonts = 0; 1622cdf0e10cSrcweir sal_uInt8 buffer[12]; 1623cdf0e10cSrcweir FILE* fd = fopen(fname, "rb"); 1624cdf0e10cSrcweir if( fd ) { 1625cdf0e10cSrcweir if (fread(buffer, 1, 12, fd) == 12) { 1626cdf0e10cSrcweir if(GetUInt32(buffer, 0, 1) == T_ttcf ) 1627cdf0e10cSrcweir nFonts = GetUInt32(buffer, 8, 1); 1628cdf0e10cSrcweir } 1629cdf0e10cSrcweir fclose(fd); 1630cdf0e10cSrcweir } 1631cdf0e10cSrcweir return nFonts; 1632cdf0e10cSrcweir } 1633cdf0e10cSrcweir 1634cdf0e10cSrcweir static void allocTrueTypeFont( TrueTypeFont** ttf ) 1635cdf0e10cSrcweir { 1636cdf0e10cSrcweir *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont)); 1637cdf0e10cSrcweir if( *ttf != NULL ) 1638cdf0e10cSrcweir { 1639cdf0e10cSrcweir (*ttf)->tag = 0; 1640cdf0e10cSrcweir (*ttf)->fname = 0; 1641cdf0e10cSrcweir (*ttf)->fsize = -1; 1642cdf0e10cSrcweir (*ttf)->ptr = 0; 1643cdf0e10cSrcweir (*ttf)->nglyphs = 0xFFFFFFFF; 1644cdf0e10cSrcweir (*ttf)->pGSubstitution = 0; 1645cdf0e10cSrcweir } 1646cdf0e10cSrcweir } 1647cdf0e10cSrcweir 1648cdf0e10cSrcweir /* forward declariotn for the two entry points to use*/ 1649cdf0e10cSrcweir static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ); 1650cdf0e10cSrcweir 1651cdf0e10cSrcweir #if !defined(WIN32) && !defined(OS2) 1652cdf0e10cSrcweir int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf ) 1653cdf0e10cSrcweir { 1654cdf0e10cSrcweir int ret, fd = -1; 1655cdf0e10cSrcweir struct stat st; 1656cdf0e10cSrcweir 1657cdf0e10cSrcweir if (!fname || !*fname) return SF_BADFILE; 1658cdf0e10cSrcweir 1659cdf0e10cSrcweir allocTrueTypeFont( ttf ); 1660cdf0e10cSrcweir if( ! *ttf ) 1661cdf0e10cSrcweir return SF_MEMORY; 1662cdf0e10cSrcweir 1663cdf0e10cSrcweir (*ttf)->fname = strdup(fname); 1664cdf0e10cSrcweir if( ! (*ttf)->fname ) 1665cdf0e10cSrcweir { 1666cdf0e10cSrcweir ret = SF_MEMORY; 1667cdf0e10cSrcweir goto cleanup; 1668cdf0e10cSrcweir } 1669cdf0e10cSrcweir 1670cdf0e10cSrcweir fd = open(fname, O_RDONLY); 1671cdf0e10cSrcweir 1672cdf0e10cSrcweir if (fd == -1) { 1673cdf0e10cSrcweir ret = SF_BADFILE; 1674cdf0e10cSrcweir goto cleanup; 1675cdf0e10cSrcweir } 1676cdf0e10cSrcweir 1677cdf0e10cSrcweir if (fstat(fd, &st) == -1) { 1678cdf0e10cSrcweir ret = SF_FILEIO; 1679cdf0e10cSrcweir goto cleanup; 1680cdf0e10cSrcweir } 1681cdf0e10cSrcweir 1682cdf0e10cSrcweir (*ttf)->fsize = st.st_size; 1683cdf0e10cSrcweir 1684cdf0e10cSrcweir /* On Mac OS, most likely will happen if a Mac user renames a font file 1685cdf0e10cSrcweir * to be .ttf when its really a Mac resource-based font. 1686cdf0e10cSrcweir * Size will be 0, but fonts smaller than 4 bytes would be broken anyway. 1687cdf0e10cSrcweir */ 1688cdf0e10cSrcweir if ((*ttf)->fsize == 0) { 1689cdf0e10cSrcweir ret = SF_BADFILE; 1690cdf0e10cSrcweir goto cleanup; 1691cdf0e10cSrcweir } 1692cdf0e10cSrcweir 1693cdf0e10cSrcweir if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { 1694cdf0e10cSrcweir ret = SF_MEMORY; 1695cdf0e10cSrcweir goto cleanup; 1696cdf0e10cSrcweir } 1697cdf0e10cSrcweir close(fd); 1698cdf0e10cSrcweir 1699cdf0e10cSrcweir return doOpenTTFont( facenum, *ttf ); 1700cdf0e10cSrcweir 1701cdf0e10cSrcweir cleanup: 1702cdf0e10cSrcweir if (fd != -1) close(fd); 1703cdf0e10cSrcweir /*- t and t->fname have been allocated! */ 1704cdf0e10cSrcweir free((*ttf)->fname); 1705cdf0e10cSrcweir free(*ttf); 1706cdf0e10cSrcweir *ttf = NULL; 1707cdf0e10cSrcweir return ret; 1708cdf0e10cSrcweir } 1709cdf0e10cSrcweir #endif 1710cdf0e10cSrcweir 1711cdf0e10cSrcweir int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) 1712cdf0e10cSrcweir { 1713cdf0e10cSrcweir allocTrueTypeFont( ttf ); 1714cdf0e10cSrcweir if( *ttf == NULL ) 1715cdf0e10cSrcweir return SF_MEMORY; 1716cdf0e10cSrcweir 1717cdf0e10cSrcweir (*ttf)->fname = NULL; 1718cdf0e10cSrcweir (*ttf)->fsize = nLen; 1719cdf0e10cSrcweir (*ttf)->ptr = (sal_uInt8*)pBuffer; 1720cdf0e10cSrcweir 1721cdf0e10cSrcweir return doOpenTTFont( facenum, *ttf ); 1722cdf0e10cSrcweir } 1723cdf0e10cSrcweir 1724cdf0e10cSrcweir static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) 1725cdf0e10cSrcweir { 1726cdf0e10cSrcweir int i; 1727cdf0e10cSrcweir sal_uInt32 length, tag; 1728cdf0e10cSrcweir sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */ 1729cdf0e10cSrcweir int indexfmt, k; 1730cdf0e10cSrcweir 1731cdf0e10cSrcweir sal_uInt32 version = GetInt32(t->ptr, 0, 1); 1732cdf0e10cSrcweir 1733cdf0e10cSrcweir if ((version == 0x00010000) || (version == T_true)) { 1734cdf0e10cSrcweir tdoffset = 0; 1735cdf0e10cSrcweir } else if (version == T_otto) { /* PS-OpenType font */ 1736cdf0e10cSrcweir tdoffset = 0; 1737cdf0e10cSrcweir } else if (version == T_ttcf) { /* TrueType collection */ 1738cdf0e10cSrcweir if (GetUInt32(t->ptr, 4, 1) != 0x00010000) { 1739cdf0e10cSrcweir CloseTTFont(t); 1740cdf0e10cSrcweir return SF_TTFORMAT; 1741cdf0e10cSrcweir } 1742cdf0e10cSrcweir if (facenum >= GetUInt32(t->ptr, 8, 1)) { 1743cdf0e10cSrcweir CloseTTFont(t); 1744cdf0e10cSrcweir return SF_FONTNO; 1745cdf0e10cSrcweir } 1746cdf0e10cSrcweir tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1); 1747cdf0e10cSrcweir } else { 1748cdf0e10cSrcweir CloseTTFont(t); 1749cdf0e10cSrcweir return SF_TTFORMAT; 1750cdf0e10cSrcweir } 1751cdf0e10cSrcweir 1752cdf0e10cSrcweir #ifdef DEBUG2 1753cdf0e10cSrcweir fprintf(stderr, "tdoffset: %d\n", tdoffset); 1754cdf0e10cSrcweir #endif 1755cdf0e10cSrcweir 1756cdf0e10cSrcweir /* magic number */ 1757cdf0e10cSrcweir t->tag = TTFontClassTag; 1758cdf0e10cSrcweir 1759cdf0e10cSrcweir t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1); 1760cdf0e10cSrcweir if( t->ntables >= 128 ) 1761cdf0e10cSrcweir return SF_TTFORMAT; 1762cdf0e10cSrcweir 1763cdf0e10cSrcweir t->tables = (const sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8*)); 1764cdf0e10cSrcweir assert(t->tables != 0); 1765cdf0e10cSrcweir t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32)); 1766cdf0e10cSrcweir assert(t->tlens != 0); 1767cdf0e10cSrcweir 1768cdf0e10cSrcweir memset(t->tables, 0, NUM_TAGS * sizeof(void *)); 1769cdf0e10cSrcweir memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32)); 1770cdf0e10cSrcweir 1771cdf0e10cSrcweir /* parse the tables */ 1772cdf0e10cSrcweir for (i=0; i<(int)t->ntables; i++) { 1773cdf0e10cSrcweir int nIndex; 1774cdf0e10cSrcweir tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1); 1775cdf0e10cSrcweir switch( tag ) { 1776cdf0e10cSrcweir case T_maxp: nIndex = O_maxp; break; 1777cdf0e10cSrcweir case T_glyf: nIndex = O_glyf; break; 1778cdf0e10cSrcweir case T_head: nIndex = O_head; break; 1779cdf0e10cSrcweir case T_loca: nIndex = O_loca; break; 1780cdf0e10cSrcweir case T_name: nIndex = O_name; break; 1781cdf0e10cSrcweir case T_hhea: nIndex = O_hhea; break; 1782cdf0e10cSrcweir case T_hmtx: nIndex = O_hmtx; break; 1783cdf0e10cSrcweir case T_cmap: nIndex = O_cmap; break; 1784cdf0e10cSrcweir case T_vhea: nIndex = O_vhea; break; 1785cdf0e10cSrcweir case T_vmtx: nIndex = O_vmtx; break; 1786cdf0e10cSrcweir case T_OS2 : nIndex = O_OS2; break; 1787cdf0e10cSrcweir case T_post: nIndex = O_post; break; 1788cdf0e10cSrcweir case T_kern: nIndex = O_kern; break; 1789cdf0e10cSrcweir case T_cvt : nIndex = O_cvt; break; 1790cdf0e10cSrcweir case T_prep: nIndex = O_prep; break; 1791cdf0e10cSrcweir case T_fpgm: nIndex = O_fpgm; break; 1792cdf0e10cSrcweir case T_gsub: nIndex = O_gsub; break; 1793cdf0e10cSrcweir case T_CFF: nIndex = O_CFF; break; 1794cdf0e10cSrcweir default: nIndex = -1; break; 1795cdf0e10cSrcweir } 1796cdf0e10cSrcweir if( nIndex >= 0 ) { 1797cdf0e10cSrcweir sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1); 1798cdf0e10cSrcweir length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1); 1799cdf0e10cSrcweir t->tables[nIndex] = t->ptr + nTableOffset; 1800cdf0e10cSrcweir t->tlens[nIndex] = length; 1801cdf0e10cSrcweir } 1802cdf0e10cSrcweir } 1803cdf0e10cSrcweir 1804cdf0e10cSrcweir /* Fixup offsets when only a TTC extract was provided */ 1805cdf0e10cSrcweir if( facenum == (sal_uInt32)~0 ) { 1806cdf0e10cSrcweir sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head]; 1807cdf0e10cSrcweir if( !pHead ) 1808cdf0e10cSrcweir return SF_TTFORMAT; 1809cdf0e10cSrcweir /* limit Head candidate to TTC extract's limits */ 1810cdf0e10cSrcweir if( pHead > t->ptr + (t->fsize - 54) ) 1811cdf0e10cSrcweir pHead = t->ptr + (t->fsize - 54); 1812cdf0e10cSrcweir /* TODO: find better method than searching head table's magic */ 1813cdf0e10cSrcweir sal_uInt8* p = NULL; 1814cdf0e10cSrcweir for( p = pHead + 12; p > t->ptr; --p ) { 1815cdf0e10cSrcweir if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) { 1816cdf0e10cSrcweir int nDelta = (pHead + 12) - p, j; 1817cdf0e10cSrcweir if( nDelta ) 1818cdf0e10cSrcweir for( j=0; j<NUM_TAGS; ++j ) 1819cdf0e10cSrcweir if( t->tables[j] ) 1820cdf0e10cSrcweir *(char**)&t->tables[j] -= nDelta; 1821cdf0e10cSrcweir break; 1822cdf0e10cSrcweir } 1823cdf0e10cSrcweir } 1824cdf0e10cSrcweir if( p <= t->ptr ) 1825cdf0e10cSrcweir return SF_TTFORMAT; 1826cdf0e10cSrcweir } 1827cdf0e10cSrcweir 1828cdf0e10cSrcweir /* Check the table offsets after TTC correction */ 1829cdf0e10cSrcweir for (i=0; i<NUM_TAGS; i++) { 1830cdf0e10cSrcweir /* sanity check: table must lay completely within the file 1831cdf0e10cSrcweir * at this point one could check the checksum of all contained 1832cdf0e10cSrcweir * tables, but this would be quite time intensive. 1833cdf0e10cSrcweir * Try to fix tables, so we can cope with minor problems. 1834cdf0e10cSrcweir */ 1835cdf0e10cSrcweir 1836cdf0e10cSrcweir if( (sal_uInt8*)t->tables[i] < t->ptr ) 1837cdf0e10cSrcweir { 1838cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1839cdf0e10cSrcweir if( t->tables[i] ) 1840cdf0e10cSrcweir fprintf( stderr, "font file %s has bad table offset %d (tagnum=%d)\n", t->fname, (sal_uInt8*)t->tables[i]-t->ptr, i ); 1841cdf0e10cSrcweir #endif 1842cdf0e10cSrcweir t->tlens[i] = 0; 1843cdf0e10cSrcweir t->tables[i] = NULL; 1844cdf0e10cSrcweir } 1845cdf0e10cSrcweir else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize ) 1846cdf0e10cSrcweir { 1847cdf0e10cSrcweir int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i]; 1848cdf0e10cSrcweir if( nMaxLen < 0 ) 1849cdf0e10cSrcweir nMaxLen = 0; 1850cdf0e10cSrcweir t->tlens[i] = nMaxLen; 1851cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 1852cdf0e10cSrcweir fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i ); 1853cdf0e10cSrcweir #endif 1854cdf0e10cSrcweir } 1855cdf0e10cSrcweir } 1856cdf0e10cSrcweir 1857cdf0e10cSrcweir /* At this point TrueTypeFont is constructed, now need to verify the font format 1858cdf0e10cSrcweir and read the basic font properties */ 1859cdf0e10cSrcweir 1860cdf0e10cSrcweir /* The following tables are absolutely required: 1861cdf0e10cSrcweir * maxp, head, name, cmap 1862cdf0e10cSrcweir */ 1863cdf0e10cSrcweir 1864cdf0e10cSrcweir if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) { 1865cdf0e10cSrcweir CloseTTFont(t); 1866cdf0e10cSrcweir return SF_TTFORMAT; 1867cdf0e10cSrcweir } 1868cdf0e10cSrcweir 1869cdf0e10cSrcweir const sal_uInt8* table = getTable(t, O_maxp); 1870cdf0e10cSrcweir t->nglyphs = GetUInt16(table, 4, 1); 1871cdf0e10cSrcweir 1872cdf0e10cSrcweir table = getTable(t, O_head); 1873cdf0e10cSrcweir t->unitsPerEm = GetUInt16(table, 18, 1); 1874cdf0e10cSrcweir indexfmt = GetInt16(table, 50, 1); 1875cdf0e10cSrcweir 1876cdf0e10cSrcweir if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { 1877cdf0e10cSrcweir CloseTTFont(t); 1878cdf0e10cSrcweir return SF_TTFORMAT; 1879cdf0e10cSrcweir } 1880cdf0e10cSrcweir 1881cdf0e10cSrcweir if( getTable(t, O_glyf) && getTable(t, O_loca) ) { /* TTF or TTF-OpenType */ 1882cdf0e10cSrcweir k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1; 1883cdf0e10cSrcweir if( k < (int)t->nglyphs ) /* Hack for broken Chinese fonts */ 1884cdf0e10cSrcweir t->nglyphs = k; 1885cdf0e10cSrcweir 1886cdf0e10cSrcweir table = getTable(t, O_loca); 1887cdf0e10cSrcweir t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1888cdf0e10cSrcweir assert(t->goffsets != 0); 1889cdf0e10cSrcweir 1890cdf0e10cSrcweir for( i = 0; i <= (int)t->nglyphs; ++i ) 1891cdf0e10cSrcweir t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1; 1892cdf0e10cSrcweir } else if( getTable(t, O_CFF) ) { /* PS-OpenType */ 1893cdf0e10cSrcweir t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32)); 1894cdf0e10cSrcweir /* TODO: implement to get subsetting */ 1895cdf0e10cSrcweir assert(t->goffsets != 0); 1896cdf0e10cSrcweir } else { 1897cdf0e10cSrcweir CloseTTFont(t); 1898cdf0e10cSrcweir return SF_TTFORMAT; 1899cdf0e10cSrcweir } 1900cdf0e10cSrcweir 1901cdf0e10cSrcweir table = getTable(t, O_hhea); 1902cdf0e10cSrcweir t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1903cdf0e10cSrcweir 1904cdf0e10cSrcweir table = getTable(t, O_vhea); 1905cdf0e10cSrcweir t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0; 1906cdf0e10cSrcweir 1907cdf0e10cSrcweir GetNames(t); 1908cdf0e10cSrcweir FindCmap(t); 1909cdf0e10cSrcweir GetKern(t); 1910cdf0e10cSrcweir ReadGSUB( t, 0, 0 ); 1911cdf0e10cSrcweir 1912cdf0e10cSrcweir return SF_OK; 1913cdf0e10cSrcweir } 1914cdf0e10cSrcweir 1915cdf0e10cSrcweir void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/ 1916cdf0e10cSrcweir { 1917cdf0e10cSrcweir if (ttf->tag != TTFontClassTag) return; 1918cdf0e10cSrcweir 1919cdf0e10cSrcweir #if !defined(WIN32) && !defined(OS2) 1920cdf0e10cSrcweir if( ttf->fname ) 1921cdf0e10cSrcweir munmap((char *) ttf->ptr, ttf->fsize); 1922cdf0e10cSrcweir #endif 1923cdf0e10cSrcweir free(ttf->fname); 1924cdf0e10cSrcweir free(ttf->goffsets); 1925cdf0e10cSrcweir free(ttf->psname); 1926cdf0e10cSrcweir free(ttf->family); 1927cdf0e10cSrcweir if( ttf->ufamily ) 1928cdf0e10cSrcweir free( ttf->ufamily ); 1929cdf0e10cSrcweir free(ttf->subfamily); 1930cdf0e10cSrcweir if( ttf->usubfamily ) 1931cdf0e10cSrcweir free( ttf->usubfamily ); 1932cdf0e10cSrcweir free(ttf->tables); 1933cdf0e10cSrcweir free(ttf->tlens); 1934cdf0e10cSrcweir free(ttf->kerntables); 1935cdf0e10cSrcweir 1936cdf0e10cSrcweir ReleaseGSUB(ttf); 1937cdf0e10cSrcweir 1938cdf0e10cSrcweir free(ttf); 1939cdf0e10cSrcweir return; 1940cdf0e10cSrcweir } 1941cdf0e10cSrcweir 1942cdf0e10cSrcweir int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray) 1943cdf0e10cSrcweir { 1944cdf0e10cSrcweir return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0); 1945cdf0e10cSrcweir } 1946cdf0e10cSrcweir 1947cdf0e10cSrcweir int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist) 1948cdf0e10cSrcweir { 1949cdf0e10cSrcweir int n = 1; 1950cdf0e10cSrcweir 1951cdf0e10cSrcweir if( glyphID >= ttf->nglyphs ) 1952cdf0e10cSrcweir return 0; 1953cdf0e10cSrcweir 1954cdf0e10cSrcweir const sal_uInt8* glyf = getTable(ttf, O_glyf); 1955cdf0e10cSrcweir const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID]; 1956cdf0e10cSrcweir 1957cdf0e10cSrcweir glyphlist.push_back( glyphID ); 1958cdf0e10cSrcweir 1959cdf0e10cSrcweir if (GetInt16(ptr, 0, 1) == -1) { 1960cdf0e10cSrcweir sal_uInt16 flags, index; 1961cdf0e10cSrcweir ptr += 10; 1962cdf0e10cSrcweir do { 1963cdf0e10cSrcweir flags = GetUInt16(ptr, 0, 1); 1964cdf0e10cSrcweir index = GetUInt16(ptr, 2, 1); 1965cdf0e10cSrcweir 1966cdf0e10cSrcweir ptr += 4; 1967cdf0e10cSrcweir n += GetTTGlyphComponents(ttf, index, glyphlist); 1968cdf0e10cSrcweir 1969cdf0e10cSrcweir if (flags & ARG_1_AND_2_ARE_WORDS) { 1970cdf0e10cSrcweir ptr += 4; 1971cdf0e10cSrcweir } else { 1972cdf0e10cSrcweir ptr += 2; 1973cdf0e10cSrcweir } 1974cdf0e10cSrcweir 1975cdf0e10cSrcweir if (flags & WE_HAVE_A_SCALE) { 1976cdf0e10cSrcweir ptr += 2; 1977cdf0e10cSrcweir } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { 1978cdf0e10cSrcweir ptr += 4; 1979cdf0e10cSrcweir } else if (flags & WE_HAVE_A_TWO_BY_TWO) { 1980cdf0e10cSrcweir ptr += 8; 1981cdf0e10cSrcweir } 1982cdf0e10cSrcweir } while (flags & MORE_COMPONENTS); 1983cdf0e10cSrcweir } 1984cdf0e10cSrcweir 1985cdf0e10cSrcweir return n; 1986cdf0e10cSrcweir } 1987cdf0e10cSrcweir 1988cdf0e10cSrcweir #ifndef NO_TYPE3 1989cdf0e10cSrcweir int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/ 1990cdf0e10cSrcweir sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, 1991cdf0e10cSrcweir int wmode) 1992cdf0e10cSrcweir { 1993cdf0e10cSrcweir ControlPoint *pa; 1994cdf0e10cSrcweir PSPathElement *path; 1995cdf0e10cSrcweir int i, j, r, n; 1996cdf0e10cSrcweir const sal_uInt8* table = getTable(ttf, O_head); 1997cdf0e10cSrcweir TTGlyphMetrics metrics; 1998cdf0e10cSrcweir int UPEm = ttf->unitsPerEm; 1999cdf0e10cSrcweir 2000cdf0e10cSrcweir const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n"; 2001cdf0e10cSrcweir const char *h02 = "%% Creator: %s %s %s\n"; 2002cdf0e10cSrcweir const char *h09 = "%% Original font name: %s\n"; 2003cdf0e10cSrcweir 2004cdf0e10cSrcweir const char *h10 = 2005cdf0e10cSrcweir "30 dict begin\n" 2006cdf0e10cSrcweir "/PaintType 0 def\n" 2007cdf0e10cSrcweir "/FontType 3 def\n" 2008cdf0e10cSrcweir "/StrokeWidth 0 def\n"; 2009cdf0e10cSrcweir 2010cdf0e10cSrcweir const char *h11 = "/FontName (%s) cvn def\n"; 2011cdf0e10cSrcweir 2012cdf0e10cSrcweir /* 2013cdf0e10cSrcweir const char *h12 = "%/UniqueID %d def\n"; 2014cdf0e10cSrcweir */ 2015cdf0e10cSrcweir const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n"; 2016cdf0e10cSrcweir const char *h14 = "/FontBBox [%d %d %d %d] def\n"; 2017cdf0e10cSrcweir 2018cdf0e10cSrcweir const char *h15= 2019cdf0e10cSrcweir "/Encoding 256 array def\n" 2020cdf0e10cSrcweir " 0 1 255 {Encoding exch /.notdef put} for\n"; 2021cdf0e10cSrcweir 2022cdf0e10cSrcweir const char *h16 = " Encoding %d /glyph%d put\n"; 2023cdf0e10cSrcweir const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n"; 2024cdf0e10cSrcweir 2025cdf0e10cSrcweir const char *h30 = "/CharProcs %d dict def\n"; 2026cdf0e10cSrcweir const char *h31 = " CharProcs begin\n"; 2027cdf0e10cSrcweir const char *h32 = " /.notdef {} def\n"; 2028cdf0e10cSrcweir const char *h33 = " /glyph%d {\n"; 2029cdf0e10cSrcweir const char *h34 = " } bind def\n"; 2030cdf0e10cSrcweir const char *h35 = " end\n"; 2031cdf0e10cSrcweir 2032cdf0e10cSrcweir const char *h40 = 2033cdf0e10cSrcweir "/BuildGlyph {\n" 2034cdf0e10cSrcweir " exch /CharProcs get exch\n" 2035cdf0e10cSrcweir " 2 copy known not\n" 2036cdf0e10cSrcweir " {pop /.notdef} if\n" 2037cdf0e10cSrcweir " get exec\n" 2038cdf0e10cSrcweir "} bind def\n" 2039cdf0e10cSrcweir "/BuildChar {\n" 2040cdf0e10cSrcweir " 1 index /Encoding get exch get\n" 2041cdf0e10cSrcweir " 1 index /BuildGlyph get exec\n" 2042cdf0e10cSrcweir "} bind def\n" 2043cdf0e10cSrcweir "currentdict end\n"; 2044cdf0e10cSrcweir 2045cdf0e10cSrcweir const char *h41 = "(%s) cvn exch definefont pop\n"; 2046cdf0e10cSrcweir 2047cdf0e10cSrcweir 2048cdf0e10cSrcweir if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM; 2049cdf0e10cSrcweir if (!glyphArray) return SF_BADARG; 2050cdf0e10cSrcweir if (!fname) fname = ttf->psname; 2051cdf0e10cSrcweir 2052cdf0e10cSrcweir fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1)); 2053cdf0e10cSrcweir fprintf(outf, h02, modname, modver, modextra); 2054cdf0e10cSrcweir fprintf(outf, h09, ttf->psname); 2055cdf0e10cSrcweir 2056cdf0e10cSrcweir fprintf(outf, h10); 2057cdf0e10cSrcweir fprintf(outf, h11, fname); 2058cdf0e10cSrcweir /* fprintf(outf, h12, 4000000); */ 2059cdf0e10cSrcweir 2060cdf0e10cSrcweir /* XUID generation: 2061cdf0e10cSrcweir * 103 0 0 C1 C2 C3 C4 2062cdf0e10cSrcweir * C1 - CRC-32 of the entire source TrueType font 2063cdf0e10cSrcweir * C2 - number of glyphs in the subset 2064cdf0e10cSrcweir * C3 - CRC-32 of the glyph array 2065cdf0e10cSrcweir * C4 - CRC-32 of the encoding array 2066cdf0e10cSrcweir * 2067cdf0e10cSrcweir * All CRC-32 numbers are presented as hexadecimal numbers 2068cdf0e10cSrcweir */ 2069cdf0e10cSrcweir 2070cdf0e10cSrcweir fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs)); 2071cdf0e10cSrcweir fprintf(outf, h13); 2072cdf0e10cSrcweir fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1))); 2073cdf0e10cSrcweir fprintf(outf, h15); 2074cdf0e10cSrcweir 2075cdf0e10cSrcweir for (i = 0; i < nGlyphs; i++) { 2076cdf0e10cSrcweir fprintf(outf, h16, encoding[i], i); 2077cdf0e10cSrcweir } 2078cdf0e10cSrcweir 2079cdf0e10cSrcweir fprintf(outf, h30, nGlyphs+1); 2080cdf0e10cSrcweir fprintf(outf, h31); 2081cdf0e10cSrcweir fprintf(outf, h32); 2082cdf0e10cSrcweir 2083cdf0e10cSrcweir for (i = 0; i < nGlyphs; i++) { 2084cdf0e10cSrcweir fprintf(outf, h33, i); 2085cdf0e10cSrcweir r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0); 2086cdf0e10cSrcweir 2087cdf0e10cSrcweir if (r > 0) { 2088cdf0e10cSrcweir n = BSplineToPSPath(pa, r, &path); 2089cdf0e10cSrcweir } else { 2090cdf0e10cSrcweir n = 0; /* glyph might have zero contours but valid metrics ??? */ 2091cdf0e10cSrcweir path = 0; 2092cdf0e10cSrcweir if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */ 2093cdf0e10cSrcweir continue; 2094cdf0e10cSrcweir } 2095cdf0e10cSrcweir } 2096cdf0e10cSrcweir fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n", 2097cdf0e10cSrcweir wmode == 0 ? XUnits(UPEm, metrics.aw) : 0, 2098cdf0e10cSrcweir wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah), 2099cdf0e10cSrcweir XUnits(UPEm, metrics.xMin), 2100cdf0e10cSrcweir XUnits(UPEm, metrics.yMin), 2101cdf0e10cSrcweir XUnits(UPEm, metrics.xMax), 2102cdf0e10cSrcweir XUnits(UPEm, metrics.yMax)); 2103cdf0e10cSrcweir 2104cdf0e10cSrcweir for (j = 0; j < n; j++) 2105cdf0e10cSrcweir { 2106cdf0e10cSrcweir switch (path[j].type) 2107cdf0e10cSrcweir { 2108cdf0e10cSrcweir case PS_MOVETO: 2109cdf0e10cSrcweir fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2110cdf0e10cSrcweir break; 2111cdf0e10cSrcweir 2112cdf0e10cSrcweir case PS_LINETO: 2113cdf0e10cSrcweir fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1)); 2114cdf0e10cSrcweir break; 2115cdf0e10cSrcweir 2116cdf0e10cSrcweir case PS_CURVETO: 2117cdf0e10cSrcweir fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3)); 2118cdf0e10cSrcweir break; 2119cdf0e10cSrcweir 2120cdf0e10cSrcweir case PS_CLOSEPATH: 2121cdf0e10cSrcweir fprintf(outf, "\tclosepath\n"); 2122cdf0e10cSrcweir break; 2123cdf0e10cSrcweir case PS_NOOP: 2124cdf0e10cSrcweir break; 2125cdf0e10cSrcweir } 2126cdf0e10cSrcweir } 2127cdf0e10cSrcweir if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */ 2128cdf0e10cSrcweir 2129cdf0e10cSrcweir fprintf(outf, h34); 2130cdf0e10cSrcweir 2131cdf0e10cSrcweir free(pa); 2132cdf0e10cSrcweir free(path); 2133cdf0e10cSrcweir } 2134cdf0e10cSrcweir fprintf(outf, h35); 2135cdf0e10cSrcweir 2136cdf0e10cSrcweir fprintf(outf, h40); 2137cdf0e10cSrcweir fprintf(outf, h41, fname); 2138cdf0e10cSrcweir 2139cdf0e10cSrcweir return SF_OK; 2140cdf0e10cSrcweir } 2141cdf0e10cSrcweir #endif 2142cdf0e10cSrcweir 2143cdf0e10cSrcweir #ifndef NO_TTCR 2144cdf0e10cSrcweir int CreateTTFromTTGlyphs(TrueTypeFont *ttf, 2145cdf0e10cSrcweir const char *fname, 2146cdf0e10cSrcweir sal_uInt16 *glyphArray, 2147cdf0e10cSrcweir sal_uInt8 *encoding, 2148cdf0e10cSrcweir int nGlyphs, 2149cdf0e10cSrcweir int nNameRecs, 2150cdf0e10cSrcweir NameRecord *nr, 2151cdf0e10cSrcweir sal_uInt32 flags) 2152cdf0e10cSrcweir { 2153cdf0e10cSrcweir TrueTypeCreator *ttcr; 2154cdf0e10cSrcweir TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0; 2155cdf0e10cSrcweir int i; 2156cdf0e10cSrcweir int res; 2157cdf0e10cSrcweir 2158cdf0e10cSrcweir TrueTypeCreatorNewEmpty(T_true, &ttcr); 2159cdf0e10cSrcweir 2160cdf0e10cSrcweir /** name **/ 2161cdf0e10cSrcweir 2162cdf0e10cSrcweir if (flags & TTCF_AutoName) { 2163cdf0e10cSrcweir /* not implemented yet 2164cdf0e10cSrcweir NameRecord *names; 2165cdf0e10cSrcweir NameRecord newname; 2166cdf0e10cSrcweir int n = GetTTNameRecords(ttf, &names); 2167cdf0e10cSrcweir int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0; 2168cdf0e10cSrcweir sal_uInt8 *cp1; 2169cdf0e10cSrcweir sal_uInt8 suffix[32]; 2170cdf0e10cSrcweir sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2); 2171cdf0e10cSrcweir sal_uInt32 c2 = crc32(encoding, nGlyphs); 2172cdf0e10cSrcweir int len; 2173cdf0e10cSrcweir snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs); 2174cdf0e10cSrcweir 2175cdf0e10cSrcweir name = TrueTypeTableNew_name(0, 0); 2176cdf0e10cSrcweir for (i = 0; i < n; i++) { 2177cdf0e10cSrcweir if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) { 2178cdf0e10cSrcweir 2179cdf0e10cSrcweir memcpy(newname, names+i, sizeof(NameRecord)); 2180cdf0e10cSrcweir newname.slen = name[i].slen + strlen(suffix); 2181cdf0e10cSrcweir */ 2182cdf0e10cSrcweir const sal_uInt8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'}; 2183cdf0e10cSrcweir NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"}; 2184cdf0e10cSrcweir NameRecord n2 = {3, 1, 1033, 6, 28, 0}; 2185cdf0e10cSrcweir n2.sptr = (sal_uInt8 *) ptr; 2186cdf0e10cSrcweir name = TrueTypeTableNew_name(0, 0); 2187cdf0e10cSrcweir nameAdd(name, &n1); 2188cdf0e10cSrcweir nameAdd(name, &n2); 2189cdf0e10cSrcweir } else { 2190cdf0e10cSrcweir if (nNameRecs == 0) { 2191cdf0e10cSrcweir NameRecord *names; 2192cdf0e10cSrcweir int n = GetTTNameRecords(ttf, &names); 2193cdf0e10cSrcweir name = TrueTypeTableNew_name(n, names); 2194cdf0e10cSrcweir DisposeNameRecords(names, n); 2195cdf0e10cSrcweir } else { 2196cdf0e10cSrcweir name = TrueTypeTableNew_name(nNameRecs, nr); 2197cdf0e10cSrcweir } 2198cdf0e10cSrcweir } 2199cdf0e10cSrcweir 2200cdf0e10cSrcweir /** maxp **/ 2201cdf0e10cSrcweir maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2202cdf0e10cSrcweir 2203cdf0e10cSrcweir /** hhea **/ 2204cdf0e10cSrcweir const sal_uInt8* p = getTable(ttf, O_hhea); 2205cdf0e10cSrcweir if (p) { 2206cdf0e10cSrcweir hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2207cdf0e10cSrcweir } else { 2208cdf0e10cSrcweir hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2209cdf0e10cSrcweir } 2210cdf0e10cSrcweir 2211cdf0e10cSrcweir /** head **/ 2212cdf0e10cSrcweir 2213cdf0e10cSrcweir p = getTable(ttf, O_head); 2214cdf0e10cSrcweir assert(p != 0); 2215cdf0e10cSrcweir head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), 2216cdf0e10cSrcweir GetUInt16(p, 16, 1), 2217cdf0e10cSrcweir GetUInt16(p, 18, 1), 2218cdf0e10cSrcweir p+20, 2219cdf0e10cSrcweir GetUInt16(p, 44, 1), 2220cdf0e10cSrcweir GetUInt16(p, 46, 1), 2221cdf0e10cSrcweir GetInt16(p, 48, 1)); 2222cdf0e10cSrcweir 2223cdf0e10cSrcweir 2224cdf0e10cSrcweir /** glyf **/ 2225cdf0e10cSrcweir 2226cdf0e10cSrcweir glyf = TrueTypeTableNew_glyf(); 2227cdf0e10cSrcweir sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2228cdf0e10cSrcweir 2229cdf0e10cSrcweir for (i = 0; i < nGlyphs; i++) { 2230cdf0e10cSrcweir gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2231cdf0e10cSrcweir } 2232cdf0e10cSrcweir 2233cdf0e10cSrcweir /** cmap **/ 2234cdf0e10cSrcweir cmap = TrueTypeTableNew_cmap(); 2235cdf0e10cSrcweir 2236cdf0e10cSrcweir for (i=0; i < nGlyphs; i++) { 2237cdf0e10cSrcweir cmapAdd(cmap, 0x010000, encoding[i], gID[i]); 2238cdf0e10cSrcweir } 2239cdf0e10cSrcweir 2240cdf0e10cSrcweir /** cvt **/ 2241cdf0e10cSrcweir if ((p = getTable(ttf, O_cvt)) != 0) { 2242cdf0e10cSrcweir cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2243cdf0e10cSrcweir } 2244cdf0e10cSrcweir 2245cdf0e10cSrcweir /** prep **/ 2246cdf0e10cSrcweir if ((p = getTable(ttf, O_prep)) != 0) { 2247cdf0e10cSrcweir prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2248cdf0e10cSrcweir } 2249cdf0e10cSrcweir 2250cdf0e10cSrcweir /** fpgm **/ 2251cdf0e10cSrcweir if ((p = getTable(ttf, O_fpgm)) != 0) { 2252cdf0e10cSrcweir fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2253cdf0e10cSrcweir } 2254cdf0e10cSrcweir 2255cdf0e10cSrcweir /** post **/ 2256cdf0e10cSrcweir if ((p = getTable(ttf, O_post)) != 0) { 2257cdf0e10cSrcweir post = TrueTypeTableNew_post(0x00030000, 2258cdf0e10cSrcweir GetUInt32(p, 4, 1), 2259cdf0e10cSrcweir GetUInt16(p, 8, 1), 2260cdf0e10cSrcweir GetUInt16(p, 10, 1), 2261cdf0e10cSrcweir GetUInt16(p, 12, 1)); 2262cdf0e10cSrcweir } else { 2263cdf0e10cSrcweir post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0); 2264cdf0e10cSrcweir } 2265cdf0e10cSrcweir 2266cdf0e10cSrcweir if (flags & TTCF_IncludeOS2) { 2267cdf0e10cSrcweir if ((p = getTable(ttf, O_OS2)) != 0) { 2268cdf0e10cSrcweir os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p); 2269cdf0e10cSrcweir } 2270cdf0e10cSrcweir } 2271cdf0e10cSrcweir 2272cdf0e10cSrcweir AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea); 2273cdf0e10cSrcweir AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap); 2274cdf0e10cSrcweir AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm); 2275cdf0e10cSrcweir AddTable(ttcr, post); AddTable(ttcr, os2); 2276cdf0e10cSrcweir 2277cdf0e10cSrcweir if ((res = StreamToFile(ttcr, fname)) != SF_OK) { 2278cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 2279cdf0e10cSrcweir fprintf(stderr, "StreamToFile: error code: %d.\n", res); 2280cdf0e10cSrcweir #endif 2281cdf0e10cSrcweir } 2282cdf0e10cSrcweir 2283cdf0e10cSrcweir TrueTypeCreatorDispose(ttcr); 2284cdf0e10cSrcweir free(gID); 2285cdf0e10cSrcweir 2286cdf0e10cSrcweir return res; 2287cdf0e10cSrcweir } 2288cdf0e10cSrcweir #endif 2289cdf0e10cSrcweir 2290cdf0e10cSrcweir 2291cdf0e10cSrcweir #ifndef NO_TYPE42 2292cdf0e10cSrcweir static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP) 2293cdf0e10cSrcweir { 2294cdf0e10cSrcweir GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets)); 2295cdf0e10cSrcweir sal_uInt8 *loca = NULL; 2296cdf0e10cSrcweir sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2297cdf0e10cSrcweir sal_uInt32 locaLen = 0; 2298cdf0e10cSrcweir sal_Int16 indexToLocFormat = 0; 2299cdf0e10cSrcweir 2300cdf0e10cSrcweir for (i = 0; i < numTables; i++) { 2301cdf0e10cSrcweir sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2302cdf0e10cSrcweir sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2303cdf0e10cSrcweir sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2304cdf0e10cSrcweir 2305cdf0e10cSrcweir if (tag == T_loca) { 2306cdf0e10cSrcweir loca = sfntP + off; 2307cdf0e10cSrcweir locaLen = len; 2308cdf0e10cSrcweir } else if (tag == T_head) { 2309cdf0e10cSrcweir indexToLocFormat = GetInt16(sfntP + off, 50, 1); 2310cdf0e10cSrcweir } 2311cdf0e10cSrcweir } 2312cdf0e10cSrcweir 2313cdf0e10cSrcweir res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2); 2314cdf0e10cSrcweir assert(res->nGlyphs != 0); 2315cdf0e10cSrcweir res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32)); 2316cdf0e10cSrcweir 2317cdf0e10cSrcweir for (i = 0; i < res->nGlyphs; i++) { 2318cdf0e10cSrcweir if (indexToLocFormat == 1) { 2319cdf0e10cSrcweir res->offs[i] = GetUInt32(loca, i * 4, 1); 2320cdf0e10cSrcweir } else { 2321cdf0e10cSrcweir res->offs[i] = GetUInt16(loca, i * 2, 1) << 1; 2322cdf0e10cSrcweir } 2323cdf0e10cSrcweir } 2324cdf0e10cSrcweir return res; 2325cdf0e10cSrcweir } 2326cdf0e10cSrcweir 2327cdf0e10cSrcweir static void GlyphOffsetsDispose(GlyphOffsets *_this) 2328cdf0e10cSrcweir { 2329cdf0e10cSrcweir if (_this) { 2330cdf0e10cSrcweir free(_this->offs); 2331cdf0e10cSrcweir free(_this); 2332cdf0e10cSrcweir } 2333cdf0e10cSrcweir } 2334cdf0e10cSrcweir 2335cdf0e10cSrcweir static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP) 2336cdf0e10cSrcweir { 2337cdf0e10cSrcweir HexFmt *h = HexFmtNew(outf); 2338cdf0e10cSrcweir sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1); 2339cdf0e10cSrcweir GlyphOffsets *go = GlyphOffsetsNew(sfntP); 2340cdf0e10cSrcweir sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */ 2341cdf0e10cSrcweir 2342cdf0e10cSrcweir assert(numTables <= 9); /* Type42 has 9 required tables */ 2343cdf0e10cSrcweir 2344cdf0e10cSrcweir sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2345cdf0e10cSrcweir // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32)); 2346cdf0e10cSrcweir 2347cdf0e10cSrcweir fputs("/sfnts [", outf); 2348cdf0e10cSrcweir HexFmtOpenString(h); 2349cdf0e10cSrcweir HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */ 2350cdf0e10cSrcweir HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */ 2351cdf0e10cSrcweir 2352cdf0e10cSrcweir for (i=0; i<numTables; i++) { 2353cdf0e10cSrcweir sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1); 2354cdf0e10cSrcweir sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1); 2355cdf0e10cSrcweir sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1); 2356cdf0e10cSrcweir 2357cdf0e10cSrcweir if (tag != T_glyf) { 2358cdf0e10cSrcweir HexFmtBlockWrite(h, sfntP + off, len); 2359cdf0e10cSrcweir } else { 2360cdf0e10cSrcweir sal_uInt8 *glyf = sfntP + off; 2361cdf0e10cSrcweir sal_uInt32 o, l, j; 2362cdf0e10cSrcweir for (j = 0; j < go->nGlyphs - 1; j++) { 2363cdf0e10cSrcweir o = go->offs[j]; 2364cdf0e10cSrcweir l = go->offs[j + 1] - o; 2365cdf0e10cSrcweir HexFmtBlockWrite(h, glyf + o, l); 2366cdf0e10cSrcweir } 2367cdf0e10cSrcweir } 2368cdf0e10cSrcweir HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3); 2369cdf0e10cSrcweir } 2370cdf0e10cSrcweir HexFmtCloseString(h); 2371cdf0e10cSrcweir fputs("] def\n", outf); 2372cdf0e10cSrcweir GlyphOffsetsDispose(go); 2373cdf0e10cSrcweir HexFmtDispose(h); 2374cdf0e10cSrcweir free(offs); 2375cdf0e10cSrcweir // free(lens); 2376cdf0e10cSrcweir } 2377cdf0e10cSrcweir 2378cdf0e10cSrcweir int CreateT42FromTTGlyphs(TrueTypeFont *ttf, 2379cdf0e10cSrcweir FILE *outf, 2380cdf0e10cSrcweir const char *psname, 2381cdf0e10cSrcweir sal_uInt16 *glyphArray, 2382cdf0e10cSrcweir sal_uInt8 *encoding, 2383cdf0e10cSrcweir int nGlyphs) 2384cdf0e10cSrcweir { 2385cdf0e10cSrcweir TrueTypeCreator *ttcr; 2386cdf0e10cSrcweir TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0; 2387cdf0e10cSrcweir int i; 2388cdf0e10cSrcweir int res; 2389cdf0e10cSrcweir 2390cdf0e10cSrcweir sal_uInt32 ver, rev; 2391cdf0e10cSrcweir 2392cdf0e10cSrcweir sal_uInt8 *sfntP; 2393cdf0e10cSrcweir sal_uInt32 sfntLen; 2394cdf0e10cSrcweir int UPEm = ttf->unitsPerEm; 2395cdf0e10cSrcweir 2396cdf0e10cSrcweir if (nGlyphs >= 256) return SF_GLYPHNUM; 2397cdf0e10cSrcweir 2398cdf0e10cSrcweir assert(psname != 0); 2399cdf0e10cSrcweir 2400cdf0e10cSrcweir TrueTypeCreatorNewEmpty(T_true, &ttcr); 2401cdf0e10cSrcweir 2402cdf0e10cSrcweir /* head */ 2403cdf0e10cSrcweir const sal_uInt8* p = getTable(ttf, O_head); 2404cdf0e10cSrcweir const sal_uInt8* headP = p; 2405cdf0e10cSrcweir assert(p != 0); 2406cdf0e10cSrcweir head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1)); 2407cdf0e10cSrcweir ver = GetUInt32(p, 0, 1); 2408cdf0e10cSrcweir rev = GetUInt32(p, 4, 1); 2409cdf0e10cSrcweir 2410cdf0e10cSrcweir /** hhea **/ 2411cdf0e10cSrcweir p = getTable(ttf, O_hhea); 2412cdf0e10cSrcweir if (p) { 2413cdf0e10cSrcweir hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1)); 2414cdf0e10cSrcweir } else { 2415cdf0e10cSrcweir hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0); 2416cdf0e10cSrcweir } 2417cdf0e10cSrcweir 2418cdf0e10cSrcweir /** maxp **/ 2419cdf0e10cSrcweir maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp)); 2420cdf0e10cSrcweir 2421cdf0e10cSrcweir /** cvt **/ 2422cdf0e10cSrcweir if ((p = getTable(ttf, O_cvt)) != 0) { 2423cdf0e10cSrcweir cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p); 2424cdf0e10cSrcweir } 2425cdf0e10cSrcweir 2426cdf0e10cSrcweir /** prep **/ 2427cdf0e10cSrcweir if ((p = getTable(ttf, O_prep)) != 0) { 2428cdf0e10cSrcweir prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p); 2429cdf0e10cSrcweir } 2430cdf0e10cSrcweir 2431cdf0e10cSrcweir /** fpgm **/ 2432cdf0e10cSrcweir if ((p = getTable(ttf, O_fpgm)) != 0) { 2433cdf0e10cSrcweir fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p); 2434cdf0e10cSrcweir } 2435cdf0e10cSrcweir 2436cdf0e10cSrcweir /** glyf **/ 2437cdf0e10cSrcweir glyf = TrueTypeTableNew_glyf(); 2438cdf0e10cSrcweir sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32)); 2439cdf0e10cSrcweir 2440cdf0e10cSrcweir for (i = 0; i < nGlyphs; i++) { 2441cdf0e10cSrcweir gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf); 2442cdf0e10cSrcweir } 2443cdf0e10cSrcweir 2444cdf0e10cSrcweir AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt); 2445cdf0e10cSrcweir AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm); 2446cdf0e10cSrcweir 2447cdf0e10cSrcweir if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) { 2448cdf0e10cSrcweir TrueTypeCreatorDispose(ttcr); 2449cdf0e10cSrcweir free(gID); 2450cdf0e10cSrcweir return res; 2451cdf0e10cSrcweir } 2452cdf0e10cSrcweir 2453cdf0e10cSrcweir fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF)); 2454cdf0e10cSrcweir fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra); 2455cdf0e10cSrcweir fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname); 2456cdf0e10cSrcweir fprintf(outf, "%%- Original font name: %s\n", ttf->psname); 2457cdf0e10cSrcweir fprintf(outf, "%%- Original font family: %s\n", ttf->family); 2458cdf0e10cSrcweir fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily); 2459cdf0e10cSrcweir fprintf(outf, "11 dict begin\n"); 2460cdf0e10cSrcweir fprintf(outf, "/FontName (%s) cvn def\n", psname); 2461cdf0e10cSrcweir fprintf(outf, "/PaintType 0 def\n"); 2462cdf0e10cSrcweir fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n"); 2463cdf0e10cSrcweir fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1))); 2464cdf0e10cSrcweir fprintf(outf, "/FontType 42 def\n"); 2465cdf0e10cSrcweir fprintf(outf, "/Encoding 256 array def\n"); 2466cdf0e10cSrcweir fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n"); 2467cdf0e10cSrcweir 2468cdf0e10cSrcweir for (i = 1; i<nGlyphs; i++) { 2469cdf0e10cSrcweir fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]); 2470cdf0e10cSrcweir } 2471cdf0e10cSrcweir fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", (unsigned int)rtl_crc32(0, ttf->ptr, ttf->fsize), (unsigned int)nGlyphs, (unsigned int)rtl_crc32(0, glyphArray, nGlyphs * 2), (unsigned int)rtl_crc32(0, encoding, nGlyphs)); 2472cdf0e10cSrcweir 2473cdf0e10cSrcweir DumpSfnts(outf, sfntP); 2474cdf0e10cSrcweir 2475cdf0e10cSrcweir /* dump charstrings */ 2476cdf0e10cSrcweir fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs); 2477cdf0e10cSrcweir fprintf(outf, "/.notdef 0 def\n"); 2478cdf0e10cSrcweir for (i = 1; i < (int)glyfCount(glyf); i++) { 2479cdf0e10cSrcweir fprintf(outf,"/glyph%d %d def\n", i, i); 2480cdf0e10cSrcweir } 2481cdf0e10cSrcweir fprintf(outf, "end readonly def\n"); 2482cdf0e10cSrcweir 2483cdf0e10cSrcweir fprintf(outf, "FontName currentdict end definefont pop\n"); 2484cdf0e10cSrcweir TrueTypeCreatorDispose(ttcr); 2485cdf0e10cSrcweir free(gID); 2486cdf0e10cSrcweir free(sfntP); 2487cdf0e10cSrcweir return SF_OK; 2488cdf0e10cSrcweir } 2489cdf0e10cSrcweir #endif 2490cdf0e10cSrcweir 2491cdf0e10cSrcweir 2492cdf0e10cSrcweir #ifndef NO_MAPPERS 2493cdf0e10cSrcweir int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical) 2494cdf0e10cSrcweir { 2495cdf0e10cSrcweir int i; 2496cdf0e10cSrcweir sal_uInt16 *cp; 2497cdf0e10cSrcweir 2498cdf0e10cSrcweir if (ttf->cmapType == CMAP_NOT_USABLE ) return -1; 2499cdf0e10cSrcweir if (!nchars) return 0; 2500cdf0e10cSrcweir 2501cdf0e10cSrcweir if (glyphArray == 0) { 2502cdf0e10cSrcweir cp = str; 2503cdf0e10cSrcweir } else { 2504cdf0e10cSrcweir cp = glyphArray; 2505cdf0e10cSrcweir } 2506cdf0e10cSrcweir 2507cdf0e10cSrcweir switch (ttf->cmapType) { 2508cdf0e10cSrcweir case CMAP_MS_Symbol: 2509cdf0e10cSrcweir if( ttf->mapper == getGlyph0 ) { 2510cdf0e10cSrcweir sal_uInt16 aChar; 2511cdf0e10cSrcweir for( i = 0; i < nchars; i++ ) { 2512cdf0e10cSrcweir aChar = str[i]; 2513cdf0e10cSrcweir if( ( aChar & 0xf000 ) == 0xf000 ) 2514cdf0e10cSrcweir aChar &= 0x00ff; 2515cdf0e10cSrcweir cp[i] = aChar; 2516cdf0e10cSrcweir } 2517cdf0e10cSrcweir } 2518cdf0e10cSrcweir else if( glyphArray ) 2519cdf0e10cSrcweir memcpy(glyphArray, str, nchars * 2); 2520cdf0e10cSrcweir break; 2521cdf0e10cSrcweir 2522cdf0e10cSrcweir case CMAP_MS_Unicode: 2523cdf0e10cSrcweir if (glyphArray != 0) { 2524cdf0e10cSrcweir memcpy(glyphArray, str, nchars * 2); 2525cdf0e10cSrcweir } 2526cdf0e10cSrcweir break; 2527cdf0e10cSrcweir 2528cdf0e10cSrcweir case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break; 2529cdf0e10cSrcweir case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break; 2530cdf0e10cSrcweir case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break; 2531cdf0e10cSrcweir case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break; 2532cdf0e10cSrcweir case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break; 2533cdf0e10cSrcweir } 2534cdf0e10cSrcweir 2535cdf0e10cSrcweir for (i = 0; i < nchars; i++) { 2536cdf0e10cSrcweir cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]); 2537cdf0e10cSrcweir if (cp[i]!=0 && bvertical!=0) 2538cdf0e10cSrcweir cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical); 2539cdf0e10cSrcweir } 2540cdf0e10cSrcweir return nchars; 2541cdf0e10cSrcweir } 2542cdf0e10cSrcweir 2543cdf0e10cSrcweir sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical) 2544cdf0e10cSrcweir { 2545cdf0e10cSrcweir switch (ttf->cmapType) { 2546cdf0e10cSrcweir case CMAP_MS_Symbol: 2547cdf0e10cSrcweir 2548cdf0e10cSrcweir if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) 2549cdf0e10cSrcweir ch &= 0x00ff; 2550cdf0e10cSrcweir return (sal_uInt16)ttf->mapper(ttf->cmap, ch ); 2551cdf0e10cSrcweir 2552cdf0e10cSrcweir case CMAP_MS_Unicode: break; 2553cdf0e10cSrcweir case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break; 2554cdf0e10cSrcweir case CMAP_MS_Big5: ch = TranslateChar13(ch); break; 2555cdf0e10cSrcweir case CMAP_MS_PRC: ch = TranslateChar14(ch); break; 2556cdf0e10cSrcweir case CMAP_MS_Wansung: ch = TranslateChar15(ch); break; 2557cdf0e10cSrcweir case CMAP_MS_Johab: ch = TranslateChar16(ch); break; 2558cdf0e10cSrcweir default: return 0; 2559cdf0e10cSrcweir } 2560cdf0e10cSrcweir ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch); 2561cdf0e10cSrcweir if (ch!=0 && bvertical!=0) 2562cdf0e10cSrcweir ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical); 2563cdf0e10cSrcweir return ch; 2564cdf0e10cSrcweir } 2565cdf0e10cSrcweir 2566cdf0e10cSrcweir int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical) 2567cdf0e10cSrcweir { 2568cdf0e10cSrcweir int nRet = 0; 2569cdf0e10cSrcweir if( bvertical) 2570cdf0e10cSrcweir nRet = HasVerticalGSUB( ttf); 2571cdf0e10cSrcweir return nRet; 2572cdf0e10cSrcweir } 2573cdf0e10cSrcweir 2574cdf0e10cSrcweir #endif 2575cdf0e10cSrcweir 2576cdf0e10cSrcweir int GetTTGlyphCount( TrueTypeFont* ttf ) 2577cdf0e10cSrcweir { 2578cdf0e10cSrcweir return ttf->nglyphs; 2579cdf0e10cSrcweir } 2580cdf0e10cSrcweir 2581cdf0e10cSrcweir bool GetSfntTable( TrueTypeFont* ttf, int nSubtableIndex, 2582cdf0e10cSrcweir const sal_uInt8** ppRawBytes, int* pRawLength ) 2583cdf0e10cSrcweir { 2584cdf0e10cSrcweir if( (nSubtableIndex < 0) || (nSubtableIndex >= NUM_TAGS) ) 2585cdf0e10cSrcweir return false; 2586cdf0e10cSrcweir *pRawLength = ttf->tlens[ nSubtableIndex ]; 2587cdf0e10cSrcweir *ppRawBytes = ttf->tables[ nSubtableIndex ]; 2588cdf0e10cSrcweir bool bOk = (*pRawLength > 0) && (ppRawBytes != NULL); 2589cdf0e10cSrcweir return bOk; 2590cdf0e10cSrcweir } 2591cdf0e10cSrcweir 2592cdf0e10cSrcweir TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode) 2593cdf0e10cSrcweir { 2594cdf0e10cSrcweir const sal_uInt8* pTable; 2595cdf0e10cSrcweir sal_uInt32 n; 2596cdf0e10cSrcweir int nTableSize; 2597cdf0e10cSrcweir 2598cdf0e10cSrcweir if (mode == 0) { 2599cdf0e10cSrcweir n = ttf->numberOfHMetrics; 2600cdf0e10cSrcweir pTable = getTable( ttf, O_hmtx ); 2601cdf0e10cSrcweir nTableSize = getTableSize( ttf, O_hmtx ); 2602cdf0e10cSrcweir } else { 2603cdf0e10cSrcweir n = ttf->numOfLongVerMetrics; 2604cdf0e10cSrcweir pTable = getTable( ttf, O_vmtx ); 2605cdf0e10cSrcweir nTableSize = getTableSize( ttf, O_vmtx ); 2606cdf0e10cSrcweir } 2607cdf0e10cSrcweir 2608cdf0e10cSrcweir if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */ 2609cdf0e10cSrcweir if (!n || !pTable) return 0; /* the font does not contain the requested metrics */ 2610cdf0e10cSrcweir 2611cdf0e10cSrcweir TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics)); 2612cdf0e10cSrcweir assert(res != 0); 2613cdf0e10cSrcweir 2614cdf0e10cSrcweir const int UPEm = ttf->unitsPerEm; 2615cdf0e10cSrcweir for( int i = 0; i < nGlyphs; ++i) { 2616cdf0e10cSrcweir int nAdvOffset, nLsbOffset; 2617cdf0e10cSrcweir sal_uInt16 glyphID = glyphArray[i]; 2618cdf0e10cSrcweir 2619cdf0e10cSrcweir if (glyphID < n) { 2620cdf0e10cSrcweir nAdvOffset = 4 * glyphID; 2621cdf0e10cSrcweir nLsbOffset = nAdvOffset + 2; 2622cdf0e10cSrcweir } else { 2623cdf0e10cSrcweir nAdvOffset = 4 * (n - 1); 2624cdf0e10cSrcweir if( glyphID < ttf->nglyphs ) 2625cdf0e10cSrcweir nLsbOffset = 4 * n + 2 * (glyphID - n); 2626cdf0e10cSrcweir else /* font is broken -> use lsb of last hmetrics */ 2627cdf0e10cSrcweir nLsbOffset = nAdvOffset + 2; 2628cdf0e10cSrcweir } 2629cdf0e10cSrcweir 2630cdf0e10cSrcweir if( nAdvOffset >= nTableSize) 2631cdf0e10cSrcweir res[i].adv = 0; /* better than a crash for buggy fonts */ 2632cdf0e10cSrcweir else 2633cdf0e10cSrcweir res[i].adv = static_cast<sal_uInt16>( 2634cdf0e10cSrcweir XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) ); 2635cdf0e10cSrcweir 2636cdf0e10cSrcweir if( nLsbOffset >= nTableSize) 2637cdf0e10cSrcweir res[i].sb = 0; /* better than a crash for buggy fonts */ 2638cdf0e10cSrcweir else 2639cdf0e10cSrcweir res[i].sb = static_cast<sal_Int16>( 2640cdf0e10cSrcweir XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) ); 2641cdf0e10cSrcweir } 2642cdf0e10cSrcweir 2643cdf0e10cSrcweir return res; 2644cdf0e10cSrcweir } 2645cdf0e10cSrcweir 2646cdf0e10cSrcweir #ifndef NO_MAPPERS 2647cdf0e10cSrcweir TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode) 2648cdf0e10cSrcweir { 2649cdf0e10cSrcweir TTSimpleGlyphMetrics *res = 0; 2650cdf0e10cSrcweir int i, n; 2651cdf0e10cSrcweir 2652cdf0e10cSrcweir sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2); 2653cdf0e10cSrcweir assert(str != 0); 2654cdf0e10cSrcweir 2655cdf0e10cSrcweir for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i); 2656cdf0e10cSrcweir if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) { 2657cdf0e10cSrcweir res = GetTTSimpleGlyphMetrics(ttf, str, n, mode); 2658cdf0e10cSrcweir } 2659cdf0e10cSrcweir 2660cdf0e10cSrcweir free(str); 2661cdf0e10cSrcweir 2662cdf0e10cSrcweir return res; 2663cdf0e10cSrcweir } 2664cdf0e10cSrcweir #endif 2665cdf0e10cSrcweir 2666cdf0e10cSrcweir void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) 2667cdf0e10cSrcweir { 2668cdf0e10cSrcweir int UPEm = ttf->unitsPerEm; 2669cdf0e10cSrcweir 2670cdf0e10cSrcweir memset(info, 0, sizeof(TTGlobalFontInfo)); 2671cdf0e10cSrcweir 2672cdf0e10cSrcweir info->family = ttf->family; 2673cdf0e10cSrcweir info->ufamily = ttf->ufamily; 2674cdf0e10cSrcweir info->subfamily = ttf->subfamily; 2675cdf0e10cSrcweir info->usubfamily = ttf->usubfamily; 2676cdf0e10cSrcweir info->psname = ttf->psname; 2677cdf0e10cSrcweir info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol); 2678cdf0e10cSrcweir 2679cdf0e10cSrcweir const sal_uInt8* table = getTable(ttf, O_OS2); 2680cdf0e10cSrcweir if (table) { 2681cdf0e10cSrcweir info->weight = GetUInt16(table, 4, 1); 2682cdf0e10cSrcweir info->width = GetUInt16(table, 6, 1); 2683cdf0e10cSrcweir 2684cdf0e10cSrcweir /* There are 3 different versions of OS/2 table: original (68 bytes long), 2685cdf0e10cSrcweir * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,) 2686cdf0e10cSrcweir * Apple's documentation recommends looking at the table length. 2687cdf0e10cSrcweir */ 2688cdf0e10cSrcweir if (getTableSize(ttf, O_OS2) > 68) { 2689cdf0e10cSrcweir info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1)); 2690cdf0e10cSrcweir info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1)); 2691cdf0e10cSrcweir info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1)); 2692cdf0e10cSrcweir info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1)); 2693cdf0e10cSrcweir info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1)); 2694cdf0e10cSrcweir /* sanity check; some fonts treat winDescent as signed 2695cdf0e10cSrcweir * violating the standard */ 2696cdf0e10cSrcweir if( info->winDescent > 5*UPEm ) 2697cdf0e10cSrcweir info->winDescent = XUnits(UPEm, GetInt16(table, 76,1)); 2698cdf0e10cSrcweir } 2699cdf0e10cSrcweir if (ttf->cmapType == CMAP_MS_Unicode) { 2700cdf0e10cSrcweir info->rangeFlag = 1; 2701cdf0e10cSrcweir info->ur1 = GetUInt32(table, 42, 1); 2702cdf0e10cSrcweir info->ur2 = GetUInt32(table, 46, 1); 2703cdf0e10cSrcweir info->ur3 = GetUInt32(table, 50, 1); 2704cdf0e10cSrcweir info->ur4 = GetUInt32(table, 54, 1); 2705cdf0e10cSrcweir } 2706cdf0e10cSrcweir memcpy(info->panose, table + 32, 10); 2707cdf0e10cSrcweir info->typeFlags = GetUInt16( table, 8, 1 ); 2708cdf0e10cSrcweir if( getTable(ttf, O_CFF) ) 2709cdf0e10cSrcweir info->typeFlags |= TYPEFLAG_PS_OPENTYPE; 2710cdf0e10cSrcweir } 2711cdf0e10cSrcweir 2712cdf0e10cSrcweir table = getTable(ttf, O_post); 2713cdf0e10cSrcweir if (table && getTableSize(ttf, O_post) >= 12+sizeof(sal_uInt32)) { 2714cdf0e10cSrcweir info->pitch = GetUInt32(table, 12, 1); 2715cdf0e10cSrcweir info->italicAngle = GetInt32(table, 4, 1); 2716cdf0e10cSrcweir } 2717cdf0e10cSrcweir 2718cdf0e10cSrcweir table = getTable(ttf, O_head); /* 'head' tables is always there */ 2719cdf0e10cSrcweir info->xMin = XUnits(UPEm, GetInt16(table, 36, 1)); 2720cdf0e10cSrcweir info->yMin = XUnits(UPEm, GetInt16(table, 38, 1)); 2721cdf0e10cSrcweir info->xMax = XUnits(UPEm, GetInt16(table, 40, 1)); 2722cdf0e10cSrcweir info->yMax = XUnits(UPEm, GetInt16(table, 42, 1)); 2723cdf0e10cSrcweir info->macStyle = GetInt16(table, 44, 1); 2724cdf0e10cSrcweir 2725cdf0e10cSrcweir table = getTable(ttf, O_hhea); 2726cdf0e10cSrcweir if (table) { 2727cdf0e10cSrcweir info->ascender = XUnits(UPEm, GetInt16(table, 4, 1)); 2728cdf0e10cSrcweir info->descender = XUnits(UPEm, GetInt16(table, 6, 1)); 2729cdf0e10cSrcweir info->linegap = XUnits(UPEm, GetInt16(table, 8, 1)); 2730cdf0e10cSrcweir } 2731cdf0e10cSrcweir 2732cdf0e10cSrcweir table = getTable(ttf, O_vhea); 2733cdf0e10cSrcweir if (table) { 2734cdf0e10cSrcweir info->vascent = XUnits(UPEm, GetInt16(table, 4, 1)); 2735cdf0e10cSrcweir info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1)); 2736cdf0e10cSrcweir } 2737cdf0e10cSrcweir } 2738cdf0e10cSrcweir 2739cdf0e10cSrcweir #ifdef TEST5 2740cdf0e10cSrcweir void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern) 2741cdf0e10cSrcweir { 2742cdf0e10cSrcweir int i; 2743cdf0e10cSrcweir 2744cdf0e10cSrcweir if (!nglyphs || !glyphs || !kern) return; 2745cdf0e10cSrcweir 2746cdf0e10cSrcweir for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0; 2747cdf0e10cSrcweir 2748cdf0e10cSrcweir switch (ttf->kerntype) { 2749cdf0e10cSrcweir case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return; 2750cdf0e10cSrcweir case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return; 2751cdf0e10cSrcweir default: return; 2752cdf0e10cSrcweir } 2753cdf0e10cSrcweir } 2754cdf0e10cSrcweir #endif 2755cdf0e10cSrcweir 2756cdf0e10cSrcweir GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID) 2757cdf0e10cSrcweir { 2758cdf0e10cSrcweir const sal_uInt8* glyf = getTable(ttf, O_glyf); 2759cdf0e10cSrcweir const sal_uInt8* hmtx = getTable(ttf, O_hmtx); 2760cdf0e10cSrcweir int i, n, m; 2761cdf0e10cSrcweir 2762cdf0e10cSrcweir if( glyphID >= ttf->nglyphs ) 2763cdf0e10cSrcweir return 0; 2764cdf0e10cSrcweir 2765cdf0e10cSrcweir /* #127161# check the glyph offsets */ 2766cdf0e10cSrcweir sal_uInt32 length = getTableSize( ttf, O_glyf ); 2767cdf0e10cSrcweir if( length < ttf->goffsets[ glyphID+1 ] ) 2768cdf0e10cSrcweir return 0; 2769cdf0e10cSrcweir 2770cdf0e10cSrcweir length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID]; 2771cdf0e10cSrcweir 2772cdf0e10cSrcweir GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData)); assert(d != 0); 2773cdf0e10cSrcweir 2774cdf0e10cSrcweir if (length > 0) { 2775cdf0e10cSrcweir const sal_uInt8* srcptr = glyf + ttf->goffsets[glyphID]; 2776cdf0e10cSrcweir d->ptr = (sal_uInt8*)malloc((length + 1) & ~1); assert(d->ptr != 0); 2777cdf0e10cSrcweir memcpy( d->ptr, srcptr, length ); 2778cdf0e10cSrcweir d->compflag = (GetInt16( srcptr, 0, 1 ) < 0); 2779cdf0e10cSrcweir } else { 2780cdf0e10cSrcweir d->ptr = 0; 2781cdf0e10cSrcweir d->compflag = 0; 2782cdf0e10cSrcweir } 2783cdf0e10cSrcweir 2784cdf0e10cSrcweir d->glyphID = glyphID; 2785cdf0e10cSrcweir d->nbytes = (sal_uInt16)((length + 1) & ~1); 2786cdf0e10cSrcweir 2787cdf0e10cSrcweir /* now calculate npoints and ncontours */ 2788cdf0e10cSrcweir ControlPoint *cp; 2789cdf0e10cSrcweir n = GetTTGlyphPoints(ttf, glyphID, &cp); 2790cdf0e10cSrcweir if (n != -1) { 2791cdf0e10cSrcweir m = 0; 2792cdf0e10cSrcweir for (i = 0; i < n; i++) { 2793cdf0e10cSrcweir if (cp[i].flags & 0x8000) m++; 2794cdf0e10cSrcweir } 2795cdf0e10cSrcweir d->npoints = (sal_uInt16)n; 2796cdf0e10cSrcweir d->ncontours = (sal_uInt16)m; 2797cdf0e10cSrcweir free(cp); 2798cdf0e10cSrcweir } else { 2799cdf0e10cSrcweir d->npoints = 0; 2800cdf0e10cSrcweir d->ncontours = 0; 2801cdf0e10cSrcweir } 2802cdf0e10cSrcweir 2803cdf0e10cSrcweir /* get advance width and left sidebearing */ 2804cdf0e10cSrcweir if (glyphID < ttf->numberOfHMetrics) { 2805cdf0e10cSrcweir d->aw = GetUInt16(hmtx, 4 * glyphID, 1); 2806cdf0e10cSrcweir d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1); 2807cdf0e10cSrcweir } else { 2808cdf0e10cSrcweir d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1); 2809cdf0e10cSrcweir d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1); 2810cdf0e10cSrcweir } 2811cdf0e10cSrcweir 2812cdf0e10cSrcweir return d; 2813cdf0e10cSrcweir } 2814cdf0e10cSrcweir 2815cdf0e10cSrcweir int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr) 2816cdf0e10cSrcweir { 2817cdf0e10cSrcweir const sal_uInt8* table = getTable(ttf, O_name); 2818cdf0e10cSrcweir int nTableSize = getTableSize(ttf, O_name ); 2819cdf0e10cSrcweir 2820cdf0e10cSrcweir if (nTableSize < 6) 2821cdf0e10cSrcweir { 2822cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 2823cdf0e10cSrcweir fprintf(stderr, "O_name table too small\n"); 2824cdf0e10cSrcweir #endif 2825cdf0e10cSrcweir return 0; 2826cdf0e10cSrcweir } 2827cdf0e10cSrcweir 2828cdf0e10cSrcweir sal_uInt16 n = GetUInt16(table, 2, 1); 2829cdf0e10cSrcweir int nStrBase = GetUInt16(table, 4, 1); 2830cdf0e10cSrcweir int i; 2831cdf0e10cSrcweir 2832cdf0e10cSrcweir *nr = 0; 2833cdf0e10cSrcweir if (n == 0) return 0; 2834cdf0e10cSrcweir 2835cdf0e10cSrcweir NameRecord* rec = (NameRecord*)calloc(n, sizeof(NameRecord)); 2836cdf0e10cSrcweir 2837cdf0e10cSrcweir for (i = 0; i < n; i++) { 2838cdf0e10cSrcweir int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1); 2839cdf0e10cSrcweir rec[i].platformID = GetUInt16(table + 6, 12 * i, 1); 2840cdf0e10cSrcweir rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1); 2841cdf0e10cSrcweir rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1); 2842cdf0e10cSrcweir rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1); 2843cdf0e10cSrcweir rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1); 2844cdf0e10cSrcweir if (rec[i].slen) { 2845cdf0e10cSrcweir if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) { 2846cdf0e10cSrcweir rec[i].sptr = 0; 2847cdf0e10cSrcweir rec[i].slen = 0; 2848cdf0e10cSrcweir continue; 2849cdf0e10cSrcweir } 2850cdf0e10cSrcweir 2851cdf0e10cSrcweir const sal_uInt8* rec_string = table + nStrBase + nStrOffset; 2852cdf0e10cSrcweir // sanity check 2853cdf0e10cSrcweir if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) ) 2854cdf0e10cSrcweir { 2855cdf0e10cSrcweir rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0); 2856cdf0e10cSrcweir memcpy(rec[i].sptr, rec_string, rec[i].slen); 2857cdf0e10cSrcweir } 2858cdf0e10cSrcweir else 2859cdf0e10cSrcweir { 2860cdf0e10cSrcweir #ifdef DEBUG 2861cdf0e10cSrcweir fprintf( stderr, "found invalid name record %d with name id %d for file %s\n", 2862cdf0e10cSrcweir i, rec[i].nameID, ttf->fname ); 2863cdf0e10cSrcweir #endif 2864cdf0e10cSrcweir rec[i].sptr = 0; 2865cdf0e10cSrcweir rec[i].slen = 0; 2866cdf0e10cSrcweir } 2867cdf0e10cSrcweir } else { 2868cdf0e10cSrcweir rec[i].sptr = 0; 2869cdf0e10cSrcweir } 2870cdf0e10cSrcweir // some fonts have 3.0 names => fix them to 3.1 2871cdf0e10cSrcweir if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) ) 2872cdf0e10cSrcweir rec[i].encodingID = 1; 2873cdf0e10cSrcweir } 2874cdf0e10cSrcweir 2875cdf0e10cSrcweir *nr = rec; 2876cdf0e10cSrcweir return n; 2877cdf0e10cSrcweir } 2878cdf0e10cSrcweir 2879cdf0e10cSrcweir void DisposeNameRecords(NameRecord* nr, int n) 2880cdf0e10cSrcweir { 2881cdf0e10cSrcweir int i; 2882cdf0e10cSrcweir for (i = 0; i < n; i++) { 2883cdf0e10cSrcweir if (nr[i].sptr) free(nr[i].sptr); 2884cdf0e10cSrcweir } 2885cdf0e10cSrcweir free(nr); 2886cdf0e10cSrcweir } 2887cdf0e10cSrcweir 2888cdf0e10cSrcweir } // namespace vcl 2889cdf0e10cSrcweir 2890cdf0e10cSrcweir 2891cdf0e10cSrcweir #ifdef TEST1 2892cdf0e10cSrcweir /* This example creates a subset of a TrueType font with two encoded characters */ 2893cdf0e10cSrcweir int main(int ac, char **av) 2894cdf0e10cSrcweir { 2895cdf0e10cSrcweir TrueTypeFont *fnt; 2896cdf0e10cSrcweir int r; 2897cdf0e10cSrcweir 2898cdf0e10cSrcweir /* Array of Unicode source characters */ 2899cdf0e10cSrcweir sal_uInt16 chars[2]; 2900cdf0e10cSrcweir 2901cdf0e10cSrcweir /* Encoding vector maps character encoding to the ordinal number 2902cdf0e10cSrcweir * of the glyph in the output file */ 2903cdf0e10cSrcweir sal_uInt8 encoding[2]; 2904cdf0e10cSrcweir 2905cdf0e10cSrcweir /* This array is for glyph IDs that source characters map to */ 2906cdf0e10cSrcweir sal_uInt16 g[2]; 2907cdf0e10cSrcweir 2908cdf0e10cSrcweir 2909cdf0e10cSrcweir if (ac < 2) return 0; 2910cdf0e10cSrcweir 2911cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2912cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2913cdf0e10cSrcweir return 0; 2914cdf0e10cSrcweir } 2915cdf0e10cSrcweir 2916cdf0e10cSrcweir 2917cdf0e10cSrcweir /* We want to create the output file that only contains two Unicode characters: 2918cdf0e10cSrcweir * L'a' and L'A' */ 2919cdf0e10cSrcweir 2920cdf0e10cSrcweir chars[0] = L'a'; 2921cdf0e10cSrcweir chars[1] = L'A'; 2922cdf0e10cSrcweir 2923cdf0e10cSrcweir /* Figure out what glyphs do these characters map in our font */ 2924cdf0e10cSrcweir MapString(fnt, chars, 2, g); 2925cdf0e10cSrcweir 2926cdf0e10cSrcweir /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2927cdf0e10cSrcweir * newly generated font */ 2928cdf0e10cSrcweir encoding[0] = chars[0]; 2929cdf0e10cSrcweir encoding[1] = chars[1]; 2930cdf0e10cSrcweir 2931cdf0e10cSrcweir 2932cdf0e10cSrcweir /* Generate a subset */ 2933cdf0e10cSrcweir CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0); 2934cdf0e10cSrcweir 2935cdf0e10cSrcweir /* Now call the dtor for the font */ 2936cdf0e10cSrcweir CloseTTFont(fnt); 2937cdf0e10cSrcweir return 0; 2938cdf0e10cSrcweir } 2939cdf0e10cSrcweir #endif 2940cdf0e10cSrcweir 2941cdf0e10cSrcweir #ifdef TEST2 2942cdf0e10cSrcweir /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */ 2943cdf0e10cSrcweir int main(int ac, char **av) 2944cdf0e10cSrcweir { 2945cdf0e10cSrcweir TrueTypeFont *fnt; 2946cdf0e10cSrcweir int i, r; 2947cdf0e10cSrcweir 2948cdf0e10cSrcweir /* Array of Unicode source characters */ 2949cdf0e10cSrcweir sal_uInt16 glyphs[224]; 2950cdf0e10cSrcweir 2951cdf0e10cSrcweir /* Encoding vector maps character encoding to the ordinal number 2952cdf0e10cSrcweir * of the glyph in the output file */ 2953cdf0e10cSrcweir sal_uInt8 encoding[224]; 2954cdf0e10cSrcweir 2955cdf0e10cSrcweir 2956cdf0e10cSrcweir 2957cdf0e10cSrcweir for (i=0; i<224; i++) { 2958cdf0e10cSrcweir glyphs[i] = i; 2959cdf0e10cSrcweir encoding[i] = 32 + i; 2960cdf0e10cSrcweir } 2961cdf0e10cSrcweir 2962cdf0e10cSrcweir if (ac < 2) return 0; 2963cdf0e10cSrcweir 2964cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2965cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2966cdf0e10cSrcweir return 0; 2967cdf0e10cSrcweir } 2968cdf0e10cSrcweir 2969cdf0e10cSrcweir 2970cdf0e10cSrcweir /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the 2971cdf0e10cSrcweir * newly generated font */ 2972cdf0e10cSrcweir 2973cdf0e10cSrcweir /* Generate a subset */ 2974cdf0e10cSrcweir CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0); 2975cdf0e10cSrcweir 2976cdf0e10cSrcweir /* Now call the dtor for the font */ 2977cdf0e10cSrcweir CloseTTFont(fnt); 2978cdf0e10cSrcweir return 0; 2979cdf0e10cSrcweir } 2980cdf0e10cSrcweir #endif 2981cdf0e10cSrcweir 2982cdf0e10cSrcweir #ifdef TEST3 2983cdf0e10cSrcweir /* Glyph metrics example */ 2984cdf0e10cSrcweir int main(int ac, char **av) 2985cdf0e10cSrcweir { 2986cdf0e10cSrcweir TrueTypeFont *fnt; 2987cdf0e10cSrcweir int i, r; 2988cdf0e10cSrcweir sal_uInt16 glyphs[224]; 2989cdf0e10cSrcweir TTSimpleGlyphMetrics *m; 2990cdf0e10cSrcweir 2991cdf0e10cSrcweir for (i=0; i<224; i++) { 2992cdf0e10cSrcweir glyphs[i] = i; 2993cdf0e10cSrcweir } 2994cdf0e10cSrcweir 2995cdf0e10cSrcweir if (ac < 2) return 0; 2996cdf0e10cSrcweir 2997cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 2998cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 2999cdf0e10cSrcweir return 0; 3000cdf0e10cSrcweir } 3001cdf0e10cSrcweir 3002cdf0e10cSrcweir if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) { 3003cdf0e10cSrcweir printf("Requested metrics is not available\n"); 3004cdf0e10cSrcweir } else { 3005cdf0e10cSrcweir for (i=0; i<224; i++) { 3006cdf0e10cSrcweir printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb); 3007cdf0e10cSrcweir } 3008cdf0e10cSrcweir } 3009cdf0e10cSrcweir 3010cdf0e10cSrcweir /* Now call the dtor for the font */ 3011cdf0e10cSrcweir free(m); 3012cdf0e10cSrcweir CloseTTFont(fnt); 3013cdf0e10cSrcweir return 0; 3014cdf0e10cSrcweir } 3015cdf0e10cSrcweir #endif 3016cdf0e10cSrcweir 3017cdf0e10cSrcweir #ifdef TEST4 3018cdf0e10cSrcweir int main(int ac, char **av) 3019cdf0e10cSrcweir { 3020cdf0e10cSrcweir TrueTypeFont *fnt; 3021cdf0e10cSrcweir TTGlobalFontInfo info; 3022cdf0e10cSrcweir int i, r; 3023cdf0e10cSrcweir 3024cdf0e10cSrcweir 3025cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3026cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3027cdf0e10cSrcweir return 0; 3028cdf0e10cSrcweir } 3029cdf0e10cSrcweir 3030cdf0e10cSrcweir printf("Font file: %s\n", av[1]); 3031cdf0e10cSrcweir 3032cdf0e10cSrcweir #ifdef PRINT_KERN 3033cdf0e10cSrcweir switch (fnt->kerntype) { 3034cdf0e10cSrcweir case KT_MICROSOFT: 3035cdf0e10cSrcweir printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern); 3036cdf0e10cSrcweir if (fnt->nkern) { 3037cdf0e10cSrcweir printf(" ["); 3038cdf0e10cSrcweir for (i=0; i<fnt->nkern; i++) { 3039cdf0e10cSrcweir printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3040cdf0e10cSrcweir } 3041cdf0e10cSrcweir printf("]"); 3042cdf0e10cSrcweir } 3043cdf0e10cSrcweir printf("\n"); 3044cdf0e10cSrcweir break; 3045cdf0e10cSrcweir 3046cdf0e10cSrcweir case KT_APPLE_NEW: 3047cdf0e10cSrcweir printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern); 3048cdf0e10cSrcweir if (fnt->nkern) { 3049cdf0e10cSrcweir printf(" ["); 3050cdf0e10cSrcweir for (i=0; i<fnt->nkern; i++) { 3051cdf0e10cSrcweir printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1)); 3052cdf0e10cSrcweir } 3053cdf0e10cSrcweir printf("]"); 3054cdf0e10cSrcweir } 3055cdf0e10cSrcweir printf("\n"); 3056cdf0e10cSrcweir break; 3057cdf0e10cSrcweir 3058cdf0e10cSrcweir case KT_NONE: 3059cdf0e10cSrcweir printf("\tkern: none.\n"); 3060cdf0e10cSrcweir break; 3061cdf0e10cSrcweir 3062cdf0e10cSrcweir default: 3063cdf0e10cSrcweir printf("\tkern: unrecoginzed.\n"); 3064cdf0e10cSrcweir break; 3065cdf0e10cSrcweir } 3066cdf0e10cSrcweir printf("\n"); 3067cdf0e10cSrcweir #endif 3068cdf0e10cSrcweir 3069cdf0e10cSrcweir GetTTGlobalFontInfo(fnt, &info); 3070cdf0e10cSrcweir printf("\tfamily name: `%s`\n", info.family); 3071cdf0e10cSrcweir printf("\tsubfamily name: `%s`\n", info.subfamily); 3072cdf0e10cSrcweir printf("\tpostscript name: `%s`\n", info.psname); 3073cdf0e10cSrcweir printf("\tweight: %d\n", info.weight); 3074cdf0e10cSrcweir printf("\twidth: %d\n", info.width); 3075cdf0e10cSrcweir printf("\tpitch: %d\n", info.pitch); 3076cdf0e10cSrcweir printf("\titalic angle: %d\n", info.italicAngle); 3077cdf0e10cSrcweir printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax); 3078cdf0e10cSrcweir printf("\tascender: %d\n", info.ascender); 3079cdf0e10cSrcweir printf("\tdescender: %d\n", info.descender); 3080cdf0e10cSrcweir printf("\tlinegap: %d\n", info.linegap); 3081cdf0e10cSrcweir printf("\tvascent: %d\n", info.vascent); 3082cdf0e10cSrcweir printf("\tvdescent: %d\n", info.vdescent); 3083cdf0e10cSrcweir printf("\ttypoAscender: %d\n", info.typoAscender); 3084cdf0e10cSrcweir printf("\ttypoDescender: %d\n", info.typoDescender); 3085cdf0e10cSrcweir printf("\ttypoLineGap: %d\n", info.typoLineGap); 3086cdf0e10cSrcweir printf("\twinAscent: %d\n", info.winAscent); 3087cdf0e10cSrcweir printf("\twinDescent: %d\n", info.winDescent); 3088cdf0e10cSrcweir printf("\tUnicode ranges:\n"); 3089cdf0e10cSrcweir for (i = 0; i < 32; i++) { 3090cdf0e10cSrcweir if ((info.ur1 >> i) & 1) { 3091cdf0e10cSrcweir printf("\t\t\t%s\n", UnicodeRangeName(i)); 3092cdf0e10cSrcweir } 3093cdf0e10cSrcweir } 3094cdf0e10cSrcweir for (i = 0; i < 32; i++) { 3095cdf0e10cSrcweir if ((info.ur2 >> i) & 1) { 3096cdf0e10cSrcweir printf("\t\t\t%s\n", UnicodeRangeName(i+32)); 3097cdf0e10cSrcweir } 3098cdf0e10cSrcweir } 3099cdf0e10cSrcweir for (i = 0; i < 32; i++) { 3100cdf0e10cSrcweir if ((info.ur3 >> i) & 1) { 3101cdf0e10cSrcweir printf("\t\t\t%s\n", UnicodeRangeName(i+64)); 3102cdf0e10cSrcweir } 3103cdf0e10cSrcweir } 3104cdf0e10cSrcweir for (i = 0; i < 32; i++) { 3105cdf0e10cSrcweir if ((info.ur4 >> i) & 1) { 3106cdf0e10cSrcweir printf("\t\t\t%s\n", UnicodeRangeName(i+96)); 3107cdf0e10cSrcweir } 3108cdf0e10cSrcweir } 3109cdf0e10cSrcweir 3110cdf0e10cSrcweir CloseTTFont(fnt); 3111cdf0e10cSrcweir return 0; 3112cdf0e10cSrcweir } 3113cdf0e10cSrcweir #endif 3114cdf0e10cSrcweir 3115cdf0e10cSrcweir #ifdef TEST5 3116cdf0e10cSrcweir /* Kerning example */ 3117cdf0e10cSrcweir int main(int ac, char **av) 3118cdf0e10cSrcweir { 3119cdf0e10cSrcweir TrueTypeFont *fnt; 3120cdf0e10cSrcweir sal_uInt16 g[224]; 3121cdf0e10cSrcweir KernData d[223]; 3122cdf0e10cSrcweir int r, i, k = 0; 3123cdf0e10cSrcweir 3124cdf0e10cSrcweir g[k++] = 11; 3125cdf0e10cSrcweir g[k++] = 36; 3126cdf0e10cSrcweir g[k++] = 11; 3127cdf0e10cSrcweir g[k++] = 98; 3128cdf0e10cSrcweir g[k++] = 11; 3129cdf0e10cSrcweir g[k++] = 144; 3130cdf0e10cSrcweir g[k++] = 41; 3131cdf0e10cSrcweir g[k++] = 171; 3132cdf0e10cSrcweir g[k++] = 51; 3133cdf0e10cSrcweir g[k++] = 15; 3134cdf0e10cSrcweir 3135cdf0e10cSrcweir if (ac < 2) return 0; 3136cdf0e10cSrcweir 3137cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3138cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3139cdf0e10cSrcweir return 0; 3140cdf0e10cSrcweir } 3141cdf0e10cSrcweir 3142cdf0e10cSrcweir KernGlyphs(fnt, g, k, 0, d); 3143cdf0e10cSrcweir 3144cdf0e10cSrcweir for (i = 0; i < k-1; i++) { 3145cdf0e10cSrcweir printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y); 3146cdf0e10cSrcweir } 3147cdf0e10cSrcweir 3148cdf0e10cSrcweir CloseTTFont(fnt); 3149cdf0e10cSrcweir return 0; 3150cdf0e10cSrcweir } 3151cdf0e10cSrcweir #endif 3152cdf0e10cSrcweir 3153cdf0e10cSrcweir 3154cdf0e10cSrcweir 3155cdf0e10cSrcweir #ifdef TEST6 3156cdf0e10cSrcweir /* This example extracts a single glyph from a font */ 3157cdf0e10cSrcweir int main(int ac, char **av) 3158cdf0e10cSrcweir { 3159cdf0e10cSrcweir TrueTypeFont *fnt; 3160cdf0e10cSrcweir int r, i; 3161cdf0e10cSrcweir 3162cdf0e10cSrcweir sal_uInt16 glyphs[256]; 3163cdf0e10cSrcweir sal_uInt8 encoding[256]; 3164cdf0e10cSrcweir 3165cdf0e10cSrcweir for (i=0; i<256; i++) { 3166cdf0e10cSrcweir glyphs[i] = 512 + i; 3167cdf0e10cSrcweir encoding[i] = i; 3168cdf0e10cSrcweir } 3169cdf0e10cSrcweir 3170cdf0e10cSrcweir #if 0 3171cdf0e10cSrcweir i=0; 3172cdf0e10cSrcweir glyphs[i++] = 2001; 3173cdf0e10cSrcweir glyphs[i++] = 2002; 3174cdf0e10cSrcweir glyphs[i++] = 2003; 3175cdf0e10cSrcweir glyphs[i++] = 2004; 3176cdf0e10cSrcweir glyphs[i++] = 2005; 3177cdf0e10cSrcweir glyphs[i++] = 2006; 3178cdf0e10cSrcweir glyphs[i++] = 2007; 3179cdf0e10cSrcweir glyphs[i++] = 2008; 3180cdf0e10cSrcweir glyphs[i++] = 2009; 3181cdf0e10cSrcweir glyphs[i++] = 2010; 3182cdf0e10cSrcweir glyphs[i++] = 2011; 3183cdf0e10cSrcweir glyphs[i++] = 2012; 3184cdf0e10cSrcweir glyphs[i++] = 2013; 3185cdf0e10cSrcweir glyphs[i++] = 2014; 3186cdf0e10cSrcweir glyphs[i++] = 2015; 3187cdf0e10cSrcweir glyphs[i++] = 2016; 3188cdf0e10cSrcweir glyphs[i++] = 2017; 3189cdf0e10cSrcweir glyphs[i++] = 2018; 3190cdf0e10cSrcweir glyphs[i++] = 2019; 3191cdf0e10cSrcweir glyphs[i++] = 2020; 3192cdf0e10cSrcweir 3193cdf0e10cSrcweir 3194cdf0e10cSrcweir r = 97; 3195cdf0e10cSrcweir i = 0; 3196cdf0e10cSrcweir encoding[i++] = r++; 3197cdf0e10cSrcweir encoding[i++] = r++; 3198cdf0e10cSrcweir encoding[i++] = r++; 3199cdf0e10cSrcweir encoding[i++] = r++; 3200cdf0e10cSrcweir encoding[i++] = r++; 3201cdf0e10cSrcweir encoding[i++] = r++; 3202cdf0e10cSrcweir encoding[i++] = r++; 3203cdf0e10cSrcweir encoding[i++] = r++; 3204cdf0e10cSrcweir encoding[i++] = r++; 3205cdf0e10cSrcweir encoding[i++] = r++; 3206cdf0e10cSrcweir encoding[i++] = r++; 3207cdf0e10cSrcweir encoding[i++] = r++; 3208cdf0e10cSrcweir encoding[i++] = r++; 3209cdf0e10cSrcweir encoding[i++] = r++; 3210cdf0e10cSrcweir encoding[i++] = r++; 3211cdf0e10cSrcweir encoding[i++] = r++; 3212cdf0e10cSrcweir encoding[i++] = r++; 3213cdf0e10cSrcweir encoding[i++] = r++; 3214cdf0e10cSrcweir encoding[i++] = r++; 3215cdf0e10cSrcweir encoding[i++] = r++; 3216cdf0e10cSrcweir #endif 3217cdf0e10cSrcweir 3218cdf0e10cSrcweir if (ac < 2) return 0; 3219cdf0e10cSrcweir 3220cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3221cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3222cdf0e10cSrcweir return 0; 3223cdf0e10cSrcweir } 3224cdf0e10cSrcweir 3225cdf0e10cSrcweir /* Generate a subset */ 3226cdf0e10cSrcweir CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0); 3227cdf0e10cSrcweir 3228cdf0e10cSrcweir fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm); 3229cdf0e10cSrcweir 3230cdf0e10cSrcweir /* Now call the dtor for the font */ 3231cdf0e10cSrcweir CloseTTFont(fnt); 3232cdf0e10cSrcweir return 0; 3233cdf0e10cSrcweir } 3234cdf0e10cSrcweir #endif 3235cdf0e10cSrcweir 3236cdf0e10cSrcweir #ifdef TEST7 3237cdf0e10cSrcweir /* NameRecord extraction example */ 3238cdf0e10cSrcweir int main(int ac, char **av) 3239cdf0e10cSrcweir { 3240cdf0e10cSrcweir TrueTypeFont *fnt; 3241cdf0e10cSrcweir int r, i, j, n; 3242cdf0e10cSrcweir NameRecord *nr; 3243cdf0e10cSrcweir 3244cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3245cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3246cdf0e10cSrcweir return 0; 3247cdf0e10cSrcweir } 3248cdf0e10cSrcweir 3249cdf0e10cSrcweir if ((n = GetTTNameRecords(fnt, &nr)) == 0) { 3250cdf0e10cSrcweir fprintf(stderr, "No name records in the font.\n"); 3251cdf0e10cSrcweir return 0; 3252cdf0e10cSrcweir } 3253cdf0e10cSrcweir 3254cdf0e10cSrcweir printf("Number of name records: %d.\n", n); 3255cdf0e10cSrcweir for (i = 0; i < n; i++) { 3256cdf0e10cSrcweir printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID); 3257cdf0e10cSrcweir for (j=0; j<nr[i].slen; j++) { 3258cdf0e10cSrcweir printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.'); 3259cdf0e10cSrcweir } 3260cdf0e10cSrcweir printf("]\n"); 3261cdf0e10cSrcweir } 3262cdf0e10cSrcweir 3263cdf0e10cSrcweir 3264cdf0e10cSrcweir DisposeNameRecords(nr, n); 3265cdf0e10cSrcweir CloseTTFont(fnt); 3266cdf0e10cSrcweir return 0; 3267cdf0e10cSrcweir } 3268cdf0e10cSrcweir #endif 3269cdf0e10cSrcweir 3270cdf0e10cSrcweir #ifdef TEST8 3271cdf0e10cSrcweir /* TrueType -> TrueType subsetting */ 3272cdf0e10cSrcweir int main(int ac, char **av) 3273cdf0e10cSrcweir { 3274cdf0e10cSrcweir TrueTypeFont *fnt; 3275cdf0e10cSrcweir sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3276cdf0e10cSrcweir sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3277cdf0e10cSrcweir int r; 3278cdf0e10cSrcweir 3279cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3280cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3281cdf0e10cSrcweir return 0; 3282cdf0e10cSrcweir } 3283cdf0e10cSrcweir 3284cdf0e10cSrcweir CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2); 3285cdf0e10cSrcweir 3286cdf0e10cSrcweir 3287cdf0e10cSrcweir CloseTTFont(fnt); 3288cdf0e10cSrcweir 3289cdf0e10cSrcweir return 0; 3290cdf0e10cSrcweir } 3291cdf0e10cSrcweir #endif 3292cdf0e10cSrcweir 3293cdf0e10cSrcweir #ifdef TEST9 3294cdf0e10cSrcweir /* TrueType -> Type42 subsetting */ 3295cdf0e10cSrcweir int main(int ac, char **av) 3296cdf0e10cSrcweir { 3297cdf0e10cSrcweir TrueTypeFont *fnt; 3298cdf0e10cSrcweir /* 3299cdf0e10cSrcweir sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34}; 3300cdf0e10cSrcweir sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3301cdf0e10cSrcweir */ 3302cdf0e10cSrcweir sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34}; 3303cdf0e10cSrcweir sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}; 3304cdf0e10cSrcweir int r; 3305cdf0e10cSrcweir 3306cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3307cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3308cdf0e10cSrcweir return 0; 3309cdf0e10cSrcweir } 3310cdf0e10cSrcweir 3311cdf0e10cSrcweir CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15); 3312cdf0e10cSrcweir 3313cdf0e10cSrcweir CloseTTFont(fnt); 3314cdf0e10cSrcweir 3315cdf0e10cSrcweir return 0; 3316cdf0e10cSrcweir } 3317cdf0e10cSrcweir #endif 3318cdf0e10cSrcweir 3319cdf0e10cSrcweir #ifdef TEST10 3320cdf0e10cSrcweir /* Component glyph test */ 3321cdf0e10cSrcweir int main(int ac, char **av) 3322cdf0e10cSrcweir { 3323cdf0e10cSrcweir TrueTypeFont *fnt; 3324cdf0e10cSrcweir int r, i; 3325cdf0e10cSrcweir list glyphlist = listNewEmpty(); 3326cdf0e10cSrcweir 3327cdf0e10cSrcweir 3328cdf0e10cSrcweir if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) { 3329cdf0e10cSrcweir fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]); 3330cdf0e10cSrcweir return 0; 3331cdf0e10cSrcweir } 3332cdf0e10cSrcweir 3333cdf0e10cSrcweir for (i = 0; i < fnt->nglyphs; i++) { 3334cdf0e10cSrcweir r = GetTTGlyphComponents(fnt, i, glyphlist); 3335cdf0e10cSrcweir if (r > 1) { 3336cdf0e10cSrcweir printf("%d -> ", i); 3337cdf0e10cSrcweir listToFirst(glyphlist); 3338cdf0e10cSrcweir do { 3339cdf0e10cSrcweir printf("%d ", (int) listCurrent(glyphlist)); 3340cdf0e10cSrcweir } while (listNext(glyphlist)); 3341cdf0e10cSrcweir printf("\n"); 3342cdf0e10cSrcweir } else { 3343cdf0e10cSrcweir printf("%d: single glyph.\n", i); 3344cdf0e10cSrcweir } 3345cdf0e10cSrcweir listClear(glyphlist); 3346cdf0e10cSrcweir } 3347cdf0e10cSrcweir 3348cdf0e10cSrcweir CloseTTFont(fnt); 3349cdf0e10cSrcweir listDispose(glyphlist); 3350cdf0e10cSrcweir 3351cdf0e10cSrcweir return 0; 3352cdf0e10cSrcweir } 3353cdf0e10cSrcweir #endif 3354cdf0e10cSrcweir 3355cdf0e10cSrcweir 3356