Bug 1400411 - text-layers: fallback if SVG fonts or tofu is found. r?jrmuizel draft
authorAlexis Beingessner <a.beingessner@gmail.com>
Fri, 22 Sep 2017 10:57:30 -0400
changeset 669881 07f230d9d8240c0f06892864b162b54cb4f08f4a
parent 669344 a7256afe828b7290ff9c97b21b71c6687982e372
child 669882 5d2ef09bc8a1e7950cb5c357938926a7cbe3bf12
push id81460
push userbmo:a.beingessner@gmail.com
push dateMon, 25 Sep 2017 14:48:33 +0000
reviewersjrmuizel
bugs1400411
milestone58.0a1
Bug 1400411 - text-layers: fallback if SVG fonts or tofu is found. r?jrmuizel MozReview-Commit-ID: 9vUK5r5sKWB
gfx/thebes/gfxFont.cpp
layout/generic/TextDrawTarget.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -35,16 +35,17 @@
 #include "mozilla/Likely.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "gfxMathTable.h"
 #include "gfxSVGGlyphs.h"
 #include "gfx2DGlue.h"
+#include "TextDrawTarget.h"
 
 #include "GreekCasing.h"
 
 #include "cairo.h"
 
 #include "harfbuzz/hb.h"
 #include "harfbuzz/hb-ot.h"
 
@@ -1917,16 +1918,20 @@ gfxFont::DrawGlyphs(const gfxShapedText 
             if (glyphCount > 0) {
                 const gfxShapedText::DetailedGlyph *details =
                     aShapedText->GetDetailedGlyphs(aOffset + i);
                 NS_ASSERTION(details, "detailedGlyph should not be missing!");
                 for (uint32_t j = 0; j < glyphCount; ++j, ++details) {
                     double advance = details->mAdvance;
 
                     if (glyphData->IsMissing()) {
+                        if (auto* textDrawer = aRunParams.context->GetTextDrawer()) {
+                            textDrawer->FoundUnsupportedFeature();
+                            return false;
+                        }
                         // Default-ignorable chars will have zero advance width;
                         // we don't have to draw the hexbox for them.
                         if (aRunParams.drawMode != DrawMode::GLYPH_PATH &&
                             advance > 0) {
                             double glyphX = aPt->x;
                             double glyphY = aPt->y;
                             if (aRunParams.isRTL) {
                                 if (aFontParams.isVerticalFont) {
@@ -2056,17 +2061,24 @@ gfxFont::Draw(const gfxTextRun *aTextRun
         fontParams.drawOptions = *aRunParams.drawOpts;
     }
 
     fontParams.scaledFont = GetScaledFont(aRunParams.dt);
     if (!fontParams.scaledFont) {
         return;
     }
 
+    auto* textDrawer = aRunParams.context->GetTextDrawer();
     fontParams.haveSVGGlyphs = GetFontEntry()->TryGetSVGData(this);
+
+    if (fontParams.haveSVGGlyphs && textDrawer) {
+        textDrawer->FoundUnsupportedFeature();
+        return;
+    }
+
     fontParams.haveColorGlyphs = GetFontEntry()->TryGetColorGlyphs();
     fontParams.contextPaint = aRunParams.runContextPaint;
     fontParams.isVerticalFont =
         aOrientation == gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT;
 
     bool sideways = false;
     gfxContextMatrixAutoSaveRestore matrixRestore;
 
--- a/layout/generic/TextDrawTarget.h
+++ b/layout/generic/TextDrawTarget.h
@@ -87,28 +87,29 @@ class TextDrawTarget : public DrawTarget
 public:
   // The different phases of drawing the text we're in
   // Each should only happen once, and in the given order.
   enum class Phase : uint8_t {
     eSelection, eUnderline, eOverline, eGlyphs, eEmphasisMarks, eLineThrough
   };
 
   explicit TextDrawTarget()
-  : mCurrentlyDrawing(Phase::eSelection)
+  : mCurrentlyDrawing(Phase::eSelection), mHasUnsupportedFeatures(false)
   {
     mCurrentTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, IntSize(1, 1), gfx::SurfaceFormat::B8G8R8A8);
     SetSelectionIndex(0);
   }
 
   // Prevent this from being copied
   TextDrawTarget(const TextDrawTarget& src) = delete;
   TextDrawTarget& operator=(const TextDrawTarget&) = delete;
 
   // Change the phase of text we're drawing.
   void StartDrawing(Phase aPhase) { mCurrentlyDrawing = aPhase; }
+  void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
 
   void SetSelectionIndex(size_t i) {
     // i should only be accessed if i-1 has already been
     MOZ_ASSERT(mParts.Length() <= i);
 
     if (mParts.Length() == i){
       mParts.AppendElement();
     }
@@ -252,16 +253,20 @@ public:
 
   }
 
   const nsTArray<SelectedTextRunFragment>& GetParts() { return mParts; }
 
   bool
   CanSerializeFonts()
   {
+    if (mHasUnsupportedFeatures) {
+      return false;
+    }
+
     for (const SelectedTextRunFragment& part : GetParts()) {
       for (const TextRunFragment& frag : part.text) {
         if (!frag.font->CanSerialize()) {
           return false;
         }
       }
     }
     return true;
@@ -380,16 +385,19 @@ private:
   SelectedTextRunFragment* mCurrentPart;
 
   // Chunks of the text, grouped by selection
   nsTArray<SelectedTextRunFragment> mParts;
 
   // A dummy to handle parts of the DrawTarget impl we don't care for
   RefPtr<DrawTarget> mCurrentTarget;
 
+  // Whether Tofu or SVG fonts were encountered
+  bool mHasUnsupportedFeatures;
+
   // The rest of this is dummy implementations of DrawTarget's API
 public:
   DrawTargetType GetType() const override {
     return DrawTargetType::SOFTWARE_RASTER;
   }
 
   BackendType GetBackendType() const override {
     return BackendType::WEBRENDER_TEXT;