summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcaryclark <caryclark@google.com>2016-08-15 10:09:46 -0700
committerCommit bot <commit-bot@chromium.org>2016-08-15 10:09:46 -0700
commitc4f3c0f183c9ce472cd22e831075c3897e14c3af (patch)
tree1dbc77920dc04eac93ba031dd552ee712c6a1afc
parent845cac29d76e03960e1de9a019bba67ced84792a (diff)
downloadpdfium-c4f3c0f183c9ce472cd22e831075c3897e14c3af.tar.xz
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
-rw-r--r--core/fpdfapi/fpdf_render/fpdf_render_image.cpp22
-rw-r--r--core/fxge/ge/cfx_renderdevice.cpp11
-rw-r--r--core/fxge/ifx_renderdevicedriver.cpp9
-rw-r--r--core/fxge/include/cfx_fxgedevice.h7
-rw-r--r--core/fxge/include/cfx_renderdevice.h6
-rw-r--r--core/fxge/include/ifx_renderdevicedriver.h6
-rw-r--r--core/fxge/skia/fx_skia_device.cpp298
-rw-r--r--core/fxge/skia/fx_skia_device.h13
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<uint8_t, FxFreeDeleter>& dst8Storage,
+ std::unique_ptr<uint32_t, FxFreeDeleter>& 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<const uint8_t*>(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<const uint8_t*>(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<SkPoint> 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<uint8_t, FxFreeDeleter> dst8Storage;
std::unique_ptr<uint32_t, FxFreeDeleter> 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<const uint8_t*>(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<const uint8_t*>(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<uint8_t, FxFreeDeleter> src8Storage, mask8Storage;
+ std::unique_ptr<uint32_t, FxFreeDeleter> 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<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap);
+ sk_sp<SkShader> skSrcShader =
+ skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask);
+ sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
+ SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ sk_sp<SkXfermode> 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<CFX_SkiaDeviceDriver*>(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<CFX_SkiaDeviceDriver*>(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);