LCOV - code coverage report
Current view: top level - vcl/source/fontsubset - ttcr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 727 0.0 %
Date: 2012-08-25 Functions: 0 58 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 314 0.0 %

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

Generated by: LCOV version 1.10