os/textandloc/fontservices/textshaperplugin/test/letest/PortableFontInstance.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
 *******************************************************************************
sl@0
     3
 *
sl@0
     4
 *   Copyright (C) 1999-2003, International Business Machines
sl@0
     5
 *   Corporation and others.  All Rights Reserved.
sl@0
     6
 *
sl@0
     7
 *******************************************************************************
sl@0
     8
 *   file name:  PortableFontInstance.cpp
sl@0
     9
 *
sl@0
    10
 *   created on: 11/22/1999
sl@0
    11
 *   created by: Eric R. Mader
sl@0
    12
 */
sl@0
    13
sl@0
    14
#include <stdio.h>
sl@0
    15
sl@0
    16
#include "layout/LETypes.h"
sl@0
    17
#include "layout/LEFontInstance.h"
sl@0
    18
#include "layout/LESwaps.h"
sl@0
    19
sl@0
    20
#include "PortableFontInstance.h"
sl@0
    21
sl@0
    22
#include "sfnt.h"
sl@0
    23
sl@0
    24
#include <string.h>
sl@0
    25
sl@0
    26
//
sl@0
    27
// Finds the high bit by binary searching
sl@0
    28
// through the bits in n.
sl@0
    29
//
sl@0
    30
le_int8 PortableFontInstance::highBit(le_int32 value)
sl@0
    31
{
sl@0
    32
    if (value <= 0) {
sl@0
    33
        return -32;
sl@0
    34
    }
sl@0
    35
sl@0
    36
    le_uint8 bit = 0;
sl@0
    37
sl@0
    38
    if (value >= 1 << 16) {
sl@0
    39
        value >>= 16;
sl@0
    40
        bit += 16;
sl@0
    41
    }
sl@0
    42
sl@0
    43
    if (value >= 1 << 8) {
sl@0
    44
        value >>= 8;
sl@0
    45
        bit += 8;
sl@0
    46
    }
sl@0
    47
sl@0
    48
    if (value >= 1 << 4) {
sl@0
    49
        value >>= 4;
sl@0
    50
        bit += 4;
sl@0
    51
    }
sl@0
    52
sl@0
    53
    if (value >= 1 << 2) {
sl@0
    54
        value >>= 2;
sl@0
    55
        bit += 2;
sl@0
    56
    }
sl@0
    57
sl@0
    58
    if (value >= 1 << 1) {
sl@0
    59
        value >>= 1;
sl@0
    60
        bit += 1;
sl@0
    61
    }
sl@0
    62
sl@0
    63
    return bit;
sl@0
    64
}
sl@0
    65
sl@0
    66
sl@0
    67
PortableFontInstance::PortableFontInstance(char *fileName, float pointSize, LEErrorCode &status)
sl@0
    68
    : fFile(NULL), fUnitsPerEM(0), fPointSize(pointSize), fAscent(0), fDescent(0), fLeading(0),
sl@0
    69
      fDirectory(NULL), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
sl@0
    70
{
sl@0
    71
    if (LE_FAILURE(status)) {
sl@0
    72
        return;
sl@0
    73
    }
sl@0
    74
sl@0
    75
    // open the font file
sl@0
    76
    fFile = fopen(fileName, "rb");
sl@0
    77
sl@0
    78
    if (fFile == NULL) {
sl@0
    79
        status = LE_FONT_FILE_NOT_FOUND_ERROR;
sl@0
    80
        return;
sl@0
    81
    }
sl@0
    82
sl@0
    83
    // read in the directory
sl@0
    84
    SFNTDirectory tempDir;
sl@0
    85
sl@0
    86
    fread(&tempDir, sizeof tempDir, 1, fFile);
sl@0
    87
sl@0
    88
    le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry));
sl@0
    89
    const LETag headTag = LE_HEAD_TABLE_TAG;
sl@0
    90
    const LETag hheaTag = LE_HHEA_TABLE_TAG;
sl@0
    91
    const HEADTable *headTable = NULL;
sl@0
    92
    const HHEATable *hheaTable = NULL;
sl@0
    93
    le_uint16 numTables = 0;
sl@0
    94
sl@0
    95
    fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize);
sl@0
    96
sl@0
    97
    if (fDirectory == NULL) {
sl@0
    98
        status = LE_MEMORY_ALLOCATION_ERROR;
sl@0
    99
        goto error_exit;
sl@0
   100
    }
sl@0
   101
sl@0
   102
    fseek(fFile, 0L, SEEK_SET);
sl@0
   103
    fread((void *) fDirectory, sizeof(char), dirSize, fFile);
sl@0
   104
sl@0
   105
    //
sl@0
   106
    // We calculate these numbers 'cause some fonts
sl@0
   107
    // have bogus values for them in the directory header.
sl@0
   108
    //
sl@0
   109
    numTables = SWAPW(fDirectory->numTables);
sl@0
   110
    fDirPower = 1 << highBit(numTables);
sl@0
   111
    fDirExtra = numTables - fDirPower;
sl@0
   112
sl@0
   113
    // read unitsPerEm from 'head' table
sl@0
   114
    headTable = (const HEADTable *) readFontTable(headTag);
sl@0
   115
sl@0
   116
    if (headTable == NULL) {
sl@0
   117
        status = LE_MISSING_FONT_TABLE_ERROR;
sl@0
   118
        goto error_exit;
sl@0
   119
    }
sl@0
   120
sl@0
   121
    fUnitsPerEM = SWAPW(headTable->unitsPerEm);
sl@0
   122
    deleteTable(headTable);
sl@0
   123
sl@0
   124
    hheaTable = (HHEATable *) readFontTable(hheaTag);
sl@0
   125
sl@0
   126
    if (hheaTable == NULL) {
sl@0
   127
        status = LE_MISSING_FONT_TABLE_ERROR;
sl@0
   128
        goto error_exit;
sl@0
   129
    }
sl@0
   130
sl@0
   131
    fAscent  = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
sl@0
   132
    fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
sl@0
   133
    fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
sl@0
   134
sl@0
   135
    fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
sl@0
   136
sl@0
   137
    deleteTable((void *) hheaTable);
sl@0
   138
sl@0
   139
    fCMAPMapper = findUnicodeMapper();
sl@0
   140
sl@0
   141
    if (fCMAPMapper == NULL) {
sl@0
   142
        status = LE_MISSING_FONT_TABLE_ERROR;
sl@0
   143
        goto error_exit;
sl@0
   144
    }
sl@0
   145
sl@0
   146
    return;
sl@0
   147
sl@0
   148
error_exit:
sl@0
   149
    fclose(fFile);
sl@0
   150
    fFile = NULL;
sl@0
   151
    return;
sl@0
   152
}
sl@0
   153
sl@0
   154
PortableFontInstance::~PortableFontInstance()
sl@0
   155
{
sl@0
   156
    if (fFile != NULL) {
sl@0
   157
        fclose(fFile);
sl@0
   158
sl@0
   159
        deleteTable(fHMTXTable);
sl@0
   160
sl@0
   161
        delete fCMAPMapper;
sl@0
   162
sl@0
   163
        LE_DELETE_ARRAY(fDirectory);
sl@0
   164
    }
sl@0
   165
};
sl@0
   166
sl@0
   167
void PortableFontInstance::deleteTable(const void *table) const
sl@0
   168
{
sl@0
   169
    LE_DELETE_ARRAY(table);
sl@0
   170
}
sl@0
   171
sl@0
   172
const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
sl@0
   173
{
sl@0
   174
    if (fDirectory != NULL) {
sl@0
   175
        le_uint16 table = 0;
sl@0
   176
        le_uint16 probe = fDirPower;
sl@0
   177
sl@0
   178
        if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
sl@0
   179
            table = fDirExtra;
sl@0
   180
        }
sl@0
   181
sl@0
   182
        while (probe > (1 << 0)) {
sl@0
   183
            probe >>= 1;
sl@0
   184
sl@0
   185
            if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
sl@0
   186
                table += probe;
sl@0
   187
            }
sl@0
   188
        }
sl@0
   189
sl@0
   190
        if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
sl@0
   191
            return &fDirectory->tableDirectory[table];
sl@0
   192
        }
sl@0
   193
    }
sl@0
   194
sl@0
   195
    return NULL;
sl@0
   196
}
sl@0
   197
sl@0
   198
const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
sl@0
   199
{
sl@0
   200
    const DirectoryEntry *entry = findTable(tag);
sl@0
   201
sl@0
   202
    if (entry == NULL) {
sl@0
   203
        *length = 0;
sl@0
   204
        return NULL;
sl@0
   205
    }
sl@0
   206
sl@0
   207
    *length = SWAPL(entry->length);
sl@0
   208
sl@0
   209
    void *table = LE_NEW_ARRAY(char, *length);
sl@0
   210
sl@0
   211
    if (table != NULL) {
sl@0
   212
        fseek(fFile, SWAPL(entry->offset), SEEK_SET);
sl@0
   213
        fread(table, sizeof(char), *length, fFile);
sl@0
   214
    }
sl@0
   215
sl@0
   216
    return table;
sl@0
   217
}
sl@0
   218
sl@0
   219
const void *PortableFontInstance::getFontTable(LETag tableTag) const
sl@0
   220
{
sl@0
   221
    return FontTableCache::find(tableTag);
sl@0
   222
}
sl@0
   223
sl@0
   224
const void *PortableFontInstance::readFontTable(LETag tableTag) const
sl@0
   225
{
sl@0
   226
    le_uint32 len;
sl@0
   227
sl@0
   228
    return readTable(tableTag, &len);
sl@0
   229
}
sl@0
   230
sl@0
   231
CMAPMapper *PortableFontInstance::findUnicodeMapper()
sl@0
   232
{
sl@0
   233
    LETag cmapTag = LE_CMAP_TABLE_TAG;
sl@0
   234
    const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
sl@0
   235
sl@0
   236
    if (cmap == NULL) {
sl@0
   237
        return NULL;
sl@0
   238
    }
sl@0
   239
sl@0
   240
    return CMAPMapper::createUnicodeMapper(cmap);
sl@0
   241
}
sl@0
   242
sl@0
   243
sl@0
   244
void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
sl@0
   245
{
sl@0
   246
    TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
sl@0
   247
sl@0
   248
    if (fHMTXTable == NULL) {
sl@0
   249
        LETag maxpTag = LE_MAXP_TABLE_TAG;
sl@0
   250
        LETag hmtxTag = LE_HMTX_TABLE_TAG;
sl@0
   251
        const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
sl@0
   252
        PortableFontInstance *realThis = (PortableFontInstance *) this;
sl@0
   253
sl@0
   254
        if (maxpTable != NULL) {
sl@0
   255
            realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
sl@0
   256
            deleteTable(maxpTable);
sl@0
   257
        }
sl@0
   258
sl@0
   259
        realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
sl@0
   260
    }
sl@0
   261
sl@0
   262
    le_uint16 index = ttGlyph;
sl@0
   263
sl@0
   264
    if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
sl@0
   265
        advance.fX = advance.fY = 0;
sl@0
   266
        return;
sl@0
   267
    }
sl@0
   268
sl@0
   269
    if (ttGlyph >= fNumLongHorMetrics) {
sl@0
   270
        index = fNumLongHorMetrics - 1;
sl@0
   271
    }
sl@0
   272
sl@0
   273
    advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
sl@0
   274
    advance.fY = 0;
sl@0
   275
}
sl@0
   276
sl@0
   277
le_bool PortableFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
sl@0
   278
{
sl@0
   279
    return FALSE;
sl@0
   280
}
sl@0
   281