1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*
3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2011 Google Inc.
4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *
5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file.
7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkEndian.h"
9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkFontHost.h"
10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkStream.h"
11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct SkSFNTHeader {
13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fVersion;
14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint16_t    fNumTables;
15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint16_t    fSearchRange;
16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint16_t    fEntrySelector;
17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint16_t    fRangeShift;
18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct SkTTCFHeader {
21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fTag;
22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fVersion;
23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fNumOffsets;
24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fOffset0;   // the first of N (fNumOffsets)
25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerunion SkSharedTTHeader {
28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkSFNTHeader    fSingle;
29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkTTCFHeader    fCollection;
30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct SkSFNTDirEntry {
33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fTag;
34f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fChecksum;
35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fOffset;
36f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t    fLength;
37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/** Return the number of tables, or if this is a TTC (collection), return the
40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    number of tables in the first element of the collection. In either case,
41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if offsetToDir is not-null, set it to the offset to the beginning of the
42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    table headers (SkSFNTDirEntry), relative to the start of the stream.
43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    On an error, return 0 for number of tables, and ignore offsetToDir
45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic int count_tables(SkStream* stream, size_t* offsetToDir = NULL) {
47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkSharedTTHeader shared;
48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // by default, SkSFNTHeader is at the start of the stream
53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    size_t offset = 0;
54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
55f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // if we're really a collection, the first 4-bytes will be 'ttcf'
56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
57f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (shared.fCollection.fNumOffsets == 0) {
59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return 0;
60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // this is the offset to the first local SkSFNTHeader
62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        offset = SkEndian_SwapBE32(shared.fCollection.fOffset0);
63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        stream->rewind();
64f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (stream->skip(offset) != offset) {
65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return 0;
66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return 0;
69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (offsetToDir) {
73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // add the size of the header, so we will point to the DirEntries
74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *offsetToDir = offset + sizeof(SkSFNTHeader);
75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
76f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkEndian_SwapBE16(shared.fSingle.fNumTables);
77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
78f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct SfntHeader {
82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SfntHeader() : fCount(0), fDir(NULL) {}
83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    ~SfntHeader() { sk_free(fDir); }
84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    /** If it returns true, then fCount and fDir are properly initialized.
86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        Note: fDir will point to the raw array of SkSFNTDirEntry values,
87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        meaning they will still be in the file's native endianness (BE).
88f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fDir will be automatically freed when this object is destroyed
90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger     */
91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    bool init(SkStream* stream) {
92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        size_t offsetToDir;
93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCount = count_tables(stream, &offsetToDir);
94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (0 == fCount) {
95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return false;
96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
98f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        stream->rewind();
99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (stream->skip(offsetToDir) != offsetToDir) {
100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return false;
101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        size_t size = fCount * sizeof(SkSFNTDirEntry);
104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return stream->read(fDir, size) == size;
106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int             fCount;
109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkSFNTDirEntry* fDir;
110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerint SkFontHost::CountTables(SkFontID fontID) {
115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkStream* stream = SkFontHost::OpenStream(fontID);
116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == stream) {
117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkAutoUnref au(stream);
121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return count_tables(stream);
122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerint SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkStream* stream = SkFontHost::OpenStream(fontID);
126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == stream) {
127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkAutoUnref au(stream);
131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SfntHeader  header;
132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!header.init(stream)) {
133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < header.fCount; i++) {
137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return header.fCount;
140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergersize_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkStream* stream = SkFontHost::OpenStream(fontID);
144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == stream) {
145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkAutoUnref au(stream);
149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SfntHeader  header;
150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!header.init(stream)) {
151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < header.fCount; i++) {
155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkEndian_SwapBE32(header.fDir[i].fLength);
157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return 0;
160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergersize_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                                size_t offset, size_t length, void* data) {
164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkStream* stream = SkFontHost::OpenStream(fontID);
165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == stream) {
166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkAutoUnref au(stream);
170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SfntHeader  header;
171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (!header.init(stream)) {
172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < header.fCount; i++) {
176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // now sanity check the caller's offset/length
180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (offset >= realLength) {
181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                return 0;
182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // if the caller is trusting the length from the file, then a
184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // hostile file might choose a value which would overflow offset +
185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // length.
186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (offset + length < offset) {
187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                return 0;
188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (offset + length > realLength) {
190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                length = realLength - offset;
191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            // skip the stream to the part of the table we want to copy from
193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            stream->rewind();
194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            size_t bytesToSkip = realOffset + offset;
195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (stream->skip(bytesToSkip) != bytesToSkip) {
196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                return 0;
197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (stream->read(data, length) != length) {
199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                return 0;
200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return length;
202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return 0;
205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
207