From c4f3c0f183c9ce472cd22e831075c3897e14c3af Mon Sep 17 00:00:00 2001 From: caryclark Date: Mon, 15 Aug 2016 10:09:46 -0700 Subject: add native draw bitmap with alpha mask PDFs draw bitmaps with alpha by supplying an image alpha mask along side the image color data. The alpha mask may not be the same scale as the image data. Skia doesn't have a direct mapping for this draw call, but can come close by using the internal SkCompositeShader class. This scales the alpha mask to match the size of the image data, then puts both in the composite shader to draw. There are more things to do: - Allow Alpha8 or Gray8 to draw scaled to a matching device (blit doesn't work today) Temporary code marked with a TODO implements this functionality. - Refactor PDFium to allow SkComposeShader's components to take a matrix. The latter goal will defer drawing so that PDFium doesn't resize the mask, discarding resolution, before Skia has a chance to record it. Additionally fix drawing text with a negative font size. R=reed@google.com,dsinclair@chromium.org,herb@chromium.org Review-Url: https://codereview.chromium.org/2182763002 --- core/fpdfapi/fpdf_render/fpdf_render_image.cpp | 22 +- core/fxge/ge/cfx_renderdevice.cpp | 11 +- core/fxge/ifx_renderdevicedriver.cpp | 9 + core/fxge/include/cfx_fxgedevice.h | 7 + core/fxge/include/cfx_renderdevice.h | 6 + core/fxge/include/ifx_renderdevicedriver.h | 6 + core/fxge/skia/fx_skia_device.cpp | 298 ++++++++++++++++++------- core/fxge/skia/fx_skia_device.h | 13 ++ 8 files changed, 289 insertions(+), 83 deletions(-) diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp index c93600f2a1..8d638f62f8 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp @@ -646,6 +646,7 @@ FX_BOOL CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return FALSE; } + FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { @@ -665,7 +666,11 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { if (!bitmap_device1.Create(width, height, FXDIB_Rgb32, nullptr)) return TRUE; +#if defined _SKIA_SUPPORT_ + bitmap_device1.Clear(0xffffff); +#else bitmap_device1.GetBitmap()->Clear(0xffffff); +#endif { CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, @@ -682,7 +687,11 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb, nullptr)) return TRUE; +#if defined _SKIA_SUPPORT_ + bitmap_device2.Clear(0); +#else bitmap_device2.GetBitmap()->Clear(0); +#endif CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, nullptr, nullptr, nullptr, nullptr, nullptr, 0, @@ -731,17 +740,21 @@ FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { } } } +#ifdef _SKIA_SUPPORT_ + m_pRenderStatus->m_pDevice->SetBitsWithMask( + bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, + rect.top, m_BitmapAlpha, m_BlendType); + } +#else bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); -#ifdef _SKIA_SUPPORT_ - CFX_SkiaDeviceDriver::PreMultiply(bitmap_device1.GetBitmap()); -#endif if (m_BitmapAlpha < 255) { bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); } } m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); +#endif // _SKIA_SUPPORT_ return FALSE; } @@ -756,7 +769,8 @@ FX_BOOL CPDF_ImageRenderer::StartDIBSource() { } #ifdef _SKIA_SUPPORT_ CFX_DIBitmap* premultiplied = m_pDIBSource->Clone(); - CFX_SkiaDeviceDriver::PreMultiply(premultiplied); + if (m_pDIBSource->HasAlpha()) + CFX_SkiaDeviceDriver::PreMultiply(premultiplied); if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, m_DeviceHandle, m_BlendType)) { diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp index f04f4bab9a..53ee039cd3 100644 --- a/core/fxge/ge/cfx_renderdevice.cpp +++ b/core/fxge/ge/cfx_renderdevice.cpp @@ -811,10 +811,19 @@ void CFX_RenderDevice::CancelDIBits(void* handle) { } #ifdef _SKIA_SUPPORT_ - void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { SkASSERT(0); } + +bool CFX_RenderDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { + return m_pDeviceDriver->SetBitsWithMask(pBitmap, pMask, left, top, + bitmap_alpha, blend_type); +} #endif FX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, diff --git a/core/fxge/ifx_renderdevicedriver.cpp b/core/fxge/ifx_renderdevicedriver.cpp index 9b7f985aee..25c3a4a23c 100644 --- a/core/fxge/ifx_renderdevicedriver.cpp +++ b/core/fxge/ifx_renderdevicedriver.cpp @@ -92,3 +92,12 @@ FX_BOOL IFX_RenderDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, FX_BOOL bAlphaMode) { return false; } + +bool IFX_RenderDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { + return false; +} diff --git a/core/fxge/include/cfx_fxgedevice.h b/core/fxge/include/cfx_fxgedevice.h index a5dba37c3e..7f34f1ca4a 100644 --- a/core/fxge/include/cfx_fxgedevice.h +++ b/core/fxge/include/cfx_fxgedevice.h @@ -28,8 +28,15 @@ class CFX_FxgeDevice : public CFX_RenderDevice { #ifdef _SKIA_SUPPORT_ bool AttachRecorder(SkPictureRecorder* recorder); + void Clear(uint32_t color); SkPictureRecorder* CreateRecorder(int size_x, int size_y); void DebugVerifyBitmapIsPreMultiplied() const override; + bool SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) override; #endif private: diff --git a/core/fxge/include/cfx_renderdevice.h b/core/fxge/include/cfx_renderdevice.h index fafa6260e1..390d39b69d 100644 --- a/core/fxge/include/cfx_renderdevice.h +++ b/core/fxge/include/cfx_renderdevice.h @@ -253,6 +253,12 @@ class CFX_RenderDevice { #ifdef _SKIA_SUPPORT_ virtual void DebugVerifyBitmapIsPreMultiplied() const; + virtual bool SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type); void Flush(); #endif diff --git a/core/fxge/include/ifx_renderdevicedriver.h b/core/fxge/include/ifx_renderdevicedriver.h index 572469b8c0..8b20cf0838 100644 --- a/core/fxge/include/ifx_renderdevicedriver.h +++ b/core/fxge/include/ifx_renderdevicedriver.h @@ -99,6 +99,12 @@ class IFX_RenderDeviceDriver { const FX_RECT& clip_rect, int alpha, FX_BOOL bAlphaMode); + virtual bool SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type); }; #endif // CORE_FXGE_INCLUDE_IFX_RENDERDEVICEDRIVER_H_ diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index 49c4639866..3effa0a6a6 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -24,9 +24,11 @@ #include "third_party/skia/include/core/SkCanvas.h" #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/SkPaint.h" #include "third_party/skia/include/core/SkPath.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/SkDashPathEffect.h" @@ -140,9 +142,10 @@ SkMatrix ToSkMatrix(const CFX_Matrix& m) { } // use when pdf's y-axis points up insead of down -SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m) { +SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m, SkScalar flip) { SkMatrix skMatrix; - skMatrix.setAll(m.a, -m.c, m.e, m.b, -m.d, m.f, 0, 0, 1); + skMatrix.setAll(m.a * flip, -m.c * flip, m.e, m.b * flip, -m.d * flip, m.f, 0, + 0, 1); return skMatrix; } @@ -367,6 +370,107 @@ void ClipAngledGradient(const SkPoint pts[2], clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); } +void SetBitmapMatrix(const CFX_Matrix* pMatrix, + int width, + int height, + SkMatrix* skMatrix) { + const CFX_Matrix& m = *pMatrix; + skMatrix->setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width, + -m.d / height, m.d + m.f, 0, 0, 1); +} + +void SetBitmapPaint(bool isAlphaMask, + uint32_t argb, + int bitmap_alpha, + int blend_type, + SkPaint* paint) { + paint->setAntiAlias(true); + if (isAlphaMask) { + paint->setColorFilter( + SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode)); + } + // paint->setFilterQuality(kHigh_SkFilterQuality); + paint->setXfermodeMode(GetSkiaBlendMode(blend_type)); + paint->setAlpha(bitmap_alpha); +} + +bool Upsample(const CFX_DIBSource* pSource, + std::unique_ptr& dst8Storage, + std::unique_ptr& dst32Storage, + SkColorTable** ctPtr, + SkBitmap* skBitmap, + int* widthPtr, + int* heightPtr, + bool forceAlpha) { + void* buffer = pSource->GetBuffer(); + if (!buffer) + return false; + SkColorType colorType = forceAlpha || pSource->IsAlphaMask() + ? SkColorType::kAlpha_8_SkColorType + : SkColorType::kGray_8_SkColorType; + SkAlphaType alphaType = + pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType; + int width = pSource->GetWidth(); + int height = pSource->GetHeight(); + int rowBytes = pSource->GetPitch(); + switch (pSource->GetBPP()) { + case 1: { + dst8Storage.reset(FX_Alloc2D(uint8_t, width, height)); + uint8_t* dst8Pixels = dst8Storage.get(); + for (int y = 0; y < height; ++y) { + const uint8_t* srcRow = + static_cast(buffer) + y * rowBytes; + uint8_t* dstRow = dst8Pixels + y * width; + for (int x = 0; x < width; ++x) + dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00; + } + buffer = dst8Storage.get(); + rowBytes = width; + break; + } + case 8: + if (pSource->GetPalette()) { + *ctPtr = + new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize()); + colorType = SkColorType::kIndex_8_SkColorType; + } + break; + case 24: { + dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); + uint32_t* dst32Pixels = dst32Storage.get(); + for (int y = 0; y < height; ++y) { + const uint8_t* srcRow = + static_cast(buffer) + y * rowBytes; + uint32_t* dstRow = dst32Pixels + y * width; + for (int x = 0; x < width; ++x) { + dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], + srcRow[x * 3 + 0]); + } + } + buffer = dst32Storage.get(); + rowBytes = width * sizeof(uint32_t); + colorType = SkColorType::kN32_SkColorType; + alphaType = kOpaque_SkAlphaType; + break; + } + case 32: + colorType = SkColorType::kN32_SkColorType; + alphaType = kPremul_SkAlphaType; + pSource->DebugVerifyBitmapIsPreMultiplied(buffer); + break; + default: + SkASSERT(0); // TODO(caryclark) ensure that all cases are covered + colorType = SkColorType::kUnknown_SkColorType; + } + SkImageInfo imageInfo = + SkImageInfo::Make(width, height, colorType, alphaType); + skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr, + nullptr); + *widthPtr = width; + *heightPtr = height; + return true; +} + } // namespace // Encapsulate the state used for successive text and path draws so that @@ -500,22 +604,24 @@ class SkiaState { int count = m_positions.count(); m_positions.setCount(nChars + count); m_glyphs.setCount(nChars + count); + SkScalar flip = m_fontSize < 0 ? -1 : 1; for (int index = 0; index < nChars; ++index) { const FXTEXT_CHARPOS& cp = pCharPos[index]; - m_positions[index + count] = {cp.m_OriginX, cp.m_OriginY}; + m_positions[index + count] = {cp.m_OriginX * flip, cp.m_OriginY * flip}; m_glyphs[index + count] = (uint16_t)cp.m_GlyphIndex; } SkPoint delta; if (MatrixOffset(pMatrix, &delta)) { for (int index = 0; index < nChars; ++index) - m_positions[index + count].offset(delta.fX, -delta.fY); + m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip); } m_drawText = true; return true; } void FlushText(CFX_SkiaDeviceDriver* pDriver) { - SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix); + SkScalar flip = m_fontSize < 0 ? -1 : 1; + SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip); SkPaint skPaint; skPaint.setAntiAlias(true); skPaint.setColor(m_fillColor); @@ -919,7 +1025,8 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, paint.setTextSize(font_size); paint.setSubpixelText(true); m_pCanvas->save(); - SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device); + SkScalar flip = font_size < 0 ? -1 : 1; + SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip); m_pCanvas->concat(skMatrix); SkTDArray positions; positions.setCount(nChars); @@ -927,7 +1034,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, glyphs.setCount(nChars); for (int index = 0; index < nChars; ++index) { const FXTEXT_CHARPOS& cp = pCharPos[index]; - positions[index] = {cp.m_OriginX, cp.m_OriginY}; + positions[index] = {cp.m_OriginX * flip, cp.m_OriginY * flip}; glyphs[index] = (uint16_t)cp.m_GlyphIndex; } m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); @@ -1339,86 +1446,39 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, void*& handle, int blend_type) { DebugValidate(m_pBitmap, m_pOriDevice); - SkColorType colorType = pSource->IsAlphaMask() - ? SkColorType::kAlpha_8_SkColorType - : SkColorType::kGray_8_SkColorType; - SkAlphaType alphaType = - pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType; SkColorTable* ct = nullptr; - void* buffer = pSource->GetBuffer(); - if (!buffer) - return FALSE; std::unique_ptr dst8Storage; std::unique_ptr dst32Storage; - int width = pSource->GetWidth(); - int height = pSource->GetHeight(); - int rowBytes = pSource->GetPitch(); - switch (pSource->GetBPP()) { - case 1: { - dst8Storage.reset(FX_Alloc2D(uint8_t, width, height)); - uint8_t* dst8Pixels = dst8Storage.get(); - for (int y = 0; y < height; ++y) { - const uint8_t* srcRow = - static_cast(buffer) + y * rowBytes; - uint8_t* dstRow = dst8Pixels + y * width; - for (int x = 0; x < width; ++x) - dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00; - } - buffer = dst8Storage.get(); - rowBytes = width; - } break; - case 8: - if (pSource->GetPalette()) { - ct = new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize()); - colorType = SkColorType::kIndex_8_SkColorType; - } - break; - case 24: { - dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); - uint32_t* dst32Pixels = dst32Storage.get(); - for (int y = 0; y < height; ++y) { - const uint8_t* srcRow = - static_cast(buffer) + y * rowBytes; - uint32_t* dstRow = dst32Pixels + y * width; - for (int x = 0; x < width; ++x) { - dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], - srcRow[x * 3 + 0]); - } - } - buffer = dst32Storage.get(); - rowBytes = width * sizeof(uint32_t); - colorType = SkColorType::kN32_SkColorType; - alphaType = kOpaque_SkAlphaType; - } break; - case 32: - colorType = SkColorType::kN32_SkColorType; - alphaType = kPremul_SkAlphaType; - pSource->DebugVerifyBitmapIsPreMultiplied(buffer); - break; - default: - SkASSERT(0); // TODO(caryclark) ensure that all cases are covered - colorType = SkColorType::kUnknown_SkColorType; - } - SkImageInfo imageInfo = - SkImageInfo::Make(width, height, colorType, alphaType); SkBitmap skBitmap; - skBitmap.installPixels(imageInfo, buffer, rowBytes, ct, nullptr, nullptr); + int width, height; + if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width, + &height, false)) { + return FALSE; + } m_pCanvas->save(); SkMatrix skMatrix; - const CFX_Matrix& m = *pMatrix; - skMatrix.setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width, - -m.d / height, m.d + m.f, 0, 0, 1); + SetBitmapMatrix(pMatrix, width, height, &skMatrix); m_pCanvas->concat(skMatrix); SkPaint paint; - paint.setAntiAlias(true); - if (pSource->IsAlphaMask()) { - paint.setColorFilter( - SkColorFilter::MakeModeFilter(argb, SkXfermode::kSrc_Mode)); + SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type, + &paint); + // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this + if (m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) { + SkMatrix inv; + SkAssertResult(skMatrix.invert(&inv)); + for (int y = 0; y < m_pBitmap->GetHeight(); ++y) { + for (int x = 0; x < m_pBitmap->GetWidth(); ++x) { + SkPoint src = {x + 0.5f, y + 0.5f}; + inv.mapPoints(&src, 1); + // TODO(caryclark) Why does the matrix map require clamping? + src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f)); + src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f)); + m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY)); + } + } + } else { + m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); } - // paint.setFilterQuality(kHigh_SkFilterQuality); - paint.setXfermodeMode(GetSkiaBlendMode(blend_type)); - paint.setAlpha(bitmap_alpha); - m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); m_pCanvas->restore(); if (ct) ct->unref(); @@ -1450,6 +1510,68 @@ void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { pDIBitmap->DebugVerifyBitmapIsPreMultiplied(); } +bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, + const CFX_DIBSource* pMask, + int bitmap_alpha, + const CFX_Matrix* pMatrix, + int blend_type) { + DebugValidate(m_pBitmap, m_pOriDevice); + SkColorTable* srcCt = nullptr; + SkColorTable* maskCt = nullptr; + std::unique_ptr src8Storage, mask8Storage; + std::unique_ptr src32Storage, mask32Storage; + SkBitmap skBitmap, skMask; + int srcWidth, srcHeight, maskWidth, maskHeight; + if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap, + &srcWidth, &srcHeight, false)) { + return false; + } + if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask, + &maskWidth, &maskHeight, true)) { + return false; + } + m_pCanvas->save(); + SkMatrix skMatrix; + SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix); + m_pCanvas->concat(skMatrix); + SkPaint paint; + SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type, + &paint); + sk_sp skSrc = SkImage::MakeFromBitmap(skBitmap); + sk_sp skSrcShader = + skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); + sk_sp skMaskImage = SkImage::MakeFromBitmap(skMask); + sk_sp skMaskShader = skMaskImage->makeShader( + SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); + sk_sp dstInMode = SkXfermode::Make(SkXfermode::kSrcIn_Mode); + paint.setShader( + SkShader::MakeComposeShader(skMaskShader, skSrcShader, dstInMode)); + SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)}; + m_pCanvas->drawRect(r, paint); + m_pCanvas->restore(); + if (srcCt) + srcCt->unref(); + DebugValidate(m_pBitmap, m_pOriDevice); + return true; +} + +bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int dest_left, + int dest_top, + int bitmap_alpha, + int blend_type) { + if (!m_pBitmap || !m_pBitmap->GetBuffer()) + return true; + CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left, + dest_top + pBitmap->GetHeight()); + return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type); +} + +void CFX_SkiaDeviceDriver::Clear(uint32_t color) { + m_pCanvas->clear(color); +} + void CFX_SkiaDeviceDriver::Dump() const { #ifdef SK_DEBUG if (m_pCache) @@ -1466,6 +1588,12 @@ CFX_FxgeDevice::CFX_FxgeDevice() { m_bOwnedBitmap = FALSE; } +void CFX_FxgeDevice::Clear(uint32_t color) { + CFX_SkiaDeviceDriver* skDriver = + static_cast(GetDeviceDriver()); + skDriver->Clear(color); +} + SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); SetDeviceDriver(WrapUnique(skDriver)); @@ -1523,6 +1651,20 @@ void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { #endif } +bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { + CFX_SkiaDeviceDriver* skDriver = + static_cast(GetDeviceDriver()); + if (skDriver) + return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha, + blend_type); + return false; +} + 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 661cf2e3b9..6e112f5f62 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -84,6 +84,12 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { int dest_left, int dest_top, int blend_type) override; + bool SetBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int dest_left, + int dest_top, + int bitmap_alpha, + int blend_type) override; FX_BOOL StretchDIBits(const CFX_DIBSource* pBitmap, uint32_t color, int dest_left, @@ -106,6 +112,12 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { void CancelDIBits(void* handle) override {} + bool DrawBitsWithMask(const CFX_DIBSource* pBitmap, + const CFX_DIBSource* pMask, + int bitmap_alpha, + const CFX_Matrix* pMatrix, + int blend_type); + FX_BOOL DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, @@ -125,6 +137,7 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { void PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState, const SkMatrix& matrix); + void Clear(uint32_t color); void Flush(); SkPictureRecorder* GetRecorder() const { return m_pRecorder; } static void PreMultiply(CFX_DIBitmap* pDIBitmap); -- cgit v1.2.3