Bug 1352528 - Hoist call to GetRoundOffsetsToPixels out of the inner loop of text shaping. r=jrmuizel

This commit is contained in:
Jonathan Kew 2017-04-03 17:49:17 +01:00
Родитель 13c3eda8c6
Коммит 6f0d451756
15 изменённых файлов: 219 добавлений и 166 удалений

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

@ -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,