commit 2a11447e4fb8ec6d64031cc41bdcef97603343cb Author: Richard Pospesel richard@torproject.org Date: Mon Nov 27 14:40:05 2017 -0800
Bug 23970: Printing to a file is broken with Linux content sandboxing enabled
Ported over firefox patch 2797f193a147 (Bug 1309205 Part 2) --- gfx/2d/2D.h | 7 + gfx/2d/Factory.cpp | 23 ++- gfx/2d/NativeFontResourceFontconfig.cpp | 65 +++++++ gfx/2d/NativeFontResourceFontconfig.h | 41 +++++ gfx/2d/RecordedEvent.cpp | 21 +-- gfx/2d/RecordedEvent.h | 10 +- gfx/2d/ScaledFontFontconfig.cpp | 315 ++++++++++++++++++++++++++++++++ gfx/2d/ScaledFontFontconfig.h | 59 +++++- gfx/2d/ScaledFontWin.cpp | 17 ++ gfx/2d/ScaledFontWin.h | 4 + gfx/2d/moz.build | 1 + 11 files changed, 540 insertions(+), 23 deletions(-)
diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 3d5fb52ad925..0b95f37cb1c3 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1388,6 +1388,13 @@ public: 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 * cairo_scaled_font_t* parameters must correspond to the same font. diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index ceebce690afb..bfe93d82c0ef 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -32,6 +32,7 @@
#ifdef MOZ_WIDGET_GTK #include "ScaledFontFontconfig.h" +#include "NativeFontResourceFontconfig.h" #endif
#ifdef WIN32 @@ -534,8 +535,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; @@ -548,6 +551,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) { #ifdef USE_CAIRO diff --git a/gfx/2d/NativeFontResourceFontconfig.cpp b/gfx/2d/NativeFontResourceFontconfig.cpp new file mode 100644 index 000000000000..a205f98fae08 --- /dev/null +++ b/gfx/2d/NativeFontResourceFontconfig.cpp @@ -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 diff --git a/gfx/2d/NativeFontResourceFontconfig.h b/gfx/2d/NativeFontResourceFontconfig.h new file mode 100644 index 000000000000..e2c386198896 --- /dev/null +++ b/gfx/2d/NativeFontResourceFontconfig.h @@ -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 diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index 3bfc5c8f6333..684ce180db1e 100644 --- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -1595,18 +1595,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; @@ -1620,7 +1615,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 @@ -1646,7 +1641,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 diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index bf660ba243c4..dcf4d9e36e02 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -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); @@ -1108,9 +1108,11 @@ public:
RecordedScaledFontCreation(ScaledFont* aScaledFont, RecordedFontDetails aFontDetails) - : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aScaledFont) + : RecordedEvent(SCALEDFONTCREATION) + , mRefPtr(aScaledFont) , mFontDataKey(aFontDetails.fontDataKey) - , mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index) + , mGlyphSize(aFontDetails.glyphSize) + , mIndex(aFontDetails.index) { aScaledFont->GetFontInstanceData(FontInstanceDataProc, this); } diff --git a/gfx/2d/ScaledFontFontconfig.cpp b/gfx/2d/ScaledFontFontconfig.cpp index d4751f86dac1..0695eebbeaa7 100644 --- a/gfx/2d/ScaledFontFontconfig.cpp +++ b/gfx/2d/ScaledFontFontconfig.cpp @@ -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 diff --git a/gfx/2d/ScaledFontFontconfig.h b/gfx/2d/ScaledFontFontconfig.h index 4d4e8217dc1f..b24928d9db05 100644 --- a/gfx/2d/ScaledFontFontconfig.h +++ b/gfx/2d/ScaledFontFontconfig.h @@ -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; };
diff --git a/gfx/2d/ScaledFontWin.cpp b/gfx/2d/ScaledFontWin.cpp index 2ebae21e5c04..b80bbea872e2 100644 --- a/gfx/2d/ScaledFontWin.cpp +++ b/gfx/2d/ScaledFontWin.cpp @@ -72,6 +72,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() { diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h index c07b263d7285..fe5816707d00 100644 --- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -25,6 +25,10 @@ public: bool GetFontInstanceData(FontInstanceDataOutput aCb, 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 diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index ad095503d97e..545ac6823390 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -91,6 +91,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): SOURCES += [ + 'NativeFontResourceFontconfig.cpp', 'ScaledFontFontconfig.cpp', ]