summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfapi/fpdf_render/fpdf_render.cpp9
-rw-r--r--core/fpdfapi/fpdf_render/fpdf_render_image.cpp11
-rw-r--r--core/fxge/dib/fx_dib_main.cpp5
-rw-r--r--core/fxge/include/fx_ge.h1
-rw-r--r--core/fxge/skia/fx_skia_device.cpp144
-rw-r--r--core/fxge/skia/fx_skia_device.h9
6 files changed, 128 insertions, 51 deletions
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp
index a3dbbdb3f2..6ac78ecd43 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -815,14 +815,19 @@ FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj,
bitmap->MultiplyAlpha(pTextMask.get());
pTextMask.reset();
}
+ int32_t blitAlpha = 255;
if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
- bitmap->MultiplyAlpha((int32_t)(group_alpha * 255));
+ blitAlpha = (int32_t)(group_alpha * 255);
+#ifndef _SKIA_SUPPORT_
+ bitmap->MultiplyAlpha(blitAlpha);
+ blitAlpha = 255;
+#endif
}
Transparency = m_Transparency;
if (pPageObj->IsForm()) {
Transparency |= PDFTRANS_GROUP;
}
- CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type,
+ CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type,
Transparency);
return TRUE;
}
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
index d3fbb7990c..acfb20314a 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
@@ -48,7 +48,15 @@ void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
if (blend_mode == FXDIB_BLEND_NORMAL) {
if (!pDIBitmap->IsAlphaMask()) {
if (bitmap_alpha < 255) {
+#ifdef _SKIA_SUPPORT_
+ void* dummy;
+ CFX_Matrix m(pDIBitmap->GetWidth(), 0, 0, -pDIBitmap->GetHeight(), left,
+ top + pDIBitmap->GetHeight());
+ m_pDevice->StartDIBits(pDIBitmap, bitmap_alpha, 0, &m, 0, dummy);
+ return;
+#else
pDIBitmap->MultiplyAlpha(bitmap_alpha);
+#endif
}
if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
return;
@@ -693,6 +701,9 @@ 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
+#endif
if (m_BitmapAlpha < 255) {
bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha);
}
diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp
index 85df71e11d..896551401a 100644
--- a/core/fxge/dib/fx_dib_main.cpp
+++ b/core/fxge/dib/fx_dib_main.cpp
@@ -344,6 +344,11 @@ void CFX_DIBitmap::Clear(uint32_t color) {
case FXDIB_Rgb32:
case FXDIB_Argb: {
color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
+#ifdef _SKIA_SUPPORT_
+ if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) {
+ color |= 0xFF000000;
+ }
+#endif
for (int i = 0; i < m_Width; i++) {
((uint32_t*)m_pBuffer)[i] = color;
}
diff --git a/core/fxge/include/fx_ge.h b/core/fxge/include/fx_ge.h
index 6a3113d070..8111e46d13 100644
--- a/core/fxge/include/fx_ge.h
+++ b/core/fxge/include/fx_ge.h
@@ -412,6 +412,7 @@ class CFX_FxgeDevice : public CFX_RenderDevice {
#ifdef _SKIA_SUPPORT_
bool AttachRecorder(SkPictureRecorder* recorder);
SkPictureRecorder* CreateRecorder(int size_x, int size_y);
+ void PreMultiply();
#endif
protected:
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 452472e40c..86a8269b79 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -81,6 +81,45 @@ 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());
+ }
+ }
+ if (device) {
+ SkASSERT(device->GetBPP() == 8 || device->GetBPP() == 32);
+ if (device->GetBPP() == 32) {
+ DebugVerifyBitmapIsPreMultiplied(device->GetBuffer(), device->GetWidth(),
+ device->GetHeight());
+ }
+ }
+}
+
SkPath BuildPath(const CFX_PathData* pPathData) {
SkPath skPath;
const CFX_PathData* pFPath = pPathData;
@@ -509,9 +548,11 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
m_bRgbByteOrder(bRgbByteOrder),
m_bGroupKnockout(bGroupKnockout) {
SkBitmap skBitmap;
- SkImageInfo imageInfo =
- SkImageInfo::Make(pBitmap->GetWidth(), pBitmap->GetHeight(),
- kN32_SkColorType, kOpaque_SkAlphaType);
+ SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32);
+ SkImageInfo imageInfo = SkImageInfo::Make(
+ pBitmap->GetWidth(), pBitmap->GetHeight(),
+ pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType,
+ kOpaque_SkAlphaType);
skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(),
nullptr, /* to do : set color table */
nullptr, nullptr);
@@ -553,7 +594,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
uint32_t color,
int alpha_flag,
void* pIccTransform) {
- CFX_TypeFace* typeface = pCache->GetDeviceCache(pFont);
+ sk_sp<SkTypeface> typeface(SkSafeRef(pCache->GetDeviceCache(pFont)));
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(color);
@@ -932,15 +973,12 @@ FX_BOOL CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
void* pIccTransform) {
if (!m_pBitmap || !m_pBitmap->GetBuffer())
return TRUE;
- if (pBitmap->IsAlphaMask()) {
- return m_pBitmap->CompositeMask(
- left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
- pSrcRect->left, pSrcRect->top, blend_type, nullptr, m_bRgbByteOrder,
- alpha_flag, pIccTransform);
- }
- return m_pBitmap->CompositeBitmap(
- left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
- pSrcRect->top, blend_type, nullptr, m_bRgbByteOrder, pIccTransform);
+
+ CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left,
+ top + pBitmap->GetHeight());
+ void* dummy;
+ return this->StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, alpha_flag,
+ pIccTransform, blend_type);
}
FX_BOOL CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
@@ -956,27 +994,19 @@ FX_BOOL CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
int blend_type) {
if (!m_pBitmap->GetBuffer())
return TRUE;
- if (dest_width == pSource->GetWidth() &&
- dest_height == pSource->GetHeight()) {
- FX_RECT rect(0, 0, dest_width, dest_height);
- return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type,
- alpha_flag, pIccTransform);
- }
- FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
- dest_top + dest_height);
- dest_rect.Normalize();
- FX_RECT dest_clip = dest_rect;
- dest_clip.Intersect(*pClipRect);
- CFX_BitmapComposer composer;
- composer.Compose(m_pBitmap, nullptr, 255, argb, dest_clip, FALSE, FALSE,
- FALSE, m_bRgbByteOrder, alpha_flag, pIccTransform,
- blend_type);
- dest_clip.Offset(-dest_rect.left, -dest_rect.top);
- CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
- dest_clip, flags);
- if (stretcher.Start())
- stretcher.Continue(nullptr);
- return TRUE;
+ CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left,
+ dest_top + dest_height);
+
+ m_pCanvas->save();
+ SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom,
+ pClipRect->right, pClipRect->top);
+ m_pCanvas->clipRect(skClipRect);
+ void* dummy;
+ FX_BOOL result = this->StartDIBits(pSource, 0xFF, argb, &m, 0, dummy,
+ alpha_flag, pIccTransform, blend_type);
+ m_pCanvas->restore();
+
+ return result;
}
FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
@@ -988,9 +1018,12 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
int alpha_flag,
void* pIccTransform,
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();
std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
@@ -1025,23 +1058,27 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
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)
+ 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;
+ DebugVerifyBitmapIsPreMultiplied(buffer, width, height);
break;
default:
+ SkASSERT(0); // TODO(caryclark) ensure that all cases are covered
colorType = SkColorType::kUnknown_SkColorType;
}
- SkImageInfo imageInfo = SkImageInfo::Make(
- width, height, colorType,
- pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
+ SkImageInfo imageInfo =
+ SkImageInfo::Make(width, height, colorType, alphaType);
SkBitmap skBitmap;
skBitmap.installPixels(imageInfo, buffer, rowBytes, ct, nullptr, nullptr);
m_pCanvas->save();
@@ -1063,19 +1100,28 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
m_pCanvas->restore();
if (ct)
ct->unref();
+ DebugValidate(m_pBitmap, m_pOriDevice);
return TRUE;
}
-FX_BOOL CFX_SkiaDeviceDriver::ContinueDIBits(void* pHandle, IFX_Pause* pPause) {
- if (!m_pBitmap->GetBuffer())
- return TRUE;
- return ((CFX_ImageRenderer*)pHandle)->Continue(pPause);
-}
-
-void CFX_SkiaDeviceDriver::CancelDIBits(void* pHandle) {
- if (!m_pBitmap->GetBuffer())
+void CFX_SkiaDeviceDriver::PreMultiply() {
+ void* buffer = m_pBitmap->GetBuffer();
+ if (!buffer)
return;
- delete (CFX_ImageRenderer*)pHandle;
+ if (m_pBitmap->GetBPP() != 32) {
+ return;
+ }
+ int height = m_pBitmap->GetHeight();
+ int width = m_pBitmap->GetWidth();
+ int rowBytes = m_pBitmap->GetPitch();
+ SkImageInfo unpremultipliedInfo =
+ SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType);
+ SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes);
+ SkImageInfo premultipliedInfo =
+ SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
+ SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes);
+ unpremultiplied.readPixels(premultiplied);
+ DebugVerifyBitmapIsPreMultiplied(buffer, width, height);
}
CFX_FxgeDevice::CFX_FxgeDevice() {
@@ -1129,4 +1175,8 @@ CFX_FxgeDevice::~CFX_FxgeDevice() {
delete GetBitmap();
}
+void CFX_FxgeDevice::PreMultiply() {
+ (static_cast<CFX_SkiaDeviceDriver*>(this->GetDeviceDriver()))->PreMultiply();
+}
+
#endif
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index dd3ba420e8..085977b66e 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -114,8 +114,12 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
int alpha_flag = 0,
void* pIccTransform = NULL,
int blend_type = FXDIB_BLEND_NORMAL) override;
- FX_BOOL ContinueDIBits(void* handle, IFX_Pause* pPause) override;
- void CancelDIBits(void* handle) override;
+
+ FX_BOOL ContinueDIBits(void* handle, IFX_Pause* pPause) override {
+ return FALSE;
+ }
+
+ void CancelDIBits(void* handle) override {}
FX_BOOL DrawDeviceText(int nChars,
const FXTEXT_CHARPOS* pCharPos,
@@ -138,6 +142,7 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
const CFX_GraphStateData* pGraphState,
const SkMatrix& matrix);
SkPictureRecorder* GetRecorder() const { return m_pRecorder; }
+ void PreMultiply();
private:
CFX_DIBitmap* m_pBitmap;