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