gfx/skia/trunk/src/core/SkFontStream.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial