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

Generated by: LCOV version 1.10