☠☠ backed out by 9bdfae920430 ☠ ☠ | |
author | Bob Owen <bobowencode@gmail.com> |
Mon, 21 Dec 2015 20:33:13 +0000 | |
changeset 277215 | 99a8859afcdbe7966b10954fbfc5665dbc78af30 |
parent 277214 | 4934e88b2d7a7274d9513c81c9ef3e03a29333f4 |
child 277216 | a40eea9145190230dbaad585924215d4b173fa60 |
push id | 29819 |
push user | cbook@mozilla.com |
push date | Tue, 22 Dec 2015 10:47:17 +0000 |
treeherder | mozilla-central@ad16863d1d45 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bas |
bugs | 1156742 |
milestone | 46.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/gfx/2d/BigEndianInts.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_BigEndianInts_h +#define mozilla_BigEndianInts_h + +#include "mozilla/Endian.h" + +namespace mozilla { + +#pragma pack(push, 1) + +struct BigEndianUint16 +{ +#ifdef __SUNPRO_CC + BigEndianUint16& operator=(const uint16_t aValue) + { + value = NativeEndian::swapToBigEndian(aValue); + return *this; + } +#else + MOZ_IMPLICIT BigEndianUint16(const uint16_t aValue) + { + value = NativeEndian::swapToBigEndian(aValue); + } +#endif + + operator uint16_t() const + { + return NativeEndian::swapFromBigEndian(value); + } + + friend inline bool + operator==(const BigEndianUint16& lhs, const BigEndianUint16& rhs) + { + return lhs.value == rhs.value; + } + + friend inline bool + operator!=(const BigEndianUint16& lhs, const BigEndianUint16& rhs) + { + return !(lhs == rhs); + } + +private: + uint16_t value; +}; + +struct BigEndianUint32 +{ +#ifdef __SUNPRO_CC + BigEndianUint32& operator=(const uint32_t aValue) + { + value = NativeEndian::swapToBigEndian(aValue); + return *this; + } +#else + MOZ_IMPLICIT BigEndianUint32(const uint32_t aValue) + { + value = NativeEndian::swapToBigEndian(aValue); + } +#endif + + operator uint32_t() const + { + return NativeEndian::swapFromBigEndian(value); + } + +private: + uint32_t value; +}; + +#pragma pack(pop) + +} // mozilla + +#endif // mozilla_BigEndianInts_h \ No newline at end of file
--- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -568,16 +568,37 @@ Factory::CreateScaledFontForTrueTypeData { switch (aType) { #ifdef WIN32 case FontType::DWRITE: { return MakeAndAddRef<ScaledFontDWrite>(aData, aSize, aFaceIndex, aGlyphSize); } #endif + case FontType::CAIRO: + { + RefPtr<ScaledFontBase> scaledFont; + +#ifdef WIN32 + if (DrawTargetD2D::GetDWriteFactory()) { + scaledFont = new ScaledFontDWrite(aData, aSize, aFaceIndex, aGlyphSize); + } else { + scaledFont = new ScaledFontWin(aData, aSize, aFaceIndex, aGlyphSize); + } + + if (!scaledFont->PopulateCairoScaledFont()) { + gfxWarning() << "Unable to create cairo scaled font from truetype data"; + return nullptr; + } +#else + gfxWarning() << "Unable to create cairo scaled font from truetype data"; +#endif + + return scaledFont.forget(); + } default: gfxWarning() << "Unable to create requested font type from truetype data"; return nullptr; } } already_AddRefed<ScaledFont> Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont)
new file mode 100644 --- /dev/null +++ b/gfx/2d/SFNTData.cpp @@ -0,0 +1,207 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SFNTData.h" + +#include <algorithm> + +#include "BigEndianInts.h" +#include "Logging.h" +#include "SFNTNameTable.h" + +namespace mozilla { +namespace gfx { + +#define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) + +#pragma pack(push, 1) + +struct TTCHeader +{ + BigEndianUint32 ttcTag; // Always 'ttcf' + BigEndianUint32 version; // Fixed, 0x00010000 + BigEndianUint32 numFonts; +}; + +struct OffsetTable +{ + BigEndianUint32 sfntVersion; // Fixed, 0x00010000 for version 1.0. + BigEndianUint16 numTables; + BigEndianUint16 searchRange; // (Maximum power of 2 <= numTables) x 16. + BigEndianUint16 entrySelector; // Log2(maximum power of 2 <= numTables). + BigEndianUint16 rangeShift; // NumTables x 16-searchRange. +}; + +struct TableDirEntry +{ + BigEndianUint32 tag; // 4 -byte identifier. + BigEndianUint32 checkSum; // CheckSum for this table. + BigEndianUint32 offset; // Offset from beginning of TrueType font file. + BigEndianUint32 length; // Length of this table. + + friend bool operator<(const TableDirEntry& lhs, const uint32_t aTag) + { + return lhs.tag < aTag; + } +}; + +#pragma pack(pop) + +class SFNTData::Font +{ +public: + Font(const OffsetTable *aOffsetTable, const uint8_t *aFontData, + uint32_t aDataLength) + : mFontData(aFontData) + , mFirstDirEntry(reinterpret_cast<const TableDirEntry*>(aOffsetTable + 1)) + , mEndOfDirEntries(mFirstDirEntry + aOffsetTable->numTables) + , mDataLength(aDataLength) + { + } + + bool GetU16FullName(mozilla::u16string& aU16FullName) + { + const TableDirEntry* dirEntry = + GetDirEntry(TRUETYPE_TAG('n', 'a', 'm', 'e')); + if (!dirEntry) { + gfxWarning() << "Name table entry not found."; + return false; + } + + UniquePtr<SFNTNameTable> nameTable = + SFNTNameTable::Create((mFontData + dirEntry->offset), dirEntry->length); + if (!nameTable) { + return false; + } + + return nameTable->GetU16FullName(aU16FullName); + } + +private: + + const TableDirEntry* + GetDirEntry(const uint32_t aTag) + { + const TableDirEntry* foundDirEntry = + std::lower_bound(mFirstDirEntry, mEndOfDirEntries, aTag); + + if (foundDirEntry == mEndOfDirEntries || foundDirEntry->tag != aTag) { + gfxWarning() << "Font data does not contain tag."; + return nullptr; + } + + if (mDataLength < (foundDirEntry->offset + foundDirEntry->length)) { + gfxWarning() << "Font data too short to contain table."; + return nullptr; + } + + return foundDirEntry; + } + + const uint8_t *mFontData; + const TableDirEntry *mFirstDirEntry; + const TableDirEntry *mEndOfDirEntries; + uint32_t mDataLength; +}; + +/* static */ +UniquePtr<SFNTData> +SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength) +{ + MOZ_ASSERT(aFontData); + + // Check to see if this is a font collection. + if (aDataLength < sizeof(TTCHeader)) { + gfxWarning() << "Font data too short."; + return false; + } + + const TTCHeader *ttcHeader = reinterpret_cast<const TTCHeader*>(aFontData); + if (ttcHeader->ttcTag == TRUETYPE_TAG('t', 't', 'c', 'f')) { + uint32_t numFonts = ttcHeader->numFonts; + if (aDataLength < sizeof(TTCHeader) + (numFonts * sizeof(BigEndianUint32))) { + gfxWarning() << "Font data too short to contain full TTC Header."; + return false; + } + + UniquePtr<SFNTData> sfntData(new SFNTData); + const BigEndianUint32* offset = + reinterpret_cast<const BigEndianUint32*>(aFontData + sizeof(TTCHeader)); + const BigEndianUint32* endOfOffsets = offset + numFonts; + while (offset != endOfOffsets) { + if (!sfntData->AddFont(aFontData, aDataLength, *offset)) { + return nullptr; + } + ++offset; + } + + return Move(sfntData); + } + + UniquePtr<SFNTData> sfntData(new SFNTData); + if (!sfntData->AddFont(aFontData, aDataLength, 0)) { + return nullptr; + } + + return Move(sfntData); +} + +SFNTData::~SFNTData() +{ + for (size_t i = 0; i < mFonts.length(); ++i) { + delete mFonts[i]; + } +} + +bool +SFNTData::GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName) +{ + if (aIndex >= mFonts.length()) { + gfxWarning() << "aIndex to font data too high."; + return false; + } + + return mFonts[aIndex]->GetU16FullName(aU16FullName); +} + +bool +SFNTData::GetIndexForU16Name(const mozilla::u16string& aU16FullName, + uint32_t* aIndex) +{ + for (size_t i = 0; i < mFonts.length(); ++i) { + mozilla::u16string name; + if (mFonts[i]->GetU16FullName(name) && name == aU16FullName) { + *aIndex = i; + return true; + } + } + + return false; +} + +bool +SFNTData::AddFont(const uint8_t *aFontData, uint32_t aDataLength, + uint32_t aOffset) +{ + uint32_t remainingLength = aDataLength - aOffset; + if (remainingLength < sizeof(OffsetTable)) { + gfxWarning() << "Font data too short to contain OffsetTable " << aOffset; + return false; + } + + const OffsetTable *offsetTable = + reinterpret_cast<const OffsetTable*>(aFontData + aOffset); + if (remainingLength < + sizeof(OffsetTable) + (offsetTable->numTables * sizeof(TableDirEntry))) { + gfxWarning() << "Font data too short to contain tables."; + return false; + } + + return mFonts.append(new Font(offsetTable, aFontData, aDataLength)); +} + +} // gfx +} // mozilla
new file mode 100644 --- /dev/null +++ b/gfx/2d/SFNTData.h @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_SFNTData_h +#define mozilla_gfx_SFNTData_h + +#include "mozilla/UniquePtr.h" +#include "mozilla/Vector.h" +#include "u16string.h" + +namespace mozilla { +namespace gfx { + +class SFNTData final +{ +public: + + /** + * Creates an SFNTData if the header is a format that we understand and + * aDataLength is sufficient for the length information in the header data. + * Note that the data is NOT copied, so must exist the SFNTData's lifetime. + * + * @param aFontData the SFNT data. + * @param aDataLength length + * @return UniquePtr to a SFNTData or nullptr if the header is invalid. + */ + static UniquePtr<SFNTData> Create(const uint8_t *aFontData, + uint32_t aDataLength); + + ~SFNTData(); + + /** + * Gets the full name from the name table of the font corresponding to the + * index. If the full name string is not present it will use the family space + * concatenated with the style. + * This will only read names that are already UTF16. + * + * @param aFontData SFNT data. + * @param aDataLength length of aFontData. + * @param aU16FullName string to be populated with the full name. + * @return true if the full name is successfully read. + */ + bool GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName); + + /** + * Returns the index for the first UTF16 name matching aU16FullName. + * + * @param aU16FullName full name to find. + * @param aIndex out param for the index if found. + * @return true if the full name is successfully read. + */ + bool GetIndexForU16Name(const mozilla::u16string& aU16FullName, uint32_t* aIndex); + +private: + + SFNTData() {} + + bool AddFont(const uint8_t *aFontData, uint32_t aDataLength, + uint32_t aOffset); + + // Internal representation of single font in font file. + class Font; + + Vector<Font*> mFonts; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_SFNTData_h
new file mode 100644 --- /dev/null +++ b/gfx/2d/SFNTNameTable.cpp @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SFNTNameTable.h" + +#include "BigEndianInts.h" +#include "Logging.h" +#include "mozilla/Move.h" + +namespace mozilla { +namespace gfx { + +static const BigEndianUint16 FORMAT_0 = 0; + +static const BigEndianUint16 NAME_ID_FAMILY = 1; +static const BigEndianUint16 NAME_ID_STYLE = 2; +static const BigEndianUint16 NAME_ID_FULL = 4; + +static const BigEndianUint16 PLATFORM_ID_UNICODE = 0; +static const BigEndianUint16 PLATFORM_ID_MAC = 1; +static const BigEndianUint16 PLATFORM_ID_MICROSOFT = 3; + +static const BigEndianUint16 ENCODING_ID_MICROSOFT_SYMBOL = 0; +static const BigEndianUint16 ENCODING_ID_MICROSOFT_UNICODEBMP = 1; +static const BigEndianUint16 ENCODING_ID_MICROSOFT_UNICODEFULL = 10; + +static const BigEndianUint16 LANG_ID_MAC_ENGLISH = 0; + +static const BigEndianUint16 LANG_ID_MICROSOFT_EN_US = 0x0409; + +#pragma pack(push, 1) + +// Name table has a header, followed by name records, followed by string data. +struct NameHeader +{ + BigEndianUint16 format; // Format selector (=0). + BigEndianUint16 count; // Number of name records. + BigEndianUint16 stringOffset; // Offset to string storage from start of table. +}; + +struct NameRecord +{ + BigEndianUint16 platformID; + BigEndianUint16 encodingID; // Platform-specific encoding ID + BigEndianUint16 languageID; + BigEndianUint16 nameID; + BigEndianUint16 length; // String length in bytes. + BigEndianUint16 offset; // String offset from start of storage in bytes. +}; + +#pragma pack(pop) + +/* static */ +UniquePtr<SFNTNameTable> +SFNTNameTable::Create(const uint8_t *aNameData, uint32_t aDataLength) +{ + MOZ_ASSERT(aNameData); + + if (aDataLength < sizeof(NameHeader)) { + gfxWarning() << "Name data too short to contain NameHeader."; + return nullptr; + } + + const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(aNameData); + if (nameHeader->format != FORMAT_0) { + gfxWarning() << "Only Name Table Format 0 is supported."; + return nullptr; + } + + uint16_t stringOffset = nameHeader->stringOffset; + + if (stringOffset != + sizeof(NameHeader) + (nameHeader->count * sizeof(NameRecord))) { + gfxWarning() << "Name table string offset is incorrect."; + return nullptr; + } + + if (aDataLength < stringOffset) { + gfxWarning() << "Name data too short to contain name records."; + return nullptr; + } + + return UniquePtr<SFNTNameTable>( + new SFNTNameTable(nameHeader, aNameData, aDataLength)); +} + +SFNTNameTable::SFNTNameTable(const NameHeader *aNameHeader, + const uint8_t *aNameData, uint32_t aDataLength) + : mFirstRecord(reinterpret_cast<const NameRecord*>(aNameData + + sizeof(NameHeader))) + , mEndOfRecords(mFirstRecord + aNameHeader->count) + , mStringData(aNameData + aNameHeader->stringOffset) + , mStringDataLength(aDataLength - aNameHeader->stringOffset) +{ + MOZ_ASSERT(reinterpret_cast<const uint8_t*>(aNameHeader) == aNameData); +} + +#if defined(XP_MACOSX) +static const BigEndianUint16 CANONICAL_LANG_ID = LANG_ID_MAC_ENGLISH; +static const BigEndianUint16 PLATFORM_ID = PLATFORM_ID_MAC; +#else +static const BigEndianUint16 CANONICAL_LANG_ID = LANG_ID_MICROSOFT_EN_US; +static const BigEndianUint16 PLATFORM_ID = PLATFORM_ID_MICROSOFT; +#endif + +static bool +IsUTF16Encoding(const NameRecord *aNameRecord) +{ + if (aNameRecord->platformID == PLATFORM_ID_MICROSOFT && + (aNameRecord->encodingID == ENCODING_ID_MICROSOFT_UNICODEBMP || + aNameRecord->encodingID == ENCODING_ID_MICROSOFT_SYMBOL)) { + return true; + } + + if (aNameRecord->platformID == PLATFORM_ID_UNICODE) { + return true; + } + + return false; +} + +static NameRecordMatchers* +CreateCanonicalU16Matchers(const BigEndianUint16& aNameID) +{ + NameRecordMatchers *matchers = new NameRecordMatchers(); + + // First, look for the English name (this will normally succeed). + matchers->append( + [=](const NameRecord *aNameRecord) { + return aNameRecord->nameID == aNameID && + aNameRecord->languageID == CANONICAL_LANG_ID && + aNameRecord->platformID == PLATFORM_ID && + IsUTF16Encoding(aNameRecord); + }); + + // Second, look for all languages. + matchers->append( + [=](const NameRecord *aNameRecord) { + return aNameRecord->nameID == aNameID && + aNameRecord->platformID == PLATFORM_ID && + IsUTF16Encoding(aNameRecord); + }); + +#if defined(XP_MACOSX) + // On Mac may be dealing with font that only has Microsoft name entries. + matchers->append( + [=](const NameRecord *aNameRecord) { + return aNameRecord->nameID == aNameID && + aNameRecord->languageID == LANG_ID_MICROSOFT_EN_US && + aNameRecord->platformID == PLATFORM_ID_MICROSOFT && + IsUTF16Encoding(aNameRecord); + }); + matchers->append( + [=](const NameRecord *aNameRecord) { + return aNameRecord->nameID == aNameID && + aNameRecord->platformID == PLATFORM_ID_MICROSOFT && + IsUTF16Encoding(aNameRecord); + }); +#endif + + return matchers; +} + +static const NameRecordMatchers& +FullNameMatchers() +{ + static const NameRecordMatchers *sFullNameMatchers = + CreateCanonicalU16Matchers(NAME_ID_FULL); + return *sFullNameMatchers; +} + +static const NameRecordMatchers& +FamilyMatchers() +{ + static const NameRecordMatchers *sFamilyMatchers = + CreateCanonicalU16Matchers(NAME_ID_FAMILY); + return *sFamilyMatchers; +} + +static const NameRecordMatchers& +StyleMatchers() +{ + static const NameRecordMatchers *sStyleMatchers = + CreateCanonicalU16Matchers(NAME_ID_STYLE); + return *sStyleMatchers; +} + +bool +SFNTNameTable::GetU16FullName(mozilla::u16string& aU16FullName) +{ + if (ReadU16Name(FullNameMatchers(), aU16FullName)) { + return true; + } + + // If the full name record doesn't exist create the name from the family space + // concatenated with the style. + mozilla::u16string familyName; + if (!ReadU16Name(FamilyMatchers(), familyName)) { + return false; + } + + mozilla::u16string styleName; + if (!ReadU16Name(StyleMatchers(), styleName)) { + return false; + } + + aU16FullName.assign(Move(familyName)); + aU16FullName.append(MOZ_UTF16(" ")); + aU16FullName.append(styleName); + return true; +} + +bool +SFNTNameTable::ReadU16Name(const NameRecordMatchers& aMatchers, + mozilla::u16string& aU16Name) +{ + MOZ_ASSERT(!aMatchers.empty()); + + for (size_t i = 0; i < aMatchers.length(); ++i) { + const NameRecord* record = mFirstRecord; + while (record != mEndOfRecords) { + if (aMatchers[i](record)) { + return ReadU16NameFromRecord(record, aU16Name); + } + ++record; + } + } + + return false; +} + +bool +SFNTNameTable::ReadU16NameFromRecord(const NameRecord *aNameRecord, + mozilla::u16string& aU16Name) +{ + uint32_t offset = aNameRecord->offset; + uint32_t length = aNameRecord->length; + if (mStringDataLength < offset + length) { + gfxWarning() << "Name data too short to contain name string."; + return false; + } + + const uint8_t *startOfName = mStringData + offset; + size_t actualLength = length / sizeof(char16_t); + UniquePtr<char16_t[]> nameData(new char16_t[actualLength]); + NativeEndian::copyAndSwapFromBigEndian(nameData.get(), startOfName, + actualLength); + + aU16Name.assign(nameData.get(), actualLength); + return true; +} + +} // gfx +} // mozilla
new file mode 100644 --- /dev/null +++ b/gfx/2d/SFNTNameTable.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_SFNTNameTable_h +#define mozilla_gfx_SFNTNameTable_h + +#include "mozilla/Function.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/Vector.h" +#include "u16string.h" + +namespace mozilla { +namespace gfx { + +struct NameHeader; +struct NameRecord; + +typedef Vector<Function<bool(const NameRecord*)>> NameRecordMatchers; + +class SFNTNameTable final +{ +public: + + /** + * Creates a SFNTNameTable if the header data is valid. Note that the data is + * NOT copied, so must exist for the lifetime of the table. + * + * @param aNameData the Name Table data. + * @param aDataLength length + * @return UniquePtr to a SFNTNameTable or nullptr if the header is invalid. + */ + static UniquePtr<SFNTNameTable> Create(const uint8_t *aNameData, + uint32_t aDataLength); + + /** + * Gets the full name from the name table. If the full name string is not + * present it will use the family space concatenated with the style. + * This will only read names that are already UTF16. + * + * @param aU16FullName string to be populated with the full name. + * @return true if the full name is successfully read. + */ + bool GetU16FullName(mozilla::u16string& aU16FullName); + +private: + + SFNTNameTable(const NameHeader *aNameHeader, const uint8_t *aNameData, + uint32_t aDataLength); + + bool ReadU16Name(const NameRecordMatchers& aMatchers, mozilla::u16string& aU16Name); + + bool ReadU16NameFromRecord(const NameRecord *aNameRecord, + mozilla::u16string& aU16Name); + + const NameRecord *mFirstRecord; + const NameRecord *mEndOfRecords; + const uint8_t *mStringData; + const uint32_t mStringDataLength; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_SFNTNameTable_h
--- a/gfx/2d/ScaledFontBase.cpp +++ b/gfx/2d/ScaledFontBase.cpp @@ -40,16 +40,43 @@ ScaledFontBase::ScaledFontBase(Float aSi #ifdef USE_SKIA mTypeface = nullptr; #endif #ifdef USE_CAIRO_SCALED_FONT mScaledFont = nullptr; #endif } +#ifdef USE_CAIRO_SCALED_FONT +bool +ScaledFontBase::PopulateCairoScaledFont() +{ + cairo_font_face_t* cairoFontFace = GetCairoFontFace(); + if (!cairoFontFace) { + return false; + } + + cairo_matrix_t sizeMatrix; + cairo_matrix_t identityMatrix; + + cairo_matrix_init_scale(&sizeMatrix, mSize, mSize); + cairo_matrix_init_identity(&identityMatrix); + + cairo_font_options_t *fontOptions = cairo_font_options_create(); + + mScaledFont = cairo_scaled_font_create(cairoFontFace, &sizeMatrix, + &identityMatrix, fontOptions); + + cairo_font_options_destroy(fontOptions); + cairo_font_face_destroy(cairoFontFace); + + return (cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS); +} +#endif + #ifdef USE_SKIA SkPath ScaledFontBase::GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer) { SkTypeface *typeFace = GetSkTypeface(); MOZ_ASSERT(typeFace); SkPaint paint;
--- a/gfx/2d/ScaledFontBase.h +++ b/gfx/2d/ScaledFontBase.h @@ -40,27 +40,30 @@ public: #ifdef USE_SKIA virtual SkTypeface* GetSkTypeface() { return mTypeface; } #endif // Not true, but required to instantiate a ScaledFontBase. virtual FontType GetType() const { return FontType::SKIA; } #ifdef USE_CAIRO_SCALED_FONT + bool PopulateCairoScaledFont(); cairo_scaled_font_t* GetCairoScaledFont() { return mScaledFont; } void SetCairoScaledFont(cairo_scaled_font_t* font); #endif protected: friend class DrawTargetSkia; #ifdef USE_SKIA SkTypeface* mTypeface; SkPath GetSkiaPathForGlyphs(const GlyphBuffer &aBuffer); #endif #ifdef USE_CAIRO_SCALED_FONT + // Overridders should ensure the cairo_font_face_t has been addrefed. + virtual cairo_font_face_t* GetCairoFontFace() { return nullptr; } cairo_scaled_font_t* mScaledFont; #endif Float mSize; }; } // namespace gfx } // namespace mozilla
--- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -5,16 +5,20 @@ #include "ScaledFontDWrite.h" #include "PathD2D.h" #include "DrawTargetD2D.h" #include "Logging.h" #include <vector> +#ifdef USE_CAIRO_SCALED_FONT +#include "cairo-win32.h" +#endif + namespace mozilla { namespace gfx { struct ffReferenceKey { uint8_t *mData; uint32_t mSize; }; @@ -426,10 +430,22 @@ ScaledFontDWrite::GetDefaultAAMode() if (defaultMode == AntialiasMode::GRAY) { if (!DoGrayscale(mFontFace, mSize)) { defaultMode = AntialiasMode::NONE; } } return defaultMode; } +#ifdef USE_CAIRO_SCALED_FONT +cairo_font_face_t* +ScaledFontDWrite::GetCairoFontFace() +{ + if (!mFontFace) { + return nullptr; + } + + return cairo_dwrite_font_face_create_for_dwrite_fontface(nullptr, mFontFace); +} +#endif + } }
--- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -39,16 +39,21 @@ public: virtual SkTypeface* GetSkTypeface() { MOZ_ASSERT(false, "Skia and DirectWrite do not mix"); return nullptr; } #endif RefPtr<IDWriteFontFace> mFontFace; + +protected: +#ifdef USE_CAIRO_SCALED_FONT + cairo_font_face_t* GetCairoFontFace() override; +#endif }; class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite) GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams) : mParams(aParams)
--- a/gfx/2d/ScaledFontWin.cpp +++ b/gfx/2d/ScaledFontWin.cpp @@ -1,34 +1,102 @@ /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScaledFontWin.h" #include "ScaledFontBase.h" +#include "Logging.h" +#include "SFNTData.h" + #ifdef USE_SKIA #include "skia/include/ports/SkTypeface_win.h" #endif +#ifdef USE_CAIRO_SCALED_FONT +#include "cairo-win32.h" +#endif + namespace mozilla { namespace gfx { ScaledFontWin::ScaledFontWin(LOGFONT* aFont, Float aSize) : ScaledFontBase(aSize) , mLogFont(*aFont) { } +ScaledFontWin::ScaledFontWin(uint8_t* aFontData, uint32_t aFontDataLength, + uint32_t aIndex, Float aGlyphSize) + : ScaledFontBase(aGlyphSize) +{ + mLogFont.lfHeight = 0; + mLogFont.lfWidth = 0; + mLogFont.lfEscapement = 0; + mLogFont.lfOrientation = 0; + mLogFont.lfWeight = FW_DONTCARE; + mLogFont.lfItalic = FALSE; + mLogFont.lfUnderline = FALSE; + mLogFont.lfStrikeOut = FALSE; + mLogFont.lfCharSet = DEFAULT_CHARSET; + mLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS; + mLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + mLogFont.lfQuality = DEFAULT_QUALITY; + mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + mLogFont.lfFaceName[0] = 0; + + UniquePtr<SFNTData> sfntData = SFNTData::Create(aFontData, aFontDataLength); + if (!sfntData) { + gfxWarning() << "Failed to create SFNTData for ScaledFontWin."; + return; + } + + mozilla::u16string fontName; + if (!sfntData->GetU16FullName(aIndex, fontName)) { + gfxWarning() << "Failed to get font name from font."; + return; + } + + // Copy name to mLogFont and add null to end. + // lfFaceName has a maximum length including null. + if (fontName.size() > LF_FACESIZE - 1) { + fontName.resize(LF_FACESIZE - 1); + } + // We cast here because for VS2015 char16_t != wchar_t, even though they are + // both 16 bit. + fontName.copy(reinterpret_cast<char16_t*>(mLogFont.lfFaceName), + fontName.length()); + mLogFont.lfFaceName[fontName.length()] = 0; + + DWORD numberOfFontsAdded; + HANDLE fontHandle = ::AddFontMemResourceEx(aFontData, aFontDataLength, 0, + &numberOfFontsAdded); + if (fontHandle) { + mMemoryFontRemover.reset(new MemoryFontRemover(fontHandle)); + } + +} + #ifdef USE_SKIA SkTypeface* ScaledFontWin::GetSkTypeface() { if (!mTypeface) { mTypeface = SkCreateTypefaceFromLOGFONT(mLogFont); } return mTypeface; } #endif +#ifdef USE_CAIRO_SCALED_FONT +cairo_font_face_t* +ScaledFontWin::GetCairoFontFace() +{ + if (mLogFont.lfFaceName[0] == 0) { + return nullptr; + } + return cairo_win32_font_face_create_for_logfontw(&mLogFont); +} +#endif } }
--- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -4,32 +4,52 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_GFX_SCALEDFONTWIN_H_ #define MOZILLA_GFX_SCALEDFONTWIN_H_ #include "ScaledFontBase.h" #include <windows.h> +#include "mozilla/UniquePtr.h" + namespace mozilla { namespace gfx { class ScaledFontWin : public ScaledFontBase { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) ScaledFontWin(LOGFONT* aFont, Float aSize); + ScaledFontWin(uint8_t* aFontData, uint32_t aFontDataLength, uint32_t aIndex, + Float aGlyphSize); + virtual FontType GetType() const { return FontType::GDI; } #ifdef USE_SKIA virtual SkTypeface* GetSkTypeface(); #endif + +protected: +#ifdef USE_CAIRO_SCALED_FONT + cairo_font_face_t* GetCairoFontFace() override; +#endif + private: #ifdef USE_SKIA friend class DrawTargetSkia; #endif LOGFONT mLogFont; + + struct MemoryFontRemover + { + HANDLE memFontHandle; + MemoryFontRemover(HANDLE aMemFontHandle) : memFontHandle(aMemFontHandle) {} + ~MemoryFontRemover() { ::RemoveFontMemResourceEx(memFontHandle); } + }; + + UniquePtr<MemoryFontRemover> mMemoryFontRemover; }; } } #endif /* MOZILLA_GFX_SCALEDFONTWIN_H_ */
--- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -148,16 +148,18 @@ UNIFIED_SOURCES += [ 'PathCairo.cpp', 'PathHelpers.cpp', 'PathRecording.cpp', 'Quaternion.cpp', 'RecordedEvent.cpp', 'Scale.cpp', 'ScaledFontBase.cpp', 'ScaledFontCairo.cpp', + 'SFNTData.cpp', + 'SFNTNameTable.cpp', 'SourceSurfaceCairo.cpp', 'SourceSurfaceRawData.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': EXPORTS.mozilla.gfx += [ 'QuartzSupport.h', ]
new file mode 100644 --- /dev/null +++ b/gfx/2d/u16string.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_u16string_h +#define mozilla_gfx_u16string_h + +#include <string> + +#include "mozilla/Char16.h" + +namespace mozilla { + +#if defined(_MSC_VER) +typedef std::u16string u16string; +#else +typedef std::basic_string<char16_t> u16string; +#endif + +} // mozilla + +#endif // mozilla_gfx_u16string_h