diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2018-01-16 21:25:27 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-01-16 21:25:27 +0000 |
commit | 027190ec8148a2f1edc18c37eae26e896f3a309a (patch) | |
tree | 6f65b1bb530309b8d6656e92e66dad1fcd1e1e44 /xfa/fxfa/cxfa_ffwidget.cpp | |
parent | 454ab87a354099fb96eee4721328d59f42ca0557 (diff) | |
download | pdfium-027190ec8148a2f1edc18c37eae26e896f3a309a.tar.xz |
Move CXFA_ImageRenderer to own file
This CL Splits CL_ImageRenderer out of CXFA_FFWidget and moves to a
separate file. Methods in CXFA_FFWidget are shuffled around to put the
global methods at the top of the file and static methods in the
anonymous namespace.
Change-Id: I9887a5c9bf9fda63deead7ff785dc4ef3d7e15c8
Reviewed-on: https://pdfium-review.googlesource.com/23031
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'xfa/fxfa/cxfa_ffwidget.cpp')
-rw-r--r-- | xfa/fxfa/cxfa_ffwidget.cpp | 1040 |
1 files changed, 291 insertions, 749 deletions
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp index 8f7bda6d9e..6aa6fd61b8 100644 --- a/xfa/fxfa/cxfa_ffwidget.cpp +++ b/xfa/fxfa/cxfa_ffwidget.cpp @@ -19,15 +19,14 @@ #include "core/fxcrt/cfx_memorystream.h" #include "core/fxcrt/maybe_owned.h" #include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" #include "core/fxge/dib/cfx_imagerenderer.h" -#include "core/fxge/dib/cfx_imagetransformer.h" #include "xfa/fwl/fwl_widgethit.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffdoc.h" #include "xfa/fxfa/cxfa_ffdocview.h" #include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_imagerenderer.h" #include "xfa/fxfa/cxfa_textlayout.h" #include "xfa/fxfa/cxfa_widgetacc.h" #include "xfa/fxfa/parser/cxfa_border.h" @@ -886,6 +885,84 @@ void XFA_DrawBox(CXFA_Box* box, XFA_BOX_Stroke(box, strokes, pGS, rtWidget, matrix, forceRound); } +void XFA_GetMatrix(CFX_Matrix& m, + int32_t iRotate, + XFA_AttributeEnum at, + const CFX_RectF& rt) { + if (!iRotate) { + return; + } + float fAnchorX = 0; + float fAnchorY = 0; + switch (at) { + case XFA_AttributeEnum::TopLeft: + fAnchorX = rt.left, fAnchorY = rt.top; + break; + case XFA_AttributeEnum::TopCenter: + fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top; + break; + case XFA_AttributeEnum::TopRight: + fAnchorX = rt.right(), fAnchorY = rt.top; + break; + case XFA_AttributeEnum::MiddleLeft: + fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2; + break; + case XFA_AttributeEnum::MiddleCenter: + fAnchorX = (rt.left + rt.right()) / 2, + fAnchorY = (rt.top + rt.bottom()) / 2; + break; + case XFA_AttributeEnum::MiddleRight: + fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2; + break; + case XFA_AttributeEnum::BottomLeft: + fAnchorX = rt.left, fAnchorY = rt.bottom(); + break; + case XFA_AttributeEnum::BottomCenter: + fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom(); + break; + case XFA_AttributeEnum::BottomRight: + fAnchorX = rt.right(), fAnchorY = rt.bottom(); + break; + default: + break; + } + switch (iRotate) { + case 90: + m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY, + m.f = fAnchorX + fAnchorY; + break; + case 180: + m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2, + m.f = fAnchorY * 2; + break; + case 270: + m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY, + m.f = fAnchorY - fAnchorX; + break; + } +} + +FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, + int32_t iComponents, + int32_t iBitsPerComponent) { + FXDIB_Format dibFormat = FXDIB_Argb; + switch (type) { + case FXCODEC_IMAGE_BMP: + case FXCODEC_IMAGE_JPG: + case FXCODEC_IMAGE_TIF: { + dibFormat = FXDIB_Rgb32; + int32_t bpp = iComponents * iBitsPerComponent; + if (bpp <= 24) { + dibFormat = FXDIB_Rgb; + } + } break; + case FXCODEC_IMAGE_PNG: + default: + break; + } + return dibFormat; +} + bool IsFXCodecErrorStatus(FXCODEC_STATUS status) { return (status == FXCODEC_STATUS_ERROR || #ifdef PDF_ENABLE_XFA @@ -899,6 +976,218 @@ bool IsFXCodecErrorStatus(FXCODEC_STATUS status) { } // namespace +int32_t XFA_StrokeTypeSetLineDash(CXFA_Graphics* pGraphics, + XFA_AttributeEnum iStrokeType, + XFA_AttributeEnum iCapType) { + switch (iStrokeType) { + case XFA_AttributeEnum::DashDot: { + float dashArray[] = {4, 1, 2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) { + dashArray[1] = 2; + dashArray[3] = 2; + } + pGraphics->SetLineDash(0, dashArray, 4); + return FX_DASHSTYLE_DashDot; + } + case XFA_AttributeEnum::DashDotDot: { + float dashArray[] = {4, 1, 2, 1, 2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) { + dashArray[1] = 2; + dashArray[3] = 2; + dashArray[5] = 2; + } + pGraphics->SetLineDash(0, dashArray, 6); + return FX_DASHSTYLE_DashDotDot; + } + case XFA_AttributeEnum::Dashed: { + float dashArray[] = {5, 1}; + if (iCapType != XFA_AttributeEnum::Butt) + dashArray[1] = 2; + + pGraphics->SetLineDash(0, dashArray, 2); + return FX_DASHSTYLE_Dash; + } + case XFA_AttributeEnum::Dotted: { + float dashArray[] = {2, 1}; + if (iCapType != XFA_AttributeEnum::Butt) + dashArray[1] = 2; + + pGraphics->SetLineDash(0, dashArray, 2); + return FX_DASHSTYLE_Dot; + } + default: + break; + } + pGraphics->SetLineDash(FX_DASHSTYLE_Solid); + return FX_DASHSTYLE_Solid; +} + +void XFA_DrawImage(CXFA_Graphics* pGS, + const CFX_RectF& rtImage, + const CFX_Matrix& matrix, + const RetainPtr<CFX_DIBitmap>& pDIBitmap, + XFA_AttributeEnum iAspect, + int32_t iImageXDpi, + int32_t iImageYDpi, + XFA_AttributeEnum iHorzAlign, + XFA_AttributeEnum iVertAlign) { + if (rtImage.IsEmpty()) + return; + if (!pDIBitmap || !pDIBitmap->GetBuffer()) + return; + + CFX_RectF rtFit( + rtImage.TopLeft(), + XFA_UnitPx2Pt((float)pDIBitmap->GetWidth(), (float)iImageXDpi), + XFA_UnitPx2Pt((float)pDIBitmap->GetHeight(), (float)iImageYDpi)); + switch (iAspect) { + case XFA_AttributeEnum::Fit: { + float f1 = rtImage.height / rtFit.height; + float f2 = rtImage.width / rtFit.width; + f1 = std::min(f1, f2); + rtFit.height = rtFit.height * f1; + rtFit.width = rtFit.width * f1; + break; + } + case XFA_AttributeEnum::Height: { + float f1 = rtImage.height / rtFit.height; + rtFit.height = rtImage.height; + rtFit.width = f1 * rtFit.width; + break; + } + case XFA_AttributeEnum::None: + rtFit.height = rtImage.height; + rtFit.width = rtImage.width; + break; + case XFA_AttributeEnum::Width: { + float f1 = rtImage.width / rtFit.width; + rtFit.width = rtImage.width; + rtFit.height = rtFit.height * f1; + break; + } + case XFA_AttributeEnum::Actual: + default: + break; + } + + if (iHorzAlign == XFA_AttributeEnum::Center) + rtFit.left += (rtImage.width - rtFit.width) / 2; + else if (iHorzAlign == XFA_AttributeEnum::Right) + rtFit.left = rtImage.right() - rtFit.width; + + if (iVertAlign == XFA_AttributeEnum::Middle) + rtFit.top += (rtImage.height - rtFit.height) / 2; + else if (iVertAlign == XFA_AttributeEnum::Bottom) + rtFit.top = rtImage.bottom() - rtImage.height; + + CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); + CFX_RenderDevice::StateRestorer restorer(pRenderDevice); + CFX_PathData path; + path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); + pRenderDevice->SetClip_PathFill(&path, &matrix, FXFILL_WINDING); + + CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); + mtImage.Concat( + CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top)); + mtImage.Concat(matrix); + + CXFA_ImageRenderer imageRender; + if (!imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, + FXDIB_INTERPOL)) { + return; + } + while (imageRender.Continue()) + continue; +} + +RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer( + const RetainPtr<IFX_SeekableReadStream>& pImageFileRead, + FXCODEC_IMAGE_TYPE type, + int32_t& iImageXDpi, + int32_t& iImageYDpi) { + CCodec_ModuleMgr* pCodecMgr = CPDF_ModuleMgr::Get()->GetCodecModule(); + std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder = + pCodecMgr->CreateProgressiveDecoder(); + + CFX_DIBAttribute dibAttr; + pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false); + switch (dibAttr.m_wDPIUnit) { + case FXCODEC_RESUNIT_CENTIMETER: + dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); + dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); + break; + case FXCODEC_RESUNIT_METER: + dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f); + dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f); + break; + default: + break; + } + iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); + iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); + if (pProgressiveDecoder->GetWidth() <= 0 || + pProgressiveDecoder->GetHeight() <= 0) { + return nullptr; + } + + type = pProgressiveDecoder->GetType(); + int32_t iComponents = pProgressiveDecoder->GetNumComponents(); + int32_t iBpc = pProgressiveDecoder->GetBPC(); + FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); + RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pBitmap->Create(pProgressiveDecoder->GetWidth(), + pProgressiveDecoder->GetHeight(), dibFormat); + pBitmap->Clear(0xffffffff); + + size_t nFrames; + FXCODEC_STATUS status; + std::tie(status, nFrames) = pProgressiveDecoder->GetFrames(); + if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) { + pBitmap = nullptr; + return pBitmap; + } + + status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), + pBitmap->GetHeight()); + if (IsFXCodecErrorStatus(status)) { + pBitmap = nullptr; + return pBitmap; + } + + while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) { + status = pProgressiveDecoder->ContinueDecode(); + if (IsFXCodecErrorStatus(status)) { + pBitmap = nullptr; + return pBitmap; + } + } + + return pBitmap; +} + +void XFA_RectWithoutMargin(CFX_RectF& rt, const CXFA_Margin* margin, bool bUI) { + if (!margin) + return; + + rt.Deflate(margin->GetLeftInset(), margin->GetTopInset(), + margin->GetRightInset(), margin->GetBottomInset()); +} + +CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { + if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType())) + return static_cast<CXFA_FFWidget*>(pLayoutItem); + return nullptr; +} + +bool XFA_IsCreateWidget(XFA_Element eType) { + return eType == XFA_Element::Field || eType == XFA_Element::Draw || + eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup; +} + +CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {} + +CXFA_CalcData::~CXFA_CalcData() {} + CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : CXFA_ContentLayoutItem(node), m_pNode(node) {} @@ -1187,63 +1476,6 @@ CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) { return mt.GetInverse().Transform(point); } -static void XFA_GetMatrix(CFX_Matrix& m, - int32_t iRotate, - XFA_AttributeEnum at, - const CFX_RectF& rt) { - if (!iRotate) { - return; - } - float fAnchorX = 0; - float fAnchorY = 0; - switch (at) { - case XFA_AttributeEnum::TopLeft: - fAnchorX = rt.left, fAnchorY = rt.top; - break; - case XFA_AttributeEnum::TopCenter: - fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top; - break; - case XFA_AttributeEnum::TopRight: - fAnchorX = rt.right(), fAnchorY = rt.top; - break; - case XFA_AttributeEnum::MiddleLeft: - fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_AttributeEnum::MiddleCenter: - fAnchorX = (rt.left + rt.right()) / 2, - fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_AttributeEnum::MiddleRight: - fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2; - break; - case XFA_AttributeEnum::BottomLeft: - fAnchorX = rt.left, fAnchorY = rt.bottom(); - break; - case XFA_AttributeEnum::BottomCenter: - fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom(); - break; - case XFA_AttributeEnum::BottomRight: - fAnchorX = rt.right(), fAnchorY = rt.bottom(); - break; - default: - break; - } - switch (iRotate) { - case 90: - m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY, - m.f = fAnchorX + fAnchorY; - break; - case 180: - m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2, - m.f = fAnchorY * 2; - break; - case 270: - m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY, - m.f = fAnchorY - fAnchorX; - break; - } -} - CFX_Matrix CXFA_FFWidget::GetRotateMatrix() { CFX_Matrix mt; int32_t iRotate = m_pNode->GetRotate(); @@ -1336,693 +1568,3 @@ void CXFA_FFWidget::SetButtonDown(bool bSet) { bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown; } - -int32_t XFA_StrokeTypeSetLineDash(CXFA_Graphics* pGraphics, - XFA_AttributeEnum iStrokeType, - XFA_AttributeEnum iCapType) { - switch (iStrokeType) { - case XFA_AttributeEnum::DashDot: { - float dashArray[] = {4, 1, 2, 1}; - if (iCapType != XFA_AttributeEnum::Butt) { - dashArray[1] = 2; - dashArray[3] = 2; - } - pGraphics->SetLineDash(0, dashArray, 4); - return FX_DASHSTYLE_DashDot; - } - case XFA_AttributeEnum::DashDotDot: { - float dashArray[] = {4, 1, 2, 1, 2, 1}; - if (iCapType != XFA_AttributeEnum::Butt) { - dashArray[1] = 2; - dashArray[3] = 2; - dashArray[5] = 2; - } - pGraphics->SetLineDash(0, dashArray, 6); - return FX_DASHSTYLE_DashDotDot; - } - case XFA_AttributeEnum::Dashed: { - float dashArray[] = {5, 1}; - if (iCapType != XFA_AttributeEnum::Butt) - dashArray[1] = 2; - - pGraphics->SetLineDash(0, dashArray, 2); - return FX_DASHSTYLE_Dash; - } - case XFA_AttributeEnum::Dotted: { - float dashArray[] = {2, 1}; - if (iCapType != XFA_AttributeEnum::Butt) - dashArray[1] = 2; - - pGraphics->SetLineDash(0, dashArray, 2); - return FX_DASHSTYLE_Dot; - } - default: - break; - } - pGraphics->SetLineDash(FX_DASHSTYLE_Solid); - return FX_DASHSTYLE_Solid; -} - -class CXFA_ImageRenderer { - public: - CXFA_ImageRenderer(); - ~CXFA_ImageRenderer(); - - bool Start(CFX_RenderDevice* pDevice, - const RetainPtr<CFX_DIBSource>& pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - int blendType = FXDIB_BLEND_NORMAL); - bool Continue(); - - protected: - bool StartDIBSource(); - void CompositeDIBitmap(const RetainPtr<CFX_DIBitmap>& pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int iTransparency); - - CFX_RenderDevice* m_pDevice; - int m_Status; - CFX_Matrix m_ImageMatrix; - RetainPtr<CFX_DIBSource> m_pDIBSource; - RetainPtr<CFX_DIBitmap> m_pCloneConvert; - int m_BitmapAlpha; - FX_ARGB m_FillArgb; - uint32_t m_Flags; - std::unique_ptr<CFX_ImageTransformer> m_pTransformer; - std::unique_ptr<CFX_ImageRenderer> m_DeviceHandle; - int32_t m_BlendType; - bool m_Result; - bool m_bPrint; -}; - -CXFA_ImageRenderer::CXFA_ImageRenderer() - : m_pDevice(nullptr), - m_Status(0), - m_BitmapAlpha(255), - m_FillArgb(0), - m_Flags(0), - m_DeviceHandle(nullptr), - m_BlendType(FXDIB_BLEND_NORMAL), - m_Result(true), - m_bPrint(false) {} - -CXFA_ImageRenderer::~CXFA_ImageRenderer() {} - -bool CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, - const RetainPtr<CFX_DIBSource>& pDIBSource, - FX_ARGB bitmap_argb, - int bitmap_alpha, - const CFX_Matrix* pImage2Device, - uint32_t flags, - int blendType) { - m_pDevice = pDevice; - m_pDIBSource = pDIBSource; - m_FillArgb = bitmap_argb; - m_BitmapAlpha = bitmap_alpha; - m_ImageMatrix = *pImage2Device; - m_Flags = flags; - m_BlendType = blendType; - return StartDIBSource(); -} - -bool CXFA_ImageRenderer::StartDIBSource() { - if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, m_BitmapAlpha, m_FillArgb, - &m_ImageMatrix, m_Flags, &m_DeviceHandle, - m_BlendType)) { - if (m_DeviceHandle) { - m_Status = 3; - return true; - } - return false; - } - CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); - FX_RECT image_rect = image_rect_f.GetOuterRect(); - int dest_width = image_rect.Width(); - int dest_height = image_rect.Height(); - if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || - (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { - if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return false; - } - RetainPtr<CFX_DIBSource> pDib = m_pDIBSource; - if (m_pDIBSource->HasAlpha() && - !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) && - !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { - m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb); - if (!m_pCloneConvert) { - m_Result = false; - return false; - } - pDib = m_pCloneConvert; - } - FX_RECT clip_box = m_pDevice->GetClipBox(); - clip_box.Intersect(image_rect); - m_Status = 2; - m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>( - pDib, &m_ImageMatrix, m_Flags, &clip_box); - return true; - } - if (m_ImageMatrix.a < 0) - dest_width = -dest_width; - if (m_ImageMatrix.d > 0) - dest_height = -dest_height; - int dest_left, dest_top; - dest_left = dest_width > 0 ? image_rect.left : image_rect.right; - dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; - if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { - if (m_pDevice->StretchDIBitsWithFlagsAndBlend( - m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags, - m_BlendType)) { - return false; - } - } - if (m_pDIBSource->IsAlphaMask()) { - if (m_BitmapAlpha != 255) { - m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - } - if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top, - dest_width, dest_height, m_FillArgb, - m_Flags)) { - return false; - } - } - if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { - m_Result = false; - return true; - } - FX_RECT clip_box = m_pDevice->GetClipBox(); - FX_RECT dest_rect = clip_box; - dest_rect.Intersect(image_rect); - FX_RECT dest_clip( - dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, - dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); - RetainPtr<CFX_DIBitmap> pStretched = - m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); - if (pStretched) { - CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb, - m_BitmapAlpha, m_BlendType, false); - } - return false; -} - -bool CXFA_ImageRenderer::Continue() { - if (m_Status == 2) { - if (m_pTransformer->Continue(nullptr)) - return true; - - RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap(); - if (!pBitmap) - return false; - - if (pBitmap->IsAlphaMask()) { - if (m_BitmapAlpha != 255) - m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); - m_Result = - m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left, - m_pTransformer->result().top, m_FillArgb); - } else { - if (m_BitmapAlpha != 255) - pBitmap->MultiplyAlpha(m_BitmapAlpha); - m_Result = m_pDevice->SetDIBitsWithBlend( - pBitmap, m_pTransformer->result().left, m_pTransformer->result().top, - m_BlendType); - } - return false; - } - if (m_Status == 3) - return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), nullptr); - - return false; -} - -void CXFA_ImageRenderer::CompositeDIBitmap( - const RetainPtr<CFX_DIBitmap>& pDIBitmap, - int left, - int top, - FX_ARGB mask_argb, - int bitmap_alpha, - int blend_mode, - int iTransparency) { - if (!pDIBitmap) { - return; - } - bool bIsolated = !!(iTransparency & PDFTRANS_ISOLATED); - bool bGroup = !!(iTransparency & PDFTRANS_GROUP); - if (blend_mode == FXDIB_BLEND_NORMAL) { - if (!pDIBitmap->IsAlphaMask()) { - if (bitmap_alpha < 255) { - pDIBitmap->MultiplyAlpha(bitmap_alpha); - } - if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { - return; - } - } else { - uint32_t fill_argb = (mask_argb); - if (bitmap_alpha < 255) { - ((uint8_t*)&fill_argb)[3] = - ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; - } - if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { - return; - } - } - } - bool bBackAlphaRequired = blend_mode && bIsolated; - bool bGetBackGround = - ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || - (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && - (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); - if (bGetBackGround) { - if (bIsolated || !bGroup) { - if (pDIBitmap->IsAlphaMask()) { - return; - } - m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode); - } else { - FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), - top + pDIBitmap->GetHeight()); - rect.Intersect(m_pDevice->GetClipBox()); - RetainPtr<CFX_DIBitmap> pClone; - if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { - pClone = m_pDevice->GetBackDrop()->Clone(&rect); - RetainPtr<CFX_DIBitmap> pForeBitmap = m_pDevice->GetBitmap(); - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pForeBitmap, rect.left, rect.top); - left = left >= 0 ? 0 : left; - top = top >= 0 ? 0 : top; - if (!pDIBitmap->IsAlphaMask()) - pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, left, top, blend_mode); - else - pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), - pDIBitmap, mask_argb, left, top, blend_mode); - } else { - pClone = pDIBitmap; - } - if (m_pDevice->GetBackDrop()) { - m_pDevice->SetDIBits(pClone, rect.left, rect.top); - } else { - if (pDIBitmap->IsAlphaMask()) - return; - m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top, - blend_mode); - } - } - return; - } - if (!pDIBitmap->HasAlpha() || - (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { - return; - } - RetainPtr<CFX_DIBitmap> pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); - if (!pCloneConvert) - return; - - CXFA_ImageRenderer imageRender; - if (!imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, m_BitmapAlpha, - &m_ImageMatrix, m_Flags)) { - return; - } - while (imageRender.Continue()) - continue; -} - -void XFA_DrawImage(CXFA_Graphics* pGS, - const CFX_RectF& rtImage, - const CFX_Matrix& matrix, - const RetainPtr<CFX_DIBitmap>& pDIBitmap, - XFA_AttributeEnum iAspect, - int32_t iImageXDpi, - int32_t iImageYDpi, - XFA_AttributeEnum iHorzAlign, - XFA_AttributeEnum iVertAlign) { - if (rtImage.IsEmpty()) - return; - if (!pDIBitmap || !pDIBitmap->GetBuffer()) - return; - - CFX_RectF rtFit( - rtImage.TopLeft(), - XFA_UnitPx2Pt((float)pDIBitmap->GetWidth(), (float)iImageXDpi), - XFA_UnitPx2Pt((float)pDIBitmap->GetHeight(), (float)iImageYDpi)); - switch (iAspect) { - case XFA_AttributeEnum::Fit: { - float f1 = rtImage.height / rtFit.height; - float f2 = rtImage.width / rtFit.width; - f1 = std::min(f1, f2); - rtFit.height = rtFit.height * f1; - rtFit.width = rtFit.width * f1; - break; - } - case XFA_AttributeEnum::Height: { - float f1 = rtImage.height / rtFit.height; - rtFit.height = rtImage.height; - rtFit.width = f1 * rtFit.width; - break; - } - case XFA_AttributeEnum::None: - rtFit.height = rtImage.height; - rtFit.width = rtImage.width; - break; - case XFA_AttributeEnum::Width: { - float f1 = rtImage.width / rtFit.width; - rtFit.width = rtImage.width; - rtFit.height = rtFit.height * f1; - break; - } - case XFA_AttributeEnum::Actual: - default: - break; - } - - if (iHorzAlign == XFA_AttributeEnum::Center) - rtFit.left += (rtImage.width - rtFit.width) / 2; - else if (iHorzAlign == XFA_AttributeEnum::Right) - rtFit.left = rtImage.right() - rtFit.width; - - if (iVertAlign == XFA_AttributeEnum::Middle) - rtFit.top += (rtImage.height - rtFit.height) / 2; - else if (iVertAlign == XFA_AttributeEnum::Bottom) - rtFit.top = rtImage.bottom() - rtImage.height; - - CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); - CFX_RenderDevice::StateRestorer restorer(pRenderDevice); - CFX_PathData path; - path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); - pRenderDevice->SetClip_PathFill(&path, &matrix, FXFILL_WINDING); - - CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); - mtImage.Concat( - CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top)); - mtImage.Concat(matrix); - - CXFA_ImageRenderer imageRender; - if (!imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, - FXDIB_INTERPOL)) { - return; - } - while (imageRender.Continue()) - continue; -} - -static const uint8_t g_inv_base64[128] = { - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, - 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, - 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 255, 255, 255, 255, 255, -}; - -static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { - uint8_t* pCP; - int32_t i = 0, j = 0; - if (iLen == 0) { - iLen = strlen((char*)pStr); - } - pCP = FX_Alloc(uint8_t, iLen + 1); - for (; i < iLen; i++) { - if ((pStr[i] & 128) == 0) { - if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { - pCP[j++] = pStr[i]; - } - } - } - pCP[j] = '\0'; - return pCP; -} - -static int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) { - if (!pStr) { - return 0; - } - uint8_t* pBuffer = - XFA_RemoveBase64Whitespace((uint8_t*)pStr, strlen((char*)pStr)); - if (!pBuffer) { - return 0; - } - int32_t iLen = strlen((char*)pBuffer); - int32_t i = 0, j = 0; - uint32_t dwLimb = 0; - for (; i + 3 < iLen; i += 4) { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || - pBuffer[i + 3] == '=') { - if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { - break; - } - if (pBuffer[i + 2] == '=') { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; - j++; - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; - j += 2; - } - } else { - dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) | - ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) | - ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) | - ((uint32_t)g_inv_base64[pBuffer[i + 3]]); - pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; - pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; - pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; - j += 3; - } - } - FX_Free(pBuffer); - return j; -} - -static const char g_base64_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -char* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { - char* out = nullptr; - int i, j; - uint32_t limb; - out = FX_Alloc(char, ((buf_len * 8 + 5) / 6) + 5); - for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { - limb = ((uint32_t)buf[i] << 16) | ((uint32_t)buf[i + 1] << 8) | - ((uint32_t)buf[i + 2]); - out[j] = g_base64_chars[(limb >> 18) & 63]; - out[j + 1] = g_base64_chars[(limb >> 12) & 63]; - out[j + 2] = g_base64_chars[(limb >> 6) & 63]; - out[j + 3] = g_base64_chars[(limb)&63]; - } - switch (buf_len - i) { - case 0: - break; - case 1: - limb = ((uint32_t)buf[i]); - out[j++] = g_base64_chars[(limb >> 2) & 63]; - out[j++] = g_base64_chars[(limb << 4) & 63]; - out[j++] = '='; - out[j++] = '='; - break; - case 2: - limb = ((uint32_t)buf[i] << 8) | ((uint32_t)buf[i + 1]); - out[j++] = g_base64_chars[(limb >> 10) & 63]; - out[j++] = g_base64_chars[(limb >> 4) & 63]; - out[j++] = g_base64_chars[(limb << 2) & 63]; - out[j++] = '='; - break; - default: - break; - } - out[j] = '\0'; - return out; -} -FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { - WideString wsContentType(wsType); - wsContentType.MakeLower(); - if (wsContentType == L"image/jpg") - return FXCODEC_IMAGE_JPG; - if (wsContentType == L"image/png") - return FXCODEC_IMAGE_PNG; - if (wsContentType == L"image/gif") - return FXCODEC_IMAGE_GIF; - if (wsContentType == L"image/bmp") - return FXCODEC_IMAGE_BMP; - if (wsContentType == L"image/tif") - return FXCODEC_IMAGE_TIF; - return FXCODEC_IMAGE_UNKNOWN; -} - -RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc, - CXFA_Image* pImage, - bool& bNameImage, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - WideString wsHref = pImage->GetHref(); - WideString wsImage = pImage->GetContent(); - if (wsHref.IsEmpty() && wsImage.IsEmpty()) - return nullptr; - - FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType()); - ByteString bsContent; - uint8_t* pImageBuffer = nullptr; - RetainPtr<IFX_SeekableReadStream> pImageFileRead; - if (wsImage.GetLength() > 0) { - XFA_AttributeEnum iEncoding = pImage->GetTransferEncoding(); - if (iEncoding == XFA_AttributeEnum::Base64) { - ByteString bsData = wsImage.UTF8Encode(); - int32_t iLength = bsData.GetLength(); - pImageBuffer = FX_Alloc(uint8_t, iLength); - int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer); - if (iRead > 0) { - pImageFileRead = - pdfium::MakeRetain<CFX_MemoryStream>(pImageBuffer, iRead, false); - } - } else { - bsContent = ByteString::FromUnicode(wsImage); - pImageFileRead = pdfium::MakeRetain<CFX_MemoryStream>( - const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength(), - false); - } - } else { - WideString wsURL = wsHref; - if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") { - RetainPtr<CFX_DIBitmap> pBitmap = - pDoc->GetPDFNamedImage(wsURL.AsStringView(), iImageXDpi, iImageYDpi); - if (pBitmap) { - bNameImage = true; - return pBitmap; - } - } - pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL); - } - if (!pImageFileRead) { - FX_Free(pImageBuffer); - return nullptr; - } - bNameImage = false; - RetainPtr<CFX_DIBitmap> pBitmap = - XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); - FX_Free(pImageBuffer); - return pBitmap; -} - -static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, - int32_t iComponents, - int32_t iBitsPerComponent) { - FXDIB_Format dibFormat = FXDIB_Argb; - switch (type) { - case FXCODEC_IMAGE_BMP: - case FXCODEC_IMAGE_JPG: - case FXCODEC_IMAGE_TIF: { - dibFormat = FXDIB_Rgb32; - int32_t bpp = iComponents * iBitsPerComponent; - if (bpp <= 24) { - dibFormat = FXDIB_Rgb; - } - } break; - case FXCODEC_IMAGE_PNG: - default: - break; - } - return dibFormat; -} - -RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer( - const RetainPtr<IFX_SeekableReadStream>& pImageFileRead, - FXCODEC_IMAGE_TYPE type, - int32_t& iImageXDpi, - int32_t& iImageYDpi) { - CCodec_ModuleMgr* pCodecMgr = CPDF_ModuleMgr::Get()->GetCodecModule(); - std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder = - pCodecMgr->CreateProgressiveDecoder(); - - CFX_DIBAttribute dibAttr; - pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false); - switch (dibAttr.m_wDPIUnit) { - case FXCODEC_RESUNIT_CENTIMETER: - dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); - dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); - break; - case FXCODEC_RESUNIT_METER: - dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f); - dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f); - break; - default: - break; - } - iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); - iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); - if (pProgressiveDecoder->GetWidth() <= 0 || - pProgressiveDecoder->GetHeight() <= 0) { - return nullptr; - } - - type = pProgressiveDecoder->GetType(); - int32_t iComponents = pProgressiveDecoder->GetNumComponents(); - int32_t iBpc = pProgressiveDecoder->GetBPC(); - FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); - RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pBitmap->Create(pProgressiveDecoder->GetWidth(), - pProgressiveDecoder->GetHeight(), dibFormat); - pBitmap->Clear(0xffffffff); - - size_t nFrames; - FXCODEC_STATUS status; - std::tie(status, nFrames) = pProgressiveDecoder->GetFrames(); - if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) { - pBitmap = nullptr; - return pBitmap; - } - - status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), - pBitmap->GetHeight()); - if (IsFXCodecErrorStatus(status)) { - pBitmap = nullptr; - return pBitmap; - } - - while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) { - status = pProgressiveDecoder->ContinueDecode(); - if (IsFXCodecErrorStatus(status)) { - pBitmap = nullptr; - return pBitmap; - } - } - - return pBitmap; -} - -void XFA_RectWithoutMargin(CFX_RectF& rt, const CXFA_Margin* margin, bool bUI) { - if (!margin) - return; - - rt.Deflate(margin->GetLeftInset(), margin->GetTopInset(), - margin->GetRightInset(), margin->GetBottomInset()); -} - -CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { - if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType())) - return static_cast<CXFA_FFWidget*>(pLayoutItem); - return nullptr; -} - -bool XFA_IsCreateWidget(XFA_Element eType) { - return eType == XFA_Element::Field || eType == XFA_Element::Draw || - eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup; -} - -CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {} - -CXFA_CalcData::~CXFA_CalcData() {} |