зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1352528 - Hoist call to GetRoundOffsetsToPixels out of the inner loop of text shaping. r=jrmuizel
This commit is contained in:
Родитель
13c3eda8c6
Коммит
6f0d451756
|
@ -122,6 +122,7 @@ gfxCoreTextShaper::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
// Create a CFAttributedString with text and style info, so we can use CoreText to lay it out.
|
||||
|
|
|
@ -18,13 +18,14 @@ public:
|
|||
|
||||
virtual ~gfxCoreTextShaper();
|
||||
|
||||
virtual bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
gfxShapedText *aShapedText);
|
||||
bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
// clean up static objects that may have been cached
|
||||
static void Shutdown();
|
||||
|
|
|
@ -45,10 +45,11 @@ gfxFT2Font::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
if (!gfxFont::ShapeText(aDrawTarget, aText, aOffset, aLength, aScript,
|
||||
aVertical, aShapedText)) {
|
||||
aVertical, aRounding, aShapedText)) {
|
||||
// harfbuzz must have failed(?!), just render raw glyphs
|
||||
AddRange(aText, aOffset, aLength, aShapedText);
|
||||
PostShapingFixup(aDrawTarget, aText, aOffset, aLength,
|
||||
|
|
|
@ -61,13 +61,14 @@ public: // new functions
|
|||
FontCacheSizes* aSizes) const override;
|
||||
|
||||
protected:
|
||||
virtual bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
gfxShapedText *aShapedText) override;
|
||||
bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
void FillGlyphDataForChar(uint32_t ch, CachedGlyphData *gd);
|
||||
|
||||
|
|
|
@ -555,90 +555,6 @@ gfxFontShaper::MergeFontFeatures(
|
|||
}
|
||||
}
|
||||
|
||||
// Work out whether cairo will snap inter-glyph spacing to pixels.
|
||||
//
|
||||
// Layout does not align text to pixel boundaries, so, with font drawing
|
||||
// backends that snap glyph positions to pixels, it is important that
|
||||
// inter-glyph spacing within words is always an integer number of pixels.
|
||||
// This ensures that the drawing backend snaps all of the word's glyphs in the
|
||||
// same direction and so inter-glyph spacing remains the same.
|
||||
//
|
||||
/* static */ void
|
||||
gfxFontShaper::GetRoundOffsetsToPixels(DrawTarget* aDrawTarget,
|
||||
bool* aRoundX, bool* aRoundY)
|
||||
{
|
||||
*aRoundX = false;
|
||||
// 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()) {
|
||||
*aRoundY = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// All raster backends snap glyphs to pixels vertically.
|
||||
// Print backends set CAIRO_HINT_METRICS_OFF.
|
||||
*aRoundY = true;
|
||||
|
||||
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) {
|
||||
*aRoundX = true; // default to the same as the fallback path below
|
||||
return;
|
||||
}
|
||||
|
||||
// Sometimes hint metrics gets set for us, most notably for printing.
|
||||
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);
|
||||
|
||||
switch (hint_metrics) {
|
||||
case CAIRO_HINT_METRICS_OFF:
|
||||
*aRoundY = false;
|
||||
return;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CAIRO_HINT_METRICS_ON:
|
||||
break;
|
||||
}
|
||||
*aRoundX = true;
|
||||
}
|
||||
|
||||
void
|
||||
gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
|
||||
const char16_t *aString,
|
||||
|
@ -872,6 +788,95 @@ gfxFont::~gfxFont()
|
|||
}
|
||||
}
|
||||
|
||||
// Work out whether cairo will snap inter-glyph spacing to pixels.
|
||||
//
|
||||
// Layout does not align text to pixel boundaries, so, with font drawing
|
||||
// backends that snap glyph positions to pixels, it is important that
|
||||
// inter-glyph spacing within words is always an integer number of pixels.
|
||||
// This ensures that the drawing backend snaps all of the word's glyphs in the
|
||||
// same direction and so inter-glyph spacing remains the same.
|
||||
//
|
||||
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;
|
||||
}
|
||||
|
||||
// All raster backends snap glyphs to pixels vertically.
|
||||
// Print backends set CAIRO_HINT_METRICS_OFF.
|
||||
result |= RoundingFlags::kRoundY;
|
||||
|
||||
// If we can't set up the cairo font, bail out.
|
||||
if (!SetupCairoFont(aDrawTarget)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Sometimes hint metrics gets set for us, most notably for printing.
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -2564,6 +2569,7 @@ gfxFont::GetShapedWord(DrawTarget *aDrawTarget,
|
|||
bool aVertical,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextPerfMetrics *aTextPerf GFX_MAYBE_UNUSED)
|
||||
{
|
||||
// if the cache is getting too big, flush it and start over
|
||||
|
@ -2620,7 +2626,8 @@ gfxFont::GetShapedWord(DrawTarget *aDrawTarget,
|
|||
}
|
||||
|
||||
DebugOnly<bool> ok =
|
||||
ShapeText(aDrawTarget, aText, 0, aLength, aRunScript, aVertical, sw);
|
||||
ShapeText(aDrawTarget, aText, 0, aLength, aRunScript, aVertical,
|
||||
aRounding, sw);
|
||||
|
||||
NS_WARNING_ASSERTION(ok, "failed to shape word - expect garbled text");
|
||||
|
||||
|
@ -2671,6 +2678,7 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
nsDependentCSubstring ascii((const char*)aText, aLength);
|
||||
|
@ -2680,7 +2688,7 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
return false;
|
||||
}
|
||||
return ShapeText(aDrawTarget, utf16.BeginReading(), aOffset, aLength,
|
||||
aScript, aVertical, aShapedText);
|
||||
aScript, aVertical, aRounding, aShapedText);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2690,6 +2698,7 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
bool ok = false;
|
||||
|
@ -2702,7 +2711,8 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
mGraphiteShaper = MakeUnique<gfxGraphiteShaper>(this);
|
||||
}
|
||||
ok = mGraphiteShaper->ShapeText(aDrawTarget, aText, aOffset, aLength,
|
||||
aScript, aVertical, aShapedText);
|
||||
aScript, aVertical, aRounding,
|
||||
aShapedText);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2711,7 +2721,8 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
mHarfBuzzShaper = MakeUnique<gfxHarfBuzzShaper>(this);
|
||||
}
|
||||
ok = mHarfBuzzShaper->ShapeText(aDrawTarget, aText, aOffset, aLength,
|
||||
aScript, aVertical, aShapedText);
|
||||
aScript, aVertical, aRounding,
|
||||
aShapedText);
|
||||
}
|
||||
|
||||
NS_WARNING_ASSERTION(ok, "shaper failed, expect scrambled or missing text");
|
||||
|
@ -2755,6 +2766,7 @@ gfxFont::ShapeFragmentWithoutWordCache(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextRun *aTextRun)
|
||||
{
|
||||
aTextRun->SetupClusterBoundaries(aOffset, aText, aLength);
|
||||
|
@ -2790,8 +2802,8 @@ gfxFont::ShapeFragmentWithoutWordCache(DrawTarget *aDrawTarget,
|
|||
}
|
||||
}
|
||||
|
||||
ok = ShapeText(aDrawTarget, aText, aOffset, fragLen, aScript, aVertical,
|
||||
aTextRun);
|
||||
ok = ShapeText(aDrawTarget, aText, aOffset, fragLen, aScript,
|
||||
aVertical, aRounding, aTextRun);
|
||||
|
||||
aText += fragLen;
|
||||
aOffset += fragLen;
|
||||
|
@ -2820,6 +2832,7 @@ gfxFont::ShapeTextWithoutWordCache(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextRun *aTextRun)
|
||||
{
|
||||
uint32_t fragStart = 0;
|
||||
|
@ -2838,7 +2851,8 @@ gfxFont::ShapeTextWithoutWordCache(DrawTarget *aDrawTarget,
|
|||
if (length > 0) {
|
||||
ok = ShapeFragmentWithoutWordCache(aDrawTarget, aText + fragStart,
|
||||
aOffset + fragStart, length,
|
||||
aScript, aVertical, aTextRun);
|
||||
aScript, aVertical, aRounding,
|
||||
aTextRun);
|
||||
}
|
||||
|
||||
if (i == aLength) {
|
||||
|
@ -2857,7 +2871,8 @@ gfxFont::ShapeTextWithoutWordCache(DrawTarget *aDrawTarget,
|
|||
if (GetFontEntry()->IsUserFont() && HasCharacter(ch)) {
|
||||
ShapeFragmentWithoutWordCache(aDrawTarget, aText + i,
|
||||
aOffset + i, 1,
|
||||
aScript, aVertical, aTextRun);
|
||||
aScript, aVertical, aRounding,
|
||||
aTextRun);
|
||||
} else {
|
||||
aTextRun->SetMissingGlyph(aOffset + i, ch, this);
|
||||
}
|
||||
|
@ -2908,6 +2923,7 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
}
|
||||
|
||||
gfxTextPerfMetrics *tp = nullptr;
|
||||
RoundingFlags rounding = GetRoundOffsetsToPixels(aDrawTarget);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
tp = aTextRun->GetFontGroup()->GetTextPerfMetrics();
|
||||
|
@ -2938,7 +2954,7 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
return ShapeTextWithoutWordCache(aDrawTarget, aString,
|
||||
aRunStart, aRunLength,
|
||||
aRunScript, aVertical,
|
||||
aTextRun);
|
||||
rounding, aTextRun);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2991,6 +3007,7 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
length,
|
||||
aRunScript,
|
||||
aVertical,
|
||||
rounding,
|
||||
aTextRun);
|
||||
if (!ok) {
|
||||
return false;
|
||||
|
@ -3009,7 +3026,7 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
aString + wordStart, length,
|
||||
hash, aRunScript, aVertical,
|
||||
appUnitsPerDevUnit,
|
||||
wordFlags, tp);
|
||||
wordFlags, rounding, tp);
|
||||
if (sw) {
|
||||
aTextRun->CopyGlyphDataFrom(sw, aRunStart + wordStart);
|
||||
} else {
|
||||
|
@ -3039,7 +3056,8 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
GetShapedWord(aDrawTarget, &boundary, 1,
|
||||
gfxShapedWord::HashMix(0, boundary),
|
||||
aRunScript, aVertical, appUnitsPerDevUnit,
|
||||
flags | gfxTextRunFactory::TEXT_IS_8BIT, tp);
|
||||
flags | gfxTextRunFactory::TEXT_IS_8BIT,
|
||||
rounding, tp);
|
||||
if (sw) {
|
||||
aTextRun->CopyGlyphDataFrom(sw, aRunStart + i);
|
||||
} else {
|
||||
|
@ -3071,7 +3089,8 @@ gfxFont::SplitAndInitTextRun(DrawTarget *aDrawTarget,
|
|||
if (GetFontEntry()->IsUserFont() && HasCharacter(ch)) {
|
||||
ShapeFragmentWithoutWordCache(aDrawTarget, aString + i,
|
||||
aRunStart + i, 1,
|
||||
aRunScript, aVertical, aTextRun);
|
||||
aRunScript, aVertical,
|
||||
rounding, aTextRun);
|
||||
} else {
|
||||
aTextRun->SetMissingGlyph(aRunStart + i, ch, this);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsIObserver.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypedEnumBits.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include <algorithm>
|
||||
#include "DrawMode.h"
|
||||
|
@ -620,6 +621,11 @@ public:
|
|||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::unicode::Script Script;
|
||||
|
||||
enum class RoundingFlags : uint8_t {
|
||||
kRoundX = 0x01,
|
||||
kRoundY = 0x02
|
||||
};
|
||||
|
||||
explicit gfxFontShaper(gfxFont *aFont)
|
||||
: mFont(aFont)
|
||||
{
|
||||
|
@ -637,6 +643,7 @@ public:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) = 0;
|
||||
|
||||
gfxFont *GetFont() const { return mFont; }
|
||||
|
@ -652,16 +659,13 @@ public:
|
|||
void* aHandleFeatureData);
|
||||
|
||||
protected:
|
||||
// Work out whether cairo will snap inter-glyph spacing to pixels.
|
||||
static void GetRoundOffsetsToPixels(DrawTarget* aDrawTarget,
|
||||
bool* aRoundX, bool* aRoundY);
|
||||
|
||||
// the font this shaper is working with. The font owns a UniquePtr reference
|
||||
// to this object, and will destroy it before it dies. Thus, mFont will always
|
||||
// be valid.
|
||||
gfxFont* MOZ_NON_OWNING_REF mFont;
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontShaper::RoundingFlags)
|
||||
|
||||
/*
|
||||
* gfxShapedText is an abstract superclass for gfxShapedWord and gfxTextRun.
|
||||
|
@ -1339,6 +1343,8 @@ protected:
|
|||
typedef mozilla::unicode::Script Script;
|
||||
typedef mozilla::SVGContextPaint SVGContextPaint;
|
||||
|
||||
typedef gfxFontShaper::RoundingFlags RoundingFlags;
|
||||
|
||||
public:
|
||||
nsrefcnt AddRef(void) {
|
||||
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
|
@ -1514,6 +1520,10 @@ public:
|
|||
|
||||
gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
|
||||
|
||||
// Work out whether cairo will snap inter-glyph spacing to pixels
|
||||
// when rendering to the given drawTarget.
|
||||
RoundingFlags GetRoundOffsetsToPixels(DrawTarget* aDrawTarget);
|
||||
|
||||
// Font metrics
|
||||
struct Metrics {
|
||||
gfxFloat capHeight;
|
||||
|
@ -1763,6 +1773,7 @@ public:
|
|||
bool aVertical,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextPerfMetrics *aTextPerf);
|
||||
|
||||
// Ensure the ShapedWord cache is initialized. This MUST be called before
|
||||
|
@ -1942,6 +1953,7 @@ protected:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText); // where to store the result
|
||||
|
||||
// Call the appropriate shaper to generate glyphs for aText and store
|
||||
|
@ -1952,6 +1964,7 @@ protected:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText);
|
||||
|
||||
// Helper to adjust for synthetic bold and set character-type flags
|
||||
|
@ -1978,6 +1991,7 @@ protected:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextRun *aTextRun);
|
||||
|
||||
// Shape a fragment of text (a run that is known to contain only
|
||||
|
@ -1992,6 +2006,7 @@ protected:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxTextRun *aTextRun);
|
||||
|
||||
void CheckForFeaturesInvolvingSpace();
|
||||
|
|
|
@ -90,6 +90,7 @@ gfxGDIFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
if (!mIsValid) {
|
||||
|
@ -106,7 +107,7 @@ gfxGDIFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
}
|
||||
|
||||
return gfxFont::ShapeText(aDrawTarget, aText, aOffset, aLength, aScript,
|
||||
aVertical, aShapedText);
|
||||
aVertical, aRounding, aShapedText);
|
||||
}
|
||||
|
||||
const gfxFont::Metrics&
|
||||
|
|
|
@ -74,13 +74,14 @@ protected:
|
|||
virtual const Metrics& GetHorizontalMetrics() override;
|
||||
|
||||
/* override to ensure the cairo font is set up properly */
|
||||
virtual bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
gfxShapedText *aShapedText) override;
|
||||
bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
void Initialize(); // creates metrics and Cairo fonts
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ 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
|
||||
|
@ -188,8 +189,8 @@ gfxGraphiteShaper::ShapeText(DrawTarget *aDrawTarget,
|
|||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = SetGlyphsFromSegment(aDrawTarget, aShapedText, aOffset, aLength,
|
||||
aText, seg);
|
||||
nsresult rv = SetGlyphsFromSegment(aShapedText, aOffset, aLength,
|
||||
aText, seg, aRounding);
|
||||
|
||||
gr_seg_destroy(seg);
|
||||
|
||||
|
@ -208,12 +209,12 @@ struct Cluster {
|
|||
};
|
||||
|
||||
nsresult
|
||||
gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
||||
gfxShapedText *aShapedText,
|
||||
gfxGraphiteShaper::SetGlyphsFromSegment(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
const char16_t *aText,
|
||||
gr_segment *aSegment)
|
||||
gr_segment *aSegment,
|
||||
RoundingFlags aRounding)
|
||||
{
|
||||
int32_t dev2appUnits = aShapedText->GetAppUnitsPerDevUnit();
|
||||
bool rtl = aShapedText->IsRightToLeft();
|
||||
|
@ -288,12 +289,12 @@ gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
|||
}
|
||||
}
|
||||
|
||||
bool roundX, roundY;
|
||||
GetRoundOffsetsToPixels(aDrawTarget, &roundX, &roundY);
|
||||
|
||||
gfxShapedText::CompressedGlyph *charGlyphs =
|
||||
aShapedText->GetCharacterGlyphs() + aOffset;
|
||||
|
||||
bool roundX = bool(aRounding & RoundingFlags::kRoundX);
|
||||
bool roundY = bool(aRounding & RoundingFlags::kRoundY);
|
||||
|
||||
// now put glyphs into the textrun, one cluster at a time
|
||||
for (uint32_t i = 0; i <= cIndex; ++i) {
|
||||
const Cluster& c = clusters[i];
|
||||
|
@ -322,8 +323,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
|||
continue;
|
||||
}
|
||||
|
||||
uint32_t appAdvance = roundX ? NSToIntRound(adv) * dev2appUnits :
|
||||
NSToIntRound(adv * dev2appUnits);
|
||||
uint32_t appAdvance = roundX ? NSToIntRound(adv) * dev2appUnits
|
||||
: NSToIntRound(adv * dev2appUnits);
|
||||
if (c.nGlyphs == 1 &&
|
||||
gfxShapedText::CompressedGlyph::IsSimpleGlyphID(gids[c.baseGlyph]) &&
|
||||
gfxShapedText::CompressedGlyph::IsSimpleAdvance(appAdvance) &&
|
||||
|
@ -338,8 +339,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
|||
for (uint32_t j = c.baseGlyph; j < c.baseGlyph + c.nGlyphs; ++j) {
|
||||
gfxShapedText::DetailedGlyph* d = details.AppendElement();
|
||||
d->mGlyphID = gids[j];
|
||||
d->mYOffset = roundY ? NSToIntRound(-yLocs[j]) * dev2appUnits :
|
||||
-yLocs[j] * dev2appUnits;
|
||||
d->mYOffset = roundY ? NSToIntRound(-yLocs[j]) * dev2appUnits
|
||||
: -yLocs[j] * dev2appUnits;
|
||||
if (j == c.baseGlyph) {
|
||||
d->mXOffset = 0;
|
||||
d->mAdvance = appAdvance;
|
||||
|
@ -347,8 +348,8 @@ gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
|||
} else {
|
||||
float dx = rtl ? (xLocs[j] - clusterLoc) :
|
||||
(xLocs[j] - clusterLoc - adv);
|
||||
d->mXOffset = roundX ? NSToIntRound(dx) * dev2appUnits :
|
||||
dx * dev2appUnits;
|
||||
d->mXOffset = roundX ? NSToIntRound(dx) * dev2appUnits
|
||||
: dx * dev2appUnits;
|
||||
d->mAdvance = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,23 +19,24 @@ public:
|
|||
explicit gfxGraphiteShaper(gfxFont *aFont);
|
||||
virtual ~gfxGraphiteShaper();
|
||||
|
||||
virtual bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
gfxShapedText *aShapedText);
|
||||
bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
protected:
|
||||
nsresult SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
||||
gfxShapedText *aShapedText,
|
||||
nsresult SetGlyphsFromSegment(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
const char16_t *aText,
|
||||
gr_segment *aSegment);
|
||||
gr_segment *aSegment,
|
||||
RoundingFlags aRounding);
|
||||
|
||||
static float GrGetAdvance(const void* appFontHandle, uint16_t glyphid);
|
||||
|
||||
|
|
|
@ -1419,6 +1419,7 @@ 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
|
||||
|
@ -1516,8 +1517,8 @@ gfxHarfBuzzShaper::ShapeText(DrawTarget *aDrawTarget,
|
|||
hb_buffer_reverse(buffer);
|
||||
}
|
||||
|
||||
nsresult rv = SetGlyphsFromRun(aDrawTarget, aShapedText, aOffset, aLength,
|
||||
aText, buffer, aVertical);
|
||||
nsresult rv = SetGlyphsFromRun(aShapedText, aOffset, aLength,
|
||||
aText, buffer, aVertical, aRounding);
|
||||
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"failed to store glyphs into gfxShapedWord");
|
||||
|
@ -1531,13 +1532,13 @@ gfxHarfBuzzShaper::ShapeText(DrawTarget *aDrawTarget,
|
|||
// for charToGlyphArray
|
||||
|
||||
nsresult
|
||||
gfxHarfBuzzShaper::SetGlyphsFromRun(DrawTarget *aDrawTarget,
|
||||
gfxShapedText *aShapedText,
|
||||
gfxHarfBuzzShaper::SetGlyphsFromRun(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
const char16_t *aText,
|
||||
hb_buffer_t *aBuffer,
|
||||
bool aVertical)
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding)
|
||||
{
|
||||
uint32_t numGlyphs;
|
||||
const hb_glyph_info_t *ginfo = hb_buffer_get_glyph_infos(aBuffer, &numGlyphs);
|
||||
|
@ -1571,9 +1572,11 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(DrawTarget *aDrawTarget,
|
|||
|
||||
bool roundI, roundB;
|
||||
if (aVertical) {
|
||||
GetRoundOffsetsToPixels(aDrawTarget, &roundB, &roundI);
|
||||
roundI = bool(aRounding & RoundingFlags::kRoundY);
|
||||
roundB = bool(aRounding & RoundingFlags::kRoundX);
|
||||
} else {
|
||||
GetRoundOffsetsToPixels(aDrawTarget, &roundI, &roundB);
|
||||
roundI = bool(aRounding & RoundingFlags::kRoundX);
|
||||
roundB = bool(aRounding & RoundingFlags::kRoundY);
|
||||
}
|
||||
|
||||
int32_t appUnitsPerDevUnit = aShapedText->GetAppUnitsPerDevUnit();
|
||||
|
|
|
@ -27,13 +27,15 @@ public:
|
|||
};
|
||||
|
||||
bool Initialize();
|
||||
virtual bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
gfxShapedText *aShapedText);
|
||||
|
||||
bool ShapeText(DrawTarget *aDrawTarget,
|
||||
const char16_t *aText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
// get a given font table in harfbuzz blob form
|
||||
hb_blob_t * GetFontTable(hb_tag_t aTag) const;
|
||||
|
@ -94,13 +96,13 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
nsresult SetGlyphsFromRun(DrawTarget *aDrawTarget,
|
||||
gfxShapedText *aShapedText,
|
||||
nsresult SetGlyphsFromRun(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
const char16_t *aText,
|
||||
hb_buffer_t *aBuffer,
|
||||
bool aVertical);
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding);
|
||||
|
||||
// retrieve glyph positions, applying advance adjustments and attachments
|
||||
// returns results in appUnits
|
||||
|
|
|
@ -289,6 +289,7 @@ gfxMacFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText)
|
||||
{
|
||||
if (!mIsValid) {
|
||||
|
@ -304,7 +305,8 @@ gfxMacFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
mCoreTextShaper = MakeUnique<gfxCoreTextShaper>(this);
|
||||
}
|
||||
if (mCoreTextShaper->ShapeText(aDrawTarget, aText, aOffset, aLength,
|
||||
aScript, aVertical, aShapedText)) {
|
||||
aScript, aVertical, aRounding,
|
||||
aShapedText)) {
|
||||
PostShapingFixup(aDrawTarget, aText, aOffset,
|
||||
aLength, aVertical, aShapedText);
|
||||
return true;
|
||||
|
@ -312,7 +314,7 @@ gfxMacFont::ShapeText(DrawTarget *aDrawTarget,
|
|||
}
|
||||
|
||||
return gfxFont::ShapeText(aDrawTarget, aText, aOffset, aLength, aScript,
|
||||
aVertical, aShapedText);
|
||||
aVertical, aRounding, aShapedText);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -85,6 +85,7 @@ protected:
|
|||
uint32_t aLength,
|
||||
Script aScript,
|
||||
bool aVertical,
|
||||
RoundingFlags aRounding,
|
||||
gfxShapedText *aShapedText) override;
|
||||
|
||||
void InitMetrics();
|
||||
|
|
|
@ -1525,6 +1525,8 @@ gfxTextRun::SetSpaceGlyph(gfxFont* aFont, DrawTarget* aDrawTarget,
|
|||
aOrientation;
|
||||
bool vertical =
|
||||
(GetFlags() & gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT) != 0;
|
||||
gfxFontShaper::RoundingFlags roundingFlags =
|
||||
aFont->GetRoundOffsetsToPixels(aDrawTarget);
|
||||
gfxShapedWord* sw = aFont->GetShapedWord(aDrawTarget,
|
||||
&space, 1,
|
||||
gfxShapedWord::HashMix(0, ' '),
|
||||
|
@ -1532,6 +1534,7 @@ gfxTextRun::SetSpaceGlyph(gfxFont* aFont, DrawTarget* aDrawTarget,
|
|||
vertical,
|
||||
mAppUnitsPerDevUnit,
|
||||
flags,
|
||||
roundingFlags,
|
||||
nullptr);
|
||||
if (sw) {
|
||||
AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false,
|
||||
|
|
Загрузка…
Ссылка в новой задаче