diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render.cpp | 41 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render_image.cpp | 19 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_render/render_int.h | 4 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge_device.cpp | 16 | ||||
-rw-r--r-- | core/fxge/include/fx_dib.h | 4 | ||||
-rw-r--r-- | core/fxge/include/fx_ge.h | 7 | ||||
-rw-r--r-- | core/fxge/skia/fx_skia_device.cpp | 243 | ||||
-rw-r--r-- | core/fxge/skia/fx_skia_device.h | 3 |
8 files changed, 170 insertions, 167 deletions
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp index add2a8ae23..81a02cc6a7 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp @@ -213,6 +213,9 @@ FX_BOOL CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext, void CPDF_RenderStatus::RenderObjectList( const CPDF_PageObjectHolder* pObjectHolder, const CFX_Matrix* pObj2Device) { +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif CFX_FloatRect clip_rect(m_pDevice->GetClipBox()); CFX_Matrix device2object; device2object.SetReverse(*pObj2Device); @@ -236,9 +239,16 @@ void CPDF_RenderStatus::RenderObjectList( if (m_bStopped) return; } +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif } + void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device) { +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth); if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) { return; @@ -254,6 +264,9 @@ void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, return; } ProcessObjectNoClip(pObj, pObj2Device); +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif } FX_BOOL CPDF_RenderStatus::ContinueSingleObject(const CPDF_PageObject* pObj, @@ -319,6 +332,9 @@ FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device) { +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif FX_BOOL bRet = FALSE; switch (pObj->GetType()) { case CPDF_PageObject::TEXT: @@ -339,6 +355,9 @@ void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, } if (!bRet) DrawObjWithBackground(pObj, pObj2Device); +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif } FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj, @@ -396,8 +415,12 @@ void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, status.RenderSingleObject(pObj, &matrix); buffer.OutputToDevice(); } + FX_BOOL CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj, const CFX_Matrix* pObj2Device) { +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDictBy("OC"); if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) { @@ -418,8 +441,12 @@ FX_BOOL CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj, status.RenderObjectList(pFormObj->m_pForm, &matrix); m_bStopped = status.m_bStopped; m_pDevice->RestoreState(false); +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif return TRUE; } + FX_BOOL IsAvailableMatrix(const CFX_Matrix& matrix) { if (matrix.a == 0 || matrix.d == 0) { return matrix.b != 0 && matrix.c != 0; @@ -645,6 +672,9 @@ FX_BOOL CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* pPathObj, } FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, const CFX_Matrix* pObj2Device) { +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState.GetObject(); int blend_type = @@ -745,12 +775,10 @@ FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, oriDevice.reset(new CFX_DIBitmap); if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height)) return TRUE; - m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top); } if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get())) return TRUE; - CFX_DIBitmap* bitmap = bitmap_device.GetBitmap(); bitmap->Clear(0); CFX_Matrix new_matrix = *pObj2Device; @@ -813,6 +841,9 @@ FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, } CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type, Transparency); +#if defined _SKIA_SUPPORT_ + DebugVerifyDeviceIsPreMultiplied(); +#endif return TRUE; } @@ -1263,3 +1294,9 @@ void CPDF_ScaledRenderBuffer::OutputToDevice() { m_Rect.top, m_Rect.Width(), m_Rect.Height()); } } + +#if defined _SKIA_SUPPORT_ +void CPDF_RenderStatus::DebugVerifyDeviceIsPreMultiplied() const { + m_pDevice->DebugVerifyBitmapIsPreMultiplied(); +} +#endif diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp index 10fd5f3f15..b9826a9338 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp @@ -63,8 +63,7 @@ void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, #endif } #ifdef _SKIA_SUPPORT_ - static_cast<CFX_SkiaDeviceDriver*>(m_pDevice->GetDeviceDriver()) - ->PreMultiply(pDIBitmap); + CFX_SkiaDeviceDriver::PreMultiply(pDIBitmap); #endif if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { return; @@ -717,7 +716,7 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); #ifdef _SKIA_SUPPORT_ - bitmap_device1.PreMultiply(); // convert unpremultiplied to premultiplied + CFX_SkiaDeviceDriver::PreMultiply(bitmap_device1.GetBitmap()); #endif if (m_BitmapAlpha < 255) { bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); @@ -737,6 +736,19 @@ FX_BOOL CPDF_ImageRenderer::StartDIBSource() { m_Flags |= RENDER_FORCE_DOWNSAMPLE; } } +#ifdef _SKIA_SUPPORT_ + CFX_DIBitmap* premultiplied = m_pDIBSource->Clone(); + CFX_SkiaDeviceDriver::PreMultiply(premultiplied); + if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( + premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, + m_DeviceHandle, m_BlendType)) { + if (m_DeviceHandle) { + m_Status = 3; + return TRUE; + } + return FALSE; + } +#else if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( m_pDIBSource, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, m_DeviceHandle, m_BlendType)) { @@ -746,6 +758,7 @@ FX_BOOL CPDF_ImageRenderer::StartDIBSource() { } return FALSE; } +#endif CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); FX_RECT image_rect = image_rect_f.GetOutterRect(); int dest_width = image_rect.Width(); diff --git a/core/fpdfapi/fpdf_render/render_int.h b/core/fpdfapi/fpdf_render/render_int.h index 67eae91f59..d86a62ab19 100644 --- a/core/fpdfapi/fpdf_render/render_int.h +++ b/core/fpdfapi/fpdf_render/render_int.h @@ -150,6 +150,10 @@ class CPDF_RenderStatus { IFX_Pause* pPause); CPDF_RenderContext* GetContext() { return m_pContext; } +#if defined _SKIA_SUPPORT_ + void DebugVerifyDeviceIsPreMultiplied() const; +#endif + CPDF_RenderOptions m_Options; CPDF_Dictionary* m_pFormResource; CPDF_Dictionary* m_pPageResource; diff --git a/core/fxge/ge/fx_ge_device.cpp b/core/fxge/ge/fx_ge_device.cpp index 00cc541c22..9bb950beed 100644 --- a/core/fxge/ge/fx_ge_device.cpp +++ b/core/fxge/ge/fx_ge_device.cpp @@ -7,6 +7,10 @@ #include "core/fxge/include/fx_ge.h" #include "core/fxge/include/ifx_renderdevicedriver.h" +#if defined _SKIA_SUPPORT_ +#include "third_party/skia/include/core/SkTypes.h" +#endif + CFX_RenderDevice::CFX_RenderDevice() : m_pBitmap(nullptr), m_Width(0), @@ -20,6 +24,11 @@ CFX_RenderDevice::~CFX_RenderDevice() { delete m_pDeviceDriver; } +void CFX_RenderDevice::Flush() { + delete m_pDeviceDriver; + m_pDeviceDriver = nullptr; +} + void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) { delete m_pDeviceDriver; m_pDeviceDriver = pDriver; @@ -480,3 +489,10 @@ FX_BOOL CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) { void CFX_RenderDevice::CancelDIBits(void* handle) { m_pDeviceDriver->CancelDIBits(handle); } + +#ifdef _SKIA_SUPPORT_ + +void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { + SkASSERT(0); +} +#endif diff --git a/core/fxge/include/fx_dib.h b/core/fxge/include/fx_dib.h index 5a31722a82..8d9f27e3f7 100644 --- a/core/fxge/include/fx_dib.h +++ b/core/fxge/include/fx_dib.h @@ -247,6 +247,10 @@ class CFX_DIBSource { int& src_top, const CFX_ClipRgn* pClipRgn); +#if defined _SKIA_SUPPORT_ + void DebugVerifyBitmapIsPreMultiplied(void* buffer = nullptr) const; +#endif + CFX_DIBitmap* m_pAlphaMask; protected: diff --git a/core/fxge/include/fx_ge.h b/core/fxge/include/fx_ge.h index 5599a75f59..ea2adec1dc 100644 --- a/core/fxge/include/fx_ge.h +++ b/core/fxge/include/fx_ge.h @@ -215,6 +215,7 @@ class CFX_RenderDevice { CFX_RenderDevice(); virtual ~CFX_RenderDevice(); + void Flush(); void SetDeviceDriver(IFX_RenderDeviceDriver* pDriver); IFX_RenderDeviceDriver* GetDeviceDriver() const { return m_pDeviceDriver; } @@ -378,6 +379,10 @@ class CFX_RenderDevice { CFX_PathData* pClippingPath, int nFlag); +#ifdef _SKIA_SUPPORT_ + virtual void DebugVerifyBitmapIsPreMultiplied() const; +#endif + private: void InitDeviceInfo(); void UpdateClipBox(); @@ -416,7 +421,7 @@ class CFX_FxgeDevice : public CFX_RenderDevice { #ifdef _SKIA_SUPPORT_ bool AttachRecorder(SkPictureRecorder* recorder); SkPictureRecorder* CreateRecorder(int size_x, int size_y); - void PreMultiply(); + void DebugVerifyBitmapIsPreMultiplied() const override; #endif protected: diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index 148f623124..222c8466e0 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -86,41 +86,18 @@ void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {} #undef SHOW_SKIA_PATH #undef DRAW_SKIA_CLIP -static void DebugVerifyBitmapIsPreMultiplied(void* buffer, - int width, - int height) { -#ifdef SK_DEBUG - // verify that input is really premultiplied - for (int y = 0; y < height; ++y) { - const uint32_t* srcRow = static_cast<const uint32_t*>(buffer) + y * width; - for (int x = 0; x < width; ++x) { - uint8_t a = SkGetPackedA32(srcRow[x]); - uint8_t r = SkGetPackedR32(srcRow[x]); - uint8_t g = SkGetPackedG32(srcRow[x]); - uint8_t b = SkGetPackedB32(srcRow[x]); - SkA32Assert(a); - SkASSERT(r <= a); - SkASSERT(g <= a); - SkASSERT(b <= a); - } - } -#endif -} - static void DebugValidate(const CFX_DIBitmap* bitmap, const CFX_DIBitmap* device) { if (bitmap) { SkASSERT(bitmap->GetBPP() == 8 || bitmap->GetBPP() == 32); if (bitmap->GetBPP() == 32) { - DebugVerifyBitmapIsPreMultiplied(bitmap->GetBuffer(), bitmap->GetWidth(), - bitmap->GetHeight()); + bitmap->DebugVerifyBitmapIsPreMultiplied(); } } if (device) { SkASSERT(device->GetBPP() == 8 || device->GetBPP() == 32); if (device->GetBPP() == 32) { - DebugVerifyBitmapIsPreMultiplied(device->GetBuffer(), device->GetWidth(), - device->GetHeight()); + device->DebugVerifyBitmapIsPreMultiplied(); } } } @@ -291,98 +268,6 @@ bool AddStitching(const CPDF_StitchFunc* pFunc, return true; } -void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, - int dest_left, - int dest_top, - int width, - int height, - const CFX_DIBSource* pSrcBitmap, - int src_left, - int src_top) { - if (!pBitmap) - return; - pBitmap->GetOverlapRect(dest_left, dest_top, width, height, - pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(), - src_left, src_top, nullptr); - if (width == 0 || height == 0) - return; - int Bpp = pBitmap->GetBPP() / 8; - FXDIB_Format dest_format = pBitmap->GetFormat(); - FXDIB_Format src_format = pSrcBitmap->GetFormat(); - int pitch = pBitmap->GetPitch(); - uint8_t* buffer = pBitmap->GetBuffer(); - if (dest_format == src_format) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp; - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; - if (Bpp == 4) { - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0], - src_scan[1], src_scan[2])); - dest_scan += 4; - src_scan += 4; - } - } else { - for (int col = 0; col < width; col++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = src_scan[0]; - src_scan += 3; - } - } - } - return; - } - uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp; - if (dest_format == FXDIB_Rgb) { - if (src_format == FXDIB_Rgb32) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * pitch; - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4; - for (int col = 0; col < width; col++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = src_scan[0]; - src_scan += 4; - } - } - } else { - ASSERT(FALSE); - } - } else if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) { - if (src_format == FXDIB_Rgb) { - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch); - uint8_t* src_scan = - (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3; - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], - src_scan[2])); - dest_scan += 4; - src_scan += 3; - } - } - } else if (src_format == FXDIB_Rgb32) { - ASSERT(dest_format == FXDIB_Argb); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_buf + row * pitch; - uint8_t* src_scan = - (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4); - for (int col = 0; col < width; col++) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], - src_scan[2])); - src_scan += 4; - dest_scan += 4; - } - } - } - } else { - ASSERT(FALSE); - } -} - // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) { return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY + @@ -525,11 +410,13 @@ class SkiaState { m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType); - m_drawState = *pDrawState; + if (pDrawState) + m_drawState.Copy(*pDrawState); m_fillColor = fill_color; m_strokeColor = stroke_color; m_blendType = blend_type; - m_drawMatrix = *pMatrix; + if (pMatrix) + m_drawMatrix = *pMatrix; } SkPath skPath = BuildPath(pPathData); SkPoint delta; @@ -633,6 +520,7 @@ class SkiaState { skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); skPaint.setTextSize(m_fontSize); skPaint.setSubpixelText(true); + skPaint.setHinting(SkPaint::kNo_Hinting); SkCanvas* skCanvas = pDriver->SkiaCanvas(); skCanvas->save(); skCanvas->concat(skMatrix); @@ -690,6 +578,9 @@ class SkiaState { } bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) { + CFX_Matrix identityMatrix; + if (!pMatrix) + pMatrix = &identityMatrix; delta->set(pMatrix->e - m_drawMatrix.e, pMatrix->f - m_drawMatrix.f); if (!delta->fX && !delta->fY) return true; @@ -789,12 +680,18 @@ class SkiaState { } bool MatrixChanged(const CFX_Matrix* pMatrix, const CFX_Matrix& refMatrix) { + CFX_Matrix identityMatrix; + if (!pMatrix) + pMatrix = &identityMatrix; return pMatrix->a != refMatrix.a || pMatrix->b != refMatrix.b || pMatrix->c != refMatrix.c || pMatrix->d != refMatrix.d; } bool StateChanged(const CFX_GraphStateData* pState, const CFX_GraphStateData& refState) { + CFX_GraphStateData identityState; + if (!pState) + pState = &identityState; return pState->m_LineWidth != refState.m_LineWidth || pState->m_LineCap != refState.m_LineCap || pState->m_LineJoin != refState.m_LineJoin || @@ -804,9 +701,10 @@ class SkiaState { bool DashChanged(const CFX_GraphStateData* pState, const CFX_GraphStateData& refState) { - if (!pState->m_DashArray && !refState.m_DashArray) + bool dashArray = pState && pState->m_DashArray; + if (!dashArray && !refState.m_DashArray) return false; - if (!pState->m_DashArray || !refState.m_DashArray) + if (!dashArray || !refState.m_DashArray) return true; if (pState->m_DashPhase != refState.m_DashPhase || pState->m_DashCount != refState.m_DashCount) { @@ -946,7 +844,6 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, m_pOriDevice(pOriDevice), m_pRecorder(nullptr), m_pCache(new SkiaState), - m_bRgbByteOrder(bRgbByteOrder), m_bGroupKnockout(bGroupKnockout) { SkBitmap skBitmap; SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32); @@ -967,7 +864,6 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y) m_pOriDevice(nullptr), m_pRecorder(new SkPictureRecorder), m_pCache(new SkiaState), - m_bRgbByteOrder(FALSE), m_bGroupKnockout(FALSE) { m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y)); m_pCanvas = m_pRecorder->getRecordingCanvas(); @@ -978,7 +874,6 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder) m_pOriDevice(nullptr), m_pRecorder(recorder), m_pCache(new SkiaState), - m_bRgbByteOrder(FALSE), m_bGroupKnockout(FALSE) { m_pCanvas = m_pRecorder->getRecordingCanvas(); } @@ -1012,6 +907,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, paint.setColor(color); paint.setTypeface(typeface); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + paint.setHinting(SkPaint::kNo_Hinting); paint.setTextSize(font_size); paint.setSubpixelText(true); m_pCanvas->save(); @@ -1354,35 +1250,33 @@ FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { FX_BOOL CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { - if (!m_pBitmap || !m_pBitmap->GetBuffer()) + if (!m_pBitmap) return TRUE; - - FX_RECT rect(left, top, left + pBitmap->GetWidth(), - top + pBitmap->GetHeight()); - std::unique_ptr<CFX_DIBitmap> pBack; - if (m_pOriDevice) { - pBack.reset(m_pOriDevice->Clone(&rect)); - if (!pBack) - return TRUE; - - pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(), - m_pBitmap, 0, 0); - } else { - pBack.reset(m_pBitmap->Clone(&rect)); - if (!pBack) - return TRUE; - } - - left = std::min(left, 0); - top = std::min(top, 0); - if (m_bRgbByteOrder) { - RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), - pBack.get(), left, top); + uint8_t* srcBuffer = m_pBitmap->GetBuffer(); + if (!srcBuffer) return TRUE; - } - - return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack.get(), - left, top); + int srcWidth = m_pBitmap->GetWidth(); + int srcHeight = m_pBitmap->GetHeight(); + int srcRowBytes = srcWidth * sizeof(uint32_t); + SkImageInfo srcImageInfo = SkImageInfo::Make( + srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); + SkBitmap skSrcBitmap; + skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr, + nullptr, nullptr); + SkASSERT(pBitmap); + uint8_t* dstBuffer = pBitmap->GetBuffer(); + SkASSERT(dstBuffer); + int dstWidth = pBitmap->GetWidth(); + int dstHeight = pBitmap->GetHeight(); + int dstRowBytes = dstWidth * sizeof(uint32_t); + SkImageInfo dstImageInfo = SkImageInfo::Make( + dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); + SkBitmap skDstBitmap; + skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr, + nullptr, nullptr); + SkCanvas canvas(skDstBitmap); + canvas.drawBitmap(skSrcBitmap, left, top, nullptr); + return TRUE; } CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() { @@ -1491,7 +1385,7 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, case 32: colorType = SkColorType::kN32_SkColorType; alphaType = kPremul_SkAlphaType; - DebugVerifyBitmapIsPreMultiplied(buffer, width, height); + pSource->DebugVerifyBitmapIsPreMultiplied(buffer); break; default: SkASSERT(0); // TODO(caryclark) ensure that all cases are covered @@ -1528,10 +1422,6 @@ FX_BOOL CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { return FALSE; } -void CFX_SkiaDeviceDriver::PreMultiply() { - PreMultiply(m_pBitmap); -} - void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { void* buffer = pDIBitmap->GetBuffer(); if (!buffer) @@ -1549,7 +1439,7 @@ void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); unpremultiplied.readPixels(premultiplied); - DebugVerifyBitmapIsPreMultiplied(buffer, width, height); + pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); } void CFX_SkiaDeviceDriver::Dump() const { @@ -1559,6 +1449,11 @@ void CFX_SkiaDeviceDriver::Dump() const { #endif } +void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { + if (m_pOriDevice) + m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); +} + CFX_FxgeDevice::CFX_FxgeDevice() { m_bOwnedBitmap = FALSE; } @@ -1606,12 +1501,42 @@ bool CFX_FxgeDevice::Create(int width, } CFX_FxgeDevice::~CFX_FxgeDevice() { + Flush(); + // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately if (m_bOwnedBitmap && GetBitmap()) delete GetBitmap(); } -void CFX_FxgeDevice::PreMultiply() { - (static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()))->PreMultiply(); +void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { +#ifdef SK_DEBUG + CFX_SkiaDeviceDriver* skDriver = + static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); + if (skDriver) + skDriver->DebugVerifyBitmapIsPreMultiplied(); +#endif +} + +void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { +#ifdef SK_DEBUG + SkASSERT(32 == GetBPP()); + const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer()); + int width = GetWidth(); + int height = GetHeight(); + // verify that input is really premultiplied + for (int y = 0; y < height; ++y) { + const uint32_t* srcRow = buffer + y * width; + for (int x = 0; x < width; ++x) { + uint8_t a = SkGetPackedA32(srcRow[x]); + uint8_t r = SkGetPackedR32(srcRow[x]); + uint8_t g = SkGetPackedG32(srcRow[x]); + uint8_t b = SkGetPackedB32(srcRow[x]); + SkA32Assert(a); + SkASSERT(r <= a); + SkASSERT(g <= a); + SkASSERT(b <= a); + } + } +#endif } #endif diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index f7e5306ab5..a7a5f85e3e 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -125,9 +125,9 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { const SkMatrix& matrix); void Flush(); SkPictureRecorder* GetRecorder() const { return m_pRecorder; } - void PreMultiply(); static void PreMultiply(CFX_DIBitmap* pDIBitmap); SkCanvas* SkiaCanvas() { return m_pCanvas; } + void DebugVerifyBitmapIsPreMultiplied() const; void Dump() const; private: @@ -138,7 +138,6 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { SkCanvas* m_pCanvas; SkPictureRecorder* const m_pRecorder; std::unique_ptr<SkiaState> m_pCache; - FX_BOOL m_bRgbByteOrder; FX_BOOL m_bGroupKnockout; }; #endif // defined(_SKIA_SUPPORT_) |