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:
Bob Owen 2016-01-05 10:08:56 +00:00
Родитель 7b7cad771e
Коммит 9536340a3a
14 изменённых файлов: 870 добавлений и 0 удалений

80
gfx/2d/BigEndianInts.h Normal file
Просмотреть файл

@ -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;

207
gfx/2d/SFNTData.cpp Normal file
Просмотреть файл

@ -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

73
gfx/2d/SFNTData.h Normal file
Просмотреть файл

@ -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

257
gfx/2d/SFNTNameTable.cpp Normal file
Просмотреть файл

@ -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

67
gfx/2d/SFNTNameTable.h Normal file
Просмотреть файл

@ -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',
]

24
gfx/2d/u16string.h Normal file
Просмотреть файл

@ -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