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

Generated by: LCOV version 1.10