/OOO330_m20/vcl/source/fontsubset/sft.cxx
C++ | 3359 lines | 2601 code | 513 blank | 245 comment | 620 complexity | 27d2a58efa1b623d0f7f56963a234b5b MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
- // MARKER(update_precomp.py): autogen include statement, do not remove
- #include "precompiled_vcl.hxx"
- /*
- * Sun Font Tools
- *
- * Author: Alexander Gelfenbain
- *
- */
- #if OSL_DEBUG_LEVEL == 0
- # ifndef NDEBUG
- # define NDEBUG
- # endif
- #endif
- #include <assert.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #ifdef UNX
- #include <sys/mman.h>
- #include <sys/stat.h>
- #endif
- #include "sft.hxx"
- #include "gsub.h"
- #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
- #include "ttcr.hxx"
- #endif
- #ifndef NO_MAPPERS /* include MapChar() and MapString() */
- #include "xlat.hxx"
- #endif
- #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
- #include <rtl/crc.h>
- #endif
- #include <osl/endian.h>
- #include <algorithm>
- #ifdef TEST7
- #include <ctype.h>
- #endif
- namespace vcl
- {
- /*- module identification */
- static const char *modname = "SunTypeTools-TT";
- static const char *modver = "1.0";
- static const char *modextra = "gelf";
- /*- private functions, constants and data types */ /*FOLD00*/
- enum PathSegmentType {
- PS_NOOP = 0,
- PS_MOVETO = 1,
- PS_LINETO = 2,
- PS_CURVETO = 3,
- PS_CLOSEPATH = 4
- };
- struct PSPathElement
- {
- PathSegmentType type;
- int x1, y1;
- int x2, y2;
- int x3, y3;
-
- PSPathElement( PathSegmentType i_eType ) : type( i_eType ),
- x1( 0 ), y1( 0 ),
- x2( 0 ), y2( 0 ),
- x3( 0 ), y3( 0 )
- {
- }
- };
- /*- In horisontal writing mode right sidebearing is calculated using this formula
- *- rsb = aw - (lsb + xMax - xMin) -*/
- typedef struct {
- sal_Int16 xMin;
- sal_Int16 yMin;
- sal_Int16 xMax;
- sal_Int16 yMax;
- sal_uInt16 aw; /*- Advance Width (horisontal writing mode) */
- sal_Int16 lsb; /*- Left sidebearing (horisontal writing mode) */
- sal_uInt16 ah; /*- advance height (vertical writing mode) */
- sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */
- } TTGlyphMetrics;
- #define HFORMAT_LINELEN 64
- typedef struct {
- FILE *o;
- char buffer[HFORMAT_LINELEN];
- int bufpos;
- int total;
- } HexFmt;
- typedef struct {
- sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */
- sal_uInt32 *offs; /* array of nGlyphs offsets */
- } GlyphOffsets;
- /* private tags */
- static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */
- static const sal_uInt32 T_true = 0x74727565; /* 'true' */
- static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */
- static const sal_uInt32 T_otto = 0x4f54544f; /* 'OTTO' */
- /* standard TrueType table tags */
- #define T_maxp 0x6D617870
- #define T_glyf 0x676C7966
- #define T_head 0x68656164
- #define T_loca 0x6C6F6361
- #define T_name 0x6E616D65
- #define T_hhea 0x68686561
- #define T_hmtx 0x686D7478
- #define T_cmap 0x636D6170
- #define T_vhea 0x76686561
- #define T_vmtx 0x766D7478
- #define T_OS2 0x4F532F32
- #define T_post 0x706F7374
- #define T_kern 0x6B65726E
- #define T_cvt 0x63767420
- #define T_prep 0x70726570
- #define T_fpgm 0x6670676D
- #define T_gsub 0x47535542
- #define T_CFF 0x43464620
- #define LAST_URANGE_BIT 69
- const char *ulcodes[LAST_URANGE_BIT+2] = {
- /* 0 */ "Basic Latin",
- /* 1 */ "Latin-1 Supplement",
- /* 2 */ "Latin Extended-A",
- /* 3 */ "Latin Extended-B",
- /* 4 */ "IPA Extensions",
- /* 5 */ "Spacing Modifier Letters",
- /* 6 */ "Combining Diacritical Marks",
- /* 7 */ "Basic Greek",
- /* 8 */ "Greek Symbols And Coptic",
- /* 9 */ "Cyrillic",
- /* 10 */ "Armenian",
- /* 11 */ "Basic Hebrew",
- /* 12 */ "Hebrew Extended (A and B blocks combined)",
- /* 13 */ "Basic Arabic",
- /* 14 */ "Arabic Extended",
- /* 15 */ "Devanagari",
- /* 16 */ "Bengali",
- /* 17 */ "Gurmukhi",
- /* 18 */ "Gujarati",
- /* 19 */ "Oriya",
- /* 20 */ "Tamil",
- /* 21 */ "Telugu",
- /* 22 */ "Kannada",
- /* 23 */ "Malayalam",
- /* 24 */ "Thai",
- /* 25 */ "Lao",
- /* 26 */ "Basic Georgian",
- /* 27 */ "Georgian Extended",
- /* 28 */ "Hangul Jamo",
- /* 29 */ "Latin Extended Additional",
- /* 30 */ "Greek Extended",
- /* 31 */ "General Punctuation",
- /* 32 */ "Superscripts And Subscripts",
- /* 33 */ "Currency Symbols",
- /* 34 */ "Combining Diacritical Marks For Symbols",
- /* 35 */ "Letterlike Symbols",
- /* 36 */ "Number Forms",
- /* 37 */ "Arrows",
- /* 38 */ "Mathematical Operators",
- /* 39 */ "Miscellaneous Technical",
- /* 40 */ "Control Pictures",
- /* 41 */ "Optical Character Recognition",
- /* 42 */ "Enclosed Alphanumerics",
- /* 43 */ "Box Drawing",
- /* 44 */ "Block Elements",
- /* 45 */ "Geometric Shapes",
- /* 46 */ "Miscellaneous Symbols",
- /* 47 */ "Dingbats",
- /* 48 */ "CJK Symbols And Punctuation",
- /* 49 */ "Hiragana",
- /* 50 */ "Katakana",
- /* 51 */ "Bopomofo",
- /* 52 */ "Hangul Compatibility Jamo",
- /* 53 */ "CJK Miscellaneous",
- /* 54 */ "Enclosed CJK Letters And Months",
- /* 55 */ "CJK Compatibility",
- /* 56 */ "Hangul",
- /* 57 */ "Reserved for Unicode SubRanges",
- /* 58 */ "Reserved for Unicode SubRanges",
- /* 59 */ "CJK Unified Ideographs",
- /* 60 */ "Private Use Area",
- /* 61 */ "CJK Compatibility Ideographs",
- /* 62 */ "Alphabetic Presentation Forms",
- /* 63 */ "Arabic Presentation Forms-A",
- /* 64 */ "Combining Half Marks",
- /* 65 */ "CJK Compatibility Forms",
- /* 66 */ "Small Form Variants",
- /* 67 */ "Arabic Presentation Forms-B",
- /* 68 */ "Halfwidth And Fullwidth Forms",
- /* 69 */ "Specials",
- /*70-127*/ "Reserved for Unicode SubRanges"
- };
- /*- inline functions */ /*FOLD01*/
- #ifdef __GNUC__
- #define _inline static __inline__
- #else
- #define _inline static
- #endif
- _inline void *smalloc(size_t size)
- {
- void *res = malloc(size);
- assert(res != 0);
- return res;
- }
- _inline void *scalloc(size_t n, size_t size)
- {
- void *res = calloc(n, size);
- assert(res != 0);
- return res;
- }
- _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
- return (a << 24) | (b << 16) | (c << 8) | d;
- }
- /*- Data access macros for data stored in big-endian or little-endian format */
- _inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
- {
- sal_Int16 t;
- assert(ptr != 0);
- if (bigendian) {
- t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
- } else {
- t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
- }
- return t;
- }
- _inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
- {
- sal_uInt16 t;
- assert(ptr != 0);
- if (bigendian) {
- t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
- } else {
- t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
- }
- return t;
- }
- _inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
- {
- sal_Int32 t;
- assert(ptr != 0);
- if (bigendian) {
- t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
- (ptr+offset)[2] << 8 | (ptr+offset)[3];
- } else {
- t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
- (ptr+offset)[1] << 8 | (ptr+offset)[0];
- }
- return t;
- }
- _inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
- {
- sal_uInt32 t;
- assert(ptr != 0);
- if (bigendian) {
- t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
- (ptr+offset)[2] << 8 | (ptr+offset)[3];
- } else {
- t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
- (ptr+offset)[1] << 8 | (ptr+offset)[0];
- }
- return t;
- }
- _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian)
- {
- assert(ptr != 0);
- if (bigendian) {
- ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
- ptr[offset+1] = (sal_uInt8)(val & 0xFF);
- } else {
- ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
- ptr[offset] = (sal_uInt8)(val & 0xFF);
- }
- }
- #if defined(OSL_BIGENDIAN)
- #define Int16FromMOTA(a) (a)
- #define Int32FromMOTA(a) (a)
- #else
- static sal_uInt16 Int16FromMOTA(sal_uInt16 a) {
- return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8));
- }
- static sal_uInt32 Int32FromMOTA(sal_uInt32 a) {
- return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24));
- }
- #endif
- _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
- {
- unsigned int a1, b1;
- unsigned int a2, b2;
- F16Dot16 res;
- int sign;
- sign = (a & 0x80000000) ^ (b & 0x80000000);
- if (a < 0) a = -a;
- if (b < 0) b = -b;
- a1 = a >> 16;
- b1 = a & 0xFFFF;
- a2 = b >> 16;
- b2 = b & 0xFFFF;
- res = a1 * a2;
- /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
- res <<= 16;
- res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16);
- return sign ? -res : res;
- }
- _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
- {
- unsigned int f, r;
- F16Dot16 res;
- int sign;
- sign = (a & 0x80000000) ^ (b & 0x80000000);
- if (a < 0) a = -a;
- if (b < 0) b = -b;
- f = a / b;
- r = a % b;
- /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
- while (r > 0xFFFF) {
- r >>= 1;
- b >>= 1;
- }
- res = (f << 16) + (r << 16) / b;
- return sign ? -res : res;
- }
- /*- returns a * b / c -*/
- /* XXX provide a real implementation that preserves accuracy */
- _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
- {
- F16Dot16 res;
- res = fixedMul(a, b);
- return fixedDiv(res, c);
- }
- /*- Translate units from TT to PS (standard 1/1000) -*/
- _inline int XUnits(int unitsPerEm, int n)
- {
- return (n * 1000) / unitsPerEm;
- }
- _inline const char *UnicodeRangeName(sal_uInt16 bit)
- {
- if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1;
- return ulcodes[bit];
- }
- _inline const sal_uInt8* getTable( TrueTypeFont *ttf, sal_uInt32 ord)
- {
- return (sal_uInt8*)ttf->tables[ord];
- }
- _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord)
- {
- return ttf->tlens[ord];
- }
- #ifndef NO_TYPE42
- /* Hex Formatter functions */
- static char HexChars[] = "0123456789ABCDEF";
- static HexFmt *HexFmtNew(FILE *outf)
- {
- HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt));
- res->bufpos = res->total = 0;
- res->o = outf;
- return res;
- }
- static void HexFmtFlush(HexFmt *_this)
- {
- if (_this->bufpos) {
- fwrite(_this->buffer, 1, _this->bufpos, _this->o);
- _this->bufpos = 0;
- }
- }
- _inline void HexFmtOpenString(HexFmt *_this)
- {
- fputs("<\n", _this->o);
- }
- _inline void HexFmtCloseString(HexFmt *_this)
- {
- HexFmtFlush(_this);
- fputs("00\n>\n", _this->o);
- }
- _inline void HexFmtDispose(HexFmt *_this)
- {
- HexFmtFlush(_this);
- free(_this);
- }
- static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
- {
- sal_uInt8 Ch;
- sal_uInt32 i;
- if (_this->total + size > 65534) {
- HexFmtFlush(_this);
- HexFmtCloseString(_this);
- _this->total = 0;
- HexFmtOpenString(_this);
- }
- for (i=0; i<size; i++) {
- Ch = ((sal_uInt8 *) ptr)[i];
- _this->buffer[_this->bufpos++] = HexChars[Ch >> 4];
- _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF];
- if (_this->bufpos == HFORMAT_LINELEN) {
- HexFmtFlush(_this);
- fputc('\n', _this->o);
- }
- }
- _this->total += size;
- }
- #endif
- /* Outline Extraction functions */ /*FOLD01*/
- /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
- static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics)
- {
- const sal_uInt8* table = getTable( ttf, O_hmtx );
- metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0;
- if (!table || !ttf->numberOfHMetrics) return;
- if (glyphID < ttf->numberOfHMetrics) {
- metrics->aw = GetUInt16(table, 4 * glyphID, 1);
- metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1);
- } else {
- metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1);
- metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
- }
- table = getTable(ttf, O_vmtx);
- if( !table || !ttf->numOfLongVerMetrics )
- return;
- if (glyphID < ttf->numOfLongVerMetrics) {
- metrics->ah = GetUInt16(table, 4 * glyphID, 1);
- metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1);
- } else {
- metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1);
- metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1);
- }
- }
- static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* );
- /* returns the number of control points, allocates the pointArray */
- static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/
- {
- const sal_uInt8* table = getTable( ttf, O_glyf );
- sal_uInt8 flag, n;
- sal_uInt16 t, lastPoint=0;
- int i, j, z;
- *pointArray = 0;
- /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
- if( glyphID >= ttf->nglyphs ) /*- glyph is not present in the font */
- return 0;
- const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
- const sal_Int16 numberOfContours = GetInt16(ptr, 0, 1);
- if( numberOfContours <= 0 ) /*- glyph is not simple */
- return 0;
- if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
- metrics->xMin = GetInt16(ptr, 2, 1);
- metrics->yMin = GetInt16(ptr, 4, 1);
- metrics->xMax = GetInt16(ptr, 6, 1);
- metrics->yMax = GetInt16(ptr, 8, 1);
- GetMetrics(ttf, glyphID, metrics);
- }
- /* determine the last point and be extra safe about it. But probably this code is not needed */
- for (i=0; i<numberOfContours; i++) {
- if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t;
- }
- sal_uInt16 instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1);
- const sal_uInt8* p = ptr + 10 + 2 * numberOfContours + 2 + instLen;
- ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint));
- i = 0;
- while (i <= lastPoint) {
- pa[i++].flags = (sal_uInt32) (flag = *p++);
- if (flag & 8) { /*- repeat flag */
- n = *p++;
- for (j=0; j<n; j++) {
- if (i > lastPoint) { /*- if the font is really broken */
- free(pa);
- return 0;
- }
- pa[i++].flags = flag;
- }
- }
- }
- /*- Process the X coordinate */
- z = 0;
- for (i = 0; i <= lastPoint; i++) {
- if (pa[i].flags & 0x02) {
- if (pa[i].flags & 0x10) {
- z += (int) (*p++);
- } else {
- z -= (int) (*p++);
- }
- } else if ( !(pa[i].flags & 0x10)) {
- z += GetInt16(p, 0, 1);
- p += 2;
- }
- pa[i].x = (sal_Int16)z;
- }
- /*- Process the Y coordinate */
- z = 0;
- for (i = 0; i <= lastPoint; i++) {
- if (pa[i].flags & 0x04) {
- if (pa[i].flags & 0x20) {
- z += *p++;
- } else {
- z -= *p++;
- }
- } else if ( !(pa[i].flags & 0x20)) {
- z += GetInt16(p, 0, 1);
- p += 2;
- }
- pa[i].y = (sal_Int16)z;
- }
- for (i=0; i<numberOfContours; i++) {
- pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */
- }
- *pointArray = pa;
- return lastPoint + 1;
- }
- static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/
- {
- sal_uInt16 flags, index;
- sal_Int16 e, f, numberOfContours;
- const sal_uInt8* table = getTable( ttf, O_glyf );
- std::vector<ControlPoint> myPoints;
- ControlPoint *nextComponent, *pa;
- int i, np;
- F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
- *pointArray = 0;
- /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
- if (glyphID >= ttf->nglyphs) /*- incorrect glyphID */
- return 0;
- const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
- if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) /*- glyph is not compound */
- return 0;
- if (metrics) {
- metrics->xMin = GetInt16(ptr, 2, 1);
- metrics->yMin = GetInt16(ptr, 4, 1);
- metrics->xMax = GetInt16(ptr, 6, 1);
- metrics->yMax = GetInt16(ptr, 8, 1);
- GetMetrics(ttf, glyphID, metrics);
- }
- ptr += 10;
- do {
- flags = GetUInt16(ptr, 0, 1);
- /* printf("flags: 0x%X\n", flags); */
- index = GetUInt16(ptr, 2, 1);
- ptr += 4;
- if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() )
- {
- #if OSL_DEBUG_LEVEL > 1
- fprintf(stderr, "Endless loop found in a compound glyph.\n");
- fprintf(stderr, "%d -> ", index);
- fprintf(stderr," [");
- for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
- it != glyphlist.end(); ++it )
- {
- fprintf( stderr,"%d ", (int) *it );
- }
- fprintf(stderr,"]\n");
- /**/
- #endif
- }
- glyphlist.push_back( index );
- #ifdef DEBUG2
- fprintf(stderr,"glyphlist: += %d\n", index);
- #endif
- if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0)
- {
- /* XXX that probably indicates a corrupted font */
- #if OSL_DEBUG_LEVEL > 1
- fprintf(stderr, "An empty compound!\n");
- /* assert(!"An empty compound"); */
- #endif
- }
- #ifdef DEBUG2
- fprintf(stderr,"%d [", (int)glyphlist.size() );
- for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
- it != glyphlist.end(); ++it )
- {
- fprintf( stderr,"%d ", (int) *it );
- }
- fprintf(stderr, "]\n");
- if( ! glyphlist.empty() )
- fprintf(stderr, "glyphlist: -= %d\n", (int) glyphlist.back());
- #endif
- if( ! glyphlist.empty() )
- glyphlist.pop_back();
- if (flags & USE_MY_METRICS) {
- if (metrics) GetMetrics(ttf, index, metrics);
- }
- if (flags & ARG_1_AND_2_ARE_WORDS) {
- e = GetInt16(ptr, 0, 1);
- f = GetInt16(ptr, 2, 1);
- /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
- ptr += 4;
- } else {
- if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */
- e = (sal_Int8) *ptr++;
- f = (sal_Int8) *ptr++;
- /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
- } else { /* args are unsigned */
- /* printf("!ARGS_ARE_XY_VALUES\n"); */
- e = *ptr++;
- f = *ptr++;
- }
- }
- a = d = 0x10000;
- b = c = 0;
- if (flags & WE_HAVE_A_SCALE) {
- #ifdef DEBUG2
- fprintf(stderr, "WE_HAVE_A_SCALE\n");
- #endif
- a = GetInt16(ptr, 0, 1) << 2;
- d = a;
- ptr += 2;
- } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
- #ifdef DEBUG2
- fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n");
- #endif
- a = GetInt16(ptr, 0, 1) << 2;
- d = GetInt16(ptr, 2, 1) << 2;
- ptr += 4;
- } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
- #ifdef DEBUG2
- fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n");
- #endif
- a = GetInt16(ptr, 0, 1) << 2;
- b = GetInt16(ptr, 2, 1) << 2;
- c = GetInt16(ptr, 4, 1) << 2;
- d = GetInt16(ptr, 6, 1) << 2;
- ptr += 8;
- }
- abs1 = (a < 0) ? -a : a;
- abs2 = (b < 0) ? -b : b;
- m = (abs1 > abs2) ? abs1 : abs2;
- abs3 = abs1 - abs2;
- if (abs3 < 0) abs3 = -abs3;
- if (abs3 <= 33) m *= 2;
- abs1 = (c < 0) ? -c : c;
- abs2 = (d < 0) ? -d : d;
- n = (abs1 > abs2) ? abs1 : abs2;
- abs3 = abs1 - abs2;
- if (abs3 < 0) abs3 = -abs3;
- if (abs3 <= 33) n *= 2;
- if (!ARGS_ARE_XY_VALUES) { /* match the points */
- assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
- }
- #ifdef DEBUG2
- fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n",
- ((double) a) / 65536,
- ((double) b) / 65536,
- ((double) c) / 65536,
- ((double) d) / 65536,
- ((double) e) / 65536,
- ((double) f) / 65536,
- ((double) m) / 65536,
- ((double) n) / 65536);
- #endif
- for (i=0; i<np; i++) {
- F16Dot16 t;
- ControlPoint cp;
- cp.flags = nextComponent[i].flags;
- t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16);
- cp.x = (sal_Int16)(fixedMul(t, m) >> 16);
- t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16);
- cp.y = (sal_Int16)(fixedMul(t, n) >> 16);
- #ifdef DEBUG2
- fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp.x, cp.y);
- #endif
- myPoints.push_back( cp );
- }
- free(nextComponent);
- } while (flags & MORE_COMPONENTS);
- np = myPoints.size();
- pa = (ControlPoint*)calloc(np, sizeof(ControlPoint));
- assert(pa != 0);
-
- memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) );
- *pointArray = pa;
- return np;
- }
- /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
- * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
- *
- * NOTE: glyphlist is the stack of glyphs traversed while constructing
- * a composite glyph. This is a safequard against endless recursion
- * in corrupted fonts.
- */
- static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist)
- {
- const sal_uInt8 *table = getTable( ttf, O_glyf );
- sal_Int16 numberOfContours;
- int res;
- *pointArray = 0;
- if (metrics) {
- memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */
- }
- if (glyphID >= ttf->nglyphs) return -1; /**/
- const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
- int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
- if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
- if (metrics) GetMetrics(ttf, glyphID, metrics);
- return 0;
- }
- numberOfContours = GetInt16(ptr, 0, 1);
- if (numberOfContours >= 0)
- {
- res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
- }
- else
- {
- std::vector< sal_uInt32 > aPrivList;
- aPrivList.push_back( glyphID );
- res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList );
- }
- #ifdef DEBUG3
- {
- int i;
- FILE *out = fopen("points.dat", "a");
- assert(out != 0);
- fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res);
- for (i=0; i<res; i++) {
- fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.');
- fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-');
- fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y);
- }
- fclose(out);
- }
- #endif
- return res;
- }
- #ifndef NO_TYPE3
- /*- returns the number of items in the path -*/
- static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
- {
- std::vector< PSPathElement > aPathList;
- int nPathCount = 0;
- PSPathElement p( PS_NOOP );
- int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury;
- int lastOff = 0; /*- last point was off-contour */
- int scflag = 1; /*- start contour flag */
- int ecflag = 0; /*- end contour flag */
- int cp = 0; /*- current point */
- int StartContour = 0, EndContour = 1;
- *path = 0;
- /* if (srcCount > 0) for(;;) */
- while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
- if (scflag) {
- int l = cp;
- StartContour = cp;
- while (!(srcA[l].flags & 0x8000)) l++;
- EndContour = l;
- if (StartContour == EndContour) {
- if (cp + 1 < srcCount) {
- cp++;
- continue;
- } else {
- break;
- }
- }
- p = PSPathElement(PS_MOVETO);
- if (!(srcA[cp].flags & 1)) {
- if (!(srcA[EndContour].flags & 1)) {
- p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
- p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
- } else {
- p.x1 = x0 = srcA[EndContour].x;
- p.y1 = y0 = srcA[EndContour].y;
- }
- } else {
- p.x1 = x0 = srcA[cp].x;
- p.y1 = y0 = srcA[cp].y;
- cp++;
- }
- aPathList.push_back( p );
- lastOff = 0;
- scflag = 0;
- }
- curx = srcA[cp].x;
- cury = srcA[cp].y;
- if (srcA[cp].flags & 1)
- {
- if (lastOff)
- {
- p = PSPathElement(PS_CURVETO);
- p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
- p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
- p.x2 = x1 + (curx - x1 + 1) / 3;
- p.y2 = y1 + (cury - y1 + 1) / 3;
- p.x3 = curx;
- p.y3 = cury;
- aPathList.push_back( p );
- }
- else
- {
- if (!(x0 == curx && y0 == cury))
- { /* eliminate empty lines */
- p = PSPathElement(PS_LINETO);
- p.x1 = curx;
- p.y1 = cury;
- aPathList.push_back( p );
- }
- }
- x0 = curx; y0 = cury; lastOff = 0;
- }
- else
- {
- if (lastOff)
- {
- x2 = (x1 + curx + 1) / 2;
- y2 = (y1 + cury + 1) / 2;
- p = PSPathElement(PS_CURVETO);
- p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
- p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
- p.x2 = x1 + (x2 - x1 + 1) / 3;
- p.y2 = y1 + (y2 - y1 + 1) / 3;
- p.x3 = x2;
- p.y3 = y2;
- aPathList.push_back( p );
- x0 = x2; y0 = y2;
- x1 = curx; y1 = cury;
- } else {
- x1 = curx; y1 = cury;
- }
- lastOff = true;
- }
- if (ecflag) {
- aPathList.push_back( PSPathElement(PS_CLOSEPATH) );
- scflag = 1;
- ecflag = 0;
- cp = EndContour + 1;
- if (cp >= srcCount) break;
- continue;
- }
- if (cp == EndContour) {
- cp = StartContour;
- ecflag = true;
- } else {
- cp++;
- }
- }
- if( (nPathCount = (int)aPathList.size()) > 0)
- {
- *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement));
- assert(*path != 0);
- memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) );
- }
- return nPathCount;
- }
- #endif
- /*- Extracts a string from the name table and allocates memory for it -*/
- static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result )
- {
- int i;
- char *res;
- const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1);
- int len = GetUInt16(name+6, 12 * n + 8, 1);
- // sanity check
- if( (len <= 0) || ((ptr+len) > (name+nTableSize)) )
- {
- if( ucs2result )
- *ucs2result = NULL;
- return NULL;
- }
- if( ucs2result )
- *ucs2result = NULL;
- if (dbFlag) {
- res = (char*)malloc(1 + len/2);
- assert(res != 0);
- for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1);
- res[len/2] = 0;
- if( ucs2result )
- {
- *ucs2result = (sal_uInt16*)malloc( len+2 );
- for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 );
- (*ucs2result)[len/2] = 0;
- }
- } else {
- res = (char*)malloc(1 + len);
- assert(res != 0);
- memcpy(res, ptr, len);
- res[len] = 0;
- }
- return res;
- }
- static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID,
- sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID )
- {
- int l = 0, r = n-1, i;
- sal_uInt32 t1, t2;
- sal_uInt32 m1, m2;
- if (n == 0) return -1;
- m1 = (platformID << 16) | encodingID;
- m2 = (languageID << 16) | nameID;
- do {
- i = (l + r) >> 1;
- t1 = GetUInt32(name + 6, i * 12 + 0, 1);
- t2 = GetUInt32(name + 6, i * 12 + 4, 1);
- if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
- if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
- } while (l <= r);
- if (l - r == 2) {
- return l - 1;
- }
- return -1;
- }
- /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
- * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
- *
- * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
- * and does not have (3, 1, 1033)
- * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
- * require a change in algorithm
- *
- * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
- * but (1, 0, 1042) strings usable
- * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
- */
- static void GetNames(TrueTypeFont *t)
- {
- const sal_uInt8* table = getTable( t, O_name );
- int nTableSize = getTableSize(t, O_name);
- if (nTableSize < 4)
- {
- #if OSL_DEBUG_LEVEL > 1
- fprintf(stderr, "O_name table too small\n");
- #endif
- return;
- }
- sal_uInt16 n = GetUInt16(table, 2, 1);
- int i, r;
- sal_Bool bPSNameOK = sal_True;
- /* #129743# simple sanity check for name table entry count */
- if( nTableSize <= n * 12 + 6 )
- n = 0;
- /* PostScript name: preferred Microsoft */
- t->psname = NULL;
- if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1)
- t->psname = nameExtract(table, nTableSize, r, 1, NULL);
- if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1)
- t->psname = nameExtract(table, nTableSize, r, 0, NULL);
- if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1)
- {
- // some symbol fonts like Marlett have a 3,0 name!
- t->psname = nameExtract(table, nTableSize, r, 1, NULL);
- }
- // for embedded font in Ghostscript PDFs
- if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1)
- {
- t->psname = nameExtract(table, nTableSize, r, 0, NULL);
- }
- if ( ! t->psname )
- {
- if ( t->fname )
- {
- char* pReverse = t->fname + strlen(t->fname);
- /* take only last token of filename */
- while(pReverse != t->fname && *pReverse != '/') pReverse--;
- if(*pReverse == '/') pReverse++;
- t->psname = strdup(pReverse);
- assert(t->psname != 0);
- for (i=strlen(t->psname) - 1; i > 0; i--)
- {
- /*- Remove the suffix -*/
- if (t->psname[i] == '.' ) {
- t->psname[i] = 0;
- break;
- }
- }
- }
- else
- t->psname = strdup( "Unknown" );
- }
- /* Font family and subfamily names: preferred Apple */
- t->family = NULL;
- if ((r = findname(table, n, 0, 0, 0, 1)) != -1)
- t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
- if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1)
- t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
- if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1)
- t->family = nameExtract(table, nTableSize, r, 0, NULL);
- if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1)
- t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
- if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1)
- t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
- if ( ! t->family )
- {
- t->family = strdup(t->psname);
- assert(t->family != 0);
- }
- t->subfamily = NULL;
- t->usubfamily = NULL;
- if ((r = findname(table, n, 1, 0, 0, 2)) != -1)
- t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily);
- if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1)
- t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily);
- if ( ! t->subfamily )
- {
- t->subfamily = strdup("");
- }
-
- /* #i60349# sanity check psname
- * psname parctically has to be 7bit ascii and should not contains spaces
- * there is a class of broken fonts which do not fullfill that at all, so let's try
- * if the family name is 7bit ascii and take it instead if so
- */
- /* check psname */
- for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ )
- if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) )
- bPSNameOK = sal_False;
- if( bPSNameOK == sal_False )
- {
- sal_Bool bReplace = sal_True;
- /* check if family is a suitable replacement */
- if( t->ufamily && t->family )
- {
- for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ )
- if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 )
- bReplace = sal_False;
- if( bReplace )
- {
- free( t->psname );
- t->psname = strdup( t->family );
- }
- }
- }
- }
- enum cmapType {
- CMAP_NOT_USABLE = -1,
- CMAP_MS_Symbol = 10,
- CMAP_MS_Unicode = 11,
- CMAP_MS_ShiftJIS = 12,
- CMAP_MS_Big5 = 13,
- CMAP_MS_PRC = 14,
- CMAP_MS_Wansung = 15,
- CMAP_MS_Johab = 16
- };
- #define MISSING_GLYPH_INDEX 0
- /*
- * getGlyph[0246]() functions and freinds are implemented by:
- * @author Manpreet Singh
- * getGlyph12() function and friends by:
- * @author HDU
- */
- static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) {
- if (c <= 255) {
- return *(cmap + 6 + c);
- } else {
- return MISSING_GLYPH_INDEX;
- }
- }
- typedef struct _subHeader2 {
- sal_uInt16 firstCode;
- sal_uInt16 entryCount;
- sal_uInt16 idDelta;
- sal_uInt16 idRangeOffset;
- } subHeader2;
- static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) {
- sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap;
- sal_uInt8 theHighByte;
- sal_uInt8 theLowByte;
- subHeader2* subHeader2s;
- sal_uInt16* subHeader2Keys;
- sal_uInt16 firstCode;
- int k;
- sal_uInt32 ToReturn;
- theHighByte = (sal_uInt8)((c >> 8) & 0x00ff);
- theLowByte = (sal_uInt8)(c & 0x00ff);
- subHeader2Keys = CMAP2 + 3;
- subHeader2s = (subHeader2 *)(subHeader2Keys + 256);
- k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8;
- if(k == 0) {
- firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
- if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
- return *((&(subHeader2s[0].idRangeOffset))
- + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */
- + theLowByte /* + to_look */
- - Int16FromMOTA(subHeader2s[0].firstCode)
- );
- } else {
- return MISSING_GLYPH_INDEX;
- }
- } else if (k > 0) {
- firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
- if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
- ToReturn = *((&(subHeader2s[k].idRangeOffset))
- + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2)
- + theLowByte - firstCode);
- if(ToReturn == 0) {
- return MISSING_GLYPH_INDEX;
- } else {
- ToReturn += Int16FromMOTA(subHeader2s[k].idDelta);
- return (ToReturn & 0xFFFF);
- }
- } else {
- return MISSING_GLYPH_INDEX;
- }
- } else {
- return MISSING_GLYPH_INDEX;
- }
- }
- static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) {
- sal_uInt16 firstCode, lastCode, count;
- sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap;
- firstCode = Int16FromMOTA(*(CMAP6 + 3));
- count = Int16FromMOTA(*(CMAP6 + 4));
- lastCode = firstCode + count - 1;
- if (c < firstCode || c > lastCode) {
- return MISSING_GLYPH_INDEX;
- } else {
- return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode));
- }
- }
- static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) {
- signed int low, mid, high, lastfound = 0xffff;
- sal_uInt16 res;
- if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) {
- return (sal_uInt16)0xFFFF;
- }
- low = 0;
- high = length - 1;
- while(high >= low) {
- mid = (high + low)/2;
- res = Int16FromMOTA(*(ar+mid));
- if(res >= toSearch) {
- lastfound = mid;
- high = --mid;
- } else {
- low = ++mid;
- }
- }
- return (sal_uInt16)lastfound;
- }
- static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) {
- sal_uInt16 i;
- int ToReturn;
- sal_uInt16 segCount;
- sal_uInt16 * startCode;
- sal_uInt16 * endCode;
- sal_uInt16 * idDelta;
- /* sal_uInt16 * glyphIdArray; */
- sal_uInt16 * idRangeOffset;
- sal_uInt16 * glyphIndexArray;
- sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap;
- /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
- segCount = Int16FromMOTA(*(CMAP4 + 3))/2;
- endCode = CMAP4 + 7;
- i = GEbinsearch(endCode, segCount, (sal_uInt16)c);
- if (i == (sal_uInt16) 0xFFFF) {
- return MISSING_GLYPH_INDEX;
- }
- startCode = endCode + segCount + 1;
- if(Int16FromMOTA(startCode[i]) > c) {
- return MISSING_GLYPH_INDEX;
- }
- idDelta = startCode + segCount;
- idRangeOffset = idDelta + segCount;
- glyphIndexArray = idRangeOffset + segCount;
- if(Int16FromMOTA(idRangeOffset[i]) != 0) {
- c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i])))));
- }
- ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF;
- return ToReturn;
- }
- static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) {
- const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap;
- int nLength = Int32FromMOTA( pCMAP12[1] );
- int nGroups = Int32FromMOTA( pCMAP12[3] );
- int nLower = 0;
- int nUpper = nGroups;
- if( nUpper > (nLength-16)/12 )
- nUpper = (nLength-16)/12;
- /* binary search in "segmented coverage" subtable */
- while( nLower < nUpper ) {
- int nIndex = (nLower + nUpper) / 2;
- const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ];
- sal_uInt32 cStart = Int32FromMOTA( pEntry[0] );
- sal_uInt32 cLast = Int32FromMOTA( pEntry[1] );
- if( cChar < cStart )
- nUpper = nIndex;
- else if( cChar > cLast )
- nLower = nIndex + 1;
- else { /* found matching entry! */
- sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] );
- nGlyph += cChar - cStart;
- return nGlyph;
- }
- }
- return MISSING_GLYPH_INDEX;
- }
- static void FindCmap(TrueTypeFont *ttf)
- {
- const sal_uInt8* table = getTable(ttf, O_cmap);
- sal_uInt32 table_size = getTableSize(ttf, O_cmap);
- sal_uInt16 ncmaps = GetUInt16(table, 2, 1);
- unsigned int i;
- sal_uInt32 AppleUni = 0; // Apple Unicode
- sal_uInt32 ThreeZero = 0; /* MS Symbol */
- sal_uInt32 ThreeOne = 0; /* MS UCS-2 */
- sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */
- sal_uInt32 ThreeThree = 0; /* MS Big5 */
- sal_uInt32 ThreeFour = 0; /* MS PRC */
- sal_uInt32 ThreeFive = 0; /* MS Wansung */
- sal_uInt32 ThreeSix = 0; /* MS Johab */
- for (i = 0; i < ncmaps; i++) {
- sal_uInt32 offset;
- sal_uInt16 pID, eID;
-
- /* sanity check, cmap entry must lie within table */
- if( i*8+4 > table_size )
- break;
- pID = GetUInt16(table, 4 + i * 8, 1);
- eID = GetUInt16(table, 6 + i * 8, 1);
- offset = GetUInt32(table, 8 + i * 8, 1);
-
- /* sanity check, cmap must lie within file */
- if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize )
- continue;
- /* Unicode tables in Apple fonts */
- if (pID == 0) {
- AppleUni = offset;
- }
- if (pID == 3) {
- switch (eID) {
- case 0: ThreeZero = offset; break;
- case 10: // UCS-4
- case 1: ThreeOne = offset; break;
- case 2: ThreeTwo = offset; break;
- case 3: ThreeThree = offset; break;
- case 4: ThreeFour = offset; break;
- case 5: ThreeFive = offset; break;
- case 6: ThreeSix = offset; break;
- }
- }
- }
- // fall back to AppleUnicode if there are no ThreeOne/Threezero tables
- if( AppleUni && !ThreeZero && !ThreeOne)
- ThreeOne = AppleUni;
- if (ThreeOne) {
- ttf->cmapType = CMAP_MS_Unicode;
- ttf->cmap = table + ThreeOne;
- } else if (ThreeTwo) {
- ttf->cmapType = CMAP_MS_ShiftJIS;
- ttf->cmap = table + ThreeTwo;
- } else if (ThreeThree) {
- ttf->cmapType = CMAP_MS_Big5;
- ttf->cmap = table + ThreeThree;
- } else if (ThreeFour) {
- ttf->cmapType = CMAP_MS_PRC;
- ttf->cmap = table + ThreeFour;
- } else if (ThreeFive) {
- ttf->cmapType = CMAP_MS_Wansung;
- ttf->cmap = table + ThreeFive;
- } else if (ThreeSix) {
- ttf->cmapType = CMAP_MS_Johab;
- ttf->cmap = table + ThreeSix;
- } else if (ThreeZero) {
- ttf->cmapType = CMAP_MS_Symbol;
- ttf->cmap = table + ThreeZero;
- } else {
- ttf->cmapType = CMAP_NOT_USABLE;
- ttf->cmap = 0;
- }
- if (ttf->cmapType != CMAP_NOT_USABLE) {
- switch (GetUInt16(ttf->cmap, 0, 1)) {
- case 0: ttf->mapper = getGlyph0; break;
- case 2: ttf->mapper = getGlyph2; break;
- case 4: ttf->mapper = getGlyph4; break;
- case 6: ttf->mapper = getGlyph6; break;
- case 12: ttf->mapper= getGlyph12; break;
- default:
- #if OSL_DEBUG_LEVEL > 1
- /*- if the cmap table is really broken */
- printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1));
- #endif
- ttf->cmapType = CMAP_NOT_USABLE;
- ttf->cmap = 0;
- ttf->mapper = 0;
- }
- }
- }
- static void GetKern(TrueTypeFont *ttf)
- {
- const sal_uInt8* table = getTable(ttf, O_kern);
- const sal_uInt8 *ptr;
- if( !table )
- goto badtable;
- if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with USHORT version and nTables fields */
- ttf->nkern = GetUInt16(table, 2, 1);
- ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *));
- assert(ttf->kerntables != 0);
- memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *));
- ttf->kerntype = KT_MICROSOFT;
- ptr = table + 4;
- for( unsigned i = 0; i < ttf->nkern; ++i) {
- ttf->kerntables[i] = ptr;
- ptr += GetUInt16(ptr, 2, 1);
- /* sanity check */
- if( ptr > ttf->ptr+ttf->fsize )
- {
- free( ttf->kerntables );
- goto badtable;
- }
- }
- return;
- }
- if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
- ttf->nkern = GetUInt32(table, 4, 1);
- ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*));
- assert(ttf->kerntables != 0);
- memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *));
- ttf->kerntype = KT_APPLE_NEW;
- ptr = table + 8;
- for( unsigned i = 0; i < ttf->nkern; ++i) {
- ttf->kerntables[i] = ptr;
- ptr += GetUInt32(ptr, 0, 1);
- /* sanity check; there are some fonts that are broken in this regard */
- if( ptr > ttf->ptr+ttf->fsize )
- {
- free( ttf->kerntables );
- goto badtable;
- }
- }
- return;
- }
- badtable:
- ttf->kerntype = KT_NONE;
- ttf->kerntables = 0;
- return;
- }
- #ifdef TEST5
- /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and
- * that x and y elements of the kern array are initialized to zeroes
- */
- static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern)
- {
- (void)ttf; /* avoid warning */
- (void)glyphs; /* avoid warning */
- (void)nglyphs; /* avoid warning */
- (void)wmode; /* avoid warning */
- (void)nglyphs; /* avoid warning */
- (void)kern; /* avoid warning */
- fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n");
- }
- static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern)
- {
- sal_uInt32 i, j;
- sal_uInt32 gpair;
- if( ! nglyphs )
- return;
- for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) {
- gpair = (glyphs[i] << 16) | glyphs[i+1];
- #ifdef DEBUG2
- /* All fonts with MS kern table that I've seen so far contain just one kern subtable.
- * MS kern documentation is very poor and I doubt that font developers will be using
- * several subtables. I expect them to be using OpenType tables instead.
- * According to MS documention, format 2 subtables are not supported by Windows and OS/2.
- */
- if (ttf->nkern > 1) {
- fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern);
- }
- #endif
- for (j = 0; j < ttf->nkern; j++) {
- sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1);
- sal_uInt8 *ptr;
- int npairs;
- sal_uInt32 t;
- int l, r, k;
- if (! ((coverage & 1) ^ wmode)) continue;
- if ((coverage & 0xFFFE) != 0) {
- #ifdef DEBUG2
- fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage);
- #endif
- continue;
- }
- ptr = ttf->kerntables[j];
- npairs = GetUInt16(ptr, 6, 1);
- ptr += 14;
- l = 0;
- r = npairs;
- do {
- k = (l + r) >> 1;
- t = GetUInt32(ptr, k * 6, 1);
- if (gpair >= t) l = k + 1;
- if (gpair <= t) r = k - 1;
- } while (l <= r);
- if (l - r == 2) {
- if (!wmode) {
- kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
- } else {
- kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
- }
- /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */
- }
- }
- }
- }
- #endif
- /*- Public functions */ /*FOLD00*/
- int CountTTCFonts(const char* fname)
- {
- int nFonts = 0;
- sal_uInt8 buffer[12];
- FILE* fd = fopen(fname, "rb");
- …
Large files files are truncated, but you can click here to view the full file