From da7985605777e3219ead454d4b639a7cbc3c8b7d Mon Sep 17 00:00:00 2001 From: Richard Pospesel Date: Mon, 27 Nov 2017 14:40:05 -0800 Subject: [PATCH] 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(-) create mode 100644 gfx/2d/NativeFontResourceFontconfig.cpp create mode 100644 gfx/2d/NativeFontResourceFontconfig.h diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 3d5fb52ad925f..0b95f37cb1c38 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1387,6 +1387,13 @@ public: static already_AddRefed 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 + 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 diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index ceebce690afb2..bfe93d82c0ef7 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; @@ -547,6 +550,24 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, } } +already_AddRefed +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 Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont) { diff --git a/gfx/2d/NativeFontResourceFontconfig.cpp b/gfx/2d/NativeFontResourceFontconfig.cpp new file mode 100644 index 0000000000000..a205f98fae082 --- /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&& aFontData, FT_Face aFace) + : mFontData(Move(aFontData)), + mFace(aFace) +{ +} + +NativeFontResourceFontconfig::~NativeFontResourceFontconfig() +{ + if (mFace) { + FT_Done_Face(mFace); + mFace = nullptr; + } +} + +already_AddRefed +NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength) +{ + if (!aFontData || !aDataLength) { + return nullptr; + } + UniquePtr 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 resource = + new NativeFontResourceFontconfig(Move(fontData), face); + return resource.forget(); +} + +already_AddRefed +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(aInstanceData), + mFace, nullptr, 0, aGlyphSize); +} + +} // gfx +} // mozilla diff --git a/gfx/2d/NativeFontResourceFontconfig.h b/gfx/2d/NativeFontResourceFontconfig.h new file mode 100644 index 0000000000000..e2c386198896d --- /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 + +namespace mozilla { +namespace gfx { + +class NativeFontResourceFontconfig final : public NativeFontResource +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFontconfig) + + static already_AddRefed + Create(uint8_t *aFontData, uint32_t aDataLength); + + already_AddRefed + CreateScaledFont(uint32_t aIndex, Float aGlyphSize, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + + ~NativeFontResourceFontconfig(); + +private: + NativeFontResourceFontconfig(UniquePtr&& aFontData, FT_Face aFace); + + UniquePtr mFontData; + FT_Face mFace; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_NativeFontResourceFontconfig_h diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index 3bfc5c8f63332..684ce180db1e5 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 font = - Factory::CreateScaledFontForNativeFont(nativeFont, mFontSize); - -#ifdef USE_CAIRO_SCALED_FONT - static_cast(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 bf660ba243c4a..dcf4d9e36e022 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(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 d4751f86dac11..0695eebbeaa7b 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 + 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(&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(pathname)) + 1; + size_t dataLength = sizeof(FontDescriptor) + pathLength; + uint8_t* data = new uint8_t[dataLength]; + FontDescriptor* desc = reinterpret_cast(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 +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(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 scaledFont = + new ScaledFontFontconfig(cairoScaledFont, pattern, aSize); + + FcPatternDestroy(pattern); + + return scaledFont.forget(); +} + +already_AddRefed +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(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(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 4d4e8217dc1f6..b24928d9db05b 100644 --- a/gfx/2d/ScaledFontFontconfig.h +++ b/gfx/2d/ScaledFontFontconfig.h @@ -8,26 +8,75 @@ #include "ScaledFontBase.h" -#include -#include +#include 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 + 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 + 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 2ebae21e5c04a..b80bbea872e22 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 +ScaledFontWin::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) +{ + NativeFont nativeFont; + nativeFont.mType = NativeFontType::GDI_FONT_FACE; + nativeFont.mFont = (void*)aData; + + RefPtr font = + Factory::CreateScaledFontForNativeFont(nativeFont, aSize); + +#ifdef USE_CAIRO_SCALED_FONT + static_cast(font.get())->PopulateCairoScaledFont(); +#endif + + return font.forget(); +} + AntialiasMode ScaledFontWin::GetDefaultAAMode() { diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h index c07b263d7285b..fe5816707d009 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 + 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 ad095503d97e0..545ac68233900 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', ] -- GitLab