From 687fbde2e4ee13637cb3fd9b1fec39a436ef73d7 Mon Sep 17 00:00:00 2001 From: caryclark Date: Tue, 22 Nov 2016 12:44:25 -0800 Subject: handle antialiased rendering as premultiplied Transparencies and bitmap patterns need to be unpremultiplied after Skia renders them so that PDFium can use its own compositing. Also added some linear (i.e. axial) gradient support, although its unclear if any of the test corpus uses this feature. R=dsinclair@chromium.org Review-Url: https://codereview.chromium.org/2520073003 --- core/fpdfapi/render/cpdf_renderstatus.cpp | 15 ++--- core/fpdfapi/render/cpdf_renderstatus.h | 4 -- core/fxge/cfx_fxgedevice.h | 4 -- core/fxge/cfx_renderdevice.h | 4 -- core/fxge/dib/fx_dib_main.cpp | 2 +- core/fxge/fx_dib.h | 19 +++--- core/fxge/ge/cfx_renderdevice.cpp | 6 -- core/fxge/skia/fx_skia_device.cpp | 97 ++++++++++++++----------------- core/fxge/skia/fx_skia_device.h | 6 -- fpdfsdk/fpdfformfill.cpp | 3 + fpdfsdk/fpdfview.cpp | 3 + 11 files changed, 69 insertions(+), 94 deletions(-) diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp index d2a17d27fc..aad9af04e3 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.cpp +++ b/core/fpdfapi/render/cpdf_renderstatus.cpp @@ -893,6 +893,9 @@ std::unique_ptr DrawPatternBitmap( CPDF_RenderContext context(pDoc, pCache); context.AppendLayer(pPattern->form(), &mtPattern2Bitmap); context.Render(&bitmap_device, &options, nullptr); +#if defined _SKIA_SUPPORT_PATHS_ + pBitmap->UnPreMultiply(); +#endif return pBitmap; } @@ -1136,9 +1139,6 @@ void CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject* pObj, #if defined _SKIA_SUPPORT_ DebugVerifyDeviceIsPreMultiplied(); #endif -#if defined _SKIA_SUPPORT_PATHS_ - UnPreMultiplyDevice(); -#endif } bool CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj, @@ -1547,6 +1547,9 @@ bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj, nullptr, nullptr, &m_Options, 0, m_bDropObjects, pFormResource, true); bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix); +#if defined _SKIA_SUPPORT_PATHS_ + bitmap->UnPreMultiply(); +#endif m_bStopped = bitmap_render.m_bStopped; if (pSMaskDict) { CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix(); @@ -1650,12 +1653,6 @@ void CPDF_RenderStatus::DebugVerifyDeviceIsPreMultiplied() const { } #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 f74f0ce9ae..b7e9fa6d0a 100644 --- a/core/fpdfapi/render/cpdf_renderstatus.h +++ b/core/fpdfapi/render/cpdf_renderstatus.h @@ -66,10 +66,6 @@ class CPDF_RenderStatus { 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 03fece7df5..8358e43666 100644 --- a/core/fxge/cfx_fxgedevice.h +++ b/core/fxge/cfx_fxgedevice.h @@ -39,10 +39,6 @@ class CFX_FxgeDevice : public CFX_RenderDevice { 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 6da1df7e92..d38b2981ba 100644 --- a/core/fxge/cfx_renderdevice.h +++ b/core/fxge/cfx_renderdevice.h @@ -230,10 +230,6 @@ class CFX_RenderDevice { 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 63db7adb91..83899553a2 100644 --- a/core/fxge/dib/fx_dib_main.cpp +++ b/core/fxge/dib/fx_dib_main.cpp @@ -67,7 +67,7 @@ CFX_DIBitmap::CFX_DIBitmap() { m_pBuffer = nullptr; m_pPalette = nullptr; #ifdef _SKIA_SUPPORT_PATHS_ - m_bUnPreMultiply = false; + m_nFormat = Format::kCleared; #endif } diff --git a/core/fxge/fx_dib.h b/core/fxge/fx_dib.h index daf2cdf9a5..1719ae13e5 100644 --- a/core/fxge/fx_dib.h +++ b/core/fxge/fx_dib.h @@ -371,20 +371,25 @@ class CFX_DIBitmap : public CFX_DIBSource { 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; } +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ + void PreMultiply(); +#endif +#if defined _SKIA_SUPPORT_PATHS_ + void UnPreMultiply(); #endif protected: bool GetGrayData(void* pIccTransform = nullptr); +#if defined _SKIA_SUPPORT_PATHS_ + enum class Format { kCleared, kPreMultiplied, kUnPreMultiplied }; +#endif + uint8_t* m_pBuffer; - bool m_bExtBuf; -#ifdef _SKIA_SUPPORT_PATHS_ - bool m_bUnPreMultiply; +#if defined _SKIA_SUPPORT_PATHS_ + Format m_nFormat; #endif + bool m_bExtBuf; }; class CFX_DIBExtractor { diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp index 10135273c6..64fa6ff452 100644 --- a/core/fxge/ge/cfx_renderdevice.cpp +++ b/core/fxge/ge/cfx_renderdevice.cpp @@ -822,12 +822,6 @@ bool CFX_RenderDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, } #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 973c4f2b34..136bab71c6 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -34,14 +34,14 @@ #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/pathops/SkPathOps.h" +#include "third_party/skia/include/core/SkShader.h" +#include "third_party/skia/include/effects/SkGradientShader.h" #ifdef _SKIA_SUPPORT_ #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkColorPriv.h" #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/effects/SkGradientShader.h" #endif // _SKIA_SUPPORT_ #ifdef SK_DEBUG @@ -313,7 +313,6 @@ SkBlendMode GetSkiaBlendMode(int blend_type) { } } -#ifdef _SKIA_SUPPORT_ bool AddColors(const CPDF_ExpIntFunc* pFunc, SkTDArray* skColors) { if (pFunc->CountInputs() != 1) return false; @@ -497,6 +496,7 @@ void ClipAngledGradient(const SkPoint pts[2], clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); } +#ifdef _SKIA_SUPPORT_ void SetBitmapMatrix(const CFX_Matrix* pMatrix, int width, int height, @@ -1171,14 +1171,12 @@ bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, positions[index] = {cp.m_OriginX * flip, cp.m_OriginY * vFlip}; glyphs[index] = (uint16_t)cp.m_GlyphIndex; } +#ifdef _SKIA_SUPPORT_PATHS_ + m_pBitmap->PreMultiply(); +#endif // _SKIA_SUPPORT_PATHS_ m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); m_pCanvas->restore(); -#ifdef _SKIA_SUPPORT_PATHS_ - if (FXARGB_A(color) < 255) { - m_pBitmap->MarkForUnPreMultiply(true); - } -#endif // _SKIA_SUPPORT_PATHS_ return true; } @@ -1449,6 +1447,9 @@ bool CFX_SkiaDeviceDriver::DrawPath( DebugShowSkiaPath(*fillPath); DebugShowCanvasMatrix(m_pCanvas); DebugShowCanvasClip(m_pCanvas); +#ifdef _SKIA_SUPPORT_PATHS_ + m_pBitmap->PreMultiply(); +#endif // _SKIA_SUPPORT_PATHS_ m_pCanvas->drawPath(*fillPath, skPaint); } if (pGraphState && stroke_alpha) { @@ -1457,15 +1458,12 @@ bool CFX_SkiaDeviceDriver::DrawPath( DebugShowCanvasClip(m_pCanvas); skPaint.setStyle(SkPaint::kStroke_Style); skPaint.setColor(stroke_color); +#ifdef _SKIA_SUPPORT_PATHS_ + m_pBitmap->PreMultiply(); +#endif // _SKIA_SUPPORT_PATHS_ m_pCanvas->drawPath(skPath, skPaint); } m_pCanvas->restore(); -#ifdef _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; } @@ -1498,7 +1496,6 @@ bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, return true; } -#ifdef _SKIA_SUPPORT_ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, const CFX_Matrix* pMatrix, const FX_RECT& clip_rect, @@ -1632,7 +1629,6 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, m_pCanvas->restore(); return true; } -#endif // _SKIA_SUPPORT_ uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const { return m_pBitmap->GetBuffer(); @@ -1680,6 +1676,7 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { #endif // _SKIA_SUPPORT_ #ifdef _SKIA_SUPPORT_PATHS_ + m_pBitmap->UnPreMultiply(); FX_RECT rect(left, top, left + pBitmap->GetWidth(), top + pBitmap->GetHeight()); CFX_DIBitmap* pBack = nullptr; @@ -1844,7 +1841,7 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, #ifdef _SKIA_SUPPORT_PATHS_ if (!m_pBitmap->GetBuffer()) return true; - + m_pBitmap->UnPreMultiply(); CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer; pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr); @@ -1866,17 +1863,27 @@ bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { #endif // _SKIA_SUPPORT_PATHS_ } -#ifdef _SKIA_SUPPORT_ +#if defined _SKIA_SUPPORT_ void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { - void* buffer = pDIBitmap->GetBuffer(); + pDIBitmap->PreMultiply(); +} +#endif // _SKIA_SUPPORT_ + +void CFX_DIBitmap::PreMultiply() { + if (this->GetBPP() != 32) + return; + void* buffer = this->GetBuffer(); if (!buffer) return; - if (pDIBitmap->GetBPP() != 32) { +#if defined _SKIA_SUPPORT_PATHS_ + Format priorFormat = m_nFormat; + m_nFormat = Format::kPreMultiplied; + if (priorFormat != Format::kUnPreMultiplied) return; - } - int height = pDIBitmap->GetHeight(); - int width = pDIBitmap->GetWidth(); - int rowBytes = pDIBitmap->GetPitch(); +#endif + int height = this->GetHeight(); + int width = this->GetWidth(); + int rowBytes = this->GetPitch(); SkImageInfo unpremultipliedInfo = SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); @@ -1884,24 +1891,24 @@ void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); unpremultiplied.readPixels(premultiplied); - pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); + this->DebugVerifyBitmapIsPreMultiplied(); } -#endif // _SKIA_SUPPORT_ #ifdef _SKIA_SUPPORT_PATHS_ -void CFX_SkiaDeviceDriver::UnPreMultiply(CFX_DIBitmap* pDIBitmap) { - if (!pDIBitmap->IsMarkedForUnPreMultiply()) +void CFX_DIBitmap::UnPreMultiply() { + if (this->GetBPP() != 32) return; - pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); - void* buffer = pDIBitmap->GetBuffer(); + void* buffer = this->GetBuffer(); if (!buffer) return; - if (pDIBitmap->GetBPP() != 32) { + Format priorFormat = m_nFormat; + m_nFormat = Format::kUnPreMultiplied; + if (priorFormat != Format::kPreMultiplied) return; - } - int height = pDIBitmap->GetHeight(); - int width = pDIBitmap->GetWidth(); - int rowBytes = pDIBitmap->GetPitch(); + this->DebugVerifyBitmapIsPreMultiplied(); + int height = this->GetHeight(); + int width = this->GetWidth(); + int rowBytes = this->GetPitch(); SkImageInfo premultipliedInfo = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); @@ -1909,7 +1916,6 @@ void CFX_SkiaDeviceDriver::UnPreMultiply(CFX_DIBitmap* pDIBitmap) { SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); premultiplied.readPixels(unpremultiplied); - pDIBitmap->MarkForUnPreMultiply(false); } #endif // _SKIA_SUPPORT_PATHS_ @@ -1977,10 +1983,10 @@ void CFX_SkiaDeviceDriver::Clear(uint32_t color) { #endif // _SKIA_SUPPORT_ void CFX_SkiaDeviceDriver::Dump() const { -#if SHOW_SKIA_PATH +#if SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ if (m_pCache) m_pCache->Dump(this); -#endif // SHOW_SKIA_PATH +#endif // SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ } #ifdef _SKIA_SUPPORT_ @@ -1990,12 +1996,6 @@ void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { } #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; @@ -2087,15 +2087,6 @@ bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, } #endif // _SKIA_SUPPORT_ -#ifdef _SKIA_SUPPORT_PATHS_ -void CFX_FxgeDevice::UnPreMultiplyDevice() { - CFX_SkiaDeviceDriver* skDriver = - static_cast(GetDeviceDriver()); - if (skDriver) - skDriver->UnPreMultiplyDevice(); -} -#endif // _SKIA_SUPPORT_PATHS_ - void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { #ifdef SK_DEBUG SkASSERT(32 == GetBPP()); diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index f2576a888d..06b7be3d82 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -140,13 +140,11 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { FX_FLOAT font_size, uint32_t color) override; -#ifdef _SKIA_SUPPORT_ bool DrawShading(const CPDF_ShadingPattern* pPattern, const CFX_Matrix* pMatrix, const FX_RECT& clip_rect, int alpha, bool bAlphaMode) override; -#endif virtual uint8_t* GetBuffer() const; @@ -157,10 +155,6 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { 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; diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp index e8a8a6e2d0..44204b766a 100644 --- a/fpdfsdk/fpdfformfill.cpp +++ b/fpdfsdk/fpdfformfill.cpp @@ -137,6 +137,9 @@ void FFLCommon(FPDF_FORMHANDLE hHandle, pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options); #endif // PDF_ENABLE_XFA +#ifdef _SKIA_SUPPORT_PATHS + CFXBitmapFromFPDFBitmap(bitmap)->UnPreMultiply(); +#endif pDevice->RestoreState(false); delete options.m_pOCContext; options.m_pOCContext = nullptr; diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp index d5f9a0e810..959bf14390 100644 --- a/fpdfsdk/fpdfview.cpp +++ b/fpdfsdk/fpdfview.cpp @@ -598,6 +598,9 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y, rotate, flags, true, nullptr); +#ifdef _SKIA_SUPPORT_PATHS_ + pBitmap->UnPreMultiply(); +#endif pPage->SetRenderContext(nullptr); } -- cgit v1.2.3