fontservices/textshaperplugin/test/letest/FontObject.cpp
changeset 0 1fb32624e06b
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /***************************************************************************
       
     2 *
       
     3 *   Copyright (C) 1998-2002, International Business Machines
       
     4 *   Corporation and others.  All Rights Reserved.
       
     5 *
       
     6 ************************************************************************/
       
     7 
       
     8 #include <stdio.h>
       
     9 
       
    10 #include "LETypes.h"
       
    11 #include "FontObject.h"
       
    12 #include "LESwaps.h"
       
    13 
       
    14 FontObject::FontObject(char *fileName)
       
    15   : directory(NULL), numTables(0), searchRange(0),entrySelector(0),
       
    16     cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0),
       
    17     cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0),
       
    18     headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL)
       
    19 {
       
    20     file = fopen(fileName, "rb");
       
    21 
       
    22     if (file == NULL) {
       
    23         printf("?? Couldn't open %s", fileName);
       
    24         return;
       
    25     }
       
    26 
       
    27     SFNTDirectory tempDir;
       
    28 
       
    29     fread(&tempDir, sizeof tempDir, 1, file);
       
    30 
       
    31     numTables       = SWAPW(tempDir.numTables);
       
    32     searchRange     = SWAPW(tempDir.searchRange) >> 4;
       
    33     entrySelector   = SWAPW(tempDir.entrySelector);
       
    34     rangeShift      = SWAPW(tempDir.rangeShift) >> 4;
       
    35 
       
    36     int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry));
       
    37 
       
    38     directory = (SFNTDirectory *) new char[dirSize];
       
    39 
       
    40     fseek(file, 0L, SEEK_SET);
       
    41     fread(directory, sizeof(char), dirSize, file);
       
    42 
       
    43     initUnicodeCMAP();
       
    44 }
       
    45 
       
    46 FontObject::~FontObject()
       
    47 {
       
    48     fclose(file);
       
    49     delete[] directory;
       
    50     delete[] cmapTable;
       
    51     delete[] headTable;
       
    52     delete[] hmtxTable;
       
    53 }
       
    54 
       
    55 void FontObject::deleteTable(void *table)
       
    56 {
       
    57     delete[] (char *) table;
       
    58 }
       
    59 
       
    60 DirectoryEntry *FontObject::findTable(LETag tag)
       
    61 {
       
    62     le_uint16 table = 0;
       
    63     le_uint16 probe = 1 << entrySelector;
       
    64 
       
    65     if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) {
       
    66         table = rangeShift;
       
    67     }
       
    68 
       
    69     while (probe > (1 << 0)) {
       
    70         probe >>= 1;
       
    71 
       
    72         if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) {
       
    73             table += probe;
       
    74         }
       
    75     }
       
    76 
       
    77     if (SWAPL(directory->tableDirectory[table].tag) == tag) {
       
    78         return &directory->tableDirectory[table];
       
    79     }
       
    80 
       
    81     return NULL;
       
    82 }
       
    83 
       
    84 void *FontObject::readTable(LETag tag, le_uint32 *length)
       
    85 {
       
    86     DirectoryEntry *entry = findTable(tag);
       
    87 
       
    88     if (entry == NULL) {
       
    89         *length = 0;
       
    90         return NULL;
       
    91     }
       
    92 
       
    93     *length = SWAPL(entry->length);
       
    94 
       
    95     void *table = new char[*length];
       
    96 
       
    97     fseek(file, SWAPL(entry->offset), SEEK_SET);
       
    98     fread(table, sizeof(char), *length, file);
       
    99 
       
   100     return table;
       
   101 }
       
   102 
       
   103 CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID)
       
   104 {
       
   105     LETag cmapTag = 0x636D6170; // 'cmap'
       
   106 
       
   107     if (cmapTable == NULL) {
       
   108         le_uint32 length;
       
   109 
       
   110         cmapTable = (CMAPTable *) readTable(cmapTag, &length);
       
   111     }
       
   112 
       
   113     if (cmapTable != NULL) {
       
   114         le_uint16 i;
       
   115         le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables);
       
   116 
       
   117 
       
   118         for (i = 0; i < nSubtables; i += 1) {
       
   119             CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i];
       
   120 
       
   121             if (SWAPW(esh->platformID) == platformID &&
       
   122                 SWAPW(esh->platformSpecificID) == platformSpecificID) {
       
   123                 return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset));
       
   124             }
       
   125         }
       
   126     }
       
   127 
       
   128     return NULL;
       
   129 }
       
   130 
       
   131 void FontObject::initUnicodeCMAP()
       
   132 {
       
   133     CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1);
       
   134 
       
   135     if (encodingSubtable == 0 ||
       
   136         SWAPW(encodingSubtable->format) != 4) {
       
   137         printf("Can't find unicode 'cmap'");
       
   138         return;
       
   139     }
       
   140 
       
   141     CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable;
       
   142 
       
   143     cmSegCount = SWAPW(header->segCountX2) / 2;
       
   144     cmSearchRange = SWAPW(header->searchRange);
       
   145     cmEntrySelector = SWAPW(header->entrySelector);
       
   146     cmRangeShift = SWAPW(header->rangeShift) / 2;
       
   147     cmEndCodes = &header->endCodes[0];
       
   148     cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad...
       
   149     cmIdDelta = &cmStartCodes[cmSegCount];
       
   150     cmIdRangeOffset = &cmIdDelta[cmSegCount];
       
   151 }
       
   152 
       
   153 LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32)
       
   154 {
       
   155     if (unicode32 >= 0x10000) {
       
   156         return 0;
       
   157     }
       
   158 
       
   159     LEUnicode16 unicode = (LEUnicode16) unicode32;
       
   160     le_uint16 index = 0;
       
   161     le_uint16 probe = 1 << cmEntrySelector;
       
   162     LEGlyphID result = 0;
       
   163 
       
   164     if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) {
       
   165         index = cmRangeShift;
       
   166     }
       
   167 
       
   168     while (probe > (1 << 0)) {
       
   169         probe >>= 1;
       
   170 
       
   171         if (SWAPW(cmStartCodes[index + probe]) <= unicode) {
       
   172             index += probe;
       
   173         }
       
   174     }
       
   175 
       
   176     if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) {
       
   177         if (cmIdRangeOffset[index] == 0) {
       
   178             result = (LEGlyphID) unicode;
       
   179         } else {
       
   180             le_uint16 offset = unicode - SWAPW(cmStartCodes[index]);
       
   181             le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]);
       
   182             le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset);
       
   183 
       
   184             result = SWAPW(glyphIndexTable[offset]);
       
   185         }
       
   186 
       
   187         result += SWAPW(cmIdDelta[index]);
       
   188     } else {
       
   189         result = 0;
       
   190     }
       
   191 
       
   192     return result;
       
   193 }
       
   194 
       
   195 le_uint16 FontObject::getUnitsPerEM()
       
   196 {
       
   197     if (headTable == NULL) {
       
   198         LETag headTag = 0x68656164; // 'head'
       
   199         le_uint32 length;
       
   200 
       
   201         headTable = (HEADTable *) readTable(headTag, &length);
       
   202     }
       
   203 
       
   204     return SWAPW(headTable->unitsPerEm);
       
   205 }
       
   206 
       
   207 le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph)
       
   208 {
       
   209     if (hmtxTable == NULL) {
       
   210         LETag maxpTag = 0x6D617870; // 'maxp'
       
   211         LETag hheaTag = 0x68686561; // 'hhea'
       
   212         LETag hmtxTag = 0x686D7478; // 'hmtx'
       
   213         le_uint32 length;
       
   214         HHEATable *hheaTable;
       
   215         MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length);
       
   216 
       
   217         numGlyphs = SWAPW(maxpTable->numGlyphs);
       
   218         deleteTable(maxpTable);
       
   219 
       
   220         hheaTable = (HHEATable *) readTable(hheaTag, &length);
       
   221         numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
       
   222         deleteTable(hheaTable);
       
   223 
       
   224         hmtxTable = (HMTXTable *) readTable(hmtxTag, &length);
       
   225     }
       
   226 
       
   227     le_uint16 index = glyph;
       
   228 
       
   229     if (glyph >= numGlyphs) {
       
   230         return 0;
       
   231     }
       
   232 
       
   233     if (glyph >= numOfLongHorMetrics) {
       
   234         index = numOfLongHorMetrics - 1;
       
   235     }
       
   236 
       
   237     return SWAPW(hmtxTable->hMetrics[index].advanceWidth);
       
   238 }
       
   239 
       
   240