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

Generated by: LCOV version 1.10