summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2018-01-16 21:25:27 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-01-16 21:25:27 +0000
commit027190ec8148a2f1edc18c37eae26e896f3a309a (patch)
tree6f65b1bb530309b8d6656e92e66dad1fcd1e1e44
parent454ab87a354099fb96eee4721328d59f42ca0557 (diff)
downloadpdfium-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>
-rw-r--r--BUILD.gn2
-rw-r--r--xfa/fxfa/cxfa_ffwidget.cpp1040
-rw-r--r--xfa/fxfa/cxfa_ffwidget.h15
-rw-r--r--xfa/fxfa/cxfa_imagerenderer.cpp238
-rw-r--r--xfa/fxfa/cxfa_imagerenderer.h61
-rw-r--r--xfa/fxfa/cxfa_widgetacc.cpp147
6 files changed, 739 insertions, 764 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 60c2e42f7a..e68a48ec36 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2019,6 +2019,8 @@ if (pdf_enable_xfa) {
"xfa/fxfa/cxfa_fwladapterwidgetmgr.h",
"xfa/fxfa/cxfa_fwltheme.cpp",
"xfa/fxfa/cxfa_fwltheme.h",
+ "xfa/fxfa/cxfa_imagerenderer.cpp",
+ "xfa/fxfa/cxfa_imagerenderer.h",
"xfa/fxfa/cxfa_linkuserdata.cpp",
"xfa/fxfa/cxfa_linkuserdata.h",
"xfa/fxfa/cxfa_loadercontext.cpp",
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() {}
diff --git a/xfa/fxfa/cxfa_ffwidget.h b/xfa/fxfa/cxfa_ffwidget.h
index 8ec92ef93f..192f559fd4 100644
--- a/xfa/fxfa/cxfa_ffwidget.h
+++ b/xfa/fxfa/cxfa_ffwidget.h
@@ -31,13 +31,6 @@ inline float XFA_UnitPx2Pt(float fPx, float fDpi) {
#define XFA_FLOAT_PERCISION 0.001f
-enum XFA_WIDGETITEM {
- XFA_WIDGETITEM_Parent,
- XFA_WIDGETITEM_FirstChild,
- XFA_WIDGETITEM_NextSibling,
- XFA_WIDGETITEM_PrevSibling,
-};
-
int32_t XFA_StrokeTypeSetLineDash(CXFA_Graphics* pGraphics,
XFA_AttributeEnum iStrokeType,
XFA_AttributeEnum iCapType);
@@ -51,20 +44,12 @@ void XFA_DrawImage(CXFA_Graphics* pGS,
XFA_AttributeEnum iHorzAlign = XFA_AttributeEnum::Left,
XFA_AttributeEnum iVertAlign = XFA_AttributeEnum::Top);
-RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc,
- CXFA_Image* pImage,
- bool& bNameImage,
- int32_t& iImageXDpi,
- int32_t& iImageYDpi);
-
RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
const RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
FXCODEC_IMAGE_TYPE type,
int32_t& iImageXDpi,
int32_t& iImageYDpi);
-FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType);
-char* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len);
void XFA_RectWithoutMargin(CFX_RectF& rt,
const CXFA_Margin* margin,
bool bUI = false);
diff --git a/xfa/fxfa/cxfa_imagerenderer.cpp b/xfa/fxfa/cxfa_imagerenderer.cpp
new file mode 100644
index 0000000000..14f8b25af1
--- /dev/null
+++ b/xfa/fxfa/cxfa_imagerenderer.cpp
@@ -0,0 +1,238 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fxfa/cxfa_imagerenderer.h"
+
+#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "core/fxge/dib/cfx_dibsource.h"
+#include "core/fxge/dib/cfx_imagerenderer.h"
+#include "core/fxge/dib/cfx_imagetransformer.h"
+#include "third_party/base/ptr_util.h"
+
+CXFA_ImageRenderer::CXFA_ImageRenderer() : m_pDevice(nullptr) {}
+
+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;
+}
diff --git a/xfa/fxfa/cxfa_imagerenderer.h b/xfa/fxfa/cxfa_imagerenderer.h
new file mode 100644
index 0000000000..ca53bf639e
--- /dev/null
+++ b/xfa/fxfa/cxfa_imagerenderer.h
@@ -0,0 +1,61 @@
+// Copyright 2018 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_FXFA_CXFA_IMAGERENDERER_H_
+#define XFA_FXFA_CXFA_IMAGERENDERER_H_
+
+#include <memory>
+
+#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxge/fx_dib.h"
+
+class CFX_RenderDevice;
+class CFX_DIBSource;
+class CFX_DIBitmap;
+class CFX_ImageTransformer;
+class CFX_ImageRenderer;
+
+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 = 0;
+ CFX_Matrix m_ImageMatrix;
+ RetainPtr<CFX_DIBSource> m_pDIBSource;
+ RetainPtr<CFX_DIBitmap> m_pCloneConvert;
+ int m_BitmapAlpha = 255;
+ FX_ARGB m_FillArgb = 0;
+ uint32_t m_Flags = 0;
+ std::unique_ptr<CFX_ImageTransformer> m_pTransformer;
+ std::unique_ptr<CFX_ImageRenderer> m_DeviceHandle;
+ int32_t m_BlendType = FXDIB_BLEND_NORMAL;
+ bool m_Result = true;
+ bool m_bPrint = false;
+};
+
+#endif // XFA_FXFA_CXFA_IMAGERENDERER_H_
diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp
index 407517f564..2ae3381bce 100644
--- a/xfa/fxfa/cxfa_widgetacc.cpp
+++ b/xfa/fxfa/cxfa_widgetacc.cpp
@@ -11,6 +11,7 @@
#include <vector>
#include "core/fxcrt/cfx_decimal.h"
+#include "core/fxcrt/cfx_memorystream.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/xml/cfx_xmlelement.h"
#include "core/fxcrt/xml/cfx_xmlnode.h"
@@ -61,6 +62,152 @@ class CXFA_WidgetLayoutData {
namespace {
+constexpr 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,
+};
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
class CXFA_TextLayoutData : public CXFA_WidgetLayoutData {
public:
CXFA_TextLayoutData() {}