LCOV - code coverage report
Current view: top level - gfx/2d - SFNTData.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 100 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "SFNTData.h"
       8             : 
       9             : #include <algorithm>
      10             : 
      11             : #include "BigEndianInts.h"
      12             : #include "Logging.h"
      13             : #include "mozilla/HashFunctions.h"
      14             : #include "SFNTNameTable.h"
      15             : 
      16             : namespace mozilla {
      17             : namespace gfx {
      18             : 
      19             : #define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
      20             : 
      21             : #pragma pack(push, 1)
      22             : 
      23             : struct TTCHeader
      24             : {
      25             :   BigEndianUint32 ttcTag;    // Always 'ttcf'
      26             :   BigEndianUint32 version;   // Fixed, 0x00010000
      27             :   BigEndianUint32 numFonts;
      28             : };
      29             : 
      30             : struct OffsetTable
      31             : {
      32             :   BigEndianUint32 sfntVersion;   // Fixed, 0x00010000 for version 1.0.
      33             :   BigEndianUint16 numTables;
      34             :   BigEndianUint16 searchRange;   // (Maximum power of 2 <= numTables) x 16.
      35             :   BigEndianUint16 entrySelector; // Log2(maximum power of 2 <= numTables).
      36             :   BigEndianUint16 rangeShift;    // NumTables x 16-searchRange.
      37             : };
      38             : 
      39             : struct TableDirEntry
      40             : {
      41             :   BigEndianUint32 tag;      // 4 -byte identifier.
      42             :   BigEndianUint32 checkSum; // CheckSum for this table.
      43             :   BigEndianUint32 offset;   // Offset from beginning of TrueType font file.
      44             :   BigEndianUint32 length;   // Length of this table.
      45             : 
      46           0 :   friend bool operator<(const TableDirEntry& lhs, const uint32_t aTag)
      47             :   {
      48           0 :     return lhs.tag < aTag;
      49             :   }
      50             : };
      51             : 
      52             : #pragma pack(pop)
      53             : 
      54             : class SFNTData::Font
      55             : {
      56             : public:
      57           0 :   Font(const OffsetTable *aOffsetTable, const uint8_t *aFontData,
      58             :        uint32_t aDataLength)
      59           0 :     : mFontData(aFontData)
      60           0 :     , mFirstDirEntry(reinterpret_cast<const TableDirEntry*>(aOffsetTable + 1))
      61           0 :     , mEndOfDirEntries(mFirstDirEntry + aOffsetTable->numTables)
      62           0 :     , mDataLength(aDataLength)
      63             :   {
      64           0 :   }
      65             : 
      66           0 :   bool GetU16FullName(mozilla::u16string& aU16FullName)
      67             :   {
      68             :     const TableDirEntry* dirEntry =
      69           0 :       GetDirEntry(TRUETYPE_TAG('n', 'a', 'm', 'e'));
      70           0 :     if (!dirEntry) {
      71           0 :       gfxWarning() << "Name table entry not found.";
      72           0 :       return false;
      73             :     }
      74             : 
      75             :     UniquePtr<SFNTNameTable> nameTable =
      76           0 :       SFNTNameTable::Create((mFontData + dirEntry->offset), dirEntry->length);
      77           0 :     if (!nameTable) {
      78           0 :       return false;
      79             :     }
      80             : 
      81           0 :     return nameTable->GetU16FullName(aU16FullName);
      82             :   }
      83             : 
      84             : private:
      85             : 
      86             :   const TableDirEntry*
      87           0 :   GetDirEntry(const uint32_t aTag)
      88             :   {
      89             :     const TableDirEntry* foundDirEntry =
      90           0 :       std::lower_bound(mFirstDirEntry, mEndOfDirEntries, aTag);
      91             : 
      92           0 :     if (foundDirEntry == mEndOfDirEntries || foundDirEntry->tag != aTag) {
      93           0 :       gfxWarning() << "Font data does not contain tag.";
      94           0 :       return nullptr;
      95             :     }
      96             : 
      97           0 :     if (mDataLength < (foundDirEntry->offset + foundDirEntry->length)) {
      98           0 :       gfxWarning() << "Font data too short to contain table.";
      99           0 :       return nullptr;
     100             :     }
     101             : 
     102           0 :     return foundDirEntry;
     103             :   }
     104             : 
     105             :   const uint8_t *mFontData;
     106             :   const TableDirEntry *mFirstDirEntry;
     107             :   const TableDirEntry *mEndOfDirEntries;
     108             :   uint32_t mDataLength;
     109             : };
     110             : 
     111             : /* static */
     112             : UniquePtr<SFNTData>
     113           0 : SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength)
     114             : {
     115           0 :   MOZ_ASSERT(aFontData);
     116             : 
     117             :   // Check to see if this is a font collection.
     118           0 :   if (aDataLength < sizeof(TTCHeader)) {
     119           0 :     gfxWarning() << "Font data too short.";
     120           0 :     return nullptr;
     121             :   }
     122             : 
     123           0 :   const TTCHeader *ttcHeader = reinterpret_cast<const TTCHeader*>(aFontData);
     124           0 :   if (ttcHeader->ttcTag == TRUETYPE_TAG('t', 't', 'c', 'f')) {
     125           0 :     uint32_t numFonts = ttcHeader->numFonts;
     126           0 :     if (aDataLength < sizeof(TTCHeader) + (numFonts * sizeof(BigEndianUint32))) {
     127           0 :       gfxWarning() << "Font data too short to contain full TTC Header.";
     128           0 :       return nullptr;
     129             :     }
     130             : 
     131           0 :     UniquePtr<SFNTData> sfntData(new SFNTData);
     132             :     const BigEndianUint32* offset =
     133           0 :       reinterpret_cast<const BigEndianUint32*>(aFontData + sizeof(TTCHeader));
     134           0 :     const BigEndianUint32* endOfOffsets = offset + numFonts;
     135           0 :     while (offset != endOfOffsets) {
     136           0 :       if (!sfntData->AddFont(aFontData, aDataLength, *offset)) {
     137           0 :         return nullptr;
     138             :       }
     139           0 :       ++offset;
     140             :     }
     141             : 
     142           0 :     return Move(sfntData);
     143             :   }
     144             : 
     145           0 :   UniquePtr<SFNTData> sfntData(new SFNTData);
     146           0 :   if (!sfntData->AddFont(aFontData, aDataLength, 0)) {
     147           0 :     return nullptr;
     148             :   }
     149             : 
     150           0 :   return Move(sfntData);
     151             : }
     152             : 
     153             : /* static */
     154             : uint64_t
     155           0 : SFNTData::GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength,
     156             :                        uint32_t aVarDataSize, const void* aVarData)
     157             : {
     158             :   uint64_t hash;
     159           0 :   UniquePtr<SFNTData> sfntData = SFNTData::Create(aFontData, aDataLength);
     160           0 :   mozilla::u16string firstName;
     161           0 :   if (sfntData && sfntData->GetU16FullName(0, firstName)) {
     162           0 :     hash = HashString(firstName.c_str(), firstName.length());
     163             :   } else {
     164           0 :     gfxWarning() << "Failed to get name from font data hashing whole font.";
     165           0 :     hash = HashString(aFontData, aDataLength);
     166             :   }
     167             : 
     168           0 :   if (aVarDataSize) {
     169           0 :     hash = AddToHash(hash, HashBytes(aVarData, aVarDataSize));
     170             :   }
     171             : 
     172           0 :   return hash << 32 | aDataLength;;
     173             : }
     174             : 
     175           0 : SFNTData::~SFNTData()
     176             : {
     177           0 :   for (size_t i = 0; i < mFonts.length(); ++i) {
     178           0 :     delete mFonts[i];
     179             :   }
     180           0 : }
     181             : 
     182             : bool
     183           0 : SFNTData::GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName)
     184             : {
     185           0 :   if (aIndex >= mFonts.length()) {
     186           0 :     gfxWarning() << "aIndex to font data too high.";
     187           0 :     return false;
     188             :   }
     189             : 
     190           0 :   return mFonts[aIndex]->GetU16FullName(aU16FullName);
     191             : }
     192             : 
     193             : bool
     194           0 : SFNTData::GetU16FullNames(Vector<mozilla::u16string>& aU16FullNames)
     195             : {
     196           0 :   bool fontFound = false;
     197           0 :   for (size_t i = 0; i < mFonts.length(); ++i) {
     198           0 :     mozilla::u16string name;
     199           0 :     if (mFonts[i]->GetU16FullName(name)) {
     200           0 :       fontFound = true;
     201             :     }
     202           0 :     if (!aU16FullNames.append(Move(name))) {
     203           0 :       return false;
     204             :     }
     205             :   }
     206             : 
     207           0 :   return fontFound;
     208             : }
     209             : 
     210             : bool
     211           0 : SFNTData::GetIndexForU16Name(const mozilla::u16string& aU16FullName,
     212             :                              uint32_t* aIndex, size_t aTruncatedLen)
     213             : {
     214           0 :   for (size_t i = 0; i < mFonts.length(); ++i) {
     215           0 :     mozilla::u16string name;
     216           0 :     if (!mFonts[i]->GetU16FullName(name)) {
     217           0 :       continue;
     218             :     }
     219             : 
     220           0 :     if (aTruncatedLen) {
     221           0 :       MOZ_ASSERT(aU16FullName.length() <= aTruncatedLen);
     222           0 :       name = name.substr(0, aTruncatedLen);
     223             :     }
     224             : 
     225           0 :     if (name == aU16FullName) {
     226           0 :       *aIndex = i;
     227           0 :       return true;
     228             :     }
     229             :   }
     230             : 
     231           0 :   return false;
     232             : }
     233             : 
     234             : bool
     235           0 : SFNTData::AddFont(const uint8_t *aFontData, uint32_t aDataLength,
     236             :                   uint32_t aOffset)
     237             : {
     238           0 :   uint32_t remainingLength = aDataLength - aOffset;
     239           0 :   if (remainingLength < sizeof(OffsetTable)) {
     240           0 :     gfxWarning() << "Font data too short to contain OffsetTable " << aOffset;
     241           0 :     return false;
     242             :   }
     243             : 
     244             :   const OffsetTable *offsetTable =
     245           0 :     reinterpret_cast<const OffsetTable*>(aFontData + aOffset);
     246           0 :   if (remainingLength <
     247           0 :       sizeof(OffsetTable) + (offsetTable->numTables * sizeof(TableDirEntry))) {
     248           0 :     gfxWarning() << "Font data too short to contain tables.";
     249           0 :     return false;
     250             :   }
     251             : 
     252           0 :   return mFonts.append(new Font(offsetTable, aFontData, aDataLength));
     253             : }
     254             : 
     255             : } // gfx
     256             : } // mozilla

Generated by: LCOV version 1.13