Bug 1571738 - Fallback as late as possible for svg/color fonts. r=jrmuizel

Also includes some documentation gardening for TextDrawTarget on what we don't support.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alexis Beingessner 2019-08-12 15:40:26 +00:00
Родитель a52cd4881c
Коммит 22dbda5b64
5 изменённых файлов: 63 добавлений и 31 удалений

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

@ -163,7 +163,7 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
void SetWebRenderLayerManager(WebRenderLayerManager* aManager);
ipc::IShmemAllocator* GetShmemAllocator();
mozilla::ipc::IShmemAllocator* GetShmemAllocator();
bool IsThreadSafe() const override { return false; }

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

@ -1919,7 +1919,7 @@ void gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt,
NS_WARNING_ASSERTION(
runParams.drawMode != DrawMode::GLYPH_PATH,
"Rendering SVG glyph despite request for glyph path");
if (RenderSVGGlyph(runParams.context, devPt, aGlyphID,
if (RenderSVGGlyph(runParams.context, textDrawer, devPt, aGlyphID,
fontParams.contextPaint, runParams.callbacks,
*aEmittedGlyphs)) {
return;
@ -1928,8 +1928,9 @@ void gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt,
if (fontParams.haveColorGlyphs &&
!gfxPlatform::GetPlatform()->HasNativeColrFontSupport() &&
RenderColorGlyph(runParams.dt, runParams.context, fontParams.scaledFont,
fontParams.drawOptions, devPt, aGlyphID)) {
RenderColorGlyph(runParams.dt, runParams.context, textDrawer,
fontParams.scaledFont, fontParams.drawOptions, devPt,
aGlyphID)) {
return;
}
@ -2082,14 +2083,6 @@ void gfxFont::Draw(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
fontParams.contextPaint = aRunParams.runContextPaint;
if (textDrawer) {
Color color;
if (fontParams.haveSVGGlyphs ||
(fontParams.haveColorGlyphs &&
aRunParams.context->HasNonOpaqueNonTransparentColor(color))) {
textDrawer->FoundUnsupportedFeature();
return;
}
fontParams.isVerticalFont = aRunParams.isVerticalRun;
} else {
fontParams.isVerticalFont =
@ -2319,13 +2312,21 @@ void gfxFont::Draw(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
}
}
bool gfxFont::RenderSVGGlyph(gfxContext* aContext, gfx::Point aPoint,
uint32_t aGlyphId,
bool gfxFont::RenderSVGGlyph(gfxContext* aContext,
layout::TextDrawTarget* aTextDrawer,
gfx::Point aPoint, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) const {
if (!GetFontEntry()->HasSVGGlyph(aGlyphId)) {
return false;
}
if (aTextDrawer) {
// WebRender doesn't support SVG Glyphs.
// (pretend to succeed, output doesn't matter, we will emit a blob)
aTextDrawer->FoundUnsupportedFeature();
return true;
}
const gfxFloat devUnitsPerSVGUnit =
GetAdjustedSize() / GetFontEntry()->UnitsPerEm();
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
@ -2341,18 +2342,21 @@ bool gfxFont::RenderSVGGlyph(gfxContext* aContext, gfx::Point aPoint,
return true;
}
bool gfxFont::RenderSVGGlyph(gfxContext* aContext, gfx::Point aPoint,
uint32_t aGlyphId, SVGContextPaint* aContextPaint,
bool gfxFont::RenderSVGGlyph(gfxContext* aContext,
layout::TextDrawTarget* aTextDrawer,
gfx::Point aPoint, uint32_t aGlyphId,
SVGContextPaint* aContextPaint,
gfxTextRunDrawCallbacks* aCallbacks,
bool& aEmittedGlyphs) const {
if (aCallbacks && aEmittedGlyphs) {
aCallbacks->NotifyGlyphPathEmitted();
aEmittedGlyphs = false;
}
return RenderSVGGlyph(aContext, aPoint, aGlyphId, aContextPaint);
return RenderSVGGlyph(aContext, aTextDrawer, aPoint, aGlyphId, aContextPaint);
}
bool gfxFont::RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
layout::TextDrawTarget* aTextDrawer,
mozilla::gfx::ScaledFont* scaledFont,
mozilla::gfx::DrawOptions aDrawOptions,
const mozilla::gfx::Point& aPoint,
@ -2369,6 +2373,16 @@ bool gfxFont::RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
return false;
}
// defaultColor is the one that comes from CSS, so it has transparency info.
bool hasTransparency = 0.f < defaultColor.a && defaultColor.a < 1.f;
if (aTextDrawer && hasTransparency && layerGlyphs.Length() > 1) {
// WebRender doesn't support drawing multi-layer transparent color-glyphs,
// as it requires compositing all the layers before applying transparency.
// (pretend to succeed, output doesn't matter, we will emit a blob)
aTextDrawer->FoundUnsupportedFeature();
return true;
}
for (uint32_t layerIndex = 0; layerIndex < layerGlyphs.Length();
layerIndex++) {
Glyph glyph;

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

@ -36,6 +36,7 @@
#include "nsColor.h"
#include "nsFontMetrics.h"
#include "mozilla/ServoUtils.h"
#include "TextDrawTarget.h"
typedef struct _cairo cairo_t;
typedef struct _cairo_scaled_font cairo_scaled_font_t;
@ -2148,14 +2149,19 @@ class gfxFont {
// if this font has bad underline offset, aIsBadUnderlineFont should be true.
void SanitizeMetrics(Metrics* aMetrics, bool aIsBadUnderlineFont);
bool RenderSVGGlyph(gfxContext* aContext, mozilla::gfx::Point aPoint,
uint32_t aGlyphId, SVGContextPaint* aContextPaint) const;
bool RenderSVGGlyph(gfxContext* aContext, mozilla::gfx::Point aPoint,
uint32_t aGlyphId, SVGContextPaint* aContextPaint,
bool RenderSVGGlyph(gfxContext* aContext,
mozilla::layout::TextDrawTarget* aTextDrawer,
mozilla::gfx::Point aPoint, uint32_t aGlyphId,
SVGContextPaint* aContextPaint) const;
bool RenderSVGGlyph(gfxContext* aContext,
mozilla::layout::TextDrawTarget* aTextDrawer,
mozilla::gfx::Point aPoint, uint32_t aGlyphId,
SVGContextPaint* aContextPaint,
gfxTextRunDrawCallbacks* aCallbacks,
bool& aEmittedGlyphs) const;
bool RenderColorGlyph(DrawTarget* aDrawTarget, gfxContext* aContext,
mozilla::layout::TextDrawTarget* aTextDrawer,
mozilla::gfx::ScaledFont* scaledFont,
mozilla::gfx::DrawOptions drawOptions,
const mozilla::gfx::Point& aPoint,

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

@ -20,7 +20,7 @@ namespace layout {
using namespace gfx;
// This class is fake DrawTarget, used to intercept text draw calls, while
// This class is a fake DrawTarget, used to intercept text draw calls, while
// also collecting up the other aspects of text natively.
//
// When using advanced-layers in nsDisplayText's constructor, we construct this
@ -350,15 +350,27 @@ class TextDrawTarget : public DrawTarget {
return wr::ToRoundedLayoutRect(mClipStack.LastElement());
}
LayoutDeviceRect GeckoClipRect() { return mClipStack.LastElement(); }
// Whether anything unsupported was encountered. Currently:
// Whether anything unsupported was encountered. This will result in this
// text being emitted as a blob, which means subpixel-AA can't be used and
// that performance will probably be a bit worse. At this point, we've
// properly implemented everything that shows up a lot, so you can assume
// that the remaining things we don't implement are fairly rare. The complete
// set of things that we don't implement are as follows:
//
// * Synthetic bold/italics
// * SVG fonts
// * Unserializable fonts
// * Tofu glyphs
// * Pratial ligatures
// * Text writing-mode
// * Text stroke
// * Unserializable Fonts: WR lives across an IPC boundary
// * Text-Combine-Upright Squishing: no one's really bothered to impl it yet
// * Text-Stroke: not a real standard (exists for webcompat)
// * SVG Glyphs: not a real standard (we got overzealous with svg)
// * Color Glyphs (Emoji) With Transparency: requires us to apply transparency
// with a composited layer (a single emoji can be many single-color glyphs)
//
// The transparent colored-glyphs issue is probably the most valuable to fix,
// since ideally it would also result in us fixing transparency for all
// intersecting glyphs (which currently look bad with or without webrender,
// so there's no fallback like with emoji). Specifically, transparency
// looks bad for "cursive" fonts where glyphs overlap at the seams. Since
// this is more common for non-latin scripts (e.g. मनीष), this amounts to us
// treating non-latin scripts poorly... unless they're emoji. Yikes!
bool mHasUnsupportedFeatures = false;
// The caller promises to call Save/Restore on the builder as needed.

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

@ -5,7 +5,7 @@ pref(gfx.font_rendering.opentype_svg.enabled,false) != svg-glyph-positioning.s
pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy-if(skiaContent,0-2,0-350) == svg-glyph-positioning.svg svg-glyph-positioning-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-html.html svg-glyph-html-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-direct.svg svg-glyph-direct-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy-if(webrender&&winWidget,129-138,2188-2461) fuzzy-if(OSX,134-134,2463-2463) == svg-glyph-invalid.html svg-glyph-invalid-ref.html
pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy-if(webrender&&OSX,176-176,2330-2330) fuzzy-if(!webrender&&OSX,134-134,2463-2463) == svg-glyph-invalid.html svg-glyph-invalid-ref.html
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-objectfill-solid.svg svg-glyph-objectfill-solid-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy-if(skiaContent,0-2,0-200) == svg-glyph-objectstroke-solid.svg svg-glyph-objectstroke-solid-ref.svg
pref(gfx.font_rendering.opentype_svg.enabled,true) fuzzy(0-1,0-7) fuzzy-if(gtkWidget&&/^Linux\x20x86_64/.test(http.oscpu),0-1,0-79) fuzzy-if(skiaContent,0-1,0-300) == svg-glyph-objectgradient.svg svg-glyph-objectgradient-ref.svg # see bug 871961#c5