LCOV - code coverage report
Current view: top level - libreoffice/vcl/source/fontsubset - ttcr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 727 0.0 %
Date: 2012-12-27 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : /*
      21             :  * TrueTypeCreator method implementation
      22             :  *
      23             :  * @author: Alexander Gelfenbain
      24             :  *
      25             :  */
      26             : 
      27             : #if OSL_DEBUG_LEVEL == 0
      28             : #  ifndef NDEBUG
      29             : #    define NDEBUG
      30             : #  endif
      31             : #endif
      32             : #include <assert.h>
      33             : 
      34             : #include "ttcr.hxx"
      35             : #include "list.h"
      36             : #include "string.h"
      37             : 
      38             : 
      39             : 
      40             : namespace vcl
      41             : {
      42             : 
      43             : /*
      44             :  * Private Data Types
      45             :  */
      46             : 
      47             :     struct _TrueTypeCreator {
      48             :         sal_uInt32 tag;                         /**< TrueType file tag */
      49             :         list   tables;                      /**< List of table tags and pointers */
      50             :     };
      51             : 
      52             : /* These must be #defined so that they can be used in initializers */
      53             : #define T_maxp  0x6D617870
      54             : #define T_glyf  0x676C7966
      55             : #define T_head  0x68656164
      56             : #define T_loca  0x6C6F6361
      57             : #define T_name  0x6E616D65
      58             : #define T_hhea  0x68686561
      59             : #define T_hmtx  0x686D7478
      60             : #define T_cmap  0x636D6170
      61             : #define T_vhea  0x76686561
      62             : #define T_vmtx  0x766D7478
      63             : #define T_OS2   0x4F532F32
      64             : #define T_post  0x706F7374
      65             : #define T_kern  0x6B65726E
      66             : #define T_cvt   0x63767420
      67             : 
      68             : typedef struct {
      69             :     sal_uInt32 tag;
      70             :     sal_uInt32 length;
      71             :     sal_uInt8  *data;
      72             : } TableEntry;
      73             : 
      74             : /*
      75             :  * this is a duplicate code from sft.c but it is left here for performance reasons
      76             :  */
      77             : #ifdef __GNUC__
      78             : #define _inline static __inline__
      79             : #else
      80             : #define _inline static
      81             : #endif
      82             : 
      83             : _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
      84             :     return (a << 24) | (b << 16) | (c << 8) | d;
      85             : }
      86             : 
      87             : /*- Data access macros for data stored in big-endian or little-endian format */
      88           0 : _inline sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
      89             : {
      90             :     sal_Int16 t;
      91             :     assert(ptr != 0);
      92             : 
      93           0 :     if (bigendian) {
      94           0 :         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
      95             :     } else {
      96           0 :         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
      97             :     }
      98             : 
      99           0 :     return t;
     100             : }
     101             : 
     102           0 : _inline sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
     103             : {
     104             :     sal_uInt16 t;
     105             :     assert(ptr != 0);
     106             : 
     107           0 :     if (bigendian) {
     108           0 :         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
     109             :     } else {
     110           0 :         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
     111             :     }
     112             : 
     113           0 :     return t;
     114             : }
     115             : 
     116             : _inline sal_Int32 GetInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
     117             : {
     118             :     sal_Int32 t;
     119             :     assert(ptr != 0);
     120             : 
     121             :     if (bigendian) {
     122             :         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
     123             :             (ptr+offset)[2] << 8  | (ptr+offset)[3];
     124             :     } else {
     125             :         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
     126             :             (ptr+offset)[1] << 8  | (ptr+offset)[0];
     127             :     }
     128             : 
     129             :     return t;
     130             : }
     131             : 
     132             : _inline sal_uInt32 GetUInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
     133             : {
     134             :     sal_uInt32 t;
     135             :     assert(ptr != 0);
     136             : 
     137             : 
     138             :     if (bigendian) {
     139             :         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
     140             :             (ptr+offset)[2] << 8  | (ptr+offset)[3];
     141             :     } else {
     142             :         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
     143             :             (ptr+offset)[1] << 8  | (ptr+offset)[0];
     144             :     }
     145             : 
     146             :     return t;
     147             : }
     148             : 
     149             : 
     150           0 : _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
     151             : {
     152             :     assert(ptr != 0);
     153             : 
     154           0 :     if (bigendian) {
     155           0 :         ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
     156           0 :         ptr[offset+1] = (sal_uInt8)(val & 0xFF);
     157             :     } else {
     158           0 :         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
     159           0 :         ptr[offset] = (sal_uInt8)(val & 0xFF);
     160             :     }
     161           0 : }
     162             : 
     163           0 : _inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
     164             : {
     165             :     assert(ptr != 0);
     166             : 
     167           0 :     if (bigendian) {
     168           0 :         ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
     169           0 :         ptr[offset+1] = (sal_uInt8)(val & 0xFF);
     170             :     } else {
     171           0 :         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
     172           0 :         ptr[offset] = (sal_uInt8)(val & 0xFF);
     173             :     }
     174           0 : }
     175             : 
     176           0 : _inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
     177             : {
     178             :     assert(ptr != 0);
     179             : 
     180           0 :     if (bigendian) {
     181           0 :         ptr[offset]   = (sal_uInt8)((val >> 24) & 0xFF);
     182           0 :         ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
     183           0 :         ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
     184           0 :         ptr[offset+3] = (sal_uInt8)(val & 0xFF);
     185             :     } else {
     186           0 :         ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
     187           0 :         ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
     188           0 :         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
     189           0 :         ptr[offset]   = (sal_uInt8)(val & 0xFF);
     190             :     }
     191             : 
     192           0 : }
     193             : 
     194             : 
     195             : _inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
     196             : {
     197             :     assert(ptr != 0);
     198             : 
     199             :     if (bigendian) {
     200             :         ptr[offset]   = (sal_uInt8)((val >> 24) & 0xFF);
     201             :         ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
     202             :         ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
     203             :         ptr[offset+3] = (sal_uInt8)(val & 0xFF);
     204             :     } else {
     205             :         ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
     206             :         ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
     207             :         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
     208             :         ptr[offset]   = (sal_uInt8)(val & 0xFF);
     209             :     }
     210             : 
     211             : }
     212             : 
     213           0 : static int TableEntryCompareF(const void *l, const void *r)
     214             : {
     215           0 :     return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag;
     216             : }
     217             : 
     218           0 : static int NameRecordCompareF(const void *l, const void *r)
     219             : {
     220           0 :     NameRecord *ll = (NameRecord *) l;
     221           0 :     NameRecord *rr = (NameRecord *) r;
     222             : 
     223           0 :     if (ll->platformID != rr->platformID) {
     224           0 :         return ll->platformID - rr->platformID;
     225           0 :     } else if (ll->encodingID != rr->encodingID) {
     226           0 :         return ll->encodingID - rr->encodingID;
     227           0 :     } else if (ll->languageID != rr->languageID) {
     228           0 :         return ll->languageID - rr->languageID;
     229           0 :     } else if (ll->nameID != rr->nameID) {
     230           0 :         return ll->nameID - rr->nameID;
     231             :     }
     232           0 :     return 0;
     233             : }
     234             : 
     235             : 
     236           0 : static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
     237             : {
     238           0 :     sal_uInt32 sum = 0;
     239           0 :     sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4;
     240             : 
     241           0 :     while (ptr < endptr) sum += *ptr++;
     242             : 
     243           0 :     return sum;
     244             : }
     245             : 
     246           0 : _inline void *smalloc(sal_uInt32 size)
     247             : {
     248           0 :     void *res = malloc(size);
     249             :     assert(res != 0);
     250           0 :     return res;
     251             : }
     252             : 
     253           0 : _inline void *scalloc(sal_uInt32 n, sal_uInt32 size)
     254             : {
     255           0 :     void *res = calloc(n, size);
     256             :     assert(res != 0);
     257           0 :     return res;
     258             : }
     259             : 
     260             : /*
     261             :  * Public functions
     262             :  */
     263             : 
     264           0 : void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this)
     265             : {
     266           0 :     TrueTypeCreator* ptr = (TrueTypeCreator*)smalloc(sizeof(TrueTypeCreator));
     267             : 
     268           0 :     ptr->tables = listNewEmpty();
     269           0 :     listSetElementDtor(ptr->tables, (list_destructor)TrueTypeTableDispose);
     270             : 
     271           0 :     ptr->tag = tag;
     272             : 
     273           0 :     *_this = ptr;
     274           0 : }
     275             : 
     276           0 : int AddTable(TrueTypeCreator *_this, TrueTypeTable *table)
     277             : {
     278           0 :     if (table != 0) {
     279           0 :         listAppend(_this->tables, table);
     280             :     }
     281           0 :     return SF_OK;
     282             : }
     283             : 
     284           0 : void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag)
     285             : {
     286           0 :     if (listCount(_this->tables))
     287             :     {
     288           0 :         listToFirst(_this->tables);
     289           0 :         int done = 0;
     290           0 :         do {
     291           0 :             if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag)
     292             :             {
     293           0 :                 listRemove(_this->tables);
     294             :             }
     295             :             else
     296             :             {
     297           0 :                 if (listNext(_this->tables))
     298             :                 {
     299           0 :                     done = 1;
     300             :                 }
     301             :             }
     302           0 :         } while (!done);
     303             :     }
     304           0 : }
     305             : 
     306             : static void ProcessTables(TrueTypeCreator *);
     307             : 
     308           0 : int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length)
     309             : {
     310           0 :     sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift;
     311           0 :     sal_uInt32 s, offset, checkSumAdjustment = 0;
     312             :     sal_uInt32 *p;
     313           0 :     int i=0, n;
     314           0 :     sal_uInt8 *head = NULL;     /* saved pointer to the head table data for checkSumAdjustment calculation */
     315             : 
     316           0 :     if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT;
     317             : 
     318           0 :     ProcessTables(_this);
     319             : 
     320             :     /* ProcessTables() adds 'loca' and 'hmtx' */
     321             : 
     322           0 :     n = listCount(_this->tables);
     323           0 :     numTables = (sal_uInt16) n;
     324             : 
     325             : 
     326           0 :     TableEntry* te = (TableEntry*)scalloc(n, sizeof(TableEntry));
     327             : 
     328           0 :     listToFirst(_this->tables);
     329           0 :     for (i = 0; i < n; i++) {
     330           0 :         GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag);
     331           0 :         listNext(_this->tables);
     332             :     }
     333             : 
     334           0 :     qsort(te, n, sizeof(TableEntry), TableEntryCompareF);
     335             : 
     336           0 :     do {
     337           0 :         searchRange *= 2;
     338           0 :         entrySelector++;
     339             :     } while (searchRange <= numTables);
     340             : 
     341           0 :     searchRange *= 8;
     342           0 :     entrySelector--;
     343           0 :     rangeShift = numTables * 16 - searchRange;
     344             : 
     345           0 :     s = offset = 12 + 16 * n;
     346             : 
     347           0 :     for (i = 0; i < n; i++) {
     348           0 :         s += (te[i].length + 3) & (sal_uInt32) ~3;
     349             :         /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
     350             :     }
     351             : 
     352           0 :     sal_uInt8* ttf = (sal_uInt8*)smalloc(s);
     353             : 
     354             :     /* Offset Table */
     355           0 :     PutUInt32(_this->tag, ttf, 0, 1);
     356           0 :     PutUInt16(numTables, ttf, 4, 1);
     357           0 :     PutUInt16(searchRange, ttf, 6, 1);
     358           0 :     PutUInt16(entrySelector, ttf, 8, 1);
     359           0 :     PutUInt16(rangeShift, ttf, 10, 1);
     360             : 
     361             :     /* Table Directory */
     362           0 :     for (i = 0; i < n; i++) {
     363           0 :         PutUInt32(te[i].tag, ttf + 12, 16 * i, 1);
     364           0 :         PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1);
     365           0 :         PutUInt32(offset, ttf + 12, 16 * i + 8, 1);
     366           0 :         PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1);
     367             : 
     368           0 :         if (te[i].tag == T_head) {
     369           0 :             head = ttf + offset;
     370             :         }
     371             : 
     372           0 :         memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 );
     373           0 :         offset += (te[i].length + 3) & (sal_uInt32) ~3;
     374             :         /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
     375             :     }
     376             : 
     377           0 :     free(te);
     378             : 
     379           0 :     p = (sal_uInt32 *) ttf;
     380           0 :     for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i];
     381           0 :     PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1);
     382             : 
     383           0 :     *ptr = ttf;
     384           0 :     *length = s;
     385             : 
     386           0 :     return SF_OK;
     387             : }
     388             : 
     389           0 : int StreamToFile(TrueTypeCreator *_this, const char* fname)
     390             : {
     391             :     sal_uInt8 *ptr;
     392             :     sal_uInt32 length;
     393             :     int r;
     394             :     FILE* fd;
     395             : 
     396           0 :     if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r;
     397           0 :     if (fname && (fd = fopen(fname, "wb")) != NULL)
     398             :     {
     399           0 :         if (fwrite(ptr, 1, length, fd) != length) {
     400           0 :             r = SF_FILEIO;
     401             :         } else {
     402           0 :             r = SF_OK;
     403             :         }
     404           0 :         fclose(fd);
     405             :     }
     406             :     else
     407             :     {
     408           0 :         r = SF_BADFILE;
     409             :     }
     410           0 :     free(ptr);
     411           0 :     return r;
     412             : }
     413             : 
     414             : 
     415             : 
     416             : /*
     417             :  * TrueTypeTable private methods
     418             :  */
     419             : 
     420             : #define TABLESIZE_head 54
     421             : #define TABLESIZE_hhea 36
     422             : #define TABLESIZE_maxp 32
     423             : 
     424             : 
     425             : 
     426             : /*    Table         data points to
     427             :  * --------------------------------------------
     428             :  *    generic       tdata_generic struct
     429             :  *    'head'        TABLESIZE_head bytes of memory
     430             :  *    'hhea'        TABLESIZE_hhea bytes of memory
     431             :  *    'loca'        tdata_loca struct
     432             :  *    'maxp'        TABLESIZE_maxp bytes of memory
     433             :  *    'glyf'        list of GlyphData structs (defined in sft.h)
     434             :  *    'name'        list of NameRecord structs (defined in sft.h)
     435             :  *    'post'        tdata_post struct
     436             :  *
     437             :  */
     438             : 
     439             : 
     440             : #define CMAP_SUBTABLE_INIT 10
     441             : #define CMAP_SUBTABLE_INCR 10
     442             : #define CMAP_PAIR_INIT 500
     443             : #define CMAP_PAIR_INCR 500
     444             : 
     445             : typedef struct {
     446             :     sal_uInt32  id;                         /* subtable ID (platform/encoding ID)    */
     447             :     sal_uInt32  n;                          /* number of used translation pairs      */
     448             :     sal_uInt32  m;                          /* number of allocated translation pairs */
     449             :     sal_uInt32 *xc;                         /* character array                       */
     450             :     sal_uInt32 *xg;                         /* glyph array                           */
     451             : } CmapSubTable;
     452             : 
     453             : typedef struct {
     454             :     sal_uInt32 n;                           /* number of used CMAP sub-tables       */
     455             :     sal_uInt32 m;                           /* number of allocated CMAP sub-tables  */
     456             :     CmapSubTable *s;                    /* sotred array of sub-tables           */
     457             : } table_cmap;
     458             : 
     459             : typedef struct {
     460             :     sal_uInt32 tag;
     461             :     sal_uInt32 nbytes;
     462             :     sal_uInt8 *ptr;
     463             : } tdata_generic;
     464             : 
     465             : typedef struct {
     466             :     sal_uInt32 nbytes;                      /* number of bytes in loca table */
     467             :     sal_uInt8 *ptr;                          /* pointer to the data */
     468             : } tdata_loca;
     469             : 
     470             : typedef struct {
     471             :     sal_uInt32 format;
     472             :     sal_uInt32 italicAngle;
     473             :     sal_Int16  underlinePosition;
     474             :     sal_Int16  underlineThickness;
     475             :     sal_uInt32 isFixedPitch;
     476             :     void   *ptr;                        /* format-specific pointer */
     477             : } tdata_post;
     478             : 
     479             : 
     480             : /* allocate memory for a TT table */
     481           0 : static sal_uInt8 *ttmalloc(sal_uInt32 nbytes)
     482             : {
     483             :     sal_uInt32 n;
     484             : 
     485           0 :     n = (nbytes + 3) & (sal_uInt32) ~3;
     486           0 :     sal_uInt8* res = (sal_uInt8*)malloc(n);
     487             :     assert(res != 0);
     488           0 :     memset(res, 0, n);
     489             : 
     490           0 :     return res;
     491             : }
     492             : 
     493           0 : static void FreeGlyphData(void *ptr)
     494             : {
     495           0 :     GlyphData *p = (GlyphData *) ptr;
     496           0 :     if (p->ptr) free(p->ptr);
     497           0 :     free(p);
     498           0 : }
     499             : 
     500           0 : static void TrueTypeTableDispose_generic(TrueTypeTable *_this)
     501             : {
     502           0 :     if (_this) {
     503           0 :         if (_this->data) {
     504           0 :             tdata_generic *pdata = (tdata_generic *) _this->data;
     505           0 :             if (pdata->nbytes) free(pdata->ptr);
     506           0 :             free(_this->data);
     507             :         }
     508           0 :         free(_this);
     509             :     }
     510           0 : }
     511             : 
     512           0 : static void TrueTypeTableDispose_head(TrueTypeTable *_this)
     513             : {
     514           0 :     if (_this) {
     515           0 :         if (_this->data) free(_this->data);
     516           0 :         free(_this);
     517             :     }
     518           0 : }
     519             : 
     520           0 : static void TrueTypeTableDispose_hhea(TrueTypeTable *_this)
     521             : {
     522           0 :     if (_this) {
     523           0 :         if (_this->data) free(_this->data);
     524           0 :         free(_this);
     525             :     }
     526           0 : }
     527             : 
     528           0 : static void TrueTypeTableDispose_loca(TrueTypeTable *_this)
     529             : {
     530           0 :     if (_this) {
     531           0 :         if (_this->data) {
     532           0 :             tdata_loca *p = (tdata_loca *) _this->data;
     533           0 :             if (p->ptr) free(p->ptr);
     534           0 :             free(_this->data);
     535             :         }
     536           0 :         free(_this);
     537             :     }
     538           0 : }
     539             : 
     540           0 : static void TrueTypeTableDispose_maxp(TrueTypeTable *_this)
     541             : {
     542           0 :     if (_this) {
     543           0 :         if (_this->data) free(_this->data);
     544           0 :         free(_this);
     545             :     }
     546           0 : }
     547             : 
     548           0 : static void TrueTypeTableDispose_glyf(TrueTypeTable *_this)
     549             : {
     550           0 :     if (_this) {
     551           0 :         if (_this->data) listDispose((list) _this->data);
     552           0 :         free(_this);
     553             :     }
     554           0 : }
     555             : 
     556           0 : static void TrueTypeTableDispose_cmap(TrueTypeTable *_this)
     557             : {
     558             :     table_cmap *t;
     559             :     CmapSubTable *s;
     560             :     sal_uInt32 i;
     561             : 
     562           0 :     if (_this) {
     563           0 :         t = (table_cmap *) _this->data;
     564           0 :         if (t) {
     565           0 :             s = t->s;
     566           0 :             if (s) {
     567           0 :                 for (i = 0; i < t->m; i++) {
     568           0 :                     if (s[i].xc) free(s[i].xc);
     569           0 :                     if (s[i].xg) free(s[i].xg);
     570             :                 }
     571           0 :                 free(s);
     572             :             }
     573           0 :             free(t);
     574             :         }
     575           0 :         free(_this);
     576             :     }
     577           0 : }
     578             : 
     579           0 : static void TrueTypeTableDispose_name(TrueTypeTable *_this)
     580             : {
     581           0 :     if (_this) {
     582           0 :         if (_this->data) listDispose((list) _this->data);
     583           0 :         free(_this);
     584             :     }
     585           0 : }
     586             : 
     587           0 : static void TrueTypeTableDispose_post(TrueTypeTable *_this)
     588             : {
     589           0 :     if (_this) {
     590           0 :         tdata_post *p = (tdata_post *) _this->data;
     591           0 :         if (p) {
     592           0 :             if (p->format == 0x00030000) {
     593             :                 /* do nothing */
     594             :             } else {
     595           0 :                 fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format);
     596             :             }
     597           0 :             free(p);
     598             :         }
     599           0 :         free(_this);
     600             :     }
     601           0 : }
     602             : 
     603             : /* destructor vtable */
     604             : 
     605             : static struct {
     606             :     sal_uInt32 tag;
     607             :     void (*f)(TrueTypeTable *);
     608             : } vtable1[] =
     609             : {
     610             :     {0,      TrueTypeTableDispose_generic},
     611             :     {T_head, TrueTypeTableDispose_head},
     612             :     {T_hhea, TrueTypeTableDispose_hhea},
     613             :     {T_loca, TrueTypeTableDispose_loca},
     614             :     {T_maxp, TrueTypeTableDispose_maxp},
     615             :     {T_glyf, TrueTypeTableDispose_glyf},
     616             :     {T_cmap, TrueTypeTableDispose_cmap},
     617             :     {T_name, TrueTypeTableDispose_name},
     618             :     {T_post, TrueTypeTableDispose_post}
     619             : 
     620             : };
     621             : 
     622           0 : static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     623             : {
     624             :     assert(_this != 0);
     625             :     assert(_this->data != 0);
     626             : 
     627           0 :     *ptr = ((tdata_generic *) _this->data)->ptr;
     628           0 :     *len = ((tdata_generic *) _this->data)->nbytes;
     629           0 :     *tag = ((tdata_generic *) _this->data)->tag;
     630             : 
     631           0 :     return TTCR_OK;
     632             : }
     633             : 
     634             : 
     635           0 : static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     636             : {
     637           0 :     *len = TABLESIZE_head;
     638           0 :     *ptr = (sal_uInt8 *) _this->data;
     639           0 :     *tag = T_head;
     640             : 
     641           0 :     return TTCR_OK;
     642             : }
     643             : 
     644           0 : static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     645             : {
     646           0 :     *len = TABLESIZE_hhea;
     647           0 :     *ptr = (sal_uInt8 *) _this->data;
     648           0 :     *tag = T_hhea;
     649             : 
     650           0 :     return TTCR_OK;
     651             : }
     652             : 
     653           0 : static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     654             : {
     655             :     tdata_loca *p;
     656             : 
     657             :     assert(_this->data != 0);
     658             : 
     659           0 :     p = (tdata_loca *) _this->data;
     660             : 
     661           0 :     if (p->nbytes == 0) return TTCR_ZEROGLYPHS;
     662             : 
     663           0 :     *ptr = p->ptr;
     664           0 :     *len = p->nbytes;
     665           0 :     *tag = T_loca;
     666             : 
     667           0 :     return TTCR_OK;
     668             : }
     669             : 
     670           0 : static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     671             : {
     672           0 :     *len = TABLESIZE_maxp;
     673           0 :     *ptr = (sal_uInt8 *) _this->data;
     674           0 :     *tag = T_maxp;
     675             : 
     676           0 :     return TTCR_OK;
     677             : }
     678             : 
     679           0 : static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     680             : {
     681           0 :     sal_uInt32 n, nbytes = 0;
     682           0 :     list l = (list) _this->data;
     683             :     /* sal_uInt16 curID = 0;    */               /* to check if glyph IDs are sequential and start from zero */
     684             :     sal_uInt8 *p;
     685             : 
     686           0 :     *ptr = 0;
     687           0 :     *len = 0;
     688           0 :     *tag = 0;
     689             : 
     690           0 :     if (listCount(l) == 0) return TTCR_ZEROGLYPHS;
     691             : 
     692           0 :     listToFirst(l);
     693           0 :     do {
     694             :         /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
     695           0 :         nbytes += ((GlyphData *) listCurrent(l))->nbytes;
     696           0 :     } while (listNext(l));
     697             : 
     698           0 :     p = _this->rawdata = ttmalloc(nbytes);
     699             : 
     700           0 :     listToFirst(l);
     701           0 :     do {
     702           0 :         n = ((GlyphData *) listCurrent(l))->nbytes;
     703           0 :         if (n != 0) {
     704           0 :             memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n);
     705           0 :             p += n;
     706             :         }
     707           0 :     } while (listNext(l));
     708             : 
     709           0 :     *len = nbytes;
     710           0 :     *ptr = _this->rawdata;
     711           0 :     *tag = T_glyf;
     712             : 
     713           0 :     return TTCR_OK;
     714             : }
     715             : 
     716             : /* cmap packers */
     717           0 : static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length)
     718             : {
     719           0 :     sal_uInt8* ptr = (sal_uInt8*)smalloc(262);
     720           0 :     sal_uInt8 *p = ptr + 6;
     721             :     sal_uInt32 i, j;
     722             :     sal_uInt16 g;
     723             : 
     724           0 :     PutUInt16(0, ptr, 0, 1);
     725           0 :     PutUInt16(262, ptr, 2, 1);
     726           0 :     PutUInt16(0, ptr, 4, 1);
     727             : 
     728           0 :     for (i = 0; i < 256; i++) {
     729           0 :         g = 0;
     730           0 :         for (j = 0; j < s->n; j++) {
     731           0 :             if (s->xc[j] == i) {
     732           0 :                 g = (sal_uInt16) s->xg[j];
     733             :             }
     734             :         }
     735           0 :         p[i] = (sal_uInt8) g;
     736             :     }
     737           0 :     *length = 262;
     738           0 :     return ptr;
     739             : }
     740             : 
     741           0 : static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length)
     742             : {
     743           0 :     sal_uInt8* ptr = (sal_uInt8*)smalloc(s->n*2 + 10);
     744           0 :     sal_uInt8 *p = ptr + 10;
     745             :     sal_uInt32 i, j;
     746             :     sal_uInt16 g;
     747             : 
     748           0 :     PutUInt16(6, ptr, 0, 1);
     749           0 :     PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1);
     750           0 :     PutUInt16(0, ptr, 4, 1);
     751           0 :     PutUInt16(0, ptr, 6, 1);
     752           0 :     PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 );
     753             : 
     754           0 :     for (i = 0; i < s->n; i++) {
     755           0 :         g = 0;
     756           0 :         for (j = 0; j < s->n; j++) {
     757           0 :             if (s->xc[j] == i) {
     758           0 :                 g = (sal_uInt16) s->xg[j];
     759             :             }
     760             :         }
     761           0 :         PutUInt16( g, p, 2*i, 1 );
     762             :     }
     763           0 :     *length = s->n*2+10;
     764           0 :     return ptr;
     765             : }
     766             : 
     767             : 
     768             : 
     769             : /* XXX it only handles Format 0 encoding tables */
     770           0 : static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length)
     771             : {
     772           0 :     if( s->xg[s->n-1] > 0xff )
     773           0 :         return PackCmapType6(s, length);
     774             :     else
     775           0 :         return PackCmapType0(s, length);
     776             : }
     777             : 
     778           0 : static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     779             : {
     780             :     table_cmap *t;
     781             :     sal_uInt32 i;
     782           0 :     sal_uInt32 tlen = 0;
     783             :     sal_uInt32 l;
     784             :     sal_uInt32 cmapsize;
     785             :     sal_uInt8 *cmap;
     786             :     sal_uInt32 coffset;
     787             : 
     788             :     assert(_this != 0);
     789           0 :     t = (table_cmap *) _this->data;
     790             :     assert(t != 0);
     791             :     assert(t->n != 0);
     792             : 
     793           0 :     sal_uInt8** subtables = (sal_uInt8**)scalloc(t->n, sizeof(sal_uInt8 *));
     794           0 :     sal_uInt32* sizes = (sal_uInt32*)scalloc(t->n, sizeof(sal_uInt32));
     795             : 
     796           0 :     for (i = 0; i < t->n; i++) {
     797           0 :         subtables[i] = PackCmap(t->s+i, &l);
     798           0 :         sizes[i] = l;
     799           0 :         tlen += l;
     800             :     }
     801             : 
     802           0 :     cmapsize = tlen + 4 + 8 * t->n;
     803           0 :     _this->rawdata = cmap = ttmalloc(cmapsize);
     804             : 
     805           0 :     PutUInt16(0, cmap, 0, 1);
     806           0 :     PutUInt16((sal_uInt16)t->n, cmap, 2, 1);
     807           0 :     coffset = 4 + t->n * 8;
     808             : 
     809           0 :     for (i = 0; i < t->n; i++) {
     810           0 :         PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1);
     811           0 :         PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1);
     812           0 :         PutUInt32(coffset, cmap + 4, 4 + i * 8, 1);
     813           0 :         memcpy(cmap + coffset, subtables[i], sizes[i]);
     814           0 :         free(subtables[i]);
     815           0 :         coffset += sizes[i];
     816             :     }
     817             : 
     818           0 :     free(subtables);
     819           0 :     free(sizes);
     820             : 
     821           0 :     *ptr = cmap;
     822           0 :     *len = cmapsize;
     823           0 :     *tag = T_cmap;
     824             : 
     825           0 :     return TTCR_OK;
     826             : }
     827             : 
     828             : 
     829           0 : static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     830             : {
     831             :     list l;
     832           0 :     sal_Int16 i=0, n;                          /* number of Name Records */
     833           0 :     int stringLen = 0;
     834             :     sal_uInt8 *p1, *p2;
     835             : 
     836           0 :     *ptr = 0;
     837           0 :     *len = 0;
     838           0 :     *tag = 0;
     839             : 
     840             :     assert(_this != 0);
     841           0 :     l = (list) _this->data;
     842             :     assert(l != 0);
     843             : 
     844           0 :     if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES;
     845             : 
     846           0 :     NameRecord* nr = (NameRecord*)scalloc(n, sizeof(NameRecord));
     847             : 
     848           0 :     listToFirst(l);
     849             : 
     850           0 :     do {
     851           0 :         memcpy(nr+i, listCurrent(l), sizeof(NameRecord));
     852           0 :         stringLen += nr[i].slen;
     853           0 :         i++;
     854           0 :     } while (listNext(l));
     855             : 
     856           0 :     if (stringLen > 65535) {
     857           0 :         free(nr);
     858           0 :         return TTCR_NAMETOOLONG;
     859             :     }
     860             : 
     861           0 :     qsort(nr, n, sizeof(NameRecord), NameRecordCompareF);
     862             : 
     863           0 :     int nameLen = stringLen + 12 * n + 6;
     864           0 :     sal_uInt8* name = (sal_uInt8*)ttmalloc(nameLen);
     865             : 
     866           0 :     PutUInt16(0, name, 0, 1);
     867           0 :     PutUInt16(n, name, 2, 1);
     868           0 :     PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1);
     869             : 
     870           0 :     p1 = name + 6;
     871           0 :     p2 = p1 + 12 * n;
     872             : 
     873           0 :     for (i = 0; i < n; i++) {
     874           0 :         PutUInt16(nr[i].platformID, p1, 0, 1);
     875           0 :         PutUInt16(nr[i].encodingID, p1, 2, 1);
     876           0 :         PutUInt16(nr[i].languageID, p1, 4, 1);
     877           0 :         PutUInt16(nr[i].nameID, p1, 6, 1);
     878           0 :         PutUInt16(nr[i].slen, p1, 8, 1);
     879           0 :         PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1);
     880           0 :         memcpy(p2, nr[i].sptr, nr[i].slen);
     881             :         /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
     882           0 :         p2 += nr[i].slen;
     883           0 :         p1 += 12;
     884             :     }
     885             : 
     886           0 :     free(nr);
     887           0 :     _this->rawdata = name;
     888             : 
     889           0 :     *ptr = name;
     890           0 :     *len = (sal_uInt16)nameLen;
     891           0 :     *tag = T_name;
     892             : 
     893             :     /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
     894             : 
     895           0 :     return TTCR_OK;
     896             : }
     897             : 
     898           0 : static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
     899             : {
     900           0 :     tdata_post *p = (tdata_post *) _this->data;
     901           0 :     sal_uInt8 *post = 0;
     902           0 :     sal_uInt32 postLen = 0;
     903             :     int ret;
     904             : 
     905           0 :     if (_this->rawdata) free(_this->rawdata);
     906             : 
     907           0 :     if (p->format == 0x00030000) {
     908           0 :         postLen = 32;
     909           0 :         post = ttmalloc(postLen);
     910           0 :         PutUInt32(0x00030000, post, 0, 1);
     911           0 :         PutUInt32(p->italicAngle, post, 4, 1);
     912           0 :         PutUInt16(p->underlinePosition, post, 8, 1);
     913           0 :         PutUInt16(p->underlineThickness, post, 10, 1);
     914           0 :         PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1);
     915           0 :         ret = TTCR_OK;
     916             :     } else {
     917           0 :         fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format);
     918           0 :         ret = TTCR_POSTFORMAT;
     919             :     }
     920             : 
     921           0 :     *ptr = _this->rawdata = post;
     922           0 :     *len = postLen;
     923           0 :     *tag = T_post;
     924             : 
     925           0 :     return ret;
     926             : }
     927             : 
     928             : 
     929             : 
     930             : 
     931             : 
     932             : static struct {
     933             :     sal_uInt32 tag;
     934             :     int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *);
     935             : } vtable2[] =
     936             : {
     937             :     {0,      GetRawData_generic},
     938             :     {T_head, GetRawData_head},
     939             :     {T_hhea, GetRawData_hhea},
     940             :     {T_loca, GetRawData_loca},
     941             :     {T_maxp, GetRawData_maxp},
     942             :     {T_glyf, GetRawData_glyf},
     943             :     {T_cmap, GetRawData_cmap},
     944             :     {T_name, GetRawData_name},
     945             :     {T_post, GetRawData_post}
     946             : 
     947             : 
     948             : };
     949             : 
     950             : /*
     951             :  * TrueTypeTable public methods
     952             :  */
     953             : 
     954             : /* Note: Type42 fonts only need these tables:
     955             :  *        head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
     956             :  *
     957             :  * Microsoft required tables
     958             :  *        cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
     959             :  *
     960             :  * Apple required tables
     961             :  *        cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
     962             :  *
     963             :  */
     964             : 
     965           0 : TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag,
     966             :                                 sal_uInt32 nbytes,
     967             :                                 const sal_uInt8* ptr)
     968             : {
     969           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
     970           0 :     tdata_generic* pdata = (tdata_generic*)smalloc(sizeof(tdata_generic));
     971           0 :     pdata->nbytes = nbytes;
     972           0 :     pdata->tag = tag;
     973           0 :     if (nbytes) {
     974           0 :         pdata->ptr = ttmalloc(nbytes);
     975           0 :         memcpy(pdata->ptr, ptr, nbytes);
     976             :     } else {
     977           0 :         pdata->ptr = 0;
     978             :     }
     979             : 
     980           0 :     table->tag = 0;
     981           0 :     table->data = pdata;
     982           0 :     table->rawdata = 0;
     983             : 
     984           0 :     return table;
     985             : }
     986             : 
     987           0 : TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision,
     988             :                                      sal_uInt16 flags,
     989             :                                      sal_uInt16 unitsPerEm,
     990             :                                      const sal_uInt8* created,
     991             :                                      sal_uInt16 macStyle,
     992             :                                      sal_uInt16 lowestRecPPEM,
     993             :                                      sal_Int16  fontDirectionHint)
     994             : {
     995             :     assert(created != 0);
     996             : 
     997           0 :     TrueTypeTable* table  = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
     998           0 :     sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_head);
     999             : 
    1000             : 
    1001           0 :     PutUInt32(0x00010000, ptr, 0, 1);             /* version */
    1002           0 :     PutUInt32(fontRevision, ptr, 4, 1);
    1003           0 :     PutUInt32(0x5F0F3CF5, ptr, 12, 1);            /* magic number */
    1004           0 :     PutUInt16(flags, ptr, 16, 1);
    1005           0 :     PutUInt16(unitsPerEm, ptr, 18, 1);
    1006           0 :     memcpy(ptr+20, created, 8);                   /* Created Long Date */
    1007           0 :     memset(ptr+28, 0, 8);                         /* Modified Long Date */
    1008           0 :     PutUInt16(macStyle, ptr, 44, 1);
    1009           0 :     PutUInt16(lowestRecPPEM, ptr, 46, 1);
    1010           0 :     PutUInt16(fontDirectionHint, ptr, 48, 1);
    1011           0 :     PutUInt16(0, ptr, 52, 1);                     /* glyph data format: 0 */
    1012             : 
    1013           0 :     table->data = (void *) ptr;
    1014           0 :     table->tag = T_head;
    1015           0 :     table->rawdata = 0;
    1016             : 
    1017           0 :     return table;
    1018             : }
    1019             : 
    1020           0 : TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16  ascender,
    1021             :                                      sal_Int16  descender,
    1022             :                                      sal_Int16  linegap,
    1023             :                                      sal_Int16  caretSlopeRise,
    1024             :                                      sal_Int16  caretSlopeRun)
    1025             : {
    1026           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1027           0 :     sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_hhea);
    1028             : 
    1029           0 :     PutUInt32(0x00010000, ptr, 0, 1);             /* version */
    1030           0 :     PutUInt16(ascender, ptr, 4, 1);
    1031           0 :     PutUInt16(descender, ptr, 6, 1);
    1032           0 :     PutUInt16(linegap, ptr, 8, 1);
    1033           0 :     PutUInt16(caretSlopeRise, ptr, 18, 1);
    1034           0 :     PutUInt16(caretSlopeRun, ptr, 20, 1);
    1035           0 :     PutUInt16(0, ptr, 22, 1);                     /* reserved 1 */
    1036           0 :     PutUInt16(0, ptr, 24, 1);                     /* reserved 2 */
    1037           0 :     PutUInt16(0, ptr, 26, 1);                     /* reserved 3 */
    1038           0 :     PutUInt16(0, ptr, 28, 1);                     /* reserved 4 */
    1039           0 :     PutUInt16(0, ptr, 30, 1);                     /* reserved 5 */
    1040           0 :     PutUInt16(0, ptr, 32, 1);                     /* metricDataFormat */
    1041             : 
    1042           0 :     table->data = (void *) ptr;
    1043           0 :     table->tag = T_hhea;
    1044           0 :     table->rawdata = 0;
    1045             : 
    1046           0 :     return table;
    1047             : }
    1048             : 
    1049           0 : TrueTypeTable *TrueTypeTableNew_loca(void)
    1050             : {
    1051           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1052           0 :     table->data = smalloc(sizeof(tdata_loca));
    1053             : 
    1054           0 :     ((tdata_loca *)table->data)->nbytes = 0;
    1055           0 :     ((tdata_loca *)table->data)->ptr = 0;
    1056             : 
    1057           0 :     table->tag = T_loca;
    1058           0 :     table->rawdata = 0;
    1059             : 
    1060           0 :     return table;
    1061             : }
    1062             : 
    1063           0 : TrueTypeTable *TrueTypeTableNew_maxp( const sal_uInt8* maxp, int size)
    1064             : {
    1065           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1066           0 :     table->data = ttmalloc(TABLESIZE_maxp);
    1067             : 
    1068           0 :     if (maxp && size == TABLESIZE_maxp) {
    1069           0 :         memcpy(table->data, maxp, TABLESIZE_maxp);
    1070             :     }
    1071             : 
    1072           0 :     table->tag = T_maxp;
    1073           0 :     table->rawdata = 0;
    1074             : 
    1075           0 :     return table;
    1076             : }
    1077             : 
    1078           0 : TrueTypeTable *TrueTypeTableNew_glyf(void)
    1079             : {
    1080           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1081           0 :     list l = listNewEmpty();
    1082             : 
    1083             :     assert(l != 0);
    1084             : 
    1085           0 :     listSetElementDtor(l, (list_destructor)FreeGlyphData);
    1086             : 
    1087           0 :     table->data = l;
    1088           0 :     table->rawdata = 0;
    1089           0 :     table->tag = T_glyf;
    1090             : 
    1091           0 :     return table;
    1092             : }
    1093             : 
    1094           0 : TrueTypeTable *TrueTypeTableNew_cmap(void)
    1095             : {
    1096           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1097           0 :     table_cmap* cmap = (table_cmap*)smalloc(sizeof(table_cmap));
    1098             : 
    1099           0 :     cmap->n = 0;
    1100           0 :     cmap->m = CMAP_SUBTABLE_INIT;
    1101           0 :     cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable));
    1102           0 :     memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT);
    1103             : 
    1104           0 :     table->data = (table_cmap *) cmap;
    1105             : 
    1106           0 :     table->rawdata = 0;
    1107           0 :     table->tag = T_cmap;
    1108             : 
    1109           0 :     return table;
    1110             : }
    1111             : 
    1112           0 : static void DisposeNameRecord(void *ptr)
    1113             : {
    1114           0 :     if (ptr != 0) {
    1115           0 :         NameRecord *nr = (NameRecord *) ptr;
    1116           0 :         if (nr->sptr) free(nr->sptr);
    1117           0 :         free(ptr);
    1118             :     }
    1119           0 : }
    1120             : 
    1121           0 : static NameRecord* NameRecordNewCopy(NameRecord *nr)
    1122             : {
    1123           0 :     NameRecord* p = (NameRecord*)smalloc(sizeof(NameRecord));
    1124             : 
    1125           0 :     memcpy(p, nr, sizeof(NameRecord));
    1126             : 
    1127           0 :     if (p->slen) {
    1128           0 :         p->sptr = (sal_uInt8*)smalloc(p->slen);
    1129           0 :         memcpy(p->sptr, nr->sptr, p->slen);
    1130             :     }
    1131             : 
    1132           0 :     return p;
    1133             : }
    1134             : 
    1135           0 : TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr)
    1136             : {
    1137           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1138           0 :     list l = listNewEmpty();
    1139             : 
    1140             :     assert(l != 0);
    1141             : 
    1142           0 :     listSetElementDtor(l, (list_destructor)DisposeNameRecord);
    1143             : 
    1144           0 :     if (n != 0) {
    1145             :         int i;
    1146           0 :         for (i = 0; i < n; i++) {
    1147           0 :             listAppend(l, NameRecordNewCopy(nr+i));
    1148             :         }
    1149             :     }
    1150             : 
    1151           0 :     table->data = l;
    1152           0 :     table->rawdata = 0;
    1153           0 :     table->tag = T_name;
    1154             : 
    1155           0 :     return table;
    1156             : }
    1157             : 
    1158           0 : TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format,
    1159             :                                      sal_uInt32 italicAngle,
    1160             :                                      sal_Int16 underlinePosition,
    1161             :                                      sal_Int16 underlineThickness,
    1162             :                                      sal_uInt32 isFixedPitch)
    1163             : {
    1164             :     assert(format == 0x00030000);                 /* Only format 3.0 is supported at this time */
    1165           0 :     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
    1166           0 :     tdata_post* post = (tdata_post*)smalloc(sizeof(tdata_post));
    1167             : 
    1168           0 :     post->format = format;
    1169           0 :     post->italicAngle = italicAngle;
    1170           0 :     post->underlinePosition = underlinePosition;
    1171           0 :     post->underlineThickness = underlineThickness;
    1172           0 :     post->isFixedPitch = isFixedPitch;
    1173           0 :     post->ptr = 0;
    1174             : 
    1175           0 :     table->data = post;
    1176           0 :     table->rawdata = 0;
    1177           0 :     table->tag = T_post;
    1178             : 
    1179           0 :     return table;
    1180             : }
    1181             : 
    1182           0 : int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
    1183             : {
    1184             :     /* XXX do a binary search */
    1185             :     unsigned int i;
    1186             : 
    1187             :     assert(_this != 0);
    1188             :     assert(ptr != 0);
    1189             :     assert(len != 0);
    1190             :     assert(tag != 0);
    1191             : 
    1192           0 :     *ptr = 0; *len = 0; *tag = 0;
    1193             : 
    1194           0 :     if (_this->rawdata) {
    1195           0 :         free(_this->rawdata);
    1196           0 :         _this->rawdata = 0;
    1197             :     }
    1198             : 
    1199           0 :     for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) {
    1200           0 :         if (_this->tag == vtable2[i].tag) {
    1201           0 :             return vtable2[i].f(_this, ptr, len, tag);
    1202             :         }
    1203             :     }
    1204             : 
    1205             :     assert(!"Unknwon TrueType table.\n");
    1206           0 :     return TTCR_UNKNOWN;
    1207             : }
    1208             : 
    1209           0 : void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
    1210             : {
    1211             :     sal_uInt32 i, found;
    1212             :     table_cmap *t;
    1213             :     CmapSubTable *s;
    1214             : 
    1215             :     assert(table != 0);
    1216             :     assert(table->tag == T_cmap);
    1217           0 :     t = (table_cmap *) table->data; assert(t != 0);
    1218           0 :     s = t->s; assert(s != 0);
    1219             : 
    1220           0 :     found = 0;
    1221             : 
    1222           0 :     for (i = 0; i < t->n; i++) {
    1223           0 :         if (s[i].id == id) {
    1224           0 :             found = 1;
    1225           0 :             break;
    1226             :         }
    1227             :     }
    1228             : 
    1229           0 :     if (!found) {
    1230           0 :         if (t->n == t->m) {
    1231           0 :             CmapSubTable* tmp = (CmapSubTable*)scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable));
    1232           0 :             memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable));
    1233           0 :             memcpy(tmp, s, sizeof(CmapSubTable) * t->m);
    1234           0 :             t->m += CMAP_SUBTABLE_INCR;
    1235           0 :             free(s);
    1236           0 :             s = tmp;
    1237           0 :             t->s = s;
    1238             :         }
    1239             : 
    1240           0 :         for (i = 0; i < t->n; i++) {
    1241           0 :             if (s[i].id > id) break;
    1242             :         }
    1243             : 
    1244           0 :         if (i < t->n) {
    1245           0 :             memmove(s+i+1, s+i, t->n-i);
    1246             :         }
    1247             : 
    1248           0 :         t->n++;
    1249             : 
    1250           0 :         s[i].id = id;
    1251           0 :         s[i].n = 0;
    1252           0 :         s[i].m = CMAP_PAIR_INIT;
    1253           0 :         s[i].xc = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
    1254           0 :         s[i].xg = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
    1255             :     }
    1256             : 
    1257           0 :     if (s[i].n == s[i].m) {
    1258           0 :         sal_uInt32* tmp1 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
    1259           0 :         sal_uInt32* tmp2 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
    1260             :         assert(tmp1 != 0);
    1261             :         assert(tmp2 != 0);
    1262           0 :         memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m);
    1263           0 :         memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m);
    1264           0 :         s[i].m += CMAP_PAIR_INCR;
    1265           0 :         free(s[i].xc);
    1266           0 :         free(s[i].xg);
    1267           0 :         s[i].xc = tmp1;
    1268           0 :         s[i].xg = tmp2;
    1269             :     }
    1270             : 
    1271           0 :     s[i].xc[s[i].n] = c;
    1272           0 :     s[i].xg[s[i].n] = g;
    1273           0 :     s[i].n++;
    1274           0 : }
    1275             : 
    1276           0 : sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt)
    1277             : {
    1278             :     list l;
    1279             :     sal_uInt32 currentID;
    1280             :     int ret, n, ncomponents;
    1281             :     GlyphData *gd;
    1282             : 
    1283             :     assert(table != 0);
    1284             :     assert(table->tag == T_glyf);
    1285             : 
    1286           0 :     if (!glyphdata) return (sal_uInt32)~0;
    1287             : 
    1288           0 :     std::vector< sal_uInt32 > glyphlist;
    1289             : 
    1290           0 :     ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
    1291             : 
    1292           0 :     l = (list) table->data;
    1293           0 :     if (listCount(l) > 0) {
    1294           0 :         listToLast(l);
    1295           0 :         ret = n = ((GlyphData *) listCurrent(l))->newID + 1;
    1296             :     } else {
    1297           0 :         ret = n = 0;
    1298             :     }
    1299           0 :     glyphdata->newID = n++;
    1300           0 :     listAppend(l, glyphdata);
    1301             : 
    1302           0 :     if (ncomponents > 1 && glyphlist.size() > 1 )
    1303             :     {
    1304           0 :         std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
    1305           0 :         ++it;
    1306             :         /* glyphData->glyphID is always the first glyph on the list */
    1307           0 :         do
    1308             :         {
    1309           0 :             int found = 0;
    1310           0 :             currentID = *it;
    1311             :             /* XXX expensive! should be rewritten with sorted arrays! */
    1312           0 :             listToFirst(l);
    1313           0 :             do {
    1314           0 :                 if (((GlyphData *) listCurrent(l))->glyphID == currentID) {
    1315           0 :                     found = 1;
    1316           0 :                     break;
    1317             :                 }
    1318           0 :             } while (listNext(l));
    1319             : 
    1320           0 :             if (!found) {
    1321           0 :                 gd = GetTTRawGlyphData(fnt, currentID);
    1322           0 :                 gd->newID = n++;
    1323           0 :                 listAppend(l, gd);
    1324             :             }
    1325           0 :         } while( ++it !=  glyphlist.end() );
    1326             :     }
    1327             : 
    1328           0 :     return ret;
    1329             : }
    1330             : 
    1331           0 : sal_uInt32 glyfCount(const TrueTypeTable *table)
    1332             : {
    1333             :     assert(table != 0);
    1334             :     assert(table->tag == T_glyf);
    1335           0 :     return listCount((list) table->data);
    1336             : }
    1337             : 
    1338             : 
    1339           0 : void nameAdd(TrueTypeTable *table, NameRecord *nr)
    1340             : {
    1341             :     list l;
    1342             : 
    1343             :     assert(table != 0);
    1344             :     assert(table->tag == T_name);
    1345             : 
    1346           0 :     l = (list) table->data;
    1347             : 
    1348           0 :     listAppend(l, NameRecordNewCopy(nr));
    1349           0 : }
    1350             : 
    1351           0 : static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag)
    1352             : {
    1353           0 :     if (listIsEmpty(tt->tables)) return 0;
    1354             : 
    1355           0 :     listToFirst(tt->tables);
    1356             : 
    1357           0 :     do {
    1358           0 :         if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) {
    1359           0 :             return (TrueTypeTable*)listCurrent(tt->tables);
    1360             :         }
    1361           0 :     } while (listNext(tt->tables));
    1362             : 
    1363           0 :     return 0;
    1364             : }
    1365             : 
    1366             : /* This function processes all the tables and synchronizes them before creating
    1367             :  * the output TrueType stream.
    1368             :  *
    1369             :  * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
    1370             :  *
    1371             :  * It does:
    1372             :  *
    1373             :  * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
    1374             :  * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
    1375             :  * - Stores indexToLocFormat in 'head'
    1376             :  * - updates 'maxp' table
    1377             :  * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
    1378             :  *   in 'hhea' table
    1379             :  *
    1380             :  */
    1381           0 : static void ProcessTables(TrueTypeCreator *tt)
    1382             : {
    1383             :     TrueTypeTable *glyf, *loca, *head, *maxp, *hhea;
    1384             :     list glyphlist;
    1385           0 :     sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0;
    1386           0 :     sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
    1387           0 :     sal_uInt32 i = 0;
    1388             :     sal_Int16 indexToLocFormat;
    1389             :     sal_uInt8 *hmtxPtr, *hheaPtr;
    1390             :     sal_uInt32 hmtxSize;
    1391             :     sal_uInt8 *p1, *p2;
    1392           0 :     sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
    1393           0 :     int nlsb = 0;
    1394             :     sal_uInt32 *gid;                        /* array of old glyphIDs */
    1395             : 
    1396           0 :     glyf = FindTable(tt, T_glyf);
    1397           0 :     glyphlist = (list) glyf->data;
    1398           0 :     nGlyphs = listCount(glyphlist);
    1399             :     assert(nGlyphs != 0);
    1400           0 :     gid = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32));
    1401             : 
    1402           0 :     RemoveTable(tt, T_loca);
    1403           0 :     RemoveTable(tt, T_hmtx);
    1404             : 
    1405             :     /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
    1406             : 
    1407           0 :     listToFirst(glyphlist);
    1408           0 :     do {
    1409           0 :         GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
    1410             :         sal_Int16 z;
    1411           0 :         glyfLen += gd->nbytes;
    1412             :         /* XXX if (gd->nbytes & 1) glyfLen++; */
    1413             : 
    1414             : 
    1415             :         assert(gd->newID == i);
    1416           0 :         gid[i++] = gd->glyphID;
    1417             :         /* gd->glyphID = i++; */
    1418             : 
    1419             :         /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
    1420             : 
    1421           0 :         if (gd->nbytes != 0) {
    1422           0 :             z = GetInt16(gd->ptr, 2, 1);
    1423           0 :             if (z < xMin) xMin = z;
    1424             : 
    1425           0 :             z = GetInt16(gd->ptr, 4, 1);
    1426           0 :             if (z < yMin) yMin = z;
    1427             : 
    1428           0 :             z = GetInt16(gd->ptr, 6, 1);
    1429           0 :             if (z > xMax) xMax = z;
    1430             : 
    1431           0 :             z = GetInt16(gd->ptr, 8, 1);
    1432           0 :             if (z > yMax) yMax = z;
    1433             :         }
    1434             : 
    1435           0 :         if (gd->compflag == 0) {                            /* non-composite glyph */
    1436           0 :             if (gd->npoints > maxPoints) maxPoints = gd->npoints;
    1437           0 :             if (gd->ncontours > maxContours) maxContours = gd->ncontours;
    1438             :         } else {                                            /* composite glyph */
    1439           0 :             if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
    1440           0 :             if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
    1441             :         }
    1442             : 
    1443           0 :     } while (listNext(glyphlist));
    1444             : 
    1445           0 :     indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
    1446           0 :     locaLen = indexToLocFormat ?  (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
    1447             : 
    1448           0 :     sal_uInt8* glyfPtr = ttmalloc(glyfLen);
    1449           0 :     sal_uInt8* locaPtr = ttmalloc(locaLen);
    1450           0 :     TTSimpleGlyphMetrics* met = (TTSimpleGlyphMetrics*)scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
    1451           0 :     i = 0;
    1452             : 
    1453           0 :     listToFirst(glyphlist);
    1454           0 :     p1 = glyfPtr;
    1455           0 :     p2 = locaPtr;
    1456           0 :     do {
    1457           0 :         GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
    1458             : 
    1459           0 :         if (gd->compflag) {                       /* re-number all components */
    1460             :             sal_uInt16 flags, index;
    1461           0 :             sal_uInt8 *ptr = gd->ptr + 10;
    1462           0 :             do {
    1463             :                 sal_uInt32 j;
    1464           0 :                 flags = GetUInt16(ptr, 0, 1);
    1465           0 :                 index = GetUInt16(ptr, 2, 1);
    1466             :                 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
    1467           0 :                 for (j = 0; j < nGlyphs; j++) {
    1468           0 :                     if (gid[j] == index) {
    1469           0 :                         break;
    1470             :                     }
    1471             :                 }
    1472             :                 /* printf("X: %d -> %d.\n", index, j); */
    1473             : 
    1474           0 :                 PutUInt16((sal_uInt16) j, ptr, 2, 1);
    1475             : 
    1476           0 :                 ptr += 4;
    1477             : 
    1478           0 :                 if (flags & ARG_1_AND_2_ARE_WORDS) {
    1479           0 :                     ptr += 4;
    1480             :                 } else {
    1481           0 :                     ptr += 2;
    1482             :                 }
    1483             : 
    1484           0 :                 if (flags & WE_HAVE_A_SCALE) {
    1485           0 :                     ptr += 2;
    1486           0 :                 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
    1487           0 :                     ptr += 4;
    1488           0 :                 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
    1489           0 :                     ptr += 8;
    1490             :                 }
    1491             :             } while (flags & MORE_COMPONENTS);
    1492             :         }
    1493             : 
    1494           0 :         if (gd->nbytes != 0) {
    1495           0 :             memcpy(p1, gd->ptr, gd->nbytes);
    1496             :         }
    1497           0 :         if (indexToLocFormat == 1) {
    1498           0 :             PutUInt32(p1 - glyfPtr, p2, 0, 1);
    1499           0 :             p2 += 4;
    1500             :         } else {
    1501           0 :             PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
    1502           0 :             p2 += 2;
    1503             :         }
    1504           0 :         p1 += gd->nbytes;
    1505             : 
    1506             :         /* fill the array of metrics */
    1507           0 :         met[i].adv = gd->aw;
    1508           0 :         met[i].sb  = gd->lsb;
    1509           0 :         i++;
    1510           0 :     } while (listNext(glyphlist));
    1511             : 
    1512           0 :     free(gid);
    1513             : 
    1514           0 :     if (indexToLocFormat == 1) {
    1515           0 :         PutUInt32(p1 - glyfPtr, p2, 0, 1);
    1516             :     } else {
    1517           0 :         PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
    1518             :     }
    1519             : 
    1520           0 :     glyf->rawdata = glyfPtr;
    1521             : 
    1522           0 :     loca = TrueTypeTableNew_loca(); assert(loca != 0);
    1523           0 :     ((tdata_loca *) loca->data)->ptr = locaPtr;
    1524           0 :     ((tdata_loca *) loca->data)->nbytes = locaLen;
    1525             : 
    1526           0 :     AddTable(tt, loca);
    1527             : 
    1528           0 :     head = FindTable(tt, T_head);
    1529           0 :     sal_uInt8* const pHeadData = (sal_uInt8*)head->data;
    1530           0 :     PutInt16(xMin, pHeadData, 36, 1);
    1531           0 :     PutInt16(yMin, pHeadData, 38, 1);
    1532           0 :     PutInt16(xMax, pHeadData, 40, 1);
    1533           0 :     PutInt16(yMax, pHeadData, 42, 1);
    1534           0 :     PutInt16(indexToLocFormat, pHeadData,  50, 1);
    1535             : 
    1536           0 :     maxp = FindTable(tt, T_maxp);
    1537             : 
    1538           0 :     sal_uInt8* const pMaxpData = (sal_uInt8*)maxp->data;
    1539           0 :     PutUInt16((sal_uInt16)nGlyphs, pMaxpData, 4, 1);
    1540           0 :     PutUInt16(maxPoints, pMaxpData, 6, 1);
    1541           0 :     PutUInt16(maxContours, pMaxpData, 8, 1);
    1542           0 :     PutUInt16(maxCompositePoints, pMaxpData, 10, 1);
    1543           0 :     PutUInt16(maxCompositeContours, pMaxpData, 12, 1);
    1544             : 
    1545             :     /*
    1546             :      * Generate an htmx table and update hhea table
    1547             :      */
    1548           0 :     hhea = FindTable(tt, T_hhea); assert(hhea != 0);
    1549           0 :     hheaPtr = (sal_uInt8 *) hhea->data;
    1550           0 :     if (nGlyphs > 2) {
    1551           0 :         for (i = nGlyphs - 1; i > 0; i--) {
    1552           0 :             if (met[i].adv != met[i-1].adv) break;
    1553             :         }
    1554           0 :         nlsb = nGlyphs - 1 - i;
    1555             :     }
    1556           0 :     hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
    1557           0 :     hmtxPtr = ttmalloc(hmtxSize);
    1558           0 :     p1 = hmtxPtr;
    1559             : 
    1560           0 :     for (i = 0; i < nGlyphs; i++) {
    1561           0 :         if (i < nGlyphs - nlsb) {
    1562           0 :             PutUInt16(met[i].adv, p1, 0, 1);
    1563           0 :             PutUInt16(met[i].sb, p1, 2, 1);
    1564           0 :             p1 += 4;
    1565             :         } else {
    1566           0 :             PutUInt16(met[i].sb, p1, 0, 1);
    1567           0 :             p1 += 2;
    1568             :         }
    1569             :     }
    1570             : 
    1571           0 :     AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr));
    1572           0 :     PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1);
    1573           0 :     free(hmtxPtr);
    1574           0 :     free(met);
    1575           0 : }
    1576             : 
    1577             : } // namespace vcl
    1578             : 
    1579             : extern "C"
    1580             : {
    1581             :     /**
    1582             :      * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it.
    1583             :      */
    1584           0 :      void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this)
    1585             :     {
    1586           0 :         listDispose(_this->tables);
    1587           0 :         free(_this);
    1588           0 :     }
    1589             : 
    1590             : 
    1591             :     /**
    1592             :      * Destructor for the TrueTypeTable object.
    1593             :      */
    1594           0 :      void TrueTypeTableDispose(vcl::TrueTypeTable *_this)
    1595             :     {
    1596             :         /* XXX do a binary search */
    1597             :         unsigned int i;
    1598             : 
    1599             :         assert(_this != 0);
    1600             : 
    1601           0 :         if (_this->rawdata) free(_this->rawdata);
    1602             : 
    1603           0 :         for(i=0; i < sizeof(vcl::vtable1)/sizeof(*vcl::vtable1); i++) {
    1604           0 :             if (_this->tag == vcl::vtable1[i].tag) {
    1605           0 :                 vcl::vtable1[i].f(_this);
    1606           0 :                 return;
    1607             :             }
    1608             :         }
    1609             :         assert(!"Unknown TrueType table.\n");
    1610             :     }
    1611             : }
    1612             : 
    1613             : 
    1614             : #ifdef TEST_TTCR
    1615             : int main(void)
    1616             : {
    1617             :     TrueTypeCreator *ttcr;
    1618             :     sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7;
    1619             : 
    1620             :     TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
    1621             : 
    1622             :     t1 = malloc(1000); memset(t1, 'a', 1000);
    1623             :     t2 = malloc(2000); memset(t2, 'b', 2000);
    1624             :     t3 = malloc(3000); memset(t3, 'c', 3000);
    1625             :     t4 = malloc(4000); memset(t4, 'd', 4000);
    1626             :     t5 = malloc(5000); memset(t5, 'e', 5000);
    1627             :     t6 = malloc(6000); memset(t6, 'f', 6000);
    1628             :     t7 = malloc(7000); memset(t7, 'g', 7000);
    1629             : 
    1630             :     AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1));
    1631             :     AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2));
    1632             :     AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3));
    1633             :     AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4));
    1634             :     AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5));
    1635             :     AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6));
    1636             :     AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7));
    1637             : 
    1638             :     free(t1);
    1639             :     free(t2);
    1640             :     free(t3);
    1641             :     free(t4);
    1642             :     free(t5);
    1643             :     free(t6);
    1644             :     free(t7);
    1645             : 
    1646             : 
    1647             :     StreamToFile(ttcr, "ttcrout.ttf");
    1648             : 
    1649             :     TrueTypeCreatorDispose(ttcr);
    1650             :     return 0;
    1651             : }
    1652             : #endif
    1653             : 
    1654             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10