[tbb-commits] [tor-browser/tor-browser-52.5.2esr-7.5-2] Bug 23970: Printing to a file is broken with Linux content sandboxing enabled
gk at torproject.org
gk at torproject.org
Fri Dec 15 10:14:14 UTC 2017
commit 2a11447e4fb8ec6d64031cc41bdcef97603343cb
Author: Richard Pospesel <richard at 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',
]
More information about the tbb-commits
mailing list