Bug 1547063 - Use FreeType metrics directly instead of querying Cairo. r=jfkthame

Differential Revision: https://phabricator.services.mozilla.com/D44497

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Lee Salzman 2019-09-15 03:01:19 +00:00
Родитель 1ad0ba9769
Коммит 0d6ebe2503
27 изменённых файлов: 325 добавлений и 414 удалений

Просмотреть файл

@ -1748,7 +1748,8 @@ class GFX2D_API Factory {
#ifdef MOZ_WIDGET_ANDROID
static already_AddRefed<ScaledFont> CreateScaledFontForFreeTypeFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace);
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace,
bool aApplySyntheticBold = false);
#endif
/**

Просмотреть файл

@ -642,9 +642,10 @@ already_AddRefed<ScaledFont> Factory::CreateScaledFontForFontconfigFont(
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<ScaledFont> Factory::CreateScaledFontForFreeTypeFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace) {
return MakeAndAddRef<ScaledFontFreeType>(aScaledFont, std::move(aFace),
aUnscaledFont, aSize);
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace,
bool aApplySyntheticBold) {
return MakeAndAddRef<ScaledFontFreeType>(
aScaledFont, std::move(aFace), aUnscaledFont, aSize, aApplySyntheticBold);
}
#endif

Просмотреть файл

@ -98,12 +98,6 @@ ScaledFontFontconfig::InstanceData::InstanceData(
embolden) {
mFlags |= EMBOLDEN;
}
FcBool vertical;
if (FcPatternGetBool(aPattern, FC_VERTICAL_LAYOUT, 0, &vertical) ==
FcResultMatch &&
vertical) {
mFlags |= VERTICAL_LAYOUT;
}
cairo_font_options_t* fontOptions = cairo_font_options_create();
cairo_scaled_font_get_font_options(aScaledFont, fontOptions);
@ -221,9 +215,6 @@ ScaledFontFontconfig::InstanceData::InstanceData(
if (aOptions->flags & wr::FontInstanceFlags_SYNTHETIC_BOLD) {
mFlags |= EMBOLDEN;
}
if (aOptions->flags & wr::FontInstanceFlags_VERTICAL_LAYOUT) {
mFlags |= VERTICAL_LAYOUT;
}
if (aOptions->render_mode == wr::FontRenderMode::Subpixel) {
mAntialias = AntialiasMode::SUBPIXEL;
if (aOptions->flags & wr::FontInstanceFlags_SUBPIXEL_BGR) {
@ -339,9 +330,6 @@ void ScaledFontFontconfig::InstanceData::SetupFontOptions(
if (mFlags & AUTOHINT) {
loadFlags |= FT_LOAD_FORCE_AUTOHINT;
}
if (mFlags & VERTICAL_LAYOUT) {
loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
}
if (mFlags & EMBOLDEN) {
synthFlags |= CAIRO_FT_SYNTHESIZE_BOLD;
}
@ -386,9 +374,6 @@ bool ScaledFontFontconfig::GetWRFontInstanceOptions(
if (mInstanceData.mFlags & InstanceData::EMBOLDEN) {
options.flags |= wr::FontInstanceFlags_SYNTHETIC_BOLD;
}
if (mInstanceData.mFlags & InstanceData::VERTICAL_LAYOUT) {
options.flags |= wr::FontInstanceFlags_VERTICAL_LAYOUT;
}
if (mInstanceData.mFlags & InstanceData::EMBEDDED_BITMAP) {
options.flags |= wr::FontInstanceFlags_EMBEDDED_BITMAPS;
}

Просмотреть файл

@ -53,10 +53,9 @@ class ScaledFontFontconfig : public ScaledFontBase {
AUTOHINT = 1 << 0,
EMBEDDED_BITMAP = 1 << 1,
EMBOLDEN = 1 << 2,
VERTICAL_LAYOUT = 1 << 3,
HINT_METRICS = 1 << 4,
LCD_VERTICAL = 1 << 5,
SUBPIXEL_BGR = 1 << 6,
HINT_METRICS = 1 << 3,
LCD_VERTICAL = 1 << 4,
SUBPIXEL_BGR = 1 << 5,
};
InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern);

Просмотреть файл

@ -25,8 +25,11 @@ namespace gfx {
// which is a requirement when we consider runtime switchable backends and so on
ScaledFontFreeType::ScaledFontFreeType(
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace>&& aFace,
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize)
: ScaledFontBase(aUnscaledFont, aSize), mFace(std::move(aFace)) {
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
bool aApplySyntheticBold)
: ScaledFontBase(aUnscaledFont, aSize),
mFace(std::move(aFace)),
mApplySyntheticBold(aApplySyntheticBold) {
SetCairoScaledFont(aScaledFont);
}
@ -39,6 +42,10 @@ void ScaledFontFreeType::SetupSkFontDrawOptions(SkFont& aFont) {
// SkFontHost_cairo does not support subpixel text positioning
aFont.setSubpixel(false);
if (mApplySyntheticBold) {
aFont.setEmbolden(true);
}
aFont.setEmbeddedBitmaps(true);
}
#endif
@ -51,7 +58,9 @@ bool ScaledFontFreeType::GetFontInstanceData(FontInstanceDataOutput aCb,
mFace->GetFace());
}
aCb(nullptr, 0, variations.data(), variations.size(), aBaton);
InstanceData instance(this);
aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance),
variations.data(), variations.size(), aBaton);
return true;
}
@ -69,6 +78,10 @@ bool ScaledFontFreeType::GetWRFontInstanceOptions(
options.synthetic_italics =
wr::DegreesToSyntheticItalics(GetSyntheticObliqueAngle());
if (mApplySyntheticBold) {
options.flags |= wr::FontInstanceFlags_SYNTHETIC_BOLD;
}
wr::FontInstancePlatformOptions platformOptions;
platformOptions.lcd_filter = wr::FontLCDFilter::None;
platformOptions.hinting = wr::FontHinting::None;
@ -84,10 +97,28 @@ bool ScaledFontFreeType::GetWRFontInstanceOptions(
return true;
}
ScaledFontFreeType::InstanceData::InstanceData(
const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions)
: mApplySyntheticBold(false) {
if (aOptions) {
if (aOptions->flags & wr::FontInstanceFlags_SYNTHETIC_BOLD) {
mApplySyntheticBold = true;
}
}
}
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
Float aGlyphSize, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength, const FontVariation* aVariations,
uint32_t aNumVariations) {
if (aInstanceDataLength < sizeof(ScaledFontFreeType::InstanceData)) {
gfxWarning() << "FreeType scaled font instance data is truncated.";
return nullptr;
}
const ScaledFontFreeType::InstanceData& instanceData =
*reinterpret_cast<const ScaledFontFreeType::InstanceData*>(aInstanceData);
RefPtr<SharedFTFace> face(InitFace());
if (!face) {
gfxWarning() << "Attempted to deserialize FreeType scaled font without "
@ -138,14 +169,24 @@ already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
ApplyVariationsToFace(aVariations, aNumVariations, face->GetFace());
}
RefPtr<ScaledFontFreeType> scaledFont = new ScaledFontFreeType(
cairoScaledFont, std::move(face), this, aGlyphSize);
RefPtr<ScaledFontFreeType> scaledFont =
new ScaledFontFreeType(cairoScaledFont, std::move(face), this, aGlyphSize,
instanceData.mApplySyntheticBold);
cairo_scaled_font_destroy(cairoScaledFont);
return scaledFont.forget();
}
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFontFromWRFont(
Float aGlyphSize, const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions,
const FontVariation* aVariations, uint32_t aNumVariations) {
ScaledFontFreeType::InstanceData instanceData(aOptions, aPlatformOptions);
return CreateScaledFont(aGlyphSize, reinterpret_cast<uint8_t*>(&instanceData),
sizeof(instanceData), aVariations, aNumVariations);
}
bool ScaledFontFreeType::HasVariationSettings() {
// Check if the FT face has been cloned.
return mFace &&

Просмотреть файл

@ -14,13 +14,16 @@
namespace mozilla {
namespace gfx {
class UnscaledFontFreeType;
class ScaledFontFreeType : public ScaledFontBase {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFreeType, override)
ScaledFontFreeType(cairo_scaled_font_t* aScaledFont,
RefPtr<SharedFTFace>&& aFace,
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize);
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
bool aApplySyntheticBold = false);
FontType GetType() const override { return FontType::FREETYPE; }
@ -43,7 +46,21 @@ class ScaledFontFreeType : public ScaledFontBase {
bool HasVariationSettings() override;
private:
friend UnscaledFontFreeType;
RefPtr<SharedFTFace> mFace;
bool mApplySyntheticBold;
struct InstanceData {
explicit InstanceData(ScaledFontFreeType* aScaledFont)
: mApplySyntheticBold(aScaledFont->mApplySyntheticBold) {}
InstanceData(const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions);
bool mApplySyntheticBold;
};
};
} // namespace gfx

Просмотреть файл

@ -48,6 +48,11 @@ class UnscaledFontFreeType : public UnscaledFont {
Float aGlyphSize, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength, const FontVariation* aVariations,
uint32_t aNumVariations) override;
already_AddRefed<ScaledFont> CreateScaledFontFromWRFont(
Float aGlyphSize, const wr::FontInstanceOptions* aOptions,
const wr::FontInstancePlatformOptions* aPlatformOptions,
const FontVariation* aVariations, uint32_t aNumVariations) override;
#endif
protected:

Просмотреть файл

@ -471,17 +471,6 @@ bool gfxDWriteFont::HasBitmapStrikeForSize(uint32_t aSize) {
uint32_t gfxDWriteFont::GetSpaceGlyph() { return mSpaceGlyph; }
bool gfxDWriteFont::SetupCairoFont(DrawTarget* aDrawTarget) {
cairo_scaled_font_t* scaledFont = InitCairoScaledFont();
if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) {
// Don't cairo_set_scaled_font as that would propagate the error to
// the cairo_t, precluding any further drawing.
return false;
}
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), scaledFont);
return true;
}
bool gfxDWriteFont::IsValid() const { return mFontFace != nullptr; }
IDWriteFontFace* gfxDWriteFont::GetFontFace() { return mFontFace.get(); }
@ -578,7 +567,7 @@ int32_t gfxDWriteFont::GetGlyphWidth(uint16_t aGID) {
return width;
}
bool gfxDWriteFont::GetForceGDIClassic() {
bool gfxDWriteFont::GetForceGDIClassic() const {
return static_cast<gfxDWriteFontEntry*>(mFontEntry.get())
->GetForceGDIClassic() &&
cairo_dwrite_get_cleartype_rendering_mode() < 0 &&
@ -587,7 +576,7 @@ bool gfxDWriteFont::GetForceGDIClassic() {
}
DWRITE_MEASURING_MODE
gfxDWriteFont::GetMeasuringMode() {
gfxDWriteFont::GetMeasuringMode() const {
return GetForceGDIClassic()
? DWRITE_MEASURING_MODE_GDI_CLASSIC
: gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode();
@ -701,3 +690,12 @@ already_AddRefed<ScaledFont> gfxDWriteFont::GetScaledFont(
RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
return scaledFont.forget();
}
bool gfxDWriteFont::ShouldRoundXOffset(cairo_t* aCairo) const {
// show_glyphs is implemented on the font and so is used for all Cairo
// surface types; however, it may pixel-snap depending on the dwrite
// rendering mode
return GetForceGDIClassic() ||
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() !=
DWRITE_MEASURING_MODE_NATURAL;
}

Просмотреть файл

@ -40,8 +40,6 @@ class gfxDWriteFont : public gfxFont {
uint32_t GetSpaceGlyph() override;
bool SetupCairoFont(DrawTarget* aDrawTarget) override;
bool AllowSubpixelAA() override { return mAllowManualShowGlyphs; }
bool IsValid() const;
@ -69,6 +67,8 @@ class gfxDWriteFont : public gfxFont {
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
mozilla::gfx::DrawTarget* aTarget) override;
bool ShouldRoundXOffset(cairo_t* aCairo) const override;
protected:
cairo_scaled_font_t* InitCairoScaledFont();
@ -84,8 +84,8 @@ class gfxDWriteFont : public gfxFont {
gfxFloat MeasureGlyphWidth(uint16_t aGlyph);
DWRITE_MEASURING_MODE GetMeasuringMode();
bool GetForceGDIClassic();
DWRITE_MEASURING_MODE GetMeasuringMode() const;
bool GetForceGDIClassic() const;
RefPtr<IDWriteFontFace> mFontFace;
RefPtr<IDWriteFontFace1> mFontFace1; // may be unavailable on older DWrite

Просмотреть файл

@ -17,6 +17,9 @@
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
#ifndef FT_LOAD_COLOR
# define FT_LOAD_COLOR (1L << 20)
#endif
#ifndef FT_FACE_FLAG_COLOR
# define FT_FACE_FLAG_COLOR (1L << 14)
#endif
@ -27,18 +30,15 @@ gfxFT2FontBase::gfxFT2FontBase(
const RefPtr<UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aScaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle, gfxFloat aAdjustedSize)
const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden)
: gfxFont(aUnscaledFont, aFontEntry, aFontStyle, kAntialiasDefault,
aScaledFont),
mFTFace(std::move(aFTFace)),
mSpaceGlyph(0) {
mEmbolden = aFontStyle->NeedsSyntheticBold(aFontEntry);
mSpaceGlyph(0),
mFTLoadFlags(aLoadFlags | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH |
FT_LOAD_COLOR),
mEmbolden(aEmbolden) {
cairo_scaled_font_reference(mScaledFont);
mAdjustedSize = aAdjustedSize;
InitMetrics();
}
gfxFT2FontBase::~gfxFT2FontBase() { cairo_scaled_font_destroy(mScaledFont); }
@ -114,22 +114,6 @@ uint32_t gfxFT2FontBase::GetGlyph(uint32_t aCharCode) {
return slot->mGlyphIndex;
}
void gfxFT2FontBase::GetGlyphExtents(uint32_t aGlyph,
cairo_text_extents_t* aExtents) {
MOZ_ASSERT(aExtents != nullptr, "aExtents must not be NULL");
cairo_glyph_t glyphs[1];
glyphs[0].index = aGlyph;
glyphs[0].x = 0.0;
glyphs[0].y = 0.0;
// cairo does some caching for us here but perhaps a small gain could be
// made by caching more. It is usually only the advance that is needed,
// so caching only the advance could allow many requests to be cached with
// little memory use. Ideally this cache would be merged with
// gfxGlyphExtents.
cairo_scaled_font_glyph_extents(GetCairoScaledFont(), glyphs, 1, aExtents);
}
// aScale is intended for a 16.16 x/y_scale of an FT_Size_Metrics
static inline FT_Long ScaleRoundDesignUnits(FT_Short aDesignMetric,
FT_Fixed aScale) {
@ -159,13 +143,18 @@ static void SnapLineToPixels(gfxFloat& aOffset, gfxFloat& aSize) {
* The return value is the glyph id of that glyph or zero if no such glyph
* exists. aExtents is only set when this returns a non-zero glyph id.
*/
uint32_t gfxFT2FontBase::GetCharExtents(char aChar,
cairo_text_extents_t* aExtents) {
uint32_t gfxFT2FontBase::GetCharExtents(char aChar, gfxFloat* aWidth,
gfxFloat* aHeight) {
FT_UInt gid = GetGlyph(aChar);
if (gid) {
GetGlyphExtents(gid, aExtents);
int32_t width;
int32_t height;
if (gid && GetFTGlyphExtents(gid, &width, &height)) {
*aWidth = FLOAT_FROM_16_16(width);
*aHeight = FLOAT_FROM_26_6(height);
return gid;
} else {
return 0;
}
return gid;
}
/**
@ -176,16 +165,13 @@ uint32_t gfxFT2FontBase::GetCharExtents(char aChar,
*/
uint32_t gfxFT2FontBase::GetCharWidth(char aChar, gfxFloat* aWidth) {
FT_UInt gid = GetGlyph(aChar);
if (gid) {
int32_t width;
if (!GetFTGlyphAdvance(gid, &width)) {
cairo_text_extents_t extents;
GetGlyphExtents(gid, &extents);
width = NS_lround(0x10000 * extents.x_advance);
}
int32_t width;
if (gid && GetFTGlyphExtents(gid, &width)) {
*aWidth = FLOAT_FROM_16_16(width);
return gid;
} else {
return 0;
}
return gid;
}
void gfxFT2FontBase::InitMetrics() {
@ -395,14 +381,15 @@ void gfxFT2FontBase::InitMetrics() {
// hinting, but maybe the x extents are not quite right in some fancy
// script fonts. CSS 2.1 suggests possibly using the height of an "o",
// which would have a more consistent glyph across fonts.
cairo_text_extents_t extents;
if (GetCharExtents('x', &extents) && extents.y_bearing < 0.0) {
mMetrics.xHeight = -extents.y_bearing;
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, extents.x_advance);
gfxFloat xWidth;
gfxFloat xHeight;
if (GetCharExtents('x', &xWidth, &xHeight) && xHeight < 0.0) {
mMetrics.xHeight = -xHeight;
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, xWidth);
}
if (GetCharExtents('H', &extents) && extents.y_bearing < 0.0) {
mMetrics.capHeight = -extents.y_bearing;
if (GetCharExtents('H', &xWidth, &xHeight) && xHeight < 0.0) {
mMetrics.capHeight = -xHeight;
}
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, mMetrics.zeroWidth);
@ -479,7 +466,27 @@ uint32_t gfxFT2FontBase::GetGlyph(uint32_t unicode,
return GetGlyph(unicode);
}
bool gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID, int32_t* aAdvance) {
FT_Fixed gfxFT2FontBase::GetEmboldenAdvance(FT_Face aFace, FT_Fixed aAdvance) {
// If freetype emboldening is being used, and it's not a zero-width glyph,
// adjust the advance to account for the increased width.
if (!mEmbolden || !aAdvance) {
return 0;
}
// This is the embolden "strength" used by FT_GlyphSlot_Embolden,
// converted from 26.6 to 16.16
FT_Fixed strength =
FT_MulFix(aFace->units_per_EM, aFace->size->metrics.y_scale) / 24;
if (aFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
strength &= -64;
if (!strength) {
strength = 64;
}
}
return strength << 10;
}
bool gfxFT2FontBase::GetFTGlyphExtents(uint16_t aGID, int32_t* aAdvance,
int32_t* aHeight) {
gfxFT2LockedFace face(this);
MOZ_ASSERT(face.get());
if (!face.get()) {
@ -488,23 +495,7 @@ bool gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID, int32_t* aAdvance) {
return false;
}
// Due to bugs like 1435234 and 1440938, we currently prefer to fall back
// to reading the advance from cairo extents, unless we're dealing with
// a variation font (for which cairo metrics may be wrong, due to FreeType
// bug 52683).
if (!(face.get()->face_flags & FT_FACE_FLAG_SCALABLE) ||
!(face.get()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
return false;
}
bool hinting = gfxPlatform::GetPlatform()->FontHintingEnabled();
int32_t flags =
hinting ? FT_LOAD_ADVANCE_ONLY
: FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
if (face.get()->face_flags & FT_FACE_FLAG_TRICKY) {
flags &= ~FT_LOAD_NO_AUTOHINT;
}
FT_Error ftError = Factory::LoadFTGlyph(face.get(), aGID, flags);
FT_Error ftError = Factory::LoadFTGlyph(face.get(), aGID, mFTLoadFlags);
if (ftError != FT_Err_Ok) {
// FT_Face was somehow broken/invalid? Don't try to access glyph slot.
// This probably shouldn't happen, but does: see bug 1440938.
@ -512,27 +503,31 @@ bool gfxFT2FontBase::GetFTGlyphAdvance(uint16_t aGID, int32_t* aAdvance) {
return false;
}
bool hintMetrics = ShouldHintMetrics();
// Due to freetype bug 52683 we MUST use the linearHoriAdvance field when
// dealing with a variation font. (And other fonts would have returned
// earlier, so only variation fonts currently reach here.)
FT_Fixed advance = face.get()->glyph->linearHoriAdvance;
// If freetype emboldening is being used, and it's not a zero-width glyph,
// adjust the advance to account for the increased width.
if (mEmbolden && advance > 0) {
// This is the embolden "strength" used by FT_GlyphSlot_Embolden,
// converted from 26.6 to 16.16
FT_Fixed strength =
1024 *
FT_MulFix(face.get()->units_per_EM, face.get()->size->metrics.y_scale) /
24;
advance += strength;
// dealing with a variation font; also use it for scalable fonts when not
// applying hinting. Otherwise, prefer hinted width from glyph->advance.x.
FT_Fixed advance;
if (face.get()->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
(!hintMetrics || FT_HAS_MULTIPLE_MASTERS(face.get()))) {
advance = face.get()->glyph->linearHoriAdvance;
} else {
advance = face.get()->glyph->advance.x << 10; // convert 26.6 to 16.16
}
advance += GetEmboldenAdvance(face.get(), advance);
if (hintMetrics && (mFTLoadFlags & FT_LOAD_NO_HINTING)) {
advance = (advance + 0x8000) & 0xffff0000u;
}
*aAdvance = advance;
// Round the 16.16 fixed-point value to whole pixels for better consistency
// with how cairo renders the glyphs.
*aAdvance = (advance + 0x8000) & 0xffff0000u;
if (aHeight) {
FT_F26Dot6 height = -face.get()->glyph->metrics.horiBearingY;
if (hintMetrics && (mFTLoadFlags & FT_LOAD_NO_HINTING)) {
height &= -64;
}
*aHeight = height;
}
return true;
}
@ -547,53 +542,14 @@ int32_t gfxFT2FontBase::GetGlyphWidth(uint16_t aGID) {
return width;
}
if (!GetFTGlyphAdvance(aGID, &width)) {
cairo_text_extents_t extents;
GetGlyphExtents(aGID, &extents);
width = NS_lround(0x10000 * extents.x_advance);
if (!GetFTGlyphExtents(aGID, &width)) {
width = 0;
}
mGlyphWidths->Put(aGID, width);
return width;
}
bool gfxFT2FontBase::SetupCairoFont(DrawTarget* aDrawTarget) {
// The scaled font ctm is not relevant right here because
// cairo_set_scaled_font does not record the scaled font itself, but
// merely the font_face, font_matrix, font_options. The scaled_font used
// for the target can be different from the scaled_font passed to
// cairo_set_scaled_font. (Unfortunately we have measured only for an
// identity ctm.)
cairo_scaled_font_t* cairoFont = GetCairoScaledFont();
if (cairo_scaled_font_status(cairoFont) != CAIRO_STATUS_SUCCESS) {
// Don't cairo_set_scaled_font as that would propagate the error to
// the cairo_t, precluding any further drawing.
return false;
}
// Thoughts on which font_options to set on the context:
//
// cairoFont has been created for screen rendering.
//
// When the context is being used for screen rendering, we should set
// font_options such that the same scaled_font gets used (when the ctm is
// the same). The use of explicit font_options recorded in
// CreateScaledFont ensures that this will happen.
//
// XXXkt: For pdf and ps surfaces, I don't know whether it's better to
// remove surface-specific options, or try to draw with the same
// scaled_font that was used to measure. As the same font_face is being
// used, its font_options will often override some values anyway (unless
// perhaps we remove those from the FcPattern at face creation).
//
// I can't see any significant difference in printing, irrespective of
// what is set here. It's too late to change things here as measuring has
// already taken place. We should really be measuring with a different
// font for pdf and ps surfaces (bug 403513).
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), cairoFont);
return true;
}
// For variation fonts, figure out the variation coordinates to be applied
// for each axis, in freetype's order (which may not match the order of
// axes in mStyle.variationSettings, so we need to search by axis tag).

Просмотреть файл

@ -20,11 +20,10 @@ class gfxFT2FontBase : public gfxFont {
const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aScaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle, gfxFloat aAdjustedSize = 0.0);
const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden);
virtual ~gfxFT2FontBase();
uint32_t GetGlyph(uint32_t aCharCode);
void GetGlyphExtents(uint32_t aGlyph, cairo_text_extents_t* aExtents);
uint32_t GetSpaceGlyph() override;
bool ProvidesGetGlyph() const override { return true; }
virtual uint32_t GetGlyph(uint32_t unicode,
@ -32,8 +31,6 @@ class gfxFT2FontBase : public gfxFont {
bool ProvidesGlyphWidths() const override { return true; }
int32_t GetGlyphWidth(uint16_t aGID) override;
bool SetupCairoFont(DrawTarget* aDrawTarget) override;
FontType GetType() const override { return FONT_TYPE_FT2; }
static void SetupVarCoords(FT_MM_Var* aMMVar,
@ -44,23 +41,24 @@ class gfxFT2FontBase : public gfxFont {
void UnlockFTFace();
private:
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
uint32_t GetCharExtents(char aChar, gfxFloat* aWidth, gfxFloat* aHeight);
uint32_t GetCharWidth(char aChar, gfxFloat* aWidth);
// Get advance of a single glyph from FreeType, and return true;
// or return false if we should fall back to getting the glyph
// extents from cairo instead.
bool GetFTGlyphAdvance(uint16_t aGID, int32_t* aWidth);
void InitMetrics();
// Get advance (and optionally height) of a single glyph from FreeType,
// and return true, or return false if we failed.
bool GetFTGlyphExtents(uint16_t aGID, int32_t* aWidth,
int32_t* aHeight = nullptr);
protected:
void InitMetrics();
const Metrics& GetHorizontalMetrics() override;
FT_Fixed GetEmboldenAdvance(FT_Face aFace, FT_Fixed aAdvance);
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
uint32_t mSpaceGlyph;
Metrics mMetrics;
int mFTLoadFlags;
bool mEmbolden;
// For variation/multiple-master fonts, this will be an array of the values

Просмотреть файл

@ -145,15 +145,25 @@ FTUserFontData* FT2FontEntry::GetUserFontData() {
*/
cairo_scaled_font_t* FT2FontEntry::CreateScaledFont(
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFace) {
int flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
? FT_LOAD_DEFAULT
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFace, int* aOutLoadFlags,
unsigned int* aOutSynthFlags) {
int loadFlags = gfxPlatform::GetPlatform()->FontHintingEnabled()
? FT_LOAD_DEFAULT
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
if (aFace->GetFace()->face_flags & FT_FACE_FLAG_TRICKY) {
flags &= ~FT_LOAD_NO_AUTOHINT;
loadFlags &= ~FT_LOAD_NO_AUTOHINT;
}
unsigned int synthFlags = 0;
if (aStyle->NeedsSyntheticBold(this)) {
synthFlags |= CAIRO_FT_SYNTHESIZE_BOLD;
}
*aOutLoadFlags = loadFlags;
*aOutSynthFlags = synthFlags;
cairo_font_face_t* cairoFace = cairo_ft_font_face_create_for_ft_face(
aFace->GetFace(), flags, 0, aFace.get());
aFace->GetFace(), loadFlags, synthFlags, aFace.get());
if (!cairoFace) {
return nullptr;
}
@ -230,7 +240,10 @@ gfxFont* FT2FontEntry::CreateFontInstance(const gfxFontStyle* aStyle) {
}
}
cairo_scaled_font_t* scaledFont = CreateScaledFont(aStyle, face);
int loadFlags;
unsigned int synthFlags;
cairo_scaled_font_t* scaledFont =
CreateScaledFont(aStyle, face, &loadFlags, &synthFlags);
if (!scaledFont) {
return nullptr;
}
@ -245,7 +258,8 @@ gfxFont* FT2FontEntry::CreateFontInstance(const gfxFontStyle* aStyle) {
}
gfxFont* font =
new gfxFT2Font(unscaledFont, scaledFont, std::move(face), this, aStyle);
new gfxFT2Font(unscaledFont, scaledFont, std::move(face), this, aStyle,
loadFlags, (synthFlags & CAIRO_FT_SYNTHESIZE_BOLD) != 0);
cairo_scaled_font_destroy(scaledFont);
return font;
}

Просмотреть файл

@ -57,7 +57,8 @@ class FT2FontEntry : public gfxFontEntry {
// Create a cairo_scaled_font for this face, with the given style.
// This may fail and return null, so caller must be prepared to handle this.
cairo_scaled_font_t* CreateScaledFont(
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFace);
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFace,
int* aOutLoadFlags, unsigned int* aOutSynthFlags);
nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;

Просмотреть файл

@ -155,14 +155,14 @@ void gfxFT2Font::AddRange(const char16_t* aText, uint32_t aOffset,
gfxFT2Font::gfxFT2Font(const RefPtr<UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aCairoFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle)
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle,
int aLoadFlags, bool aEmbolden)
: gfxFT2FontBase(aUnscaledFont, aCairoFont, std::move(aFTFace), aFontEntry,
aFontStyle),
aFontStyle, aLoadFlags, aEmbolden),
mCharGlyphCache(32) {
NS_ASSERTION(mFontEntry,
"Unable to find font entry for font. Something is whack.");
// TODO: use FreeType emboldening instead of multi-strike?
mApplySyntheticBold = aFontStyle->NeedsSyntheticBold(aFontEntry);
InitMetrics();
}
gfxFT2Font::~gfxFT2Font() {}
@ -170,7 +170,8 @@ gfxFT2Font::~gfxFT2Font() {}
already_AddRefed<ScaledFont> gfxFT2Font::GetScaledFont(DrawTarget* aTarget) {
if (!mAzureScaledFont) {
mAzureScaledFont = Factory::CreateScaledFontForFreeTypeFont(
GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont(), mFTFace);
GetUnscaledFont(), GetAdjustedSize(), GetCairoScaledFont(), mFTFace,
GetStyle()->NeedsSyntheticBold(GetFontEntry()));
InitializeScaledFont();
}
@ -178,6 +179,10 @@ already_AddRefed<ScaledFont> gfxFT2Font::GetScaledFont(DrawTarget* aTarget) {
return scaledFont.forget();
}
bool gfxFT2Font::ShouldHintMetrics() const {
return !gfxPlatform::GetPlatform()->RequiresLinearZoom();
}
void gfxFT2Font::FillGlyphDataForChar(FT_Face face, uint32_t ch,
CachedGlyphData* gd) {
if (!face->charmap || (face->charmap->encoding != FT_ENCODING_UNICODE &&
@ -198,13 +203,7 @@ void gfxFT2Font::FillGlyphDataForChar(FT_Face face, uint32_t ch,
return;
}
FT_Int32 flags = gfxPlatform::GetPlatform()->FontHintingEnabled()
? FT_LOAD_DEFAULT
: (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
if (face->face_flags & FT_FACE_FLAG_TRICKY) {
flags &= ~FT_LOAD_NO_AUTOHINT;
}
FT_Error err = Factory::LoadFTGlyph(face, gid, flags);
FT_Error err = Factory::LoadFTGlyph(face, gid, mFTLoadFlags);
if (err) {
// hmm, this is weird, we failed to load a glyph that we had?
@ -217,7 +216,8 @@ void gfxFT2Font::FillGlyphDataForChar(FT_Face face, uint32_t ch,
gd->glyphIndex = gid;
gd->lsbDelta = face->glyph->lsb_delta;
gd->rsbDelta = face->glyph->rsb_delta;
gd->xAdvance = face->glyph->advance.x;
gd->xAdvance =
face->glyph->advance.x + GetEmboldenAdvance(face, face->glyph->advance.x);
}
void gfxFT2Font::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,

Просмотреть файл

@ -22,7 +22,8 @@ class gfxFT2Font : public gfxFT2FontBase {
gfxFT2Font(const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aCairoFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle);
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle,
int aLoadFlags, bool aEmbolden);
virtual ~gfxFT2Font();
FT2FontEntry* GetFontEntry();
@ -30,6 +31,8 @@ class gfxFT2Font : public gfxFT2FontBase {
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
DrawTarget* aTarget) override;
bool ShouldHintMetrics() const override;
void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const override;
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,

Просмотреть файл

@ -527,11 +527,12 @@ double gfxFontconfigFontEntry::GetAspect() {
static void PrepareFontOptions(FcPattern* aPattern,
cairo_font_options_t* aFontOptions,
int* aOutLoadFlags,
int* aOutLoadFlags, int* aOutLoadTarget,
unsigned int* aOutSynthFlags) {
NS_ASSERTION(aFontOptions, "null font options passed to PrepareFontOptions");
int loadFlags = FT_LOAD_DEFAULT;
int loadTarget = 0;
unsigned int synthFlags = 0;
// xxx - taken from the gfxFontconfigFonts code, needs to be reviewed
@ -543,8 +544,8 @@ static void PrepareFontOptions(FcPattern* aPattern,
}
// Font options are set explicitly here to improve cairo's caching
// behavior and to record the relevant parts of the pattern for
// SetupCairoFont (so that the pattern can be released).
// behavior and to record the relevant parts of the pattern so that
// the pattern can be released.
//
// Most font_options have already been set as defaults on the FcPattern
// with cairo_ft_font_options_substitute(), then user and system
@ -611,29 +612,28 @@ static void PrepareFontOptions(FcPattern* aPattern,
}
cairo_hint_style_t hint_style;
if (printing || !hinting) {
hint_style = CAIRO_HINT_STYLE_NONE;
} else {
int fc_hintstyle;
if (FcPatternGetInteger(aPattern, FC_HINT_STYLE, 0, &fc_hintstyle) !=
FcResultMatch) {
fc_hintstyle = FC_HINT_FULL;
}
switch (fc_hintstyle) {
case FC_HINT_NONE:
hint_style = CAIRO_HINT_STYLE_NONE;
break;
case FC_HINT_SLIGHT:
hint_style = CAIRO_HINT_STYLE_SLIGHT;
break;
case FC_HINT_MEDIUM:
default: // This fallback mirrors _get_pattern_ft_options in cairo.
hint_style = CAIRO_HINT_STYLE_MEDIUM;
break;
case FC_HINT_FULL:
hint_style = CAIRO_HINT_STYLE_FULL;
break;
}
int fc_hintstyle = FC_HINT_NONE;
if ((!printing || hinting) &&
FcPatternGetInteger(aPattern, FC_HINT_STYLE, 0, &fc_hintstyle) !=
FcResultMatch) {
fc_hintstyle = FC_HINT_FULL;
}
switch (fc_hintstyle) {
case FC_HINT_NONE:
hint_style = CAIRO_HINT_STYLE_NONE;
loadTarget = FT_LOAD_NO_HINTING;
break;
case FC_HINT_SLIGHT:
hint_style = CAIRO_HINT_STYLE_SLIGHT;
loadTarget = FT_LOAD_TARGET_LIGHT;
break;
case FC_HINT_MEDIUM:
default: // This fallback mirrors _get_pattern_ft_options in cairo.
hint_style = CAIRO_HINT_STYLE_MEDIUM;
break;
case FC_HINT_FULL:
hint_style = CAIRO_HINT_STYLE_FULL;
break;
}
cairo_font_options_set_hint_style(aFontOptions, hint_style);
@ -676,10 +676,19 @@ static void PrepareFontOptions(FcPattern* aPattern,
cairo_antialias_t antialias;
if (!fc_antialias) {
antialias = CAIRO_ANTIALIAS_NONE;
if (fc_hintstyle != FC_HINT_NONE) {
loadTarget = FT_LOAD_TARGET_MONO;
}
loadTarget |= FT_LOAD_MONOCHROME;
} else if (rgba == FC_RGBA_NONE) {
antialias = CAIRO_ANTIALIAS_GRAY;
} else {
antialias = CAIRO_ANTIALIAS_SUBPIXEL;
if (fc_hintstyle == FC_HINT_FULL) {
loadTarget = rgba == FC_RGBA_VRGB || rgba == FC_RGBA_VBGR
? FT_LOAD_TARGET_LCD_V
: FT_LOAD_TARGET_LCD;
}
}
cairo_font_options_set_antialias(aFontOptions, antialias);
@ -719,13 +728,6 @@ static void PrepareFontOptions(FcPattern* aPattern,
loadFlags |= FT_LOAD_FORCE_AUTOHINT;
}
FcBool vertical;
if (FcPatternGetBool(aPattern, FC_VERTICAL_LAYOUT, 0, &vertical) ==
FcResultMatch &&
vertical) {
loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
}
FcBool embolden;
if (FcPatternGetBool(aPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch &&
embolden) {
@ -733,12 +735,14 @@ static void PrepareFontOptions(FcPattern* aPattern,
}
*aOutLoadFlags = loadFlags;
*aOutLoadTarget = loadTarget;
*aOutSynthFlags = synthFlags;
}
cairo_scaled_font_t* gfxFontconfigFontEntry::CreateScaledFont(
FcPattern* aRenderPattern, gfxFloat aAdjustedSize,
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFTFace) {
const gfxFontStyle* aStyle, RefPtr<SharedFTFace> aFTFace,
int* aOutLoadFlags, unsigned int* aOutSynthFlags) {
if (aStyle->NeedsSyntheticBold(this)) {
FcPatternAddBool(aRenderPattern, FC_EMBOLDEN, FcTrue);
}
@ -762,8 +766,13 @@ cairo_scaled_font_t* gfxFontconfigFontEntry::CreateScaledFont(
cairo_font_options_t* fontOptions = cairo_font_options_create();
int loadFlags;
int loadTarget;
unsigned int synthFlags;
PrepareFontOptions(aRenderPattern, fontOptions, &loadFlags, &synthFlags);
PrepareFontOptions(aRenderPattern, fontOptions, &loadFlags, &loadTarget,
&synthFlags);
*aOutLoadFlags = loadFlags | loadTarget;
*aOutSynthFlags = synthFlags;
cairo_font_face_t* face = cairo_ft_font_face_create_for_ft_face(
aFTFace->GetFace(), loadFlags, synthFlags, aFTFace.get());
@ -960,8 +969,10 @@ gfxFont* gfxFontconfigFontEntry::CreateFontInstance(
return nullptr;
}
cairo_scaled_font_t* scaledFont =
CreateScaledFont(renderPattern, size, aFontStyle, face);
int loadFlags;
unsigned int synthFlags;
cairo_scaled_font_t* scaledFont = CreateScaledFont(
renderPattern, size, aFontStyle, face, &loadFlags, &synthFlags);
std::string file;
int index = 0;
@ -986,9 +997,9 @@ gfxFont* gfxFontconfigFontEntry::CreateFontInstance(
mUnscaledFontCache.Add(unscaledFont);
}
gfxFont* newFont =
new gfxFontconfigFont(unscaledFont, scaledFont, std::move(face),
renderPattern, size, this, aFontStyle);
gfxFont* newFont = new gfxFontconfigFont(
unscaledFont, scaledFont, std::move(face), renderPattern, size, this,
aFontStyle, loadFlags, (synthFlags & CAIRO_FT_SYNTHESIZE_BOLD) != 0);
cairo_scaled_font_destroy(scaledFont);
return newFont;
@ -1345,10 +1356,12 @@ gfxFontconfigFont::gfxFontconfigFont(
const RefPtr<UnscaledFontFontconfig>& aUnscaledFont,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace>&& aFTFace,
FcPattern* aPattern, gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle)
const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden)
: gfxFT2FontBase(aUnscaledFont, aScaledFont, std::move(aFTFace), aFontEntry,
aFontStyle, aAdjustedSize),
aFontStyle, aLoadFlags, aEmbolden),
mPattern(aPattern) {
mAdjustedSize = aAdjustedSize;
InitMetrics();
}
gfxFontconfigFont::~gfxFontconfigFont() {}
@ -1366,6 +1379,10 @@ already_AddRefed<ScaledFont> gfxFontconfigFont::GetScaledFont(
return scaledFont.forget();
}
bool gfxFontconfigFont::ShouldHintMetrics() const {
return !GetStyle()->printerFont;
}
gfxFcPlatformFontList::gfxFcPlatformFontList()
: mLocalNames(64),
mGenericMappings(32),

Просмотреть файл

@ -103,7 +103,8 @@ class gfxFontconfigFontEntry : public gfxFontEntry {
// helper method for creating cairo font from pattern
cairo_scaled_font_t* CreateScaledFont(
FcPattern* aRenderPattern, gfxFloat aAdjustedSize,
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFTFace);
const gfxFontStyle* aStyle, RefPtr<mozilla::gfx::SharedFTFace> aFTFace,
int* aOutLoadFlags, unsigned int* aOutSynthFlags);
// override to pull data from FTFace
virtual nsresult CopyFontTable(uint32_t aTableTag,
@ -209,7 +210,7 @@ class gfxFontconfigFont : public gfxFT2FontBase {
cairo_scaled_font_t* aScaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, FcPattern* aPattern,
gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle);
const gfxFontStyle* aFontStyle, int aLoadFlags, bool aEmbolden);
FontType GetType() const override { return FONT_TYPE_FONTCONFIG; }
virtual FcPattern* GetPattern() const { return mPattern; }
@ -217,6 +218,8 @@ class gfxFontconfigFont : public gfxFT2FontBase {
virtual already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
DrawTarget* aTarget) override;
bool ShouldHintMetrics() const override;
private:
virtual ~gfxFontconfigFont();

Просмотреть файл

@ -822,95 +822,45 @@ gfxFont::~gfxFont() {
//
gfxFont::RoundingFlags gfxFont::GetRoundOffsetsToPixels(
DrawTarget* aDrawTarget) {
RoundingFlags result = RoundingFlags(0);
// Could do something fancy here for ScaleFactors of
// AxisAlignedTransforms, but we leave things simple.
// Not much point rounding if a matrix will mess things up anyway.
// Also return false for non-cairo contexts.
if (aDrawTarget->GetTransform().HasNonTranslation()) {
return result;
// Also check if the font already knows hint metrics is off...
if (aDrawTarget->GetTransform().HasNonTranslation() || !ShouldHintMetrics()) {
return RoundingFlags(0);
}
// All raster backends snap glyphs to pixels vertically.
// Print backends set CAIRO_HINT_METRICS_OFF.
result |= RoundingFlags::kRoundY;
cairo_t* cr = nullptr;
if (aDrawTarget->GetBackendType() == BackendType::CAIRO) {
cr = static_cast<cairo_t*>(
aDrawTarget->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
cairo_surface_t* target = cairo_get_target(cr);
// If we can't set up the cairo font, bail out.
if (!SetupCairoFont(aDrawTarget)) {
return result;
// Check whether the cairo surface's font options hint metrics.
cairo_font_options_t* fontOptions = cairo_font_options_create();
cairo_surface_get_font_options(target, fontOptions);
cairo_hint_metrics_t hintMetrics =
cairo_font_options_get_hint_metrics(fontOptions);
cairo_font_options_destroy(fontOptions);
switch (hintMetrics) {
case CAIRO_HINT_METRICS_OFF:
return RoundingFlags(0);
case CAIRO_HINT_METRICS_ON:
return RoundingFlags::kRoundX | RoundingFlags::kRoundY;
default:
break;
}
}
cairo_t* cr = gfxFont::RefCairo(aDrawTarget);
cairo_scaled_font_t* scaled_font = cairo_get_scaled_font(cr);
// bug 1198921 - this sometimes fails under Windows for whatver reason
NS_ASSERTION(scaled_font,
"null cairo scaled font should never be returned "
"by cairo_get_scaled_font");
if (!scaled_font) {
result |= RoundingFlags::kRoundX; // default to the same as the fallback
// path below
return result;
if (ShouldRoundXOffset(cr)) {
return RoundingFlags::kRoundX | RoundingFlags::kRoundY;
} else {
return RoundingFlags::kRoundY;
}
// Sometimes hint metrics gets set for us, most notably for printing.
#ifdef MOZ_TREE_CAIRO
cairo_hint_metrics_t hint_metrics =
cairo_scaled_font_get_hint_metrics(scaled_font);
#else
cairo_font_options_t* font_options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, font_options);
cairo_hint_metrics_t hint_metrics =
cairo_font_options_get_hint_metrics(font_options);
cairo_font_options_destroy(font_options);
#endif
switch (hint_metrics) {
case CAIRO_HINT_METRICS_OFF:
result &= ~RoundingFlags::kRoundY;
return result;
case CAIRO_HINT_METRICS_DEFAULT:
// Here we mimic what cairo surface/font backends do. Printing
// surfaces have already been handled by hint_metrics. The
// fallback show_glyphs implementation composites pixel-aligned
// glyph surfaces, so we just pick surface/font combinations that
// override this.
switch (cairo_scaled_font_get_type(scaled_font)) {
#if CAIRO_HAS_DWRITE_FONT // dwrite backend is not in std cairo releases yet
case CAIRO_FONT_TYPE_DWRITE:
// show_glyphs is implemented on the font and so is used for
// all surface types; however, it may pixel-snap depending on
// the dwrite rendering mode
if (!cairo_dwrite_scaled_font_get_force_GDI_classic(scaled_font) &&
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL) {
return result;
}
MOZ_FALLTHROUGH;
#endif
case CAIRO_FONT_TYPE_QUARTZ:
// Quartz surfaces implement show_glyphs for Quartz fonts
if (cairo_surface_get_type(cairo_get_target(cr)) ==
CAIRO_SURFACE_TYPE_QUARTZ) {
return result;
}
break;
default:
break;
}
break;
case CAIRO_HINT_METRICS_ON:
break;
}
result |= RoundingFlags::kRoundX;
return result;
}
gfxFloat gfxFont::GetGlyphHAdvance(DrawTarget* aDrawTarget, uint16_t aGID) {
if (!SetupCairoFont(aDrawTarget)) {
return 0;
}
if (ProvidesGlyphWidths()) {
return GetGlyphWidth(aGID) / 65536.0;
}
@ -3396,38 +3346,6 @@ gfxFont* gfxFont::GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) {
return fe->FindOrMakeFont(&style, mUnicodeRangeMap);
}
static void DestroyRefCairo(void* aData) {
cairo_t* refCairo = static_cast<cairo_t*>(aData);
MOZ_ASSERT(refCairo);
cairo_destroy(refCairo);
}
/* static */
cairo_t* gfxFont::RefCairo(DrawTarget* aDT) {
// DrawTargets that don't use a Cairo backend can be given a 1x1 "reference"
// |cairo_t*|, stored in the DrawTarget's user data, for doing font-related
// operations.
static UserDataKey sRefCairo;
cairo_t* refCairo = nullptr;
if (aDT->GetBackendType() == BackendType::CAIRO) {
refCairo = static_cast<cairo_t*>(
aDT->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
if (refCairo) {
return refCairo;
}
}
refCairo = static_cast<cairo_t*>(aDT->GetUserData(&sRefCairo));
if (!refCairo) {
refCairo = cairo_create(
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->CairoSurface());
aDT->AddUserData(&sRefCairo, refCairo, DestroyRefCairo);
}
return refCairo;
}
gfxGlyphExtents* gfxFont::GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit) {
uint32_t i, count = mGlyphExtentsArray.Length();
for (i = 0; i < count; ++i) {

Просмотреть файл

@ -1520,6 +1520,9 @@ class gfxFont {
// when rendering to the given drawTarget.
RoundingFlags GetRoundOffsetsToPixels(DrawTarget* aDrawTarget);
virtual bool ShouldHintMetrics() const { return true; }
virtual bool ShouldRoundXOffset(cairo_t* aCairo) const { return true; }
// Font metrics
struct Metrics {
gfxFloat capHeight;
@ -1686,13 +1689,9 @@ class gfxFont {
gfxGlyphExtents* GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit);
// You need to call SetupCairoFont on aDrawTarget just before calling this.
void SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID,
bool aNeedTight, gfxGlyphExtents* aExtents);
// This is called by the default Draw() implementation above.
virtual bool SetupCairoFont(DrawTarget* aDrawTarget) = 0;
virtual bool AllowSubpixelAA() { return true; }
bool IsSyntheticBold() const { return mApplySyntheticBold; }
@ -1862,11 +1861,6 @@ class gfxFont {
// glyphs. This does not add a reference to the returned font.
gfxFont* GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel);
/**
* Return the reference cairo_t object from aDT.
*/
static cairo_t* RefCairo(mozilla::gfx::DrawTarget* aDT);
protected:
virtual const Metrics& GetHorizontalMetrics() = 0;

Просмотреть файл

@ -88,14 +88,6 @@ bool gfxGDIFont::ShapeText(DrawTarget* aDrawTarget, const char16_t* aText,
return false;
}
// Ensure the cairo font is set up, so there's no risk it'll fall back to
// creating a "toy" font internally (see bug 544617).
// We must check that this succeeded, otherwise we risk cairo creating the
// wrong kind of font internally as a fallback (bug 744480).
if (!SetupCairoFont(aDrawTarget)) {
return false;
}
return gfxFont::ShapeText(aDrawTarget, aText, aOffset, aLength, aScript,
aVertical, aRounding, aShapedText);
}
@ -104,17 +96,6 @@ const gfxFont::Metrics& gfxGDIFont::GetHorizontalMetrics() { return *mMetrics; }
uint32_t gfxGDIFont::GetSpaceGlyph() { return mSpaceGlyph; }
bool gfxGDIFont::SetupCairoFont(DrawTarget* aDrawTarget) {
if (!mScaledFont ||
cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
// Don't cairo_set_scaled_font as that would propagate the error to
// the cairo_t, precluding any further drawing.
return false;
}
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), mScaledFont);
return true;
}
already_AddRefed<ScaledFont> gfxGDIFont::GetScaledFont(DrawTarget* aTarget) {
if (!mAzureScaledFont) {
NativeFont nativeFont;

Просмотреть файл

@ -30,8 +30,6 @@ class gfxGDIFont : public gfxFont {
/* overrides for the pure virtual methods in gfxFont */
uint32_t GetSpaceGlyph() override;
bool SetupCairoFont(DrawTarget* aDrawTarget) override;
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
DrawTarget* aTarget) override;

Просмотреть файл

@ -47,13 +47,11 @@ bool gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont* aFont,
return false;
}
if (aFont->SetupCairoFont(aDrawTarget)) {
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupLazyTight;
++gGlyphExtentsSetupLazyTight;
#endif
aFont->SetupGlyphExtents(aDrawTarget, aGlyphID, true, this);
entry = mTightGlyphExtents.GetEntry(aGlyphID);
}
aFont->SetupGlyphExtents(aDrawTarget, aGlyphID, true, this);
entry = mTightGlyphExtents.GetEntry(aGlyphID);
if (!entry) {
NS_WARNING("Could not get glyph extents");
return false;

Просмотреть файл

@ -80,11 +80,6 @@ bool gfxGraphiteShaper::ShapeText(DrawTarget* aDrawTarget,
uint32_t aLength, Script aScript,
bool aVertical, RoundingFlags aRounding,
gfxShapedText* aShapedText) {
// some font back-ends require this in order to get proper hinted metrics
if (!mFont->SetupCairoFont(aDrawTarget)) {
return false;
}
const gfxFontStyle* style = mFont->GetStyle();
if (!mGrFont) {

Просмотреть файл

@ -1319,11 +1319,6 @@ bool gfxHarfBuzzShaper::ShapeText(DrawTarget* aDrawTarget,
uint32_t aLength, Script aScript,
bool aVertical, RoundingFlags aRounding,
gfxShapedText* aShapedText) {
// some font back-ends require this in order to get proper hinted metrics
if (!mFont->SetupCairoFont(aDrawTarget)) {
return false;
}
mUseVerticalPresentationForms = false;
if (!Initialize()) {

Просмотреть файл

@ -230,16 +230,6 @@ bool gfxMacFont::ShapeText(DrawTarget* aDrawTarget, const char16_t* aText,
aVertical, aRounding, aShapedText);
}
bool gfxMacFont::SetupCairoFont(DrawTarget* aDrawTarget) {
if (cairo_scaled_font_status(mScaledFont) != CAIRO_STATUS_SUCCESS) {
// Don't cairo_set_scaled_font as that would propagate the error to
// the cairo_t, precluding any further drawing.
return false;
}
cairo_set_scaled_font(gfxFont::RefCairo(aDrawTarget), mScaledFont);
return true;
}
gfxFont::RunMetrics gfxMacFont::Measure(const gfxTextRun* aTextRun,
uint32_t aStart, uint32_t aEnd,
BoundingBoxType aBoundingBoxType,
@ -581,6 +571,12 @@ already_AddRefed<ScaledFont> gfxMacFont::GetScaledFont(DrawTarget* aTarget) {
return scaledFont.forget();
}
bool gfxMacFont::ShouldRoundXOffset(cairo_t* aCairo) const {
// Quartz surfaces implement show_glyphs for Quartz fonts
return aCairo && cairo_surface_get_type(cairo_get_target(aCairo)) !=
CAIRO_SURFACE_TYPE_QUARTZ;
}
void gfxMacFont::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const {
gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);

Просмотреть файл

@ -27,8 +27,6 @@ class gfxMacFont : public gfxFont {
/* overrides for the pure virtual methods in gfxFont */
uint32_t GetSpaceGlyph() override { return mSpaceGlyph; }
bool SetupCairoFont(DrawTarget* aDrawTarget) override;
/* override Measure to add padding for antialiasing */
RunMetrics Measure(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
BoundingBoxType aBoundingBoxType, DrawTarget* aDrawTargetForTightBoundingBox,
@ -46,6 +44,8 @@ class gfxMacFont : public gfxFont {
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
mozilla::gfx::DrawTarget* aTarget) override;
bool ShouldRoundXOffset(cairo_t* aCairo) const override;
void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const override;
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,

Просмотреть файл

@ -16,7 +16,7 @@ use freetype::freetype::{FT_Fixed, FT_Matrix, FT_Set_Transform, FT_String, FT_UL
use freetype::freetype::{FT_Err_Unimplemented_Feature};
use freetype::freetype::{FT_LOAD_COLOR, FT_LOAD_DEFAULT, FT_LOAD_FORCE_AUTOHINT};
use freetype::freetype::{FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH, FT_LOAD_NO_AUTOHINT};
use freetype::freetype::{FT_LOAD_NO_BITMAP, FT_LOAD_NO_HINTING, FT_LOAD_VERTICAL_LAYOUT};
use freetype::freetype::{FT_LOAD_NO_BITMAP, FT_LOAD_NO_HINTING};
use freetype::freetype::{FT_FACE_FLAG_SCALABLE, FT_FACE_FLAG_FIXED_SIZES};
use freetype::freetype::{FT_FACE_FLAG_MULTIPLE_MASTERS};
use freetype::succeeded;
@ -415,9 +415,6 @@ impl FontContext {
if !font.flags.contains(FontInstanceFlags::EMBEDDED_BITMAPS) {
load_flags |= FT_LOAD_NO_BITMAP;
}
if font.flags.contains(FontInstanceFlags::VERTICAL_LAYOUT) {
load_flags |= FT_LOAD_VERTICAL_LAYOUT;
}
load_flags |= FT_LOAD_COLOR;
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;