зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1156742 Part 3: Add support for FontType::CAIRO to CreateScaledFontForTrueTypeData on Windows. r=bas
Parts of this change and related code get moved around in Part 24.
This commit is contained in:
Родитель
7b7cad771e
Коммит
9536340a3a
|
@ -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
|
|
@ -573,6 +573,27 @@ Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize,
|
|||
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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -45,6 +45,33 @@ ScaledFontBase::ScaledFontBase(Float aSize)
|
|||
#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)
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
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
|
||||
|
@ -56,6 +57,8 @@ protected:
|
|||
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;
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
#include "cairo-win32.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -431,5 +435,17 @@ ScaledFontDWrite::GetDefaultAAMode()
|
|||
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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ public:
|
|||
#endif
|
||||
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
protected:
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
cairo_font_face_t* GetCairoFontFace() override;
|
||||
#endif
|
||||
};
|
||||
|
||||
class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
|
||||
|
|
|
@ -6,10 +6,17 @@
|
|||
#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 {
|
||||
|
||||
|
@ -19,6 +26,57 @@ ScaledFontWin::ScaledFontWin(LOGFONT* aFont, Float aSize)
|
|||
{
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -29,6 +87,16 @@ SkTypeface* ScaledFontWin::GetSkTypeface()
|
|||
}
|
||||
#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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "ScaledFontBase.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -18,15 +20,33 @@ 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -153,6 +153,8 @@ UNIFIED_SOURCES += [
|
|||
'Scale.cpp',
|
||||
'ScaledFontBase.cpp',
|
||||
'ScaledFontCairo.cpp',
|
||||
'SFNTData.cpp',
|
||||
'SFNTNameTable.cpp',
|
||||
'SourceSurfaceCairo.cpp',
|
||||
'SourceSurfaceRawData.cpp',
|
||||
]
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче