LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/sfnt - SkOTUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 96 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  */
       7             : 
       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"
      16             : 
      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
      23             : 
      24             :     0x0,0x0, //SkOTTableGlyphDataInstructions::length
      25             : };
      26             : 
      27           0 : uint32_t SkOTUtils::CalcTableChecksum(SK_OT_ULONG *data, size_t length) {
      28           0 :     uint32_t sum = 0;
      29           0 :     SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG);
      30           0 :     for (; data < dataEnd; ++data) {
      31           0 :         sum += SkEndian_SwapBE32(*data);
      32             :     }
      33           0 :     return sum;
      34             : }
      35             : 
      36           0 : SkData* SkOTUtils::RenameFont(SkStreamAsset* fontData, const char* fontName, int fontNameLen) {
      37             : 
      38             :     // Get the sfnt header.
      39             :     SkSFNTHeader sfntHeader;
      40           0 :     if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) {
      41           0 :         return nullptr;
      42             :     }
      43             : 
      44             :     // Find the existing 'name' table.
      45             :     int tableIndex;
      46             :     SkSFNTHeader::TableDirectoryEntry tableEntry;
      47           0 :     int numTables = SkEndian_SwapBE16(sfntHeader.numTables);
      48           0 :     for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
      49           0 :         if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) {
      50           0 :             return nullptr;
      51             :         }
      52           0 :         if (SkOTTableName::TAG == tableEntry.tag) {
      53           0 :             break;
      54             :         }
      55             :     }
      56           0 :     if (tableIndex == numTables) {
      57           0 :         return nullptr;
      58             :     }
      59             : 
      60           0 :     if (!fontData->rewind()) {
      61           0 :         return nullptr;
      62             :     }
      63             : 
      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           0 :     };
      72           0 :     const int namesCount = SK_ARRAY_COUNT(namesToCreate);
      73             : 
      74             :     // Copy the data, leaving out the old name table.
      75             :     // In theory, we could also remove the DSIG table if it exists.
      76           0 :     size_t nameTableLogicalSize = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record)) + (fontNameLen * sizeof(wchar_t));
      77           0 :     size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4.
      78             : 
      79           0 :     size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) & ~3; // Rounded up to a multiple of 4.
      80           0 :     size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset);
      81             : 
      82             :     //originalDataSize is the size of the original data without the name table.
      83           0 :     size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize;
      84           0 :     size_t newDataSize = originalDataSize + nameTablePhysicalSize;
      85             : 
      86           0 :     auto rewrittenFontData = SkData::MakeUninitialized(newDataSize);
      87           0 :     SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(rewrittenFontData->writable_data());
      88             : 
      89           0 :     if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) {
      90           0 :         return nullptr;
      91             :     }
      92           0 :     if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) {
      93           0 :         return nullptr;
      94             :     }
      95           0 :     if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) {
      96           0 :         return nullptr;
      97             :     }
      98             : 
      99             :     //Fix up the offsets of the directory entries after the old 'name' table entry.
     100           0 :     SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader));
     101           0 :     SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables;
     102           0 :     SkSFNTHeader::TableDirectoryEntry* headTableEntry = nullptr;
     103           0 :     for (; currentEntry < endEntry; ++currentEntry) {
     104           0 :         uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
     105           0 :         if (oldOffset > oldNameTableOffset) {
     106           0 :             currentEntry->offset = SkEndian_SwapBE32(SkToU32(oldOffset - oldNameTablePhysicalSize));
     107             :         }
     108           0 :         if (SkOTTableHead::TAG == currentEntry->tag) {
     109           0 :             headTableEntry = currentEntry;
     110             :         }
     111             :     }
     112             : 
     113             :     // Make the table directory entry point to the new 'name' table.
     114           0 :     SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
     115           0 :     nameTableEntry->logicalLength = SkEndian_SwapBE32(SkToU32(nameTableLogicalSize));
     116           0 :     nameTableEntry->offset = SkEndian_SwapBE32(SkToU32(originalDataSize));
     117             : 
     118             :     // Write the new 'name' table after the original font data.
     119           0 :     SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
     120           0 :     unsigned short stringOffset = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record));
     121           0 :     nameTable->format = SkOTTableName::format_0;
     122           0 :     nameTable->count = SkEndian_SwapBE16(namesCount);
     123           0 :     nameTable->stringOffset = SkEndian_SwapBE16(stringOffset);
     124             : 
     125           0 :     SkOTTableName::Record* nameRecords = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName));
     126           0 :     for (int i = 0; i < namesCount; ++i) {
     127           0 :         nameRecords[i].platformID.value = SkOTTableName::Record::PlatformID::Windows;
     128           0 :         nameRecords[i].encodingID.windows.value = SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2;
     129           0 :         nameRecords[i].languageID.windows.value = SkOTTableName::Record::LanguageID::Windows::English_UnitedStates;
     130           0 :         nameRecords[i].nameID.predefined.value = namesToCreate[i];
     131           0 :         nameRecords[i].offset = SkEndian_SwapBE16(0);
     132           0 :         nameRecords[i].length = SkEndian_SwapBE16(SkToU16(fontNameLen * sizeof(wchar_t)));
     133             :     }
     134             : 
     135           0 :     SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset);
     136           0 :     for (int i = 0; i < fontNameLen; ++i) {
     137           0 :         nameString[i] = SkEndian_SwapBE16(fontName[i]);
     138             :     }
     139             : 
     140           0 :     unsigned char* logical = data + originalDataSize + nameTableLogicalSize;
     141           0 :     unsigned char* physical = data + originalDataSize + nameTablePhysicalSize;
     142           0 :     for (; logical < physical; ++logical) {
     143           0 :         *logical = 0;
     144             :     }
     145             : 
     146             :     // Update the table checksum in the directory entry.
     147           0 :     nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize));
     148             : 
     149             :     // Update the checksum adjustment in the head table.
     150           0 :     if (headTableEntry) {
     151           0 :         size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset);
     152           0 :         if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) {
     153           0 :             SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset);
     154           0 :             headTable->checksumAdjustment = SkEndian_SwapBE32(0);
     155           0 :             uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize);
     156           0 :             headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum);
     157             :         }
     158             :     }
     159             : 
     160           0 :     return rewrittenFontData.release();
     161             : }
     162             : 
     163             : 
     164             : SkOTUtils::LocalizedStrings_NameTable*
     165           0 : SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(const SkTypeface& typeface) {
     166             :     static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
     167           0 :     size_t nameTableSize = typeface.getTableSize(nameTag);
     168           0 :     if (0 == nameTableSize) {
     169           0 :         return nullptr;
     170             :     }
     171           0 :     std::unique_ptr<uint8_t[]> nameTableData(new uint8_t[nameTableSize]);
     172           0 :     size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get());
     173           0 :     if (copied != nameTableSize) {
     174           0 :         return nullptr;
     175             :     }
     176             : 
     177           0 :     return new SkOTUtils::LocalizedStrings_NameTable((SkOTTableName*)nameTableData.release(),
     178             :         SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
     179           0 :         SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
     180             : }
     181             : 
     182           0 : bool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) {
     183             :     do {
     184           0 :         SkOTTableName::Iterator::Record record;
     185           0 :         if (fFamilyNameIter.next(record)) {
     186           0 :             localizedString->fString = record.name;
     187           0 :             localizedString->fLanguage = record.language;
     188           0 :             return true;
     189             :         }
     190           0 :         if (fTypesCount == fTypesIndex + 1) {
     191           0 :             return false;
     192             :         }
     193           0 :         ++fTypesIndex;
     194           0 :         fFamilyNameIter.reset(fTypes[fTypesIndex]);
     195             :     } while (true);
     196             : }
     197             : 
     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             : };

Generated by: LCOV version 1.13