fix corpus tests

All corpus tests draw reasonably well.
There are pixel differences, but no missing
features or large scale errors.

This was verified by running run_corpus_tests.py
on skiapaths and agg build dirs, then running
the skdiff tool to generate a report of the
pixel difference. For example, after running

$ ninja -C out/skia skdiff
$ ./out/skia/skdiff /repo/pdfium/out/agg/gen/pdfium/testing/corpus/ /repo/pdfium/out/skiapaths/gen/pdfium/testing/corpus/ ~/aggskiadiffs

view the report in a browser at ~/aggskiadiffs/index.html

R=dsinclair@chromium.org
BUG=skia:5973

Review-Url: https://codereview.chromium.org/2504863003
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index f16d3f8..d9f2a82 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -1125,6 +1125,9 @@
 #if defined _SKIA_SUPPORT_
   DebugVerifyDeviceIsPreMultiplied();
 #endif
+#if defined _SKIA_SUPPORT_PATHS_
+  UnPreMultiplyDevice();
+#endif
 }
 
 bool CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj,
@@ -1646,6 +1649,12 @@
 }
 #endif
 
+#if defined _SKIA_SUPPORT_PATHS_
+void CPDF_RenderStatus::UnPreMultiplyDevice() {
+  m_pDevice->UnPreMultiplyDevice();
+}
+#endif
+
 bool CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj,
                                     const CFX_Matrix* pObj2Device,
                                     CFX_PathData* pClippingPath) {
diff --git a/core/fpdfapi/render/cpdf_renderstatus.h b/core/fpdfapi/render/cpdf_renderstatus.h
index b7e9fa6..f74f0ce 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.h
+++ b/core/fpdfapi/render/cpdf_renderstatus.h
@@ -66,6 +66,10 @@
   void DebugVerifyDeviceIsPreMultiplied() const;
 #endif
 
+#if defined _SKIA_SUPPORT_PATHS_
+  void UnPreMultiplyDevice();
+#endif
+
   CPDF_RenderOptions m_Options;
   CPDF_Dictionary* m_pFormResource;
   CPDF_Dictionary* m_pPageResource;
diff --git a/core/fxge/cfx_fxgedevice.h b/core/fxge/cfx_fxgedevice.h
index 8358e43..03fece7 100644
--- a/core/fxge/cfx_fxgedevice.h
+++ b/core/fxge/cfx_fxgedevice.h
@@ -39,6 +39,10 @@
                        int blend_type) override;
 #endif
 
+#ifdef _SKIA_SUPPORT_PATHS_
+  void UnPreMultiplyDevice() override;
+#endif
+
  private:
   bool m_bOwnedBitmap;
 };
diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h
index d38b298..6da1df7 100644
--- a/core/fxge/cfx_renderdevice.h
+++ b/core/fxge/cfx_renderdevice.h
@@ -230,6 +230,10 @@
   void Flush();
 #endif
 
+#ifdef _SKIA_SUPPORT_PATHS_
+  virtual void UnPreMultiplyDevice();
+#endif
+
  private:
   void InitDeviceInfo();
   void UpdateClipBox();
diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp
index e593a63..9c91c74 100644
--- a/core/fxge/dib/fx_dib_main.cpp
+++ b/core/fxge/dib/fx_dib_main.cpp
@@ -63,6 +63,9 @@
   m_bExtBuf = false;
   m_pBuffer = nullptr;
   m_pPalette = nullptr;
+#ifdef _SKIA_SUPPORT_PATHS_
+  m_bUnPreMultiply = false;
+#endif
 }
 
 #define _MAX_OOM_LIMIT_ 12000000
diff --git a/core/fxge/fx_dib.h b/core/fxge/fx_dib.h
index c42c964..daf2cdf 100644
--- a/core/fxge/fx_dib.h
+++ b/core/fxge/fx_dib.h
@@ -248,7 +248,7 @@
                       int& src_top,
                       const CFX_ClipRgn* pClipRgn);
 
-#if defined _SKIA_SUPPORT_
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
   void DebugVerifyBitmapIsPreMultiplied(void* buffer = nullptr) const;
 #endif
 
@@ -371,11 +371,20 @@
 
   bool ConvertColorScale(uint32_t forecolor, uint32_t backcolor);
 
+#ifdef _SKIA_SUPPORT_PATHS_
+  bool IsMarkedForUnPreMultiply() const { return m_bUnPreMultiply; }
+
+  void MarkForUnPreMultiply(bool mark) { m_bUnPreMultiply = mark; }
+#endif
+
  protected:
   bool GetGrayData(void* pIccTransform = nullptr);
 
   uint8_t* m_pBuffer;
   bool m_bExtBuf;
+#ifdef _SKIA_SUPPORT_PATHS_
+  bool m_bUnPreMultiply;
+#endif
 };
 
 class CFX_DIBExtractor {
diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp
index 64bf0dd..a4ce6b7 100644
--- a/core/fxge/ge/cfx_renderdevice.cpp
+++ b/core/fxge/ge/cfx_renderdevice.cpp
@@ -13,7 +13,7 @@
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/ifx_renderdevicedriver.h"
 
-#if defined _SKIA_SUPPORT_
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
 #include "third_party/skia/include/core/SkTypes.h"
 #endif
 
@@ -817,6 +817,12 @@
 }
 #endif
 
+#ifdef _SKIA_SUPPORT_PATHS_
+void CFX_RenderDevice::UnPreMultiplyDevice() {
+  SkASSERT(0);
+}
+#endif
+
 bool CFX_RenderDevice::DrawNormalText(int nChars,
                                       const FXTEXT_CHARPOS* pCharPos,
                                       CFX_Font* pFont,
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 3ab0709..6c97637 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -20,15 +20,16 @@
 #include "core/fxge/cfx_renderdevice.h"
 #include "core/fxge/skia/fx_skia_device.h"
 
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
 #include "core/fxge/ge/cfx_cliprgn.h"
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 
 #include "third_party/base/ptr_util.h"
 
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/include/effects/SkDashPathEffect.h"
 #include "third_party/skia/include/pathops/SkPathOps.h"
 
@@ -38,18 +39,17 @@
 #include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
 #include "third_party/skia/include/core/SkShader.h"
-#include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
-#endif
+#endif  // _SKIA_SUPPORT_
 
 #ifdef SK_DEBUG
 #include "third_party/skia/include/core/SkClipStack.h"
-#endif
+#endif  // SK_DEBUG
 
 namespace {
 
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
 void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap,
                                 int dest_left,
                                 int dest_top,
@@ -149,7 +149,7 @@
   ASSERT(false);
 }
 
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 
 #define SHOW_SKIA_PATH 0  // set to 1 to print the path contents
 #define DRAW_SKIA_CLIP 0  // set to 1 to draw a green rectangle around the clip
@@ -174,6 +174,21 @@
 #endif  // SHOW_SKIA_PATH
 }
 
+void DebugShowCanvasClip(const SkCanvas* canvas) {
+#if SHOW_SKIA_PATH
+  SkRect local;
+  SkIRect device;
+  canvas->getClipBounds(&local);
+  printf("local bounds %g %g %g %g\n", local.fLeft, local.fTop, local.fRight,
+         local.fBottom);
+  canvas->getClipDeviceBounds(&device);
+  printf("device bounds %d %d %d %d\n", device.fLeft, device.fTop,
+         device.fRight, device.fBottom);
+  const SkClipStack* clipStack = canvas->getClipStack();
+  clipStack->dump();
+#endif  // SHOW_SKIA_PATH
+}
+
 #if DRAW_SKIA_CLIP
 
 SkPaint DebugClipPaint() {
@@ -184,12 +199,10 @@
   return paint;
 }
 
-#ifdef _SKIA_SUPPORT_
 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {
   SkPaint paint = DebugClipPaint();
   canvas->drawRect(rect, paint);
 }
-#endif
 
 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {
   SkPaint paint = DebugClipPaint();
@@ -198,17 +211,12 @@
 
 #else  // DRAW_SKIA_CLIP
 
-#ifdef _SKIA_SUPPORT_
 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {}
-#endif
 
 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {}
 
 #endif  // DRAW_SKIA_CLIP
 
-#undef SHOW_SKIA_PATH
-#undef DRAW_SKIA_CLIP
-
 #ifdef _SKIA_SUPPORT_
 static void DebugValidate(const CFX_DIBitmap* bitmap,
                           const CFX_DIBitmap* device) {
@@ -225,7 +233,7 @@
     }
   }
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 SkPath BuildPath(const CFX_PathData* pPathData) {
   SkPath skPath;
@@ -254,7 +262,7 @@
 
 SkMatrix ToSkMatrix(const CFX_Matrix& m) {
   SkMatrix skMatrix;
-  skMatrix.setAll(m.a, m.b, m.e, m.c, m.d, m.f, 0, 0, 1);
+  skMatrix.setAll(m.a, m.c, m.e, m.b, m.d, m.f, 0, 0, 1);
   return skMatrix;
 }
 
@@ -266,7 +274,7 @@
                   0, 1);
   return skMatrix;
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 SkBlendMode GetSkiaBlendMode(int blend_type) {
   switch (blend_type) {
@@ -590,7 +598,7 @@
   *heightPtr = height;
   return true;
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 }  // namespace
 
@@ -613,7 +621,7 @@
         m_commandIndex(0),
 #if _SKIA_SUPPORT_
         m_drawText(false),
-#endif
+#endif  // _SKIA_SUPPORT_
         m_drawPath(false),
         m_fillPath(false),
         m_debugDisable(true) {
@@ -634,7 +642,7 @@
 #if _SKIA_SUPPORT_
     if (m_drawText)
       FlushText(pDriver);
-#endif
+#endif  // _SKIA_SUPPORT_
     if (m_drawPath && DrawChanged(pMatrix, pDrawState, fill_color, stroke_color,
                                   fill_mode, blend_type)) {
       FlushPath(pDriver);
@@ -765,7 +773,7 @@
     skCanvas->restore();
     m_drawText = false;
   }
-#endif
+#endif  // _SKIA_SUPPORT_
 
   bool SetClipFill(const CFX_PathData* pPathData,
                    const CFX_Matrix* pMatrix,
@@ -958,11 +966,11 @@
 #ifdef _SKIA_SUPPORT_
     if (m_drawText)
       FlushText(pDriver);
-#endif
+#endif  // _SKIA_SUPPORT_
   }
 
-#ifdef SK_DEBUG
   void Dump(const CFX_SkiaDeviceDriver* pDriver) const {
+#if SHOW_SKIA_PATH
     SkDebugf("\n\nSkia Save Count %d:\n", pDriver->m_pCanvas->getSaveCount());
     pDriver->m_pCanvas->getClipStack()->dump();
     SkDebugf("Cache:\n");
@@ -981,8 +989,8 @@
     }
     if (m_commandIndex == m_commands.count())
       SkDebugf("-->\n");
+#endif  // SHOW_SKIA_PATH
   }
-#endif
 
  private:
   SkTArray<SkPath> m_clips;        // stack of clips that may be reused
@@ -1003,7 +1011,7 @@
   int m_commandIndex;  // active position in clip command stack
 #ifdef _SKIA_SUPPORT_
   bool m_drawText;
-#endif
+#endif  // _SKIA_SUPPORT_
   bool m_drawPath;
   bool m_fillPath;
   bool m_debugDisable;  // turn off cache for debugging
@@ -1082,11 +1090,11 @@
       m_pOriDevice(pOriDevice),
       m_pRecorder(nullptr),
       m_pCache(new SkiaState),
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
       m_pClipRgn(nullptr),
       m_FillFlags(0),
       m_bRgbByteOrder(bRgbByteOrder),
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
       m_bGroupKnockout(bGroupKnockout) {
   SkBitmap skBitmap;
   SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32);
@@ -1119,7 +1127,7 @@
       m_bGroupKnockout(false) {
   m_pCanvas = m_pRecorder->getRecordingCanvas();
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
   Flush();
@@ -1168,9 +1176,11 @@
   m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint);
   m_pCanvas->restore();
   return true;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   return false;
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const {
@@ -1191,7 +1201,9 @@
       return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
              FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT |
              FXRC_FILLSTROKE_PATH | FXRC_SHADING;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
     case FXDC_PIXEL_WIDTH:
       return m_pBitmap->GetWidth();
     case FXDC_PIXEL_HEIGHT:
@@ -1218,30 +1230,30 @@
       }
       return flags;
     }
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   }
   return 0;
 }
 
 void CFX_SkiaDeviceDriver::SaveState() {
-#ifdef _SKIA_SUPPORT_
   if (!m_pCache->ClipSave(this))
     m_pCanvas->save();
-#else
+
+#ifdef _SKIA_SUPPORT_PATHS_
   std::unique_ptr<CFX_ClipRgn> pClip;
   if (m_pClipRgn)
     pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn);
   m_StateStack.push_back(std::move(pClip));
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) {
-#ifdef _SKIA_SUPPORT_
   if (!m_pCache->ClipRestore(this))
     m_pCanvas->restore();
-  if (bKeepSaved)
-    SaveState();
-#else
+  if (bKeepSaved && !m_pCache->ClipSave(this))
+    m_pCanvas->save();
+
+#ifdef _SKIA_SUPPORT_PATHS_
   m_pClipRgn.reset();
 
   if (m_StateStack.empty())
@@ -1254,10 +1266,10 @@
     m_pClipRgn = std::move(m_StateStack.back());
     m_StateStack.pop_back();
   }
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
 void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox,
                                        const SkPath& path) {
   FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1,
@@ -1276,18 +1288,15 @@
                        pThisLayer->GetPitch(), nullptr, nullptr, nullptr);
   SkCanvas* canvas = new SkCanvas(bitmap);
   canvas->translate(
-      clipBox.left,
-      clipBox.top);  // FIXME(caryclark) wrong sign(s)? upside down?
+      -path_rect.left,
+      -path_rect.top);  // FIXME(caryclark) wrong sign(s)? upside down?
   SkPaint paint;
   paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0);
   canvas->drawPath(path, paint);
-  std::unique_ptr<uint8_t, FxFreeDeleter> raw_buf;
-  raw_buf.reset(
-      FX_Alloc2D(uint8_t, pThisLayer->GetWidth(), pThisLayer->GetHeight()));
   m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask);
   delete canvas;
 }
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 
 bool CFX_SkiaDeviceDriver::SetClip_PathFill(
     const CFX_PathData* pPathData,     // path info
@@ -1299,29 +1308,31 @@
 #ifdef _SKIA_SUPPORT_
   if (m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode, this))
     return true;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   m_FillFlags = fill_mode;
   if (!m_pClipRgn) {
     m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   }
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   if (pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) {
     CFX_FloatRect rectf;
     if (pPathData->IsRect(deviceMatrix, &rectf)) {
       rectf.Intersect(
           CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
                         (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
-#ifdef _SKIA_SUPPORT_
       // note that PDF's y-axis goes up; Skia's y-axis goes down
       SkRect skClipRect =
           SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top);
       DebugDrawSkiaClipRect(m_pCanvas, skClipRect);
       m_pCanvas->clipRect(skClipRect, SkCanvas::kIntersect_Op, true);
-#else
+
+#ifdef _SKIA_SUPPORT_PATHS_
       FX_RECT rect = rectf.GetOuterRect();
       m_pClipRgn->IntersectRect(rect);
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
       return true;
     }
   }
@@ -1334,11 +1345,11 @@
   DebugShowSkiaPath(skClipPath);
   DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
   m_pCanvas->clipPath(skClipPath, SkCanvas::kIntersect_Op, true);
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
   FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
                   GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   SetClipMask(clipBox, skClipPath);
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   return true;
 }
 
@@ -1350,12 +1361,14 @@
 #ifdef _SKIA_SUPPORT_
   if (m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState, this))
     return true;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   if (!m_pClipRgn) {
     m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
         GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   }
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   // build path data
   SkPath skPath = BuildPath(pPathData);
   SkMatrix skMatrix = ToSkMatrix(*pObject2Device);
@@ -1367,11 +1380,13 @@
   DebugDrawSkiaClipPath(m_pCanvas, dst_path);
 #ifdef _SKIA_SUPPORT_
   m_pCanvas->clipPath(dst_path, SkCanvas::kIntersect_Op, true);
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
                   GetDeviceCaps(FXDC_PIXEL_HEIGHT));
   SetClipMask(clipBox, dst_path);
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   return true;
 }
 
@@ -1422,16 +1437,26 @@
     }
     skPaint.setStyle(SkPaint::kFill_Style);
     skPaint.setColor(fill_color);
+    DebugShowSkiaPath(*fillPath);
+    DebugShowCanvasMatrix(m_pCanvas);
+    DebugShowCanvasClip(m_pCanvas);
     m_pCanvas->drawPath(*fillPath, skPaint);
   }
   if (pGraphState && stroke_alpha) {
     DebugShowSkiaPath(skPath);
     DebugShowCanvasMatrix(m_pCanvas);
+    DebugShowCanvasClip(m_pCanvas);
     skPaint.setStyle(SkPaint::kStroke_Style);
     skPaint.setColor(stroke_color);
     m_pCanvas->drawPath(skPath, skPaint);
   }
   m_pCanvas->restore();
+#if defined _SKIA_SUPPORT_PATHS_
+  if ((fill_mode & 3 && FXARGB_A(fill_color) < 255) ||
+      (pGraphState && stroke_alpha < 255)) {
+    m_pBitmap->MarkForUnPreMultiply(true);
+  }
+#endif  // _SKIA_SUPPORT_PATHS_
   return true;
 }
 
@@ -1451,10 +1476,16 @@
   spaint.setAntiAlias(true);
   spaint.setColor(fill_color);
   spaint.setBlendMode(GetSkiaBlendMode(blend_type));
-
-  m_pCanvas->drawRect(
-      SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom),
-      spaint);
+  DebugShowCanvasClip(m_pCanvas);
+  DebugShowCanvasMatrix(m_pCanvas);
+  SkRect rect =
+      SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom),
+                       pRect->right, SkTMax(pRect->bottom, pRect->top));
+#if SHOW_SKIA_PATH
+  printf("fill rect = %g %g %g %g\n\n", rect.fLeft, rect.fTop, rect.fRight,
+         rect.fBottom);
+#endif  // SHOW_SKIA_PATH
+  m_pCanvas->drawRect(rect, spaint);
   return true;
 }
 
@@ -1592,7 +1623,7 @@
   m_pCanvas->restore();
   return true;
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
   return m_pBitmap->GetBuffer();
@@ -1637,7 +1668,9 @@
   SkCanvas canvas(skDstBitmap);
   canvas.drawBitmap(skSrcBitmap, left, top, nullptr);
   return true;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   FX_RECT rect(left, top, left + pBitmap->GetWidth(),
                top + pBitmap->GetHeight());
   CFX_DIBitmap* pBack = nullptr;
@@ -1666,7 +1699,7 @@
   }
   delete pBack;
   return bRet;
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() {
@@ -1687,7 +1720,9 @@
                top + pBitmap->GetHeight());
   void* dummy;
   return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type);
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   if (pBitmap->IsAlphaMask()) {
     return m_pBitmap->CompositeMask(
         left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
@@ -1697,7 +1732,7 @@
   return m_pBitmap->CompositeBitmap(
       left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
       pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr);
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
@@ -1724,7 +1759,9 @@
   m_pCanvas->restore();
 
   return result;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   if (dest_width == pSource->GetWidth() &&
       dest_height == pSource->GetHeight()) {
     FX_RECT rect(0, 0, dest_width, dest_height);
@@ -1744,7 +1781,7 @@
   if (stretcher.Start())
     stretcher.Continue(nullptr);
   return true;
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
@@ -1793,7 +1830,9 @@
   if (ct)
     ct->unref();
   DebugValidate(m_pBitmap, m_pOriDevice);
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   if (!m_pBitmap->GetBuffer())
     return true;
 
@@ -1801,19 +1840,21 @@
   pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb,
                    pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr);
   handle = pRenderer;
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
   return true;
 }
 
 bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) {
 #ifdef _SKIA_SUPPORT_
   return false;
-#else
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
   if (!m_pBitmap->GetBuffer()) {
     return true;
   }
   return static_cast<CFX_ImageRenderer*>(handle)->Continue(pPause);
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
 }
 
 #ifdef _SKIA_SUPPORT_
@@ -1836,7 +1877,34 @@
   unpremultiplied.readPixels(premultiplied);
   pDIBitmap->DebugVerifyBitmapIsPreMultiplied();
 }
+#endif  // _SKIA_SUPPORT_
 
+#ifdef _SKIA_SUPPORT_PATHS_
+void CFX_SkiaDeviceDriver::UnPreMultiply(CFX_DIBitmap* pDIBitmap) {
+  if (!pDIBitmap->IsMarkedForUnPreMultiply())
+    return;
+  pDIBitmap->DebugVerifyBitmapIsPreMultiplied();
+  void* buffer = pDIBitmap->GetBuffer();
+  if (!buffer)
+    return;
+  if (pDIBitmap->GetBPP() != 32) {
+    return;
+  }
+  int height = pDIBitmap->GetHeight();
+  int width = pDIBitmap->GetWidth();
+  int rowBytes = pDIBitmap->GetPitch();
+  SkImageInfo premultipliedInfo =
+      SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
+  SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
+  SkImageInfo unpremultipliedInfo =
+      SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
+  SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
+  premultiplied.readPixels(unpremultiplied);
+  pDIBitmap->MarkForUnPreMultiply(false);
+}
+#endif  // _SKIA_SUPPORT_PATHS_
+
+#ifdef _SKIA_SUPPORT_
 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource,
                                             const CFX_DIBSource* pMask,
                                             int bitmap_alpha,
@@ -1897,13 +1965,13 @@
 void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
   m_pCanvas->clear(color);
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 void CFX_SkiaDeviceDriver::Dump() const {
-#ifdef SK_DEBUG
+#if SHOW_SKIA_PATH
   if (m_pCache)
     m_pCache->Dump(this);
-#endif
+#endif  // SHOW_SKIA_PATH
 }
 
 #ifdef _SKIA_SUPPORT_
@@ -1911,12 +1979,18 @@
   if (m_pOriDevice)
     m_pOriDevice->DebugVerifyBitmapIsPreMultiplied();
 }
-#endif
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
+void CFX_SkiaDeviceDriver::UnPreMultiplyDevice() {
+  UnPreMultiply(m_pBitmap);
+}
+#endif  // _SKIA_SUPPORT_PATHS_
 
 CFX_FxgeDevice::CFX_FxgeDevice() {
 #ifdef _SKIA_SUPPORT_
   m_bOwnedBitmap = false;
-#endif
+#endif  // _SKIA_SUPPORT_
 }
 
 #ifdef _SKIA_SUPPORT_
@@ -1931,7 +2005,7 @@
   SetDeviceDriver(pdfium::WrapUnique(skDriver));
   return skDriver->GetRecorder();
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap,
                             bool bRgbByteOrder,
@@ -1952,7 +2026,7 @@
   SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(recorder));
   return true;
 }
-#endif
+#endif  // _SKIA_SUPPORT_
 
 bool CFX_FxgeDevice::Create(int width,
                             int height,
@@ -1976,7 +2050,7 @@
   // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately
   if (m_bOwnedBitmap && GetBitmap())
     delete GetBitmap();
-#endif
+#endif  // _SKIA_SUPPORT_
 }
 
 #ifdef _SKIA_SUPPORT_
@@ -1986,7 +2060,7 @@
       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
   if (skDriver)
     skDriver->DebugVerifyBitmapIsPreMultiplied();
-#endif
+#endif  // SK_DEBUG
 }
 
 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap,
@@ -2002,6 +2076,16 @@
                                      blend_type);
   return false;
 }
+#endif  // _SKIA_SUPPORT_
+
+#ifdef _SKIA_SUPPORT_PATHS_
+void CFX_FxgeDevice::UnPreMultiplyDevice() {
+  CFX_SkiaDeviceDriver* skDriver =
+      static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
+  if (skDriver)
+    skDriver->UnPreMultiplyDevice();
+}
+#endif  // _SKIA_SUPPORT_PATHS_
 
 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const {
 #ifdef SK_DEBUG
@@ -2023,11 +2107,10 @@
       SkASSERT(b <= a);
     }
   }
-#endif
+#endif  // SK_DEBUG
 }
-#endif
 
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
 class CFX_Renderer {
  private:
   int m_Alpha, m_Red, m_Green, m_Blue, m_Gray;
@@ -2856,4 +2939,4 @@
   }
 };
 
-#endif
+#endif  // _SKIA_SUPPORT_PATHS_
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index ca5707c..e14ea7c 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -93,7 +93,9 @@
                        int dest_top,
                        int bitmap_alpha,
                        int blend_type) override;
-#else
+#endif
+
+#ifdef _SKIA_SUPPORT_PATHS_
   void SetClipMask(const FX_RECT& clipBox, const SkPath& skClipPath);
 #endif
 
@@ -149,6 +151,10 @@
   void Flush();
   SkPictureRecorder* GetRecorder() const { return m_pRecorder; }
   static void PreMultiply(CFX_DIBitmap* pDIBitmap);
+#ifdef _SKIA_SUPPORT_PATHS_
+  void UnPreMultiplyDevice();
+  void UnPreMultiply(CFX_DIBitmap* pDIBitmap);
+#endif
   SkCanvas* SkiaCanvas() { return m_pCanvas; }
   void DebugVerifyBitmapIsPreMultiplied() const;
   void Dump() const;
@@ -161,7 +167,7 @@
   SkCanvas* m_pCanvas;
   SkPictureRecorder* const m_pRecorder;
   std::unique_ptr<SkiaState> m_pCache;
-#ifndef _SKIA_SUPPORT_
+#ifdef _SKIA_SUPPORT_PATHS_
   std::unique_ptr<CFX_ClipRgn> m_pClipRgn;
   std::vector<std::unique_ptr<CFX_ClipRgn>> m_StateStack;
   int m_FillFlags;