gfx/skia/trunk/src/sfnt/SkOTUtils.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.

     1 /*
     2  * Copyright 2012 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkData.h"
     9 #include "SkEndian.h"
    10 #include "SkSFNTHeader.h"
    11 #include "SkStream.h"
    12 #include "SkOTTable_head.h"
    13 #include "SkOTTable_name.h"
    14 #include "SkOTTableTypes.h"
    15 #include "SkOTUtils.h"
    17 extern const uint8_t SK_OT_GlyphData_NoOutline[] = {
    18     0x0,0x0, //SkOTTableGlyphData::numberOfContours
    19     0x0,0x0, //SkOTTableGlyphData::xMin
    20     0x0,0x0, //SkOTTableGlyphData::yMin
    21     0x0,0x0, //SkOTTableGlyphData::xMax
    22     0x0,0x0, //SkOTTableGlyphData::yMax
    24     0x0,0x0, //SkOTTableGlyphDataInstructions::length
    25 };
    27 uint32_t SkOTUtils::CalcTableChecksum(SK_OT_ULONG *data, size_t length) {
    28     uint32_t sum = 0;
    29     SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG);
    30     for (; data < dataEnd; ++data) {
    31         sum += SkEndian_SwapBE32(*data);
    32     }
    33     return sum;
    34 }
    36 SkData* SkOTUtils::RenameFont(SkStream* fontData, const char* fontName, int fontNameLen) {
    38     // Get the sfnt header.
    39     SkSFNTHeader sfntHeader;
    40     if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) {
    41         return NULL;
    42     }
    44     // Find the existing 'name' table.
    45     int tableIndex;
    46     SkSFNTHeader::TableDirectoryEntry tableEntry;
    47     int numTables = SkEndian_SwapBE16(sfntHeader.numTables);
    48     for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
    49         if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) {
    50             return NULL;
    51         }
    52         if (SkOTTableName::TAG == tableEntry.tag) {
    53             break;
    54         }
    55     }
    56     if (tableIndex == numTables) {
    57         return NULL;
    58     }
    60     if (!fontData->rewind()) {
    61         return NULL;
    62     }
    64     // The required 'name' record types: Family, Style, Unique, Full and PostScript.
    65     const SkOTTableName::Record::NameID::Predefined::Value namesToCreate[] = {
    66         SkOTTableName::Record::NameID::Predefined::FontFamilyName,
    67         SkOTTableName::Record::NameID::Predefined::FontSubfamilyName,
    68         SkOTTableName::Record::NameID::Predefined::UniqueFontIdentifier,
    69         SkOTTableName::Record::NameID::Predefined::FullFontName,
    70         SkOTTableName::Record::NameID::Predefined::PostscriptName,
    71     };
    72     const int namesCount = SK_ARRAY_COUNT(namesToCreate);
    74     // Copy the data, leaving out the old name table.
    75     // In theory, we could also remove the DSIG table if it exists.
    76     size_t nameTableLogicalSize = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record)) + (fontNameLen * sizeof(wchar_t));
    77     size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4.
    79     size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) & ~3; // Rounded up to a multiple of 4.
    80     size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset);
    82     //originalDataSize is the size of the original data without the name table.
    83     size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize;
    84     size_t newDataSize = originalDataSize + nameTablePhysicalSize;
    86     SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(sk_malloc_throw(newDataSize));
    87     SkAutoTUnref<SkData> rewrittenFontData(SkData::NewFromMalloc(data, newDataSize));
    89     if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) {
    90         return NULL;
    91     }
    92     if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) {
    93         return NULL;
    94     }
    95     if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) {
    96         return NULL;
    97     }
    99     //Fix up the offsets of the directory entries after the old 'name' table entry.
   100     SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader));
   101     SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables;
   102     SkSFNTHeader::TableDirectoryEntry* headTableEntry = NULL;
   103     for (; currentEntry < endEntry; ++currentEntry) {
   104         uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
   105         if (oldOffset > oldNameTableOffset) {
   106             currentEntry->offset = SkEndian_SwapBE32(oldOffset - oldNameTablePhysicalSize);
   107         }
   108         if (SkOTTableHead::TAG == currentEntry->tag) {
   109             headTableEntry = currentEntry;
   110         }
   111     }
   113     // Make the table directory entry point to the new 'name' table.
   114     SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
   115     nameTableEntry->logicalLength = SkEndian_SwapBE32(nameTableLogicalSize);
   116     nameTableEntry->offset = SkEndian_SwapBE32(originalDataSize);
   118     // Write the new 'name' table after the original font data.
   119     SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
   120     unsigned short stringOffset = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record));
   121     nameTable->format = SkOTTableName::format_0;
   122     nameTable->count = SkEndian_SwapBE16(namesCount);
   123     nameTable->stringOffset = SkEndian_SwapBE16(stringOffset);
   125     SkOTTableName::Record* nameRecords = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName));
   126     for (int i = 0; i < namesCount; ++i) {
   127         nameRecords[i].platformID.value = SkOTTableName::Record::PlatformID::Windows;
   128         nameRecords[i].encodingID.windows.value = SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2;
   129         nameRecords[i].languageID.windows.value = SkOTTableName::Record::LanguageID::Windows::English_UnitedStates;
   130         nameRecords[i].nameID.predefined.value = namesToCreate[i];
   131         nameRecords[i].offset = SkEndian_SwapBE16(0);
   132         nameRecords[i].length = SkEndian_SwapBE16(fontNameLen * sizeof(wchar_t));
   133     }
   135     SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset);
   136     for (int i = 0; i < fontNameLen; ++i) {
   137         nameString[i] = SkEndian_SwapBE16(fontName[i]);
   138     }
   140     unsigned char* logical = data + originalDataSize + nameTableLogicalSize;
   141     unsigned char* physical = data + originalDataSize + nameTablePhysicalSize;
   142     for (; logical < physical; ++logical) {
   143         *logical = 0;
   144     }
   146     // Update the table checksum in the directory entry.
   147     nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize));
   149     // Update the checksum adjustment in the head table.
   150     if (headTableEntry) {
   151         size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset);
   152         if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) {
   153             SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset);
   154             headTable->checksumAdjustment = SkEndian_SwapBE32(0);
   155             uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize);
   156             headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum);
   157         }
   158     }
   160     return rewrittenFontData.detach();
   161 }
   164 SkOTUtils::LocalizedStrings_NameTable*
   165 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(const SkTypeface& typeface) {
   166     static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
   167     size_t nameTableSize = typeface.getTableSize(nameTag);
   168     if (0 == nameTableSize) {
   169         return NULL;
   170     }
   171     SkAutoTDeleteArray<uint8_t> nameTableData(new uint8_t[nameTableSize]);
   172     size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get());
   173     if (copied != nameTableSize) {
   174         return NULL;
   175     }
   177     return new SkOTUtils::LocalizedStrings_NameTable((SkOTTableName*)nameTableData.detach(),
   178         SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
   179         SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
   180 }
   182 bool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) {
   183     do {
   184         SkOTTableName::Iterator::Record record;
   185         if (fFamilyNameIter.next(record)) {
   186             localizedString->fString = record.name;
   187             localizedString->fLanguage = record.language;
   188             return true;
   189         }
   190         if (fTypesCount == fTypesIndex + 1) {
   191             return false;
   192         }
   193         ++fTypesIndex;
   194         fFamilyNameIter.reset(fTypes[fTypesIndex]);
   195     } while (true);
   196 }
   198 SkOTTableName::Record::NameID::Predefined::Value
   199 SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
   200     SkOTTableName::Record::NameID::Predefined::FontFamilyName,
   201     SkOTTableName::Record::NameID::Predefined::PreferredFamily,
   202     SkOTTableName::Record::NameID::Predefined::WWSFamilyName,
   203 };

mercurial