diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render.cpp | 9 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render_image.cpp | 11 | ||||
-rw-r--r-- | core/fxge/dib/fx_dib_main.cpp | 5 | ||||
-rw-r--r-- | core/fxge/include/fx_ge.h | 1 | ||||
-rw-r--r-- | core/fxge/skia/fx_skia_device.cpp | 144 | ||||
-rw-r--r-- | core/fxge/skia/fx_skia_device.h | 9 |
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; |