зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1309205 - part 2 - provide NativeFontResourceFontconfig so that print_via_parent works on Linux. r=jfkthame
MozReview-Commit-ID: 94XcLKgwTPq
This commit is contained in:
Родитель
d5f91aa244
Коммит
3cff1c818b
19
gfx/2d/2D.h
19
gfx/2d/2D.h
|
@ -679,8 +679,9 @@ public:
|
|||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
|
||||
virtual ~ScaledFont() {}
|
||||
|
||||
typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton);
|
||||
typedef void (*FontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, Float aFontSize, void *aBaton);
|
||||
typedef void (*FontFileDataOutput)(const uint8_t* aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void* aBaton);
|
||||
typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton);
|
||||
typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, Float aFontSize, void* aBaton);
|
||||
|
||||
virtual FontType GetType() const = 0;
|
||||
virtual AntialiasMode GetDefaultAAMode() {
|
||||
|
@ -711,6 +712,8 @@ public:
|
|||
|
||||
virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; }
|
||||
|
||||
virtual bool GetFontInstanceData(FontInstanceDataOutput, void *) { return false; }
|
||||
|
||||
virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; }
|
||||
|
||||
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
|
||||
|
@ -741,10 +744,13 @@ public:
|
|||
*
|
||||
* @param aIndex index for the font within the resource.
|
||||
* @param aGlyphSize the size of ScaledFont required.
|
||||
* @param aInstanceData pointer to read-only buffer of any available instance data.
|
||||
* @param aInstanceDataLength the size of the instance data.
|
||||
* @return an already_addrefed ScaledFont, containing nullptr if failed.
|
||||
*/
|
||||
virtual already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize) = 0;
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) = 0;
|
||||
|
||||
virtual ~NativeFontResource() {};
|
||||
};
|
||||
|
@ -1398,6 +1404,13 @@ public:
|
|||
static already_AddRefed<NativeFontResource>
|
||||
CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType);
|
||||
|
||||
/**
|
||||
* This creates a scaled font of the given type based on font descriptor
|
||||
* data retrieved from ScaledFont::GetFontDescriptor.
|
||||
*/
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize);
|
||||
|
||||
/**
|
||||
* This creates a scaled font with an associated cairo_scaled_font_t, and
|
||||
* must be used when using the Cairo backend. The NativeFont and
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include "ScaledFontFontconfig.h"
|
||||
#include "NativeFontResourceFontconfig.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -524,8 +525,10 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
|
|||
return NativeFontResourceGDI::Create(aData, aSize,
|
||||
/* aNeedsCairo = */ true);
|
||||
}
|
||||
#elif XP_DARWIN
|
||||
#elif defined(XP_DARWIN)
|
||||
return NativeFontResourceMac::Create(aData, aSize);
|
||||
#elif defined(MOZ_WIDGET_GTK)
|
||||
return NativeFontResourceFontconfig::Create(aData, aSize);
|
||||
#else
|
||||
gfxWarning() << "Unable to create cairo scaled font from truetype data";
|
||||
return nullptr;
|
||||
|
@ -537,6 +540,24 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
Factory::CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize)
|
||||
{
|
||||
switch (aType) {
|
||||
#ifdef WIN32
|
||||
case FontType::GDI:
|
||||
return ScaledFontWin::CreateFromFontDescriptor(aData, aDataLength, aSize);
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
case FontType::FONTCONFIG:
|
||||
return ScaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aSize);
|
||||
#endif
|
||||
default:
|
||||
gfxWarning() << "Invalid type specified for ScaledFont font descriptor";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont)
|
||||
{
|
||||
|
|
|
@ -259,7 +259,8 @@ NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
|
|||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize)
|
||||
NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength)
|
||||
{
|
||||
if (aIndex >= mNumberOfFaces) {
|
||||
gfxWarning() << "Font face index is too high for font resource.";
|
||||
|
|
|
@ -32,7 +32,8 @@ public:
|
|||
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize) final;
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceDWrite(IDWriteFactory *aFactory,
|
||||
|
@ -53,4 +54,4 @@ private:
|
|||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceDWrite_h
|
||||
#endif // mozilla_gfx_NativeFontResourceDWrite_h
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- 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 "NativeFontResourceFontconfig.h"
|
||||
#include "ScaledFontFontconfig.h"
|
||||
#include "Logging.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
NativeFontResourceFontconfig::NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace)
|
||||
: mFontData(Move(aFontData)),
|
||||
mFace(aFace)
|
||||
{
|
||||
}
|
||||
|
||||
NativeFontResourceFontconfig::~NativeFontResourceFontconfig()
|
||||
{
|
||||
if (mFace) {
|
||||
FT_Done_Face(mFace);
|
||||
mFace = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<NativeFontResourceFontconfig>
|
||||
NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength)
|
||||
{
|
||||
if (!aFontData || !aDataLength) {
|
||||
return nullptr;
|
||||
}
|
||||
UniquePtr<uint8_t[]> fontData(new uint8_t[aDataLength]);
|
||||
memcpy(fontData.get(), aFontData, aDataLength);
|
||||
|
||||
FT_Face face;
|
||||
if (FT_New_Memory_Face(Factory::GetFTLibrary(), fontData.get(), aDataLength, 0, &face) != FT_Err_Ok) {
|
||||
return nullptr;
|
||||
}
|
||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != FT_Err_Ok) {
|
||||
FT_Done_Face(face);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<NativeFontResourceFontconfig> resource =
|
||||
new NativeFontResourceFontconfig(Move(fontData), face);
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceFontconfig::CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength)
|
||||
{
|
||||
if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) {
|
||||
gfxWarning() << "Fontconfig scaled font instance data is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
return ScaledFontFontconfig::CreateFromInstanceData(
|
||||
*reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(aInstanceData),
|
||||
mFace, nullptr, 0, aGlyphSize);
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- 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_NativeFontResourceFontconfig_h
|
||||
#define mozilla_gfx_NativeFontResourceFontconfig_h
|
||||
|
||||
#include "2D.h"
|
||||
|
||||
#include <cairo-ft.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class NativeFontResourceFontconfig final : public NativeFontResource
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFontconfig)
|
||||
|
||||
static already_AddRefed<NativeFontResourceFontconfig>
|
||||
Create(uint8_t *aFontData, uint32_t aDataLength);
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
|
||||
|
||||
~NativeFontResourceFontconfig();
|
||||
|
||||
private:
|
||||
NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace);
|
||||
|
||||
UniquePtr<uint8_t[]> mFontData;
|
||||
FT_Face mFace;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceFontconfig_h
|
|
@ -65,7 +65,8 @@ NativeFontResourceGDI::~NativeFontResourceGDI()
|
|||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize)
|
||||
NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength)
|
||||
{
|
||||
if (aIndex >= mFontNames.length()) {
|
||||
gfxWarning() << "Font index is too high for font resource.";
|
||||
|
|
|
@ -36,7 +36,8 @@ public:
|
|||
~NativeFontResourceGDI();
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize) final;
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceGDI(HANDLE aFontResourceHandle,
|
||||
|
@ -54,4 +55,4 @@ private:
|
|||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceGDI_h
|
||||
#endif // mozilla_gfx_NativeFontResourceGDI_h
|
||||
|
|
|
@ -50,7 +50,8 @@ NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength)
|
|||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize)
|
||||
NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength)
|
||||
{
|
||||
RefPtr<ScaledFontBase> scaledFont = new ScaledFontMac(mFontRef, aGlyphSize);
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ public:
|
|||
Create(uint8_t *aFontData, uint32_t aDataLength);
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize);
|
||||
CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
|
||||
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
|
||||
|
||||
~NativeFontResourceMac()
|
||||
{
|
||||
|
|
|
@ -1586,18 +1586,13 @@ RecordedFontDescriptor::~RecordedFontDescriptor()
|
|||
bool
|
||||
RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
MOZ_ASSERT(mType == FontType::GDI);
|
||||
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = (NativeFontType)mType;
|
||||
nativeFont.mFont = (void*)&mData[0];
|
||||
|
||||
RefPtr<ScaledFont> font =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont, mFontSize);
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont();
|
||||
#endif
|
||||
Factory::CreateScaledFontFromFontDescriptor(mType, mData.data(), mData.size(), mFontSize);
|
||||
if (!font) {
|
||||
gfxDevCrash(LogReason::InvalidFont) <<
|
||||
"Failed creating ScaledFont of type " << int(mType) << " from font descriptor";
|
||||
return false;
|
||||
}
|
||||
|
||||
aTranslator->AddScaledFont(mRefPtr, font);
|
||||
return true;
|
||||
|
@ -1611,7 +1606,7 @@ RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const
|
|||
WriteElement(aStream, mFontSize);
|
||||
WriteElement(aStream, mRefPtr);
|
||||
WriteElement(aStream, (size_t)mData.size());
|
||||
aStream.write((char*)&mData[0], mData.size());
|
||||
aStream.write((char*)mData.data(), mData.size());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1637,7 +1632,7 @@ RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream)
|
|||
size_t size;
|
||||
ReadElement(aStream, size);
|
||||
mData.resize(size);
|
||||
aStream.read((char*)&mData[0], size);
|
||||
aStream.read((char*)mData.data(), size);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1650,7 +1645,8 @@ RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const
|
|||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont> scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize);
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
fontResource->CreateScaledFont(mIndex, mGlyphSize, mInstanceData.data(), mInstanceData.size());
|
||||
aTranslator->AddScaledFont(mRefPtr, scaledFont);
|
||||
return true;
|
||||
}
|
||||
|
@ -1662,6 +1658,8 @@ RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const
|
|||
WriteElement(aStream, mFontDataKey);
|
||||
WriteElement(aStream, mIndex);
|
||||
WriteElement(aStream, mGlyphSize);
|
||||
WriteElement(aStream, (size_t)mInstanceData.size());
|
||||
aStream.write((char*)mInstanceData.data(), mInstanceData.size());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1670,6 +1668,12 @@ RecordedScaledFontCreation::OutputSimpleEventInfo(stringstream &aStringStream) c
|
|||
aStringStream << "[" << mRefPtr << "] ScaledFont Created";
|
||||
}
|
||||
|
||||
void
|
||||
RecordedScaledFontCreation::SetFontInstanceData(const uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
mInstanceData.assign(aData, aData + aSize);
|
||||
}
|
||||
|
||||
RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream)
|
||||
: RecordedEvent(SCALEDFONTCREATION)
|
||||
{
|
||||
|
@ -1677,6 +1681,11 @@ RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream)
|
|||
ReadElement(aStream, mFontDataKey);
|
||||
ReadElement(aStream, mIndex);
|
||||
ReadElement(aStream, mGlyphSize);
|
||||
|
||||
size_t size;
|
||||
ReadElement(aStream, size);
|
||||
mInstanceData.resize(size);
|
||||
aStream.read((char*)mInstanceData.data(), size);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -24,7 +24,7 @@ const uint32_t kMagicInt = 0xc001feed;
|
|||
// loss of backwards compatibility. Old streams will not work in a player
|
||||
// using a newer major revision. And new streams will not work in a player
|
||||
// using an older major revision.
|
||||
const uint16_t kMajorRevision = 5;
|
||||
const uint16_t kMajorRevision = 6;
|
||||
// A change in minor revision means additions of new events. New streams will
|
||||
// not play in older players.
|
||||
const uint16_t kMinorRevision = 0;
|
||||
|
@ -1047,7 +1047,7 @@ private:
|
|||
uint8_t *mData;
|
||||
RecordedFontDetails mFontDetails;
|
||||
|
||||
bool mGetFontFileDataSucceeded = false;
|
||||
bool mGetFontFileDataSucceeded;
|
||||
|
||||
MOZ_IMPLICIT RecordedFontData(std::istream &aStream);
|
||||
};
|
||||
|
@ -1055,7 +1055,7 @@ private:
|
|||
class RecordedFontDescriptor : public RecordedEvent {
|
||||
public:
|
||||
|
||||
static void FontDescCb(const uint8_t *aData, uint32_t aSize,
|
||||
static void FontDescCb(const uint8_t* aData, uint32_t aSize,
|
||||
Float aFontSize, void* aBaton)
|
||||
{
|
||||
auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
|
||||
|
@ -1100,12 +1100,21 @@ private:
|
|||
class RecordedScaledFontCreation : public RecordedEvent {
|
||||
public:
|
||||
|
||||
RecordedScaledFontCreation(ReferencePtr aRefPtr,
|
||||
RecordedFontDetails aFontDetails)
|
||||
: RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr)
|
||||
, mFontDataKey(aFontDetails.fontDataKey)
|
||||
, mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index)
|
||||
static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize, void* aBaton)
|
||||
{
|
||||
auto recordedScaledFontCreation = static_cast<RecordedScaledFontCreation*>(aBaton);
|
||||
recordedScaledFontCreation->SetFontInstanceData(aData, aSize);
|
||||
}
|
||||
|
||||
RecordedScaledFontCreation(ScaledFont* aScaledFont,
|
||||
RecordedFontDetails aFontDetails)
|
||||
: RecordedEvent(SCALEDFONTCREATION)
|
||||
, mRefPtr(aScaledFont)
|
||||
, mFontDataKey(aFontDetails.fontDataKey)
|
||||
, mGlyphSize(aFontDetails.glyphSize)
|
||||
, mIndex(aFontDetails.index)
|
||||
{
|
||||
aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
|
||||
}
|
||||
|
||||
virtual bool PlayEvent(Translator *aTranslator) const;
|
||||
|
@ -1116,6 +1125,8 @@ public:
|
|||
virtual std::string GetName() const { return "ScaledFont Creation"; }
|
||||
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
|
||||
|
||||
void SetFontInstanceData(const uint8_t *aData, uint32_t aSize);
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
|
@ -1123,6 +1134,7 @@ private:
|
|||
uint64_t mFontDataKey;
|
||||
Float mGlyphSize;
|
||||
uint32_t mIndex;
|
||||
std::vector<uint8_t> mInstanceData;
|
||||
|
||||
MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream);
|
||||
};
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include "skia/include/ports/SkTypeface_cairo.h"
|
||||
#endif
|
||||
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -43,5 +47,316 @@ SkTypeface* ScaledFontFontconfig::GetSkTypeface()
|
|||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
ScaledFontFontconfig::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton)
|
||||
{
|
||||
bool success = false;
|
||||
// Lock the Cairo scaled font to force it to resolve the Fontconfig pattern to an FT_Face.
|
||||
if (FT_Face face = cairo_ft_scaled_font_lock_face(GetCairoScaledFont())) {
|
||||
FT_ULong length = 0;
|
||||
// Request the SFNT file. This may not always succeed for all font types.
|
||||
if (FT_Load_Sfnt_Table(face, 0, 0, nullptr, &length) == FT_Err_Ok) {
|
||||
uint8_t* fontData = new uint8_t[length];
|
||||
if (FT_Load_Sfnt_Table(face, 0, 0, fontData, &length) == FT_Err_Ok) {
|
||||
aDataCallback(fontData, length, 0, mSize, aBaton);
|
||||
success = true;
|
||||
}
|
||||
delete[] fontData;
|
||||
}
|
||||
cairo_ft_scaled_font_unlock_face(GetCairoScaledFont());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
ScaledFontFontconfig::InstanceData::InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern)
|
||||
: mFlags(0)
|
||||
, mHintStyle(FC_HINT_NONE)
|
||||
, mSubpixelOrder(FC_RGBA_UNKNOWN)
|
||||
, mLcdFilter(FC_LCD_LEGACY)
|
||||
{
|
||||
// Record relevant Fontconfig properties into instance data.
|
||||
FcBool autohint;
|
||||
if (FcPatternGetBool(aPattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && autohint) {
|
||||
mFlags |= AUTOHINT;
|
||||
}
|
||||
FcBool bitmap;
|
||||
if (FcPatternGetBool(aPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == FcResultMatch && bitmap) {
|
||||
mFlags |= EMBEDDED_BITMAP;
|
||||
}
|
||||
FcBool embolden;
|
||||
if (FcPatternGetBool(aPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && embolden) {
|
||||
mFlags |= EMBOLDEN;
|
||||
}
|
||||
FcBool vertical;
|
||||
if (FcPatternGetBool(aPattern, FC_VERTICAL_LAYOUT, 0, &vertical) == FcResultMatch && vertical) {
|
||||
mFlags |= VERTICAL_LAYOUT;
|
||||
}
|
||||
|
||||
FcBool antialias;
|
||||
if (FcPatternGetBool(aPattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch || antialias) {
|
||||
mFlags |= ANTIALIAS;
|
||||
|
||||
// Only record subpixel order and lcd filtering if antialiasing is enabled.
|
||||
int rgba;
|
||||
if (FcPatternGetInteger(aPattern, FC_RGBA, 0, &rgba) == FcResultMatch) {
|
||||
mSubpixelOrder = rgba;
|
||||
}
|
||||
int filter;
|
||||
if (FcPatternGetInteger(aPattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) {
|
||||
mLcdFilter = filter;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_font_options_t* fontOptions = cairo_font_options_create();
|
||||
cairo_scaled_font_get_font_options(aScaledFont, fontOptions);
|
||||
// For printer fonts, Cairo hint metrics and hinting will be disabled.
|
||||
// For other fonts, allow hint metrics and hinting.
|
||||
if (cairo_font_options_get_hint_metrics(fontOptions) != CAIRO_HINT_METRICS_OFF) {
|
||||
mFlags |= HINT_METRICS;
|
||||
|
||||
FcBool hinting;
|
||||
if (FcPatternGetBool(aPattern, FC_HINTING, 0, &hinting) != FcResultMatch || hinting) {
|
||||
int hintstyle;
|
||||
if (FcPatternGetInteger(aPattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) {
|
||||
hintstyle = FC_HINT_FULL;
|
||||
}
|
||||
mHintStyle = hintstyle;
|
||||
}
|
||||
}
|
||||
cairo_font_options_destroy(fontOptions);
|
||||
|
||||
// Some fonts supply an adjusted size or otherwise use the font matrix for italicization.
|
||||
// Record the scale and the skew to accomodate both of these cases.
|
||||
cairo_matrix_t fontMatrix;
|
||||
cairo_scaled_font_get_font_matrix(aScaledFont, &fontMatrix);
|
||||
mScale = Float(fontMatrix.xx);
|
||||
mSkew = Float(fontMatrix.xy);
|
||||
}
|
||||
|
||||
void
|
||||
ScaledFontFontconfig::InstanceData::SetupPattern(FcPattern* aPattern) const
|
||||
{
|
||||
if (mFlags & AUTOHINT) {
|
||||
FcPatternAddBool(aPattern, FC_AUTOHINT, FcTrue);
|
||||
}
|
||||
if (mFlags & EMBEDDED_BITMAP) {
|
||||
FcPatternAddBool(aPattern, FC_EMBEDDED_BITMAP, FcTrue);
|
||||
}
|
||||
if (mFlags & EMBOLDEN) {
|
||||
FcPatternAddBool(aPattern, FC_EMBOLDEN, FcTrue);
|
||||
}
|
||||
if (mFlags & VERTICAL_LAYOUT) {
|
||||
FcPatternAddBool(aPattern, FC_VERTICAL_LAYOUT, FcTrue);
|
||||
}
|
||||
|
||||
if (mFlags & ANTIALIAS) {
|
||||
FcPatternAddBool(aPattern, FC_ANTIALIAS, FcTrue);
|
||||
if (mSubpixelOrder != FC_RGBA_UNKNOWN) {
|
||||
FcPatternAddInteger(aPattern, FC_RGBA, mSubpixelOrder);
|
||||
}
|
||||
if (mLcdFilter != FC_LCD_LEGACY) {
|
||||
FcPatternAddInteger(aPattern, FC_LCD_FILTER, mLcdFilter);
|
||||
}
|
||||
} else {
|
||||
FcPatternAddBool(aPattern, FC_ANTIALIAS, FcFalse);
|
||||
}
|
||||
|
||||
if (mHintStyle) {
|
||||
FcPatternAddBool(aPattern, FC_HINTING, FcTrue);
|
||||
FcPatternAddInteger(aPattern, FC_HINT_STYLE, mHintStyle);
|
||||
} else {
|
||||
FcPatternAddBool(aPattern, FC_HINTING, FcFalse);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScaledFontFontconfig::InstanceData::SetupFontOptions(cairo_font_options_t* aFontOptions) const
|
||||
{
|
||||
// Try to build a sane initial set of Cairo font options based on the Fontconfig
|
||||
// pattern.
|
||||
if (mFlags & HINT_METRICS) {
|
||||
// For regular (non-printer) fonts, enable hint metrics as well as hinting
|
||||
// and (possibly subpixel) antialiasing.
|
||||
cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_ON);
|
||||
|
||||
cairo_hint_style_t hinting;
|
||||
switch (mHintStyle) {
|
||||
case FC_HINT_NONE:
|
||||
hinting = CAIRO_HINT_STYLE_NONE;
|
||||
break;
|
||||
case FC_HINT_SLIGHT:
|
||||
hinting = CAIRO_HINT_STYLE_SLIGHT;
|
||||
break;
|
||||
case FC_HINT_MEDIUM:
|
||||
default:
|
||||
hinting = CAIRO_HINT_STYLE_MEDIUM;
|
||||
break;
|
||||
case FC_HINT_FULL:
|
||||
hinting = CAIRO_HINT_STYLE_FULL;
|
||||
break;
|
||||
}
|
||||
cairo_font_options_set_hint_style(aFontOptions, hinting);
|
||||
|
||||
if (mFlags & ANTIALIAS) {
|
||||
cairo_subpixel_order_t subpixel = CAIRO_SUBPIXEL_ORDER_DEFAULT;
|
||||
switch (mSubpixelOrder) {
|
||||
case FC_RGBA_RGB:
|
||||
subpixel = CAIRO_SUBPIXEL_ORDER_RGB;
|
||||
break;
|
||||
case FC_RGBA_BGR:
|
||||
subpixel = CAIRO_SUBPIXEL_ORDER_BGR;
|
||||
break;
|
||||
case FC_RGBA_VRGB:
|
||||
subpixel = CAIRO_SUBPIXEL_ORDER_VRGB;
|
||||
break;
|
||||
case FC_RGBA_VBGR:
|
||||
subpixel = CAIRO_SUBPIXEL_ORDER_VBGR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (subpixel != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
|
||||
cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
|
||||
cairo_font_options_set_subpixel_order(aFontOptions, subpixel);
|
||||
} else {
|
||||
cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_GRAY);
|
||||
}
|
||||
} else {
|
||||
cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_NONE);
|
||||
}
|
||||
} else {
|
||||
// For printer fonts, disable hint metrics and hinting. Don't allow subpixel
|
||||
// antialiasing.
|
||||
cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_OFF);
|
||||
cairo_font_options_set_hint_style(aFontOptions, CAIRO_HINT_STYLE_NONE);
|
||||
cairo_font_options_set_antialias(aFontOptions,
|
||||
mFlags & ANTIALIAS ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScaledFontFontconfig::InstanceData::SetupFontMatrix(cairo_matrix_t* aFontMatrix) const
|
||||
{
|
||||
// Build a font matrix that will reproduce a possibly adjusted size
|
||||
// and any italics/skew. This is just the concatenation of a simple
|
||||
// scale matrix with a matrix that skews on the X axis.
|
||||
cairo_matrix_init(aFontMatrix, mScale, 0, mSkew, mScale, 0, 0);
|
||||
}
|
||||
|
||||
bool
|
||||
ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton)
|
||||
{
|
||||
InstanceData instance(GetCairoScaledFont(), mPattern);
|
||||
|
||||
aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance), aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScaledFontFontconfig::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
|
||||
{
|
||||
// Check if the Fontconfig pattern uses a font file and index to specify which
|
||||
// font to load. If so, record these as a font descriptor along with any instance
|
||||
// data required to rebuild a scaled font from it.
|
||||
FcChar8* pathname = nullptr;
|
||||
if (FcPatternGetString(mPattern, FC_FILE, 0, &pathname) != FcResultMatch) {
|
||||
return false;
|
||||
}
|
||||
int index = 0;
|
||||
FcPatternGetInteger(mPattern, FC_INDEX, 0, &index);
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t pathLength = strlen(reinterpret_cast<char*>(pathname)) + 1;
|
||||
size_t dataLength = sizeof(FontDescriptor) + pathLength;
|
||||
uint8_t* data = new uint8_t[dataLength];
|
||||
FontDescriptor* desc = reinterpret_cast<FontDescriptor*>(data);
|
||||
desc->mPathLength = pathLength;
|
||||
desc->mIndex = index;
|
||||
desc->mInstanceData = InstanceData(GetCairoScaledFont(), mPattern);
|
||||
memcpy(data + sizeof(FontDescriptor), pathname, pathLength);
|
||||
|
||||
aCb(data, dataLength, mSize, aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
||||
FT_Face aFace, const char* aPathname, uint32_t aIndex,
|
||||
Float aSize)
|
||||
|
||||
{
|
||||
FcPattern* pattern = FcPatternCreate();
|
||||
if (!pattern) {
|
||||
gfxWarning() << "Failing initializing Fontconfig pattern for scaled font";
|
||||
return nullptr;
|
||||
}
|
||||
if (aFace) {
|
||||
FcPatternAddFTFace(pattern, FC_FT_FACE, aFace);
|
||||
} else {
|
||||
FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(aPathname));
|
||||
FcPatternAddInteger(pattern, FC_INDEX, aIndex);
|
||||
}
|
||||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
|
||||
aInstanceData.SetupPattern(pattern);
|
||||
|
||||
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern);
|
||||
if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) {
|
||||
gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern";
|
||||
FcPatternDestroy(pattern);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cairo_matrix_t sizeMatrix;
|
||||
aInstanceData.SetupFontMatrix(&sizeMatrix);
|
||||
|
||||
cairo_matrix_t identityMatrix;
|
||||
cairo_matrix_init_identity(&identityMatrix);
|
||||
|
||||
cairo_font_options_t *fontOptions = cairo_font_options_create();
|
||||
aInstanceData.SetupFontOptions(fontOptions);
|
||||
|
||||
cairo_scaled_font_t* cairoScaledFont =
|
||||
cairo_scaled_font_create(font, &sizeMatrix, &identityMatrix, fontOptions);
|
||||
|
||||
cairo_font_options_destroy(fontOptions);
|
||||
cairo_font_face_destroy(font);
|
||||
|
||||
if (cairo_scaled_font_status(cairoScaledFont) != CAIRO_STATUS_SUCCESS) {
|
||||
gfxWarning() << "Failed creating Cairo scaled font for font face";
|
||||
FcPatternDestroy(pattern);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ScaledFontFontconfig> scaledFont =
|
||||
new ScaledFontFontconfig(cairoScaledFont, pattern, aSize);
|
||||
|
||||
FcPatternDestroy(pattern);
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
ScaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize)
|
||||
{
|
||||
if (aDataLength < sizeof(FontDescriptor)) {
|
||||
gfxWarning() << "Fontconfig font descriptor is truncated.";
|
||||
return nullptr;
|
||||
}
|
||||
const FontDescriptor* desc = reinterpret_cast<const FontDescriptor*>(aData);
|
||||
if (desc->mPathLength < 1 ||
|
||||
desc->mPathLength > aDataLength - sizeof(FontDescriptor)) {
|
||||
gfxWarning() << "Pathname in Fontconfig font descriptor has invalid size.";
|
||||
return nullptr;
|
||||
}
|
||||
const char* pathname = reinterpret_cast<const char*>(aData + sizeof(FontDescriptor));
|
||||
if (pathname[desc->mPathLength - 1] != '\0') {
|
||||
gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated.";
|
||||
return nullptr;
|
||||
}
|
||||
return CreateFromInstanceData(desc->mInstanceData, nullptr, pathname, desc->mIndex, aSize);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -8,26 +8,75 @@
|
|||
|
||||
#include "ScaledFontBase.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <cairo.h>
|
||||
#include <cairo-ft.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class NativeFontResourceFontconfig;
|
||||
|
||||
class ScaledFontFontconfig : public ScaledFontBase
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFontconfig)
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFontconfig, override)
|
||||
ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, Float aSize);
|
||||
~ScaledFontFontconfig();
|
||||
|
||||
virtual FontType GetType() const { return FontType::FONTCONFIG; }
|
||||
FontType GetType() const override { return FontType::FONTCONFIG; }
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface();
|
||||
SkTypeface* GetSkTypeface() override;
|
||||
#endif
|
||||
|
||||
bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override;
|
||||
|
||||
bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
|
||||
|
||||
bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
|
||||
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize);
|
||||
|
||||
private:
|
||||
friend class NativeFontResourceFontconfig;
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
enum {
|
||||
ANTIALIAS = 1 << 0,
|
||||
AUTOHINT = 1 << 1,
|
||||
EMBEDDED_BITMAP = 1 << 2,
|
||||
EMBOLDEN = 1 << 3,
|
||||
VERTICAL_LAYOUT = 1 << 4,
|
||||
HINT_METRICS = 1 << 5
|
||||
};
|
||||
|
||||
InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern);
|
||||
|
||||
void SetupPattern(FcPattern* aPattern) const;
|
||||
void SetupFontOptions(cairo_font_options_t* aFontOptions) const;
|
||||
void SetupFontMatrix(cairo_matrix_t* aFontMatrix) const;
|
||||
|
||||
uint8_t mFlags;
|
||||
uint8_t mHintStyle;
|
||||
uint8_t mSubpixelOrder;
|
||||
uint8_t mLcdFilter;
|
||||
Float mScale;
|
||||
Float mSkew;
|
||||
};
|
||||
|
||||
struct FontDescriptor
|
||||
{
|
||||
uint32_t mPathLength;
|
||||
uint32_t mIndex;
|
||||
InstanceData mInstanceData;
|
||||
};
|
||||
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateFromInstanceData(const InstanceData& aInstanceData,
|
||||
FT_Face aFace, const char* aPathname, uint32_t aIndex,
|
||||
Float aSize);
|
||||
|
||||
FcPattern* mPattern;
|
||||
};
|
||||
|
||||
|
|
|
@ -88,6 +88,23 @@ ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
|
|||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
ScaledFontWin::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize)
|
||||
{
|
||||
NativeFont nativeFont;
|
||||
nativeFont.mType = NativeFontType::GDI_FONT_FACE;
|
||||
nativeFont.mFont = (void*)aData;
|
||||
|
||||
RefPtr<ScaledFont> font =
|
||||
Factory::CreateScaledFontForNativeFont(nativeFont, aSize);
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont();
|
||||
#endif
|
||||
|
||||
return font.forget();
|
||||
}
|
||||
|
||||
AntialiasMode
|
||||
ScaledFontWin::GetDefaultAAMode()
|
||||
{
|
||||
|
|
|
@ -23,6 +23,10 @@ public:
|
|||
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
|
||||
|
||||
virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
|
||||
|
||||
static already_AddRefed<ScaledFont>
|
||||
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize);
|
||||
|
||||
virtual AntialiasMode GetDefaultAAMode() override;
|
||||
|
||||
#ifdef USE_SKIA
|
||||
|
|
|
@ -90,6 +90,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
|
|||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
|
||||
SOURCES += [
|
||||
'NativeFontResourceFontconfig.cpp',
|
||||
'ScaledFontFontconfig.cpp',
|
||||
]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче