Chromium Code Reviews| Index: core/fpdfapi/render/cpdf_imagerenderer.cpp | 
| diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp | 
| index 6d951a8d39ef988594597a1015342aaf1e6dd721..8a15f0bb624318ad66e19f273a0006eb006668ba 100644 | 
| --- a/core/fpdfapi/render/cpdf_imagerenderer.cpp | 
| +++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp | 
| @@ -6,6 +6,7 @@ | 
| #include "core/fpdfapi/render/cpdf_imagerenderer.h" | 
| +#include <algorithm> | 
| #include <memory> | 
| #include "core/fpdfapi/page/cpdf_docpagedata.h" | 
| @@ -56,12 +57,10 @@ bool CPDF_ImageRenderer::StartLoadDIBSource() { | 
| if (!image_rect.Valid()) | 
| return false; | 
| - int dest_width = image_rect.Width(); | 
| - int dest_height = image_rect.Height(); | 
| - if (m_ImageMatrix.a < 0) | 
| - dest_width = -dest_width; | 
| - if (m_ImageMatrix.d > 0) | 
| - dest_height = -dest_height; | 
| + int dest_width = | 
| + m_ImageMatrix.a >= 0 ? image_rect.Width() : -image_rect.Width(); | 
| + int dest_height = | 
| + m_ImageMatrix.d <= 0 ? image_rect.Height() : -image_rect.Height(); | 
| if (m_Loader.Start( | 
| m_pImageObject, m_pRenderStatus->m_pContext->GetPageCache(), m_bStdCS, | 
| m_pRenderStatus->m_GroupFamily, m_pRenderStatus->m_bLoadMask, | 
| @@ -225,21 +224,75 @@ bool CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, | 
| return StartDIBSource(); | 
| } | 
| -bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { | 
| - if (m_pRenderStatus->m_bPrint && | 
| - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | 
| +bool CPDF_ImageRenderer::NotDrawing() { | 
| + bool bRet = m_pRenderStatus->m_bPrint && | 
| + !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE); | 
| + if (bRet) | 
| m_Result = false; | 
| 
 
Tom Sepez
2016/11/28 18:42:53
I'd prefer to make this a const method, and make t
 
npm
2016/11/28 20:51:30
Done.
 
 | 
| - return false; | 
| - } | 
| + return bRet; | 
| +} | 
| + | 
| +FX_RECT CPDF_ImageRenderer::GetDrawRect() { | 
| FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); | 
| rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | 
| - if (rect.IsEmpty()) | 
| - return false; | 
| + return rect; | 
| +} | 
| +CFX_Matrix CPDF_ImageRenderer::GetDrawMatrix(const FX_RECT& rect) { | 
| CFX_Matrix new_matrix = m_ImageMatrix; | 
| new_matrix.TranslateI(-rect.left, -rect.top); | 
| - int width = rect.Width(); | 
| - int height = rect.Height(); | 
| + return new_matrix; | 
| +} | 
| + | 
| +void CPDF_ImageRenderer::CalculateDrawImage(CFX_FxgeDevice* pBitmapDevice1, | 
| + CFX_FxgeDevice* pBitmapDevice2, | 
| + const CFX_DIBSource* pDIBSource, | 
| + CFX_Matrix* pNewMatrix, | 
| + const FX_RECT& rect) { | 
| + CPDF_RenderStatus bitmap_render; | 
| + bitmap_render.Initialize(m_pRenderStatus->m_pContext, pBitmapDevice2, nullptr, | 
| + nullptr, nullptr, nullptr, nullptr, 0, | 
| + m_pRenderStatus->m_bDropObjects, nullptr, true); | 
| + CPDF_ImageRenderer image_render; | 
| + if (image_render.Start(&bitmap_render, pDIBSource, 0xffffffff, 255, | 
| + pNewMatrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { | 
| + image_render.Continue(nullptr); | 
| + } | 
| + if (m_Loader.m_MatteColor == 0xffffffff) | 
| + return; | 
| + int matte_r = FXARGB_R(m_Loader.m_MatteColor); | 
| + int matte_g = FXARGB_G(m_Loader.m_MatteColor); | 
| + int matte_b = FXARGB_B(m_Loader.m_MatteColor); | 
| + for (int row = 0; row < rect.Height(); row++) { | 
| + uint8_t* dest_scan = | 
| + (uint8_t*)pBitmapDevice1->GetBitmap()->GetScanline(row); | 
| 
 
Tom Sepez
2016/11/28 18:42:53
nit: const_cast<uint8_t*>() so that we know that i
 
npm
2016/11/28 20:51:30
Done.
 
 | 
| + const uint8_t* mask_scan = pBitmapDevice2->GetBitmap()->GetScanline(row); | 
| + for (int col = 0; col < rect.Width(); col++) { | 
| + int alpha = *mask_scan++; | 
| + if (!alpha) { | 
| + dest_scan += 4; | 
| + continue; | 
| + } | 
| + int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | 
| + *dest_scan++ = std::min(std::max(orig, 0), 255); | 
| + orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | 
| + *dest_scan++ = std::min(std::max(orig, 0), 255); | 
| + orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | 
| + *dest_scan++ = std::min(std::max(orig, 0), 255); | 
| + dest_scan++; | 
| + } | 
| + } | 
| +} | 
| + | 
| +bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { | 
| + if (NotDrawing()) | 
| + return false; | 
| + | 
| + FX_RECT rect = GetDrawRect(); | 
| + if (rect.IsEmpty()) | 
| + return false; | 
| + | 
| + CFX_Matrix new_matrix = GetDrawMatrix(rect); | 
| CFX_FxgeDevice bitmap_device1; | 
| if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) | 
| return true; | 
| @@ -267,51 +320,8 @@ bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { | 
| return true; | 
| } | 
| bitmap_device2.GetBitmap()->Clear(0); | 
| - CPDF_RenderStatus bitmap_render2; | 
| - bitmap_render2.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, | 
| - nullptr, nullptr, nullptr, nullptr, nullptr, 0, | 
| - m_pRenderStatus->m_bDropObjects, nullptr, true); | 
| - CPDF_ImageRenderer image_render; | 
| - if (image_render.Start(&bitmap_render2, m_pDIBSource, 0xffffffff, 255, | 
| - &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { | 
| - image_render.Continue(nullptr); | 
| - } | 
| - if (m_Loader.m_MatteColor != 0xffffffff) { | 
| - int matte_r = FXARGB_R(m_Loader.m_MatteColor); | 
| - int matte_g = FXARGB_G(m_Loader.m_MatteColor); | 
| - int matte_b = FXARGB_B(m_Loader.m_MatteColor); | 
| - for (int row = 0; row < height; row++) { | 
| - uint8_t* dest_scan = | 
| - (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); | 
| - const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | 
| - for (int col = 0; col < width; col++) { | 
| - int alpha = *mask_scan++; | 
| - if (!alpha) { | 
| - dest_scan += 4; | 
| - continue; | 
| - } | 
| - int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | 
| - if (orig < 0) | 
| - orig = 0; | 
| - else if (orig > 255) | 
| - orig = 255; | 
| - *dest_scan++ = orig; | 
| - orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | 
| - if (orig < 0) | 
| - orig = 0; | 
| - else if (orig > 255) | 
| - orig = 255; | 
| - *dest_scan++ = orig; | 
| - orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | 
| - if (orig < 0) | 
| - orig = 0; | 
| - else if (orig > 255) | 
| - orig = 255; | 
| - *dest_scan++ = orig; | 
| - dest_scan++; | 
| - } | 
| - } | 
| - } | 
| + CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_pDIBSource, | 
| + &new_matrix, rect); | 
| bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); | 
| bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); | 
| bitmap_device1.GetBitmap()->MultiplyAlpha(255); | 
| @@ -321,22 +331,16 @@ bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { | 
| } | 
| bool CPDF_ImageRenderer::DrawMaskedImage() { | 
| - if (m_pRenderStatus->m_bPrint && | 
| - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | 
| - m_Result = false; | 
| + if (NotDrawing()) | 
| return false; | 
| - } | 
| - FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); | 
| - rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | 
| + | 
| + FX_RECT rect = GetDrawRect(); | 
| if (rect.IsEmpty()) | 
| return false; | 
| - CFX_Matrix new_matrix = m_ImageMatrix; | 
| - new_matrix.TranslateI(-rect.left, -rect.top); | 
| - int width = rect.Width(); | 
| - int height = rect.Height(); | 
| + CFX_Matrix new_matrix = GetDrawMatrix(rect); | 
| CFX_FxgeDevice bitmap_device1; | 
| - if (!bitmap_device1.Create(width, height, FXDIB_Rgb32, nullptr)) | 
| + if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) | 
| return true; | 
| #if defined _SKIA_SUPPORT_ | 
| @@ -354,7 +358,8 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { | 
| image_render.Continue(nullptr); | 
| } | 
| CFX_FxgeDevice bitmap_device2; | 
| - if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb, nullptr)) | 
| + if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, | 
| + nullptr)) | 
| return true; | 
| #if defined _SKIA_SUPPORT_ | 
| @@ -362,54 +367,8 @@ bool CPDF_ImageRenderer::DrawMaskedImage() { | 
| #else | 
| bitmap_device2.GetBitmap()->Clear(0); | 
| #endif | 
| - CPDF_RenderStatus bitmap_render2; | 
| - bitmap_render2.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, | 
| - nullptr, nullptr, nullptr, nullptr, nullptr, 0, | 
| - m_pRenderStatus->m_bDropObjects, nullptr, true); | 
| - CPDF_ImageRenderer image_render2; | 
| - if (image_render2.Start(&bitmap_render2, m_Loader.m_pMask, 0xffffffff, 255, | 
| - &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { | 
| - image_render2.Continue(nullptr); | 
| - } | 
| - if (m_Loader.m_MatteColor != 0xffffffff) { | 
| - int matte_r = FXARGB_R(m_Loader.m_MatteColor); | 
| - int matte_g = FXARGB_G(m_Loader.m_MatteColor); | 
| - int matte_b = FXARGB_B(m_Loader.m_MatteColor); | 
| - for (int row = 0; row < height; row++) { | 
| - uint8_t* dest_scan = | 
| - (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); | 
| - const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | 
| - for (int col = 0; col < width; col++) { | 
| - int alpha = *mask_scan++; | 
| - if (alpha) { | 
| - int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | 
| - if (orig < 0) { | 
| - orig = 0; | 
| - } else if (orig > 255) { | 
| - orig = 255; | 
| - } | 
| - *dest_scan++ = orig; | 
| - orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | 
| - if (orig < 0) { | 
| - orig = 0; | 
| - } else if (orig > 255) { | 
| - orig = 255; | 
| - } | 
| - *dest_scan++ = orig; | 
| - orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | 
| - if (orig < 0) { | 
| - orig = 0; | 
| - } else if (orig > 255) { | 
| - orig = 255; | 
| - } | 
| - *dest_scan++ = orig; | 
| - dest_scan++; | 
| - } else { | 
| - dest_scan += 4; | 
| - } | 
| - } | 
| - } | 
| - } | 
| + CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_Loader.m_pMask, | 
| + &new_matrix, rect); | 
| #ifdef _SKIA_SUPPORT_ | 
| m_pRenderStatus->m_pDevice->SetBitsWithMask( | 
| bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, | 
| @@ -469,11 +428,9 @@ bool CPDF_ImageRenderer::StartDIBSource() { | 
| int dest_height = image_rect.Height(); | 
| if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || | 
| (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { | 
| - if (m_pRenderStatus->m_bPrint && | 
| - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | 
| - m_Result = false; | 
| + if (NotDrawing()) | 
| return false; | 
| - } | 
| + | 
| FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | 
| clip_box.Intersect(image_rect); | 
| m_Status = 2; | 
| @@ -506,11 +463,8 @@ bool CPDF_ImageRenderer::StartDIBSource() { | 
| return false; | 
| } | 
| } | 
| - if (m_pRenderStatus->m_bPrint && | 
| - !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | 
| - m_Result = false; | 
| + if (NotDrawing()) | 
| return true; | 
| - } | 
| FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | 
| FX_RECT dest_rect = clip_box; | 
| @@ -606,3 +560,7 @@ bool CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { | 
| } | 
| return false; | 
| } | 
| + | 
| +bool CPDF_ImageRenderer::GetResult() { | 
| 
 
Tom Sepez
2016/11/28 18:42:53
nit: a one-liner like this can go in the header.
 
npm
2016/11/28 20:51:30
Done.
 
 | 
| + return m_Result; | 
| +} |