Index: xfa/src/fxfa/src/app/xfa_ffwidget.cpp |
diff --git a/xfa/src/fxfa/src/app/xfa_ffwidget.cpp b/xfa/src/fxfa/src/app/xfa_ffwidget.cpp |
index 08194bade152b93ecfc0ad2200cd8b0832516c61..f97e272b04fd34c27ba3c2e2011ced9ff1e43904 100644 |
--- a/xfa/src/fxfa/src/app/xfa_ffwidget.cpp |
+++ b/xfa/src/fxfa/src/app/xfa_ffwidget.cpp |
@@ -1,1959 +1,1959 @@ |
-// Copyright 2014 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 <algorithm> |
- |
-#include "xfa/src/foxitlib.h" |
-#include "xfa/src/fxfa/src/common/xfa_common.h" |
-#include "xfa_ffapp.h" |
-#include "xfa_ffdoc.h" |
-#include "xfa_ffdocview.h" |
-#include "xfa_ffwidget.h" |
-#include "xfa_ffpageview.h" |
-#include "xfa_textlayout.h" |
-CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView, |
- CXFA_WidgetAcc* pDataAcc) |
- : CXFA_ContentLayoutItem(pDataAcc->GetNode()), |
- m_pPageView(pPageView), |
- m_pDataAcc(pDataAcc) { |
- m_rtWidget.Set(0, 0, 0, 0); |
-} |
-CXFA_FFWidget::~CXFA_FFWidget() {} |
-IXFA_PageView* CXFA_FFWidget::GetPageView() { |
- return m_pPageView; |
-} |
-void CXFA_FFWidget::SetPageView(IXFA_PageView* pPageView) { |
- m_pPageView = static_cast<CXFA_FFPageView*>(pPageView); |
-} |
-void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) { |
- if ((m_dwStatus & XFA_WIDGETSTATUS_RectCached) == 0) { |
- m_dwStatus |= XFA_WIDGETSTATUS_RectCached; |
- GetRect(m_rtWidget); |
- } |
- rtWidget = m_rtWidget; |
-} |
-CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() { |
- m_dwStatus |= XFA_WIDGETSTATUS_RectCached; |
- GetRect(m_rtWidget); |
- return m_rtWidget; |
-} |
-void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) { |
- GetWidgetRect(rtWidget); |
- FX_FLOAT fValue = 0; |
- switch (m_pDataAcc->GetRotate()) { |
- case 90: |
- rtWidget.top = rtWidget.bottom(); |
- fValue = rtWidget.width; |
- rtWidget.width = rtWidget.height; |
- rtWidget.height = fValue; |
- break; |
- case 180: |
- rtWidget.left = rtWidget.right(); |
- rtWidget.top = rtWidget.bottom(); |
- break; |
- case 270: |
- rtWidget.left = rtWidget.right(); |
- fValue = rtWidget.width; |
- rtWidget.width = rtWidget.height; |
- rtWidget.height = fValue; |
- break; |
- } |
-} |
-FX_DWORD CXFA_FFWidget::GetStatus() { |
- return m_dwStatus; |
-} |
-void CXFA_FFWidget::ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved) { |
- m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; |
-} |
-FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox, |
- FX_DWORD dwStatus, |
- FX_BOOL bDrawFocus) { |
- if (bDrawFocus) { |
- return FALSE; |
- } |
-#ifndef _XFA_EMB |
- if (m_pPageView) { |
- m_pPageView->GetPageViewRect(rtBox); |
- } |
- return TRUE; |
-#endif |
- GetWidgetRect(rtBox); |
- return TRUE; |
-} |
-CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() { |
- return m_pDataAcc; |
-} |
-FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) { |
- if (CXFA_Assist assist = m_pDataAcc->GetAssist()) { |
- if (CXFA_ToolTip toolTip = assist.GetToolTip()) { |
- return toolTip.GetTip(wsToolTip); |
- } |
- } |
- return GetCaptionText(wsToolTip); |
-} |
-void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwStatus, |
- int32_t iRotate) { |
- if (!IsMatchVisibleStatus(dwStatus)) { |
- return; |
- } |
- CXFA_Border border = m_pDataAcc->GetBorder(); |
- if (border) { |
- CFX_RectF rtBorder; |
- GetRectWithoutRotate(rtBorder); |
- CXFA_Margin margin = border.GetMargin(); |
- if (margin.IsExistInXML()) { |
- XFA_RectWidthoutMargin(rtBorder, margin); |
- } |
- rtBorder.Normalize(); |
- DrawBorder(pGS, border, rtBorder, pMatrix); |
- } |
-} |
-FX_BOOL CXFA_FFWidget::IsLoaded() { |
- return m_pPageView != NULL; |
-} |
-FX_BOOL CXFA_FFWidget::LoadWidget() { |
- PerformLayout(); |
- return TRUE; |
-} |
-void CXFA_FFWidget::UnloadWidget() {} |
-FX_BOOL CXFA_FFWidget::PerformLayout() { |
- ReCacheWidgetRect(); |
- return TRUE; |
-} |
-FX_BOOL CXFA_FFWidget::UpdateFWLData() { |
- return FALSE; |
-} |
-void CXFA_FFWidget::UpdateWidgetProperty() {} |
-void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS, |
- CXFA_Box box, |
- const CFX_RectF& rtBorder, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwFlags) { |
- XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags); |
-} |
-void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) { |
- if (!pRect) { |
- CFX_RectF rtWidget; |
- GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); |
- rtWidget.Inflate(2, 2); |
- GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget, |
- XFA_INVALIDATE_CurrentPage); |
- } else { |
- GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect, |
- XFA_INVALIDATE_CurrentPage); |
- } |
-} |
-void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) { |
- CFX_RectF rtWidget; |
- if (pRect) { |
- rtWidget = *pRect; |
- } else { |
- GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); |
- rtWidget.Inflate(2, 2); |
- } |
- m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); |
-} |
-FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) { |
- CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout(); |
- if (!pCapTextlayout) { |
- return FALSE; |
- } |
- pCapTextlayout->GetText(wsCap); |
- return TRUE; |
-} |
-FX_BOOL CXFA_FFWidget::IsFocused() { |
- return m_dwStatus & XFA_WIDGETSTATUS_Focused; |
-} |
-FX_BOOL CXFA_FFWidget::OnMouseEnter() { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnMouseExit() { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnLButtonDown(FX_DWORD dwFlags, |
- FX_FLOAT fx, |
- FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnLButtonDblClk(FX_DWORD dwFlags, |
- FX_FLOAT fx, |
- FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnMouseWheel(FX_DWORD dwFlags, |
- int16_t zDelta, |
- FX_FLOAT fx, |
- FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnRButtonDown(FX_DWORD dwFlags, |
- FX_FLOAT fx, |
- FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnRButtonDblClk(FX_DWORD dwFlags, |
- FX_FLOAT fx, |
- FX_FLOAT fy) { |
- return FALSE; |
-} |
- |
-FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { |
- CXFA_FFWidget* pParent = GetParent(); |
- if (pParent != NULL && !pParent->IsAncestorOf(pOldWidget)) { |
- pParent->OnSetFocus(pOldWidget); |
- } |
- m_dwStatus |= XFA_WIDGETSTATUS_Focused; |
- CXFA_EventParam eParam; |
- eParam.m_eType = XFA_EVENT_Enter; |
- eParam.m_pTarget = m_pDataAcc; |
- m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam); |
- return TRUE; |
-} |
-FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { |
- m_dwStatus &= ~XFA_WIDGETSTATUS_Focused; |
- EventKillFocus(); |
- if (pNewWidget != NULL) { |
- CXFA_FFWidget* pParent = GetParent(); |
- if (pParent != NULL && !pParent->IsAncestorOf(pNewWidget)) { |
- pParent->OnKillFocus(pNewWidget); |
- } |
- } |
- return TRUE; |
-} |
-FX_BOOL CXFA_FFWidget::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) { |
- return FALSE; |
-} |
-FX_DWORD CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) { |
- return FALSE; |
-} |
-void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) { |
- CFX_Matrix mt; |
- GetRotateMatrix(mt); |
- if (mt.IsIdentity()) { |
- return; |
- } |
- CFX_Matrix mtReverse; |
- mtReverse.SetReverse(mt); |
- mtReverse.TransformPoint(fx, fy); |
-} |
-static void XFA_GetMatrix(CFX_Matrix& m, |
- int32_t iRotate, |
- int32_t at, |
- const CFX_RectF& rt) { |
- if (!iRotate) { |
- return; |
- } |
- FX_FLOAT fAnchorX, fAnchorY; |
- 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; |
- } |
- 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; |
- } |
-} |
-void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) { |
- mt.Set(1, 0, 0, 1, 0, 0); |
- int32_t iRotate = m_pDataAcc->GetRotate(); |
- if (!iRotate) { |
- return; |
- } |
- CFX_RectF rcWidget; |
- GetRectWithoutRotate(rcWidget); |
- XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft; |
- XFA_GetMatrix(mt, iRotate, at, rcWidget); |
-} |
-FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() { |
- CFX_RectF rtLayout; |
- GetRectWithoutRotate(rtLayout); |
- return rtLayout.width < 0.1f && rtLayout.height < 0.1f; |
-} |
-CXFA_FFWidget* CXFA_FFWidget::GetParent() { |
- CXFA_Node* pParentNode = |
- m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent); |
- if (pParentNode != NULL) { |
- CXFA_WidgetAcc* pParentWidgetAcc = |
- (CXFA_WidgetAcc*)pParentNode->GetWidgetData(); |
- if (pParentWidgetAcc != NULL) { |
- return pParentWidgetAcc->GetNextWidget(NULL); |
- } |
- } |
- return NULL; |
-} |
-FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { |
- if (!pWidget) { |
- return FALSE; |
- } |
- CXFA_Node* pNode = m_pDataAcc->GetNode(); |
- CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode(); |
- while (pChildNode) { |
- if (pChildNode == pNode) { |
- return TRUE; |
- } |
- pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent); |
- } |
- return FALSE; |
-} |
-FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) { |
- CFX_RectF rtWidget; |
- GetWidgetRect(rtWidget); |
- if (rtWidget.Contains(fx, fy)) { |
- return TRUE; |
- } |
- return FALSE; |
-} |
-CXFA_FFDocView* CXFA_FFWidget::GetDocView() { |
- return m_pDocView; |
-} |
-CXFA_FFDoc* CXFA_FFWidget::GetDoc() { |
- return (CXFA_FFDoc*)m_pDocView->GetDoc(); |
-} |
-CXFA_FFApp* CXFA_FFWidget::GetApp() { |
- return GetDoc()->GetApp(); |
-} |
-IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { |
- return GetApp()->GetAppProvider(); |
-} |
-void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) { |
- fMinWidth = fMaxWidth = 0; |
- FX_FLOAT fWidth = 0; |
- if (m_pDataAcc->GetWidth(fWidth)) { |
- fMinWidth = fMaxWidth = fWidth; |
- } else { |
- m_pDataAcc->GetMinWidth(fMinWidth); |
- m_pDataAcc->GetMaxWidth(fMaxWidth); |
- } |
-} |
-void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) { |
- fMinHeight = fMaxHeight = 0; |
- FX_FLOAT fHeight = 0; |
- if (m_pDataAcc->GetHeight(fHeight)) { |
- fMinHeight = fMaxHeight = fHeight; |
- } else { |
- m_pDataAcc->GetMinHeight(fMinHeight); |
- m_pDataAcc->GetMaxHeight(fMaxHeight); |
- } |
-} |
-FX_BOOL CXFA_FFWidget::IsMatchVisibleStatus(FX_DWORD dwStatus) { |
- return m_dwStatus & XFA_WIDGETSTATUS_Visible; |
-} |
-void CXFA_FFWidget::EventKillFocus() { |
- if (m_dwStatus & XFA_WIDGETSTATUS_Access) { |
- m_dwStatus &= ~XFA_WIDGETSTATUS_Access; |
- return; |
- } |
- CXFA_EventParam eParam; |
- eParam.m_eType = XFA_EVENT_Exit; |
- eParam.m_pTarget = m_pDataAcc; |
- m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam); |
-} |
-FX_BOOL CXFA_FFWidget::IsButtonDown() { |
- return (m_dwStatus & XFA_WIDGETSTATUS_ButtonDown) != 0; |
-} |
-void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) { |
- bSet ? m_dwStatus |= XFA_WIDGETSTATUS_ButtonDown |
- : m_dwStatus &= ~XFA_WIDGETSTATUS_ButtonDown; |
-} |
-int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, |
- int32_t iStrokeType, |
- int32_t iCapType) { |
- switch (iStrokeType) { |
- case XFA_ATTRIBUTEENUM_DashDot: { |
- FX_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: { |
- FX_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: { |
- FX_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: { |
- FX_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; |
-} |
-CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) { |
- switch (iLineCap) { |
- case XFA_ATTRIBUTEENUM_Round: |
- return CFX_GraphStateData::LineCapRound; |
- case XFA_ATTRIBUTEENUM_Butt: |
- return CFX_GraphStateData::LineCapButt; |
- default: |
- break; |
- } |
- return CFX_GraphStateData::LineCapSquare; |
-} |
-class CXFA_ImageRenderer { |
- public: |
- CXFA_ImageRenderer(); |
- ~CXFA_ImageRenderer(); |
- FX_BOOL Start(CFX_RenderDevice* pDevice, |
- CFX_DIBSource* pDIBSource, |
- FX_ARGB bitmap_argb, |
- int bitmap_alpha, |
- const CFX_Matrix* pImage2Device, |
- FX_DWORD flags, |
- int blendType = FXDIB_BLEND_NORMAL); |
- FX_BOOL Continue(IFX_Pause* pPause); |
- |
- protected: |
- CFX_RenderDevice* m_pDevice; |
- int m_Status; |
- CFX_Matrix m_ImageMatrix; |
- CFX_DIBSource* m_pDIBSource; |
- CFX_DIBitmap* m_pCloneConvert; |
- int m_BitmapAlpha; |
- FX_ARGB m_FillArgb; |
- FX_DWORD m_Flags; |
- CFX_ImageTransformer* m_pTransformer; |
- void* m_DeviceHandle; |
- int32_t m_BlendType; |
- FX_BOOL m_Result; |
- FX_BOOL m_bPrint; |
- FX_BOOL StartDIBSource(); |
- void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, |
- int left, |
- int top, |
- FX_ARGB mask_argb, |
- int bitmap_alpha, |
- int blend_mode, |
- int Transparency); |
-}; |
-CXFA_ImageRenderer::CXFA_ImageRenderer() { |
- m_pDevice = NULL; |
- m_Status = 0; |
- m_pDIBSource = NULL; |
- m_pCloneConvert = NULL; |
- m_BitmapAlpha = 255; |
- m_FillArgb = 0; |
- m_Flags = 0; |
- m_pTransformer = NULL; |
- m_DeviceHandle = NULL; |
- m_BlendType = FXDIB_BLEND_NORMAL; |
- m_Result = TRUE; |
- m_bPrint = FALSE; |
-} |
-CXFA_ImageRenderer::~CXFA_ImageRenderer() { |
- if (m_pCloneConvert) { |
- delete m_pCloneConvert; |
- } |
- if (m_pTransformer) { |
- delete m_pTransformer; |
- } |
- if (m_DeviceHandle) { |
- m_pDevice->CancelDIBits(m_DeviceHandle); |
- } |
-} |
-FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, |
- CFX_DIBSource* pDIBSource, |
- FX_ARGB bitmap_argb, |
- int bitmap_alpha, |
- const CFX_Matrix* pImage2Device, |
- FX_DWORD 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(); |
-} |
-FX_BOOL CXFA_ImageRenderer::StartDIBSource() { |
- if (m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb, |
- &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, |
- m_BlendType)) { |
- if (m_DeviceHandle != NULL) { |
- m_Status = 3; |
- return TRUE; |
- } |
- return FALSE; |
- } |
- CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); |
- FX_RECT image_rect = image_rect_f.GetOutterRect(); |
- int dest_width = image_rect.Width(); |
- 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_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { |
- m_Result = FALSE; |
- return FALSE; |
- } |
- 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 = new CFX_ImageTransformer; |
- m_pTransformer->Start(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->StretchDIBits(m_pDIBSource, dest_left, dest_top, dest_width, |
- dest_height, m_Flags, NULL, m_BlendType)) { |
- return FALSE; |
- } |
- } |
- if (m_pDIBSource->IsAlphaMask()) { |
- if (m_BitmapAlpha != 255) { |
- m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); |
- } |
- if (m_pDevice->StretchBitMask(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); |
- 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); |
- delete pStretched; |
- pStretched = NULL; |
- } |
- return FALSE; |
-} |
-FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) { |
- if (m_Status == 2) { |
- if (m_pTransformer->Continue(pPause)) { |
- return TRUE; |
- } |
- CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach(); |
- if (pBitmap == NULL) { |
- 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->m_ResultLeft, |
- m_pTransformer->m_ResultTop, m_FillArgb); |
- } else { |
- if (m_BitmapAlpha != 255) { |
- pBitmap->MultiplyAlpha(m_BitmapAlpha); |
- } |
- m_Result = m_pDevice->SetDIBits(pBitmap, m_pTransformer->m_ResultLeft, |
- m_pTransformer->m_ResultTop, m_BlendType); |
- } |
- delete pBitmap; |
- return FALSE; |
- } else if (m_Status == 3) { |
- return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); |
- } |
- return FALSE; |
-} |
-void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, |
- int left, |
- int top, |
- FX_ARGB mask_argb, |
- int bitmap_alpha, |
- int blend_mode, |
- int Transparency) { |
- if (pDIBitmap == NULL) { |
- return; |
- } |
- FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; |
- FX_BOOL bGroup = Transparency & 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 { |
- FX_DWORD 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; |
- } |
- } |
- } |
- FX_BOOL bBackAlphaRequired = blend_mode && bIsolated; |
- FX_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->SetDIBits(pDIBitmap, left, top, blend_mode); |
- } else { |
- FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), |
- top + pDIBitmap->GetHeight()); |
- rect.Intersect(m_pDevice->GetClipBox()); |
- CFX_DIBitmap* pClone = NULL; |
- FX_BOOL bClone = FALSE; |
- if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { |
- bClone = TRUE; |
- pClone = m_pDevice->GetBackDrop()->Clone(&rect); |
- 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->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); |
- } |
- if (bClone) { |
- delete pClone; |
- } |
- } |
- return; |
- } |
- if (pDIBitmap->HasAlpha() && |
- !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { |
- CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); |
- if (!pCloneConvert) { |
- return; |
- } |
- CXFA_ImageRenderer imageRender; |
- FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, |
- m_BitmapAlpha, &m_ImageMatrix, m_Flags); |
- while (bRet) { |
- bRet = imageRender.Continue(NULL); |
- } |
- delete pCloneConvert; |
- return; |
- } |
-} |
-void XFA_DrawImage(CFX_Graphics* pGS, |
- const CFX_RectF& rtImage, |
- CFX_Matrix* pMatrix, |
- CFX_DIBitmap* pDIBitmap, |
- int32_t iAspect, |
- int32_t iImageXDpi, |
- int32_t iImageYDpi, |
- int32_t iHorzAlign, |
- int32_t iVertAlign) { |
- if (rtImage.IsEmpty()) { |
- return; |
- } |
- if (!pDIBitmap || !pDIBitmap->GetBuffer()) { |
- return; |
- } |
- FX_FLOAT fWidth = |
- XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi); |
- FX_FLOAT fHeight = |
- XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi); |
- CFX_RectF rtFit; |
- rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight); |
- switch (iAspect) { |
- case XFA_ATTRIBUTEENUM_Fit: { |
- FX_FLOAT f1 = rtImage.height / rtFit.height; |
- FX_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_Actual: |
- break; |
- case XFA_ATTRIBUTEENUM_Height: { |
- FX_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: { |
- FX_FLOAT f1 = rtImage.width / rtFit.width; |
- rtFit.width = rtImage.width; |
- rtFit.height = rtFit.height * f1; |
- } 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(); |
- pRenderDevice->SaveState(); |
- CFX_PathData path; |
- path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); |
- pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING); |
- CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); |
- mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top); |
- mtImage.Concat(*pMatrix); |
- CXFA_ImageRenderer imageRender; |
- FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, |
- FXDIB_INTERPOL); |
- while (bRet) { |
- bRet = imageRender.Continue(NULL); |
- } |
- pRenderDevice->RestoreState(); |
-} |
-const static 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 = FXSYS_strlen((FX_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 FX_CHAR* pStr, uint8_t* pOutBuffer) { |
- if (pStr == NULL) { |
- return 0; |
- } |
- uint8_t* pBuffer = |
- XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr)); |
- if (pBuffer == NULL) { |
- return 0; |
- } |
- int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer); |
- int32_t i = 0, j = 0; |
- FX_DWORD 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 = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 6) | |
- ((FX_DWORD)g_inv_base64[pBuffer[i + 1]]); |
- pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; |
- j++; |
- } else { |
- dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 12) | |
- ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 6) | |
- ((FX_DWORD)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 = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 18) | |
- ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 12) | |
- ((FX_DWORD)g_inv_base64[pBuffer[i + 2]] << 6) | |
- ((FX_DWORD)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 FX_CHAR g_base64_chars[] = |
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
-FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { |
- FX_CHAR* out = NULL; |
- int i, j; |
- FX_DWORD limb; |
- out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5); |
- for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { |
- limb = ((FX_DWORD)buf[i] << 16) | ((FX_DWORD)buf[i + 1] << 8) | |
- ((FX_DWORD)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 = ((FX_DWORD)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 = ((FX_DWORD)buf[i] << 8) | ((FX_DWORD)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 CFX_WideStringC& wsType) { |
- CFX_WideString wsContentType(wsType); |
- wsContentType.MakeLower(); |
- if (wsContentType == FX_WSTRC(L"image/jpg")) { |
- return FXCODEC_IMAGE_JPG; |
- } |
- if (wsContentType == FX_WSTRC(L"image/png")) { |
- return FXCODEC_IMAGE_PNG; |
- } |
- if (wsContentType == FX_WSTRC(L"image/gif")) { |
- return FXCODEC_IMAGE_GIF; |
- } |
- if (wsContentType == FX_WSTRC(L"image/bmp")) { |
- return FXCODEC_IMAGE_BMP; |
- } |
- if (wsContentType == FX_WSTRC(L"image/tif")) { |
- return FXCODEC_IMAGE_TIF; |
- } |
- return FXCODEC_IMAGE_UNKNOWN; |
-} |
-CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, |
- CXFA_Image* pImage, |
- FX_BOOL& bNameImage, |
- int32_t& iImageXDpi, |
- int32_t& iImageYDpi) { |
- CFX_WideString wsHref; |
- pImage->GetHref(wsHref); |
- CFX_WideString wsImage; |
- pImage->GetContent(wsImage); |
- if (wsHref.IsEmpty() && wsImage.IsEmpty()) { |
- return NULL; |
- } |
- CFX_WideString wsContentType; |
- pImage->GetContentType(wsContentType); |
- FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType); |
- CFX_ByteString bsContent; |
- uint8_t* pImageBuffer = NULL; |
- IFX_FileRead* pImageFileRead = NULL; |
- if (wsImage.GetLength() > 0) { |
- XFA_ATTRIBUTEENUM iEncoding = |
- (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding(); |
- if (iEncoding == XFA_ATTRIBUTEENUM_Base64) { |
- CFX_ByteString bsData = wsImage.UTF8Encode(); |
- int32_t iLength = bsData.GetLength(); |
- pImageBuffer = FX_Alloc(uint8_t, iLength); |
- int32_t iRead = XFA_Base64Decode((const FX_CHAR*)bsData, pImageBuffer); |
- if (iRead > 0) { |
- pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead); |
- } |
- } else { |
- bsContent = CFX_ByteString::FromUnicode(wsImage); |
- pImageFileRead = FX_CreateMemoryStream( |
- (uint8_t*)(const uint8_t*)bsContent, bsContent.GetLength()); |
- } |
- } else { |
- CFX_WideString wsURL = wsHref; |
- if (wsURL.Left(7) != FX_WSTRC(L"http://") && |
- wsURL.Left(6) != FX_WSTRC(L"ftp://")) { |
- CFX_DIBitmap* pBitmap = |
- pDoc->GetPDFNamedImage(wsURL, iImageXDpi, iImageYDpi); |
- if (pBitmap != NULL) { |
- bNameImage = TRUE; |
- return pBitmap; |
- } |
- } |
- pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL); |
- } |
- if (!pImageFileRead) { |
- FX_Free(pImageBuffer); |
- return NULL; |
- } |
- bNameImage = FALSE; |
- CFX_DIBitmap* pBitmap = |
- XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); |
- FX_Free(pImageBuffer); |
- pImageFileRead->Release(); |
- 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; |
-} |
-CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead, |
- FXCODEC_IMAGE_TYPE type, |
- int32_t& iImageXDpi, |
- int32_t& iImageYDpi) { |
- CFX_GEModule* pGeModule = CFX_GEModule::Get(); |
- if (!pGeModule) { |
- return NULL; |
- } |
- CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); |
- if (!pCodecMgr) { |
- return NULL; |
- } |
- CFX_DIBAttribute dibAttr; |
- CFX_DIBitmap* pBitmap = NULL; |
- ICodec_ProgressiveDecoder* pProgressiveDecoder = |
- pCodecMgr->CreateProgressiveDecoder(); |
- pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr); |
- 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 / (FX_FLOAT)100 * 2.54f); |
- dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_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) { |
- type = pProgressiveDecoder->GetType(); |
- int32_t iComponents = pProgressiveDecoder->GetNumComponents(); |
- int32_t iBpc = pProgressiveDecoder->GetBPC(); |
- FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); |
- pBitmap = new CFX_DIBitmap(); |
- pBitmap->Create(pProgressiveDecoder->GetWidth(), |
- pProgressiveDecoder->GetHeight(), dibFormat); |
- pBitmap->Clear(0xffffffff); |
- int32_t nFrames; |
- if ((pProgressiveDecoder->GetFrames(nFrames) == |
- FXCODEC_STATUS_DECODE_READY) && |
- (nFrames > 0)) { |
- pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), |
- pBitmap->GetHeight()); |
- pProgressiveDecoder->ContinueDecode(); |
- } |
- } |
- delete pProgressiveDecoder; |
- return pBitmap; |
-} |
-void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) { |
- if (!mg) { |
- return; |
- } |
- FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; |
- mg.GetLeftInset(fLeftInset); |
- mg.GetTopInset(fTopInset); |
- mg.GetRightInset(fRightInset); |
- mg.GetBottomInset(fBottomInset); |
- rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); |
-} |
-CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { |
- XFA_ELEMENT iType = pLayoutItem->GetFormNode()->GetClassID(); |
- if (XFA_IsCreateWidget(iType)) { |
- return static_cast<CXFA_FFWidget*>(pLayoutItem); |
- } |
- return nullptr; |
-} |
-FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType) { |
- return iType == XFA_ELEMENT_Field || iType == XFA_ELEMENT_Draw || |
- iType == XFA_ELEMENT_Subform || iType == XFA_ELEMENT_ExclGroup; |
-} |
-static void XFA_BOX_GetPath_Arc(CXFA_Box box, |
- CFX_RectF rtDraw, |
- CFX_Path& fillPath, |
- FX_DWORD dwFlags) { |
- FX_FLOAT a, b; |
- a = rtDraw.width / 2.0f; |
- b = rtDraw.height / 2.0f; |
- if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
- a = b = std::min(a, b); |
- } |
- CFX_PointF center = rtDraw.Center(); |
- rtDraw.left = center.x - a; |
- rtDraw.top = center.y - b; |
- rtDraw.width = a + a; |
- rtDraw.height = b + b; |
- FX_FLOAT startAngle = 0, sweepAngle = 360; |
- FX_BOOL bStart = box.GetStartAngle(startAngle); |
- FX_BOOL bEnd = box.GetSweepAngle(sweepAngle); |
- if (!bStart && !bEnd) { |
- fillPath.AddEllipse(rtDraw); |
- return; |
- } |
- startAngle = -startAngle * FX_PI / 180.0f; |
- sweepAngle = -sweepAngle * FX_PI / 180.0f; |
- fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height, |
- startAngle, sweepAngle); |
-} |
-static void XFA_BOX_GetPath(CXFA_Box box, |
- const CXFA_StrokeArray& strokes, |
- CFX_RectF rtWidget, |
- CFX_Path& path, |
- int32_t nIndex, |
- FX_BOOL bStart, |
- FX_BOOL bCorner) { |
- FXSYS_assert(nIndex >= 0 && nIndex < 8); |
- FX_BOOL bInverted, bRound; |
- FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny, offsetY, offsetX, |
- offsetEX, offsetEY; |
- CFX_PointF cpStart, cp, cp1, cp2; |
- CFX_RectF rtRadius; |
- int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; |
- CXFA_Corner corner1 = (CXFA_Node*)strokes[n]; |
- CXFA_Corner corner2 = (CXFA_Node*)strokes[(n + 2) % 8]; |
- fRadius1 = bCorner ? corner1.GetRadius() : 0; |
- fRadius2 = bCorner ? corner2.GetRadius() : 0; |
- bInverted = corner1.IsInverted(); |
- offsetY = 0.0f; |
- offsetX = 0.0f; |
- bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; |
- FX_FLOAT halfAfter = 0.0f; |
- FX_FLOAT halfBefore = 0.0f; |
- CXFA_Stroke stroke = strokes[nIndex]; |
- if (stroke.IsCorner()) { |
- CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; |
- CXFA_Stroke edgeAfter = strokes[nIndex + 1]; |
- if (stroke.IsInverted()) { |
- if (!stroke.SameStyles(edgeBefore)) { |
- halfBefore = edgeBefore.GetThickness() / 2; |
- } |
- if (!stroke.SameStyles(edgeAfter)) { |
- halfAfter = edgeAfter.GetThickness() / 2; |
- } |
- } |
- } else { |
- CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8]; |
- CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8]; |
- if (!bRound && !bInverted) { |
- { halfBefore = edgeBefore.GetThickness() / 2; } |
- { halfAfter = edgeAfter.GetThickness() / 2; } |
- } |
- } |
- offsetEX = 0.0f; |
- offsetEY = 0.0f; |
- if (bRound) { |
- sy = FX_PI / 2; |
- } |
- switch (nIndex) { |
- case 0: |
- case 1: |
- cp1 = rtWidget.TopLeft(); |
- cp2 = rtWidget.TopRight(); |
- if (nIndex == 0) { |
- cpStart.x = cp1.x - halfBefore; |
- cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; |
- } else { |
- cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, |
- offsetEX = halfAfter; |
- } |
- vx = 1, vy = 1; |
- nx = -1, ny = 0; |
- if (bRound) { |
- sx = bInverted ? FX_PI / 2 : FX_PI; |
- } else { |
- sx = 1, sy = 0; |
- } |
- break; |
- case 2: |
- case 3: |
- cp1 = rtWidget.TopRight(); |
- cp2 = rtWidget.BottomRight(); |
- if (nIndex == 2) { |
- cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, |
- offsetX = halfAfter; |
- } else { |
- cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, |
- offsetEY = halfAfter; |
- } |
- vx = -1, vy = 1; |
- nx = 0, ny = -1; |
- if (bRound) { |
- sx = bInverted ? FX_PI : FX_PI * 3 / 2; |
- } else { |
- sx = 0, sy = 1; |
- } |
- break; |
- case 4: |
- case 5: |
- cp1 = rtWidget.BottomRight(); |
- cp2 = rtWidget.BottomLeft(); |
- if (nIndex == 4) { |
- cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, |
- offsetY = halfAfter; |
- } else { |
- cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, |
- offsetEX = -halfAfter; |
- } |
- vx = -1, vy = -1; |
- nx = 1, ny = 0; |
- if (bRound) { |
- sx = bInverted ? FX_PI * 3 / 2 : 0; |
- } else { |
- sx = -1, sy = 0; |
- } |
- break; |
- case 6: |
- case 7: |
- cp1 = rtWidget.BottomLeft(); |
- cp2 = rtWidget.TopLeft(); |
- if (nIndex == 6) { |
- cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, |
- offsetX = -halfAfter; |
- } else { |
- cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, |
- offsetEY = -halfAfter; |
- } |
- vx = 1, vy = -1; |
- nx = 0, ny = 1; |
- if (bRound) { |
- sx = bInverted ? 0 : FX_PI / 2; |
- } else { |
- sx = 0, sy = -1; |
- } |
- break; |
- } |
- if (bStart) { |
- path.MoveTo(cpStart.x, cpStart.y); |
- } |
- if (nIndex & 1) { |
- path.LineTo(cp2.x + fRadius2 * nx + offsetEX, |
- cp2.y + fRadius2 * ny + offsetEY); |
- return; |
- } |
- if (bRound) { |
- if (fRadius1 < 0) { |
- sx -= FX_PI; |
- } |
- if (bInverted) { |
- sy *= -1; |
- } |
- rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2, |
- fRadius1 * 2 * vx - offsetX * 2, |
- fRadius1 * 2 * vy - offsetY * 2); |
- rtRadius.Normalize(); |
- if (bInverted) { |
- rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); |
- } |
- path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx, |
- sy); |
- } else { |
- if (bInverted) { |
- cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; |
- } else { |
- cp = cp1; |
- } |
- path.LineTo(cp.x, cp.y); |
- path.LineTo(cp1.x + fRadius1 * sx + offsetX, |
- cp1.y + fRadius1 * sy + offsetY); |
- } |
-} |
-static void XFA_BOX_GetFillPath(CXFA_Box box, |
- const CXFA_StrokeArray& strokes, |
- CFX_RectF rtWidget, |
- CFX_Path& fillPath, |
- FX_WORD dwFlags) { |
- if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
- CXFA_Edge edge = box.GetEdge(0); |
- FX_FLOAT fThickness = edge.GetThickness(); |
- if (fThickness < 0) { |
- fThickness = 0; |
- } |
- FX_FLOAT fHalf = fThickness / 2; |
- int32_t iHand = box.GetHand(); |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.Inflate(fHalf, fHalf); |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.Deflate(fHalf, fHalf); |
- } |
- XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags); |
- return; |
- } |
- FX_BOOL bSameStyles = TRUE; |
- int32_t i; |
- CXFA_Stroke stroke1 = strokes[0]; |
- for (i = 1; i < 8; i++) { |
- CXFA_Stroke stroke2 = strokes[i]; |
- if (!stroke1.SameStyles(stroke2)) { |
- bSameStyles = FALSE; |
- break; |
- } |
- stroke1 = stroke2; |
- } |
- if (bSameStyles) { |
- stroke1 = strokes[0]; |
- for (i = 2; i < 8; i += 2) { |
- CXFA_Stroke stroke2 = strokes[i]; |
- if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | |
- XFA_STROKE_SAMESTYLE_Corner)) { |
- bSameStyles = FALSE; |
- break; |
- } |
- stroke1 = stroke2; |
- } |
- if (bSameStyles) { |
- stroke1 = strokes[0]; |
- if (stroke1.IsInverted()) { |
- bSameStyles = FALSE; |
- } |
- if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { |
- bSameStyles = FALSE; |
- } |
- } |
- } |
- if (bSameStyles) { |
- fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, |
- rtWidget.height); |
- return; |
- } |
- FX_BOOL bInverted, bRound; |
- FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny; |
- CFX_PointF cp, cp1, cp2; |
- CFX_RectF rtRadius; |
- for (int32_t i = 0; i < 8; i += 2) { |
- CXFA_Corner corner1 = (CXFA_Node*)strokes[i]; |
- CXFA_Corner corner2 = (CXFA_Node*)strokes[(i + 2) % 8]; |
- fRadius1 = corner1.GetRadius(); |
- fRadius2 = corner2.GetRadius(); |
- bInverted = corner1.IsInverted(); |
- bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; |
- if (bRound) { |
- sy = FX_PI / 2; |
- } |
- switch (i) { |
- case 0: |
- cp1 = rtWidget.TopLeft(); |
- cp2 = rtWidget.TopRight(); |
- vx = 1, vy = 1; |
- nx = -1, ny = 0; |
- if (bRound) { |
- sx = bInverted ? FX_PI / 2 : FX_PI; |
- } else { |
- sx = 1, sy = 0; |
- } |
- break; |
- case 2: |
- cp1 = rtWidget.TopRight(); |
- cp2 = rtWidget.BottomRight(); |
- vx = -1, vy = 1; |
- nx = 0, ny = -1; |
- if (bRound) { |
- sx = bInverted ? FX_PI : FX_PI * 3 / 2; |
- } else { |
- sx = 0, sy = 1; |
- } |
- break; |
- case 4: |
- cp1 = rtWidget.BottomRight(); |
- cp2 = rtWidget.BottomLeft(); |
- vx = -1, vy = -1; |
- nx = 1, ny = 0; |
- if (bRound) { |
- sx = bInverted ? FX_PI * 3 / 2 : 0; |
- } else { |
- sx = -1, sy = 0; |
- } |
- break; |
- case 6: |
- cp1 = rtWidget.BottomLeft(); |
- cp2 = rtWidget.TopLeft(); |
- vx = 1, vy = -1; |
- nx = 0, ny = 1; |
- if (bRound) { |
- sx = bInverted ? 0 : FX_PI / 2; |
- } else { |
- sx = 0, sy = -1; |
- } |
- break; |
- } |
- if (i == 0) { |
- fillPath.MoveTo(cp1.x, cp1.y + fRadius1); |
- } |
- if (bRound) { |
- if (fRadius1 < 0) { |
- sx -= FX_PI; |
- } |
- if (bInverted) { |
- sy *= -1; |
- } |
- rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); |
- rtRadius.Normalize(); |
- if (bInverted) { |
- rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); |
- } |
- fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, |
- rtRadius.height, sx, sy); |
- } else { |
- if (bInverted) { |
- cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; |
- } else { |
- cp = cp1; |
- } |
- fillPath.LineTo(cp.x, cp.y); |
- fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy); |
- } |
- fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny); |
- } |
-} |
-static void XFA_BOX_Fill_Radial(CXFA_Box box, |
- CFX_Graphics* pGS, |
- CFX_Path& fillPath, |
- CFX_RectF rtFill, |
- CFX_Matrix* pMatrix) { |
- CXFA_Fill fill = box.GetFill(); |
- FX_ARGB crStart, crEnd; |
- crStart = fill.GetColor(); |
- int32_t iType = fill.GetRadial(crEnd); |
- CFX_Shading shading; |
- if (iType != XFA_ATTRIBUTEENUM_ToEdge) { |
- FX_ARGB temp = crEnd; |
- crEnd = crStart; |
- crStart = temp; |
- } |
- shading.CreateRadial(rtFill.Center(), rtFill.Center(), 0, |
- FXSYS_sqrt(rtFill.Width() * rtFill.Width() + |
- rtFill.Height() * rtFill.Height()) / |
- 2, |
- TRUE, TRUE, crStart, crEnd); |
- CFX_Color cr(&shading); |
- pGS->SetFillColor(&cr); |
- pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
-} |
-static void XFA_BOX_Fill_Pattern(CXFA_Box box, |
- CFX_Graphics* pGS, |
- CFX_Path& fillPath, |
- CFX_RectF rtFill, |
- CFX_Matrix* pMatrix) { |
- CXFA_Fill fill = box.GetFill(); |
- FX_ARGB crStart, crEnd; |
- crStart = fill.GetColor(); |
- int32_t iType = fill.GetPattern(crEnd); |
- int32_t iHatch = FX_HATCHSTYLE_Cross; |
- switch (iType) { |
- case XFA_ATTRIBUTEENUM_CrossDiagonal: |
- iHatch = FX_HATCHSTYLE_DiagonalCross; |
- break; |
- case XFA_ATTRIBUTEENUM_DiagonalLeft: |
- iHatch = FX_HATCHSTYLE_ForwardDiagonal; |
- break; |
- case XFA_ATTRIBUTEENUM_DiagonalRight: |
- iHatch = FX_HATCHSTYLE_BackwardDiagonal; |
- break; |
- case XFA_ATTRIBUTEENUM_Horizontal: |
- iHatch = FX_HATCHSTYLE_Horizontal; |
- break; |
- case XFA_ATTRIBUTEENUM_Vertical: |
- iHatch = FX_HATCHSTYLE_Vertical; |
- break; |
- default: |
- break; |
- } |
- CFX_Pattern pattern; |
- pattern.Create(iHatch, crEnd, crStart); |
- CFX_Color cr(&pattern); |
- pGS->SetFillColor(&cr); |
- pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
-} |
-static void XFA_BOX_Fill_Linear(CXFA_Box box, |
- CFX_Graphics* pGS, |
- CFX_Path& fillPath, |
- CFX_RectF rtFill, |
- CFX_Matrix* pMatrix) { |
- CXFA_Fill fill = box.GetFill(); |
- FX_ARGB crStart, crEnd; |
- crStart = fill.GetColor(); |
- int32_t iType = fill.GetLinear(crEnd); |
- CFX_PointF ptStart, ptEnd; |
- switch (iType) { |
- case XFA_ATTRIBUTEENUM_ToRight: |
- ptStart.Set(rtFill.left, rtFill.top); |
- ptEnd.Set(rtFill.right(), rtFill.top); |
- break; |
- case XFA_ATTRIBUTEENUM_ToBottom: |
- ptStart.Set(rtFill.left, rtFill.top); |
- ptEnd.Set(rtFill.left, rtFill.bottom()); |
- break; |
- case XFA_ATTRIBUTEENUM_ToLeft: |
- ptStart.Set(rtFill.right(), rtFill.top); |
- ptEnd.Set(rtFill.left, rtFill.top); |
- break; |
- case XFA_ATTRIBUTEENUM_ToTop: |
- ptStart.Set(rtFill.left, rtFill.bottom()); |
- ptEnd.Set(rtFill.left, rtFill.top); |
- break; |
- default: |
- break; |
- } |
- CFX_Shading shading; |
- shading.CreateAxial(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd); |
- CFX_Color cr(&shading); |
- pGS->SetFillColor(&cr); |
- pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
-} |
-static void XFA_BOX_Fill(CXFA_Box box, |
- const CXFA_StrokeArray& strokes, |
- CFX_Graphics* pGS, |
- const CFX_RectF& rtWidget, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwFlags) { |
- CXFA_Fill fill = box.GetFill(); |
- if (!fill.IsExistInXML() || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { |
- return; |
- } |
- pGS->SaveGraphState(); |
- CFX_Path fillPath; |
- fillPath.Create(); |
- XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath, |
- (dwFlags & XFA_DRAWBOX_ForceRound) != 0); |
- fillPath.Close(); |
- int32_t eType = fill.GetFillType(); |
- switch (eType) { |
- case XFA_ELEMENT_Radial: |
- XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix); |
- break; |
- case XFA_ELEMENT_Pattern: |
- XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix); |
- break; |
- case XFA_ELEMENT_Linear: |
- XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix); |
- break; |
- default: { |
- FX_ARGB cr; |
- if (eType == XFA_ELEMENT_Stipple) { |
- int32_t iRate = fill.GetStipple(cr); |
- if (iRate == 0) { |
- iRate = 100; |
- } |
- int32_t a = 0; |
- FX_COLORREF rgb; |
- ArgbDecode(cr, a, rgb); |
- cr = ArgbEncode(iRate * a / 100, rgb); |
- } else { |
- cr = fill.GetColor(); |
- } |
- CFX_Color fillColor(cr); |
- pGS->SetFillColor(&fillColor); |
- pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
- } break; |
- } |
- pGS->RestoreGraphState(); |
-} |
-static void XFA_BOX_StrokePath(CXFA_Stroke stroke, |
- CFX_Path* pPath, |
- CFX_Graphics* pGS, |
- CFX_Matrix* pMatrix) { |
- if (!stroke.IsExistInXML() || !stroke.IsVisible()) { |
- return; |
- } |
- FX_FLOAT fThickness = stroke.GetThickness(); |
- if (fThickness < 0.001f) { |
- return; |
- } |
- pGS->SaveGraphState(); |
- if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) { |
- fThickness = 2 * stroke.GetRadius(); |
- } |
- pGS->SetLineWidth(fThickness, TRUE); |
- pGS->SetLineCap(CFX_GraphStateData::LineCapButt); |
- XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(), |
- XFA_ATTRIBUTEENUM_Butt); |
- CFX_Color fxColor(stroke.GetColor()); |
- pGS->SetStrokeColor(&fxColor); |
- pGS->StrokePath(pPath, pMatrix); |
- pGS->RestoreGraphState(); |
-} |
-static void XFA_BOX_StrokeArc(CXFA_Box box, |
- CFX_Graphics* pGS, |
- CFX_RectF rtWidget, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwFlags) { |
- CXFA_Edge edge = box.GetEdge(0); |
- if (!edge.IsExistInXML() || !edge.IsVisible()) { |
- return; |
- } |
- FX_BOOL bVisible = FALSE; |
- FX_FLOAT fThickness = 0; |
- int32_t i3DType = box.Get3DStyle(bVisible, fThickness); |
- if (i3DType) { |
- if (bVisible && fThickness >= 0.001f) { |
- dwFlags |= XFA_DRAWBOX_Lowered3D; |
- } |
- } |
- FX_FLOAT fHalf = edge.GetThickness() / 2; |
- if (fHalf < 0) { |
- fHalf = 0; |
- } |
- int32_t iHand = box.GetHand(); |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.Inflate(fHalf, fHalf); |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.Deflate(fHalf, fHalf); |
- } |
- if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 || |
- (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) { |
- if (fHalf < 0.001f) { |
- return; |
- } |
- CFX_Path arcPath; |
- arcPath.Create(); |
- XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags); |
- XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix); |
- return; |
- } |
- pGS->SaveGraphState(); |
- pGS->SetLineWidth(fHalf); |
- FX_FLOAT a, b; |
- a = rtWidget.width / 2.0f; |
- b = rtWidget.height / 2.0f; |
- if (dwFlags & XFA_DRAWBOX_ForceRound) { |
- a = b = std::min(a, b); |
- } |
- CFX_PointF center = rtWidget.Center(); |
- rtWidget.left = center.x - a; |
- rtWidget.top = center.y - b; |
- rtWidget.width = a + a; |
- rtWidget.height = b + b; |
- FX_FLOAT startAngle = 0, sweepAngle = 360; |
- startAngle = startAngle * FX_PI / 180.0f; |
- sweepAngle = -sweepAngle * FX_PI / 180.0f; |
- CFX_Path arcPath; |
- arcPath.Create(); |
- arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
- 3.0f * FX_PI / 4.0f, FX_PI); |
- CFX_Color cr(0xFF808080); |
- pGS->SetStrokeColor(&cr); |
- pGS->StrokePath(&arcPath, pMatrix); |
- arcPath.Clear(); |
- arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
- -1.0f * FX_PI / 4.0f, FX_PI); |
- cr.Set(0xFFFFFFFF); |
- pGS->SetStrokeColor(&cr); |
- pGS->StrokePath(&arcPath, pMatrix); |
- rtWidget.Deflate(fHalf, fHalf); |
- arcPath.Clear(); |
- arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
- 3.0f * FX_PI / 4.0f, FX_PI); |
- cr.Set(0xFF404040); |
- pGS->SetStrokeColor(&cr); |
- pGS->StrokePath(&arcPath, pMatrix); |
- arcPath.Clear(); |
- arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
- -1.0f * FX_PI / 4.0f, FX_PI); |
- cr.Set(0xFFC0C0C0); |
- pGS->SetStrokeColor(&cr); |
- pGS->StrokePath(&arcPath, pMatrix); |
- pGS->RestoreGraphState(); |
-} |
-static void XFA_Draw3DRect(CFX_Graphics* pGraphic, |
- const CFX_RectF& rt, |
- FX_FLOAT fLineWidth, |
- CFX_Matrix* pMatrix, |
- FX_ARGB argbTopLeft, |
- FX_ARGB argbBottomRight) { |
- CFX_Color crLT(argbTopLeft); |
- pGraphic->SetFillColor(&crLT); |
- FX_FLOAT fBottom = rt.bottom(); |
- FX_FLOAT fRight = rt.right(); |
- CFX_Path pathLT; |
- pathLT.Create(); |
- pathLT.MoveTo(rt.left, fBottom); |
- pathLT.LineTo(rt.left, rt.top); |
- pathLT.LineTo(fRight, rt.top); |
- pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth); |
- pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth); |
- pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); |
- pathLT.LineTo(rt.left, fBottom); |
- pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix); |
- CFX_Color crRB(argbBottomRight); |
- pGraphic->SetFillColor(&crRB); |
- CFX_Path pathRB; |
- pathRB.Create(); |
- pathRB.MoveTo(fRight, rt.top); |
- pathRB.LineTo(fRight, fBottom); |
- pathRB.LineTo(rt.left, fBottom); |
- pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); |
- pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth); |
- pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth); |
- pathRB.LineTo(fRight, rt.top); |
- pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix); |
-} |
-static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS, |
- CFX_RectF rt, |
- FX_FLOAT fThickness, |
- CFX_Matrix* pMatrix) { |
- FX_FLOAT fHalfWidth = fThickness / 2.0f; |
- CFX_RectF rtInner(rt); |
- rtInner.Deflate(fHalfWidth, fHalfWidth); |
- CFX_Color cr(0xFF000000); |
- pGS->SetFillColor(&cr); |
- CFX_Path path; |
- path.Create(); |
- path.AddRectangle(rt.left, rt.top, rt.width, rt.height); |
- path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); |
- pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); |
- XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0); |
-} |
-static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS, |
- CFX_RectF rt, |
- FX_FLOAT fThickness, |
- CFX_Matrix* pMatrix) { |
- FX_FLOAT fHalfWidth = fThickness / 2.0f; |
- CFX_RectF rtInner(rt); |
- rtInner.Deflate(fHalfWidth, fHalfWidth); |
- CFX_Color cr(0xFF000000); |
- pGS->SetFillColor(&cr); |
- CFX_Path path; |
- path.Create(); |
- path.AddRectangle(rt.left, rt.top, rt.width, rt.height); |
- path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); |
- pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); |
- XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); |
-} |
-static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS, |
- CFX_RectF rt, |
- FX_FLOAT fThickness, |
- CFX_Matrix* pMatrix) { |
- FX_FLOAT fHalfWidth = fThickness / 2.0f; |
- XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF); |
- CFX_RectF rtInner(rt); |
- rtInner.Deflate(fHalfWidth, fHalfWidth); |
- XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); |
-} |
-static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS, |
- CFX_RectF rt, |
- FX_FLOAT fThickness, |
- CFX_Matrix* pMatrix) { |
- FX_FLOAT fHalfWidth = fThickness / 2.0f; |
- XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000); |
- CFX_RectF rtInner(rt); |
- rtInner.Deflate(fHalfWidth, fHalfWidth); |
- XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080); |
-} |
-static void XFA_BOX_Stroke_Rect(CXFA_Box box, |
- const CXFA_StrokeArray& strokes, |
- CFX_Graphics* pGS, |
- CFX_RectF rtWidget, |
- CFX_Matrix* pMatrix) { |
- FX_BOOL bVisible = FALSE; |
- FX_FLOAT fThickness = 0; |
- int32_t i3DType = box.Get3DStyle(bVisible, fThickness); |
- if (i3DType) { |
- if (!bVisible || fThickness < 0.001f) { |
- return; |
- } |
- switch (i3DType) { |
- case XFA_ATTRIBUTEENUM_Lowered: |
- XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix); |
- break; |
- case XFA_ATTRIBUTEENUM_Raised: |
- XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix); |
- break; |
- case XFA_ATTRIBUTEENUM_Etched: |
- XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix); |
- break; |
- case XFA_ATTRIBUTEENUM_Embossed: |
- XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix); |
- break; |
- } |
- return; |
- } |
- FX_BOOL bClose = FALSE; |
- FX_BOOL bSameStyles = TRUE; |
- int32_t i; |
- CXFA_Stroke stroke1 = strokes[0]; |
- for (i = 1; i < 8; i++) { |
- CXFA_Stroke stroke2 = strokes[i]; |
- if (!stroke1.SameStyles(stroke2)) { |
- bSameStyles = FALSE; |
- break; |
- } |
- stroke1 = stroke2; |
- } |
- if (bSameStyles) { |
- stroke1 = strokes[0]; |
- bClose = TRUE; |
- for (i = 2; i < 8; i += 2) { |
- CXFA_Stroke stroke2 = strokes[i]; |
- if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | |
- XFA_STROKE_SAMESTYLE_Corner)) { |
- bSameStyles = FALSE; |
- break; |
- } |
- stroke1 = stroke2; |
- } |
- if (bSameStyles) { |
- stroke1 = strokes[0]; |
- if (stroke1.IsInverted()) { |
- bSameStyles = FALSE; |
- } |
- if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { |
- bSameStyles = FALSE; |
- } |
- } |
- } |
- FX_BOOL bStart = TRUE; |
- CFX_Path path; |
- path.Create(); |
- for (i = 0; i < 8; i++) { |
- CXFA_Stroke stroke1 = strokes[i]; |
- if ((i % 1) == 0 && stroke1.GetRadius() < 0) { |
- FX_BOOL bEmpty = path.IsEmpty(); |
- if (!bEmpty) { |
- XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); |
- path.Clear(); |
- } |
- bStart = TRUE; |
- continue; |
- } |
- XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles); |
- CXFA_Stroke stroke2 = strokes[(i + 1) % 8]; |
- bStart = !stroke1.SameStyles(stroke2); |
- if (bStart) { |
- XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); |
- path.Clear(); |
- } |
- } |
- FX_BOOL bEmpty = path.IsEmpty(); |
- if (!bEmpty) { |
- if (bClose) { |
- path.Close(); |
- } |
- XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix); |
- } |
-} |
-static void XFA_BOX_Stroke(CXFA_Box box, |
- const CXFA_StrokeArray& strokes, |
- CFX_Graphics* pGS, |
- CFX_RectF rtWidget, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwFlags) { |
- if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
- XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags); |
- return; |
- } |
- FX_BOOL bVisible = FALSE; |
- for (int32_t j = 0; j < 4; j++) { |
- bVisible |= strokes[j * 2 + 1].IsVisible(); |
- if (bVisible) { |
- break; |
- } |
- } |
- if (!bVisible) { |
- return; |
- } |
- for (int32_t i = 1; i < 8; i += 2) { |
- CXFA_Edge edge = (CXFA_Node*)strokes[i]; |
- FX_FLOAT fThickness = edge.GetThickness(); |
- if (fThickness < 0) { |
- fThickness = 0; |
- } |
- FX_FLOAT fHalf = fThickness / 2; |
- int32_t iHand = box.GetHand(); |
- switch (i) { |
- case 1: |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.top -= fHalf; |
- rtWidget.height += fHalf; |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.top += fHalf; |
- rtWidget.height -= fHalf; |
- } |
- break; |
- case 3: |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.width += fHalf; |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.width -= fHalf; |
- } |
- break; |
- case 5: |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.height += fHalf; |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.height -= fHalf; |
- } |
- break; |
- case 7: |
- if (iHand == XFA_ATTRIBUTEENUM_Left) { |
- rtWidget.left -= fHalf; |
- rtWidget.width += fHalf; |
- } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
- rtWidget.left += fHalf; |
- rtWidget.width -= fHalf; |
- } |
- break; |
- } |
- } |
- XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix); |
-} |
-void XFA_DrawBox(CXFA_Box box, |
- CFX_Graphics* pGS, |
- const CFX_RectF& rtWidget, |
- CFX_Matrix* pMatrix, |
- FX_DWORD dwFlags) { |
- if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { |
- return; |
- } |
- int32_t iType = box.GetClassID(); |
- if (iType != XFA_ELEMENT_Arc && iType != XFA_ELEMENT_Border && |
- iType != XFA_ELEMENT_Rectangle) { |
- return; |
- } |
- CXFA_StrokeArray strokes; |
- if (!(dwFlags & XFA_DRAWBOX_ForceRound) && iType != XFA_ELEMENT_Arc) { |
- box.GetStrokes(strokes); |
- } |
- XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags); |
- XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags); |
-} |
+// Copyright 2014 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 <algorithm> |
+ |
+#include "xfa/src/foxitlib.h" |
+#include "xfa/src/fxfa/src/common/xfa_common.h" |
+#include "xfa_ffapp.h" |
+#include "xfa_ffdoc.h" |
+#include "xfa_ffdocview.h" |
+#include "xfa_ffwidget.h" |
+#include "xfa_ffpageview.h" |
+#include "xfa_textlayout.h" |
+CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView, |
+ CXFA_WidgetAcc* pDataAcc) |
+ : CXFA_ContentLayoutItem(pDataAcc->GetNode()), |
+ m_pPageView(pPageView), |
+ m_pDataAcc(pDataAcc) { |
+ m_rtWidget.Set(0, 0, 0, 0); |
+} |
+CXFA_FFWidget::~CXFA_FFWidget() {} |
+IXFA_PageView* CXFA_FFWidget::GetPageView() { |
+ return m_pPageView; |
+} |
+void CXFA_FFWidget::SetPageView(IXFA_PageView* pPageView) { |
+ m_pPageView = static_cast<CXFA_FFPageView*>(pPageView); |
+} |
+void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) { |
+ if ((m_dwStatus & XFA_WIDGETSTATUS_RectCached) == 0) { |
+ m_dwStatus |= XFA_WIDGETSTATUS_RectCached; |
+ GetRect(m_rtWidget); |
+ } |
+ rtWidget = m_rtWidget; |
+} |
+CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() { |
+ m_dwStatus |= XFA_WIDGETSTATUS_RectCached; |
+ GetRect(m_rtWidget); |
+ return m_rtWidget; |
+} |
+void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) { |
+ GetWidgetRect(rtWidget); |
+ FX_FLOAT fValue = 0; |
+ switch (m_pDataAcc->GetRotate()) { |
+ case 90: |
+ rtWidget.top = rtWidget.bottom(); |
+ fValue = rtWidget.width; |
+ rtWidget.width = rtWidget.height; |
+ rtWidget.height = fValue; |
+ break; |
+ case 180: |
+ rtWidget.left = rtWidget.right(); |
+ rtWidget.top = rtWidget.bottom(); |
+ break; |
+ case 270: |
+ rtWidget.left = rtWidget.right(); |
+ fValue = rtWidget.width; |
+ rtWidget.width = rtWidget.height; |
+ rtWidget.height = fValue; |
+ break; |
+ } |
+} |
+FX_DWORD CXFA_FFWidget::GetStatus() { |
+ return m_dwStatus; |
+} |
+void CXFA_FFWidget::ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved) { |
+ m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; |
+} |
+FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox, |
+ FX_DWORD dwStatus, |
+ FX_BOOL bDrawFocus) { |
+ if (bDrawFocus) { |
+ return FALSE; |
+ } |
+#ifndef _XFA_EMB |
+ if (m_pPageView) { |
+ m_pPageView->GetPageViewRect(rtBox); |
+ } |
+ return TRUE; |
+#endif |
+ GetWidgetRect(rtBox); |
+ return TRUE; |
+} |
+CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() { |
+ return m_pDataAcc; |
+} |
+FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) { |
+ if (CXFA_Assist assist = m_pDataAcc->GetAssist()) { |
+ if (CXFA_ToolTip toolTip = assist.GetToolTip()) { |
+ return toolTip.GetTip(wsToolTip); |
+ } |
+ } |
+ return GetCaptionText(wsToolTip); |
+} |
+void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwStatus, |
+ int32_t iRotate) { |
+ if (!IsMatchVisibleStatus(dwStatus)) { |
+ return; |
+ } |
+ CXFA_Border border = m_pDataAcc->GetBorder(); |
+ if (border) { |
+ CFX_RectF rtBorder; |
+ GetRectWithoutRotate(rtBorder); |
+ CXFA_Margin margin = border.GetMargin(); |
+ if (margin.IsExistInXML()) { |
+ XFA_RectWidthoutMargin(rtBorder, margin); |
+ } |
+ rtBorder.Normalize(); |
+ DrawBorder(pGS, border, rtBorder, pMatrix); |
+ } |
+} |
+FX_BOOL CXFA_FFWidget::IsLoaded() { |
+ return m_pPageView != NULL; |
+} |
+FX_BOOL CXFA_FFWidget::LoadWidget() { |
+ PerformLayout(); |
+ return TRUE; |
+} |
+void CXFA_FFWidget::UnloadWidget() {} |
+FX_BOOL CXFA_FFWidget::PerformLayout() { |
+ ReCacheWidgetRect(); |
+ return TRUE; |
+} |
+FX_BOOL CXFA_FFWidget::UpdateFWLData() { |
+ return FALSE; |
+} |
+void CXFA_FFWidget::UpdateWidgetProperty() {} |
+void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS, |
+ CXFA_Box box, |
+ const CFX_RectF& rtBorder, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwFlags) { |
+ XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags); |
+} |
+void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) { |
+ if (!pRect) { |
+ CFX_RectF rtWidget; |
+ GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); |
+ rtWidget.Inflate(2, 2); |
+ GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget, |
+ XFA_INVALIDATE_CurrentPage); |
+ } else { |
+ GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect, |
+ XFA_INVALIDATE_CurrentPage); |
+ } |
+} |
+void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) { |
+ CFX_RectF rtWidget; |
+ if (pRect) { |
+ rtWidget = *pRect; |
+ } else { |
+ GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); |
+ rtWidget.Inflate(2, 2); |
+ } |
+ m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); |
+} |
+FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) { |
+ CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout(); |
+ if (!pCapTextlayout) { |
+ return FALSE; |
+ } |
+ pCapTextlayout->GetText(wsCap); |
+ return TRUE; |
+} |
+FX_BOOL CXFA_FFWidget::IsFocused() { |
+ return m_dwStatus & XFA_WIDGETSTATUS_Focused; |
+} |
+FX_BOOL CXFA_FFWidget::OnMouseEnter() { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnMouseExit() { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnLButtonDown(FX_DWORD dwFlags, |
+ FX_FLOAT fx, |
+ FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnLButtonDblClk(FX_DWORD dwFlags, |
+ FX_FLOAT fx, |
+ FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnMouseWheel(FX_DWORD dwFlags, |
+ int16_t zDelta, |
+ FX_FLOAT fx, |
+ FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnRButtonDown(FX_DWORD dwFlags, |
+ FX_FLOAT fx, |
+ FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnRButtonDblClk(FX_DWORD dwFlags, |
+ FX_FLOAT fx, |
+ FX_FLOAT fy) { |
+ return FALSE; |
+} |
+ |
+FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { |
+ CXFA_FFWidget* pParent = GetParent(); |
+ if (pParent != NULL && !pParent->IsAncestorOf(pOldWidget)) { |
+ pParent->OnSetFocus(pOldWidget); |
+ } |
+ m_dwStatus |= XFA_WIDGETSTATUS_Focused; |
+ CXFA_EventParam eParam; |
+ eParam.m_eType = XFA_EVENT_Enter; |
+ eParam.m_pTarget = m_pDataAcc; |
+ m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam); |
+ return TRUE; |
+} |
+FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { |
+ m_dwStatus &= ~XFA_WIDGETSTATUS_Focused; |
+ EventKillFocus(); |
+ if (pNewWidget != NULL) { |
+ CXFA_FFWidget* pParent = GetParent(); |
+ if (pParent != NULL && !pParent->IsAncestorOf(pNewWidget)) { |
+ pParent->OnKillFocus(pNewWidget); |
+ } |
+ } |
+ return TRUE; |
+} |
+FX_BOOL CXFA_FFWidget::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) { |
+ return FALSE; |
+} |
+FX_DWORD CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) { |
+ return FALSE; |
+} |
+void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) { |
+ CFX_Matrix mt; |
+ GetRotateMatrix(mt); |
+ if (mt.IsIdentity()) { |
+ return; |
+ } |
+ CFX_Matrix mtReverse; |
+ mtReverse.SetReverse(mt); |
+ mtReverse.TransformPoint(fx, fy); |
+} |
+static void XFA_GetMatrix(CFX_Matrix& m, |
+ int32_t iRotate, |
+ int32_t at, |
+ const CFX_RectF& rt) { |
+ if (!iRotate) { |
+ return; |
+ } |
+ FX_FLOAT fAnchorX, fAnchorY; |
+ 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; |
+ } |
+ 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; |
+ } |
+} |
+void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) { |
+ mt.Set(1, 0, 0, 1, 0, 0); |
+ int32_t iRotate = m_pDataAcc->GetRotate(); |
+ if (!iRotate) { |
+ return; |
+ } |
+ CFX_RectF rcWidget; |
+ GetRectWithoutRotate(rcWidget); |
+ XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft; |
+ XFA_GetMatrix(mt, iRotate, at, rcWidget); |
+} |
+FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() { |
+ CFX_RectF rtLayout; |
+ GetRectWithoutRotate(rtLayout); |
+ return rtLayout.width < 0.1f && rtLayout.height < 0.1f; |
+} |
+CXFA_FFWidget* CXFA_FFWidget::GetParent() { |
+ CXFA_Node* pParentNode = |
+ m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent); |
+ if (pParentNode != NULL) { |
+ CXFA_WidgetAcc* pParentWidgetAcc = |
+ (CXFA_WidgetAcc*)pParentNode->GetWidgetData(); |
+ if (pParentWidgetAcc != NULL) { |
+ return pParentWidgetAcc->GetNextWidget(NULL); |
+ } |
+ } |
+ return NULL; |
+} |
+FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { |
+ if (!pWidget) { |
+ return FALSE; |
+ } |
+ CXFA_Node* pNode = m_pDataAcc->GetNode(); |
+ CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode(); |
+ while (pChildNode) { |
+ if (pChildNode == pNode) { |
+ return TRUE; |
+ } |
+ pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent); |
+ } |
+ return FALSE; |
+} |
+FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) { |
+ CFX_RectF rtWidget; |
+ GetWidgetRect(rtWidget); |
+ if (rtWidget.Contains(fx, fy)) { |
+ return TRUE; |
+ } |
+ return FALSE; |
+} |
+CXFA_FFDocView* CXFA_FFWidget::GetDocView() { |
+ return m_pDocView; |
+} |
+CXFA_FFDoc* CXFA_FFWidget::GetDoc() { |
+ return (CXFA_FFDoc*)m_pDocView->GetDoc(); |
+} |
+CXFA_FFApp* CXFA_FFWidget::GetApp() { |
+ return GetDoc()->GetApp(); |
+} |
+IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { |
+ return GetApp()->GetAppProvider(); |
+} |
+void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) { |
+ fMinWidth = fMaxWidth = 0; |
+ FX_FLOAT fWidth = 0; |
+ if (m_pDataAcc->GetWidth(fWidth)) { |
+ fMinWidth = fMaxWidth = fWidth; |
+ } else { |
+ m_pDataAcc->GetMinWidth(fMinWidth); |
+ m_pDataAcc->GetMaxWidth(fMaxWidth); |
+ } |
+} |
+void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) { |
+ fMinHeight = fMaxHeight = 0; |
+ FX_FLOAT fHeight = 0; |
+ if (m_pDataAcc->GetHeight(fHeight)) { |
+ fMinHeight = fMaxHeight = fHeight; |
+ } else { |
+ m_pDataAcc->GetMinHeight(fMinHeight); |
+ m_pDataAcc->GetMaxHeight(fMaxHeight); |
+ } |
+} |
+FX_BOOL CXFA_FFWidget::IsMatchVisibleStatus(FX_DWORD dwStatus) { |
+ return m_dwStatus & XFA_WIDGETSTATUS_Visible; |
+} |
+void CXFA_FFWidget::EventKillFocus() { |
+ if (m_dwStatus & XFA_WIDGETSTATUS_Access) { |
+ m_dwStatus &= ~XFA_WIDGETSTATUS_Access; |
+ return; |
+ } |
+ CXFA_EventParam eParam; |
+ eParam.m_eType = XFA_EVENT_Exit; |
+ eParam.m_pTarget = m_pDataAcc; |
+ m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam); |
+} |
+FX_BOOL CXFA_FFWidget::IsButtonDown() { |
+ return (m_dwStatus & XFA_WIDGETSTATUS_ButtonDown) != 0; |
+} |
+void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) { |
+ bSet ? m_dwStatus |= XFA_WIDGETSTATUS_ButtonDown |
+ : m_dwStatus &= ~XFA_WIDGETSTATUS_ButtonDown; |
+} |
+int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, |
+ int32_t iStrokeType, |
+ int32_t iCapType) { |
+ switch (iStrokeType) { |
+ case XFA_ATTRIBUTEENUM_DashDot: { |
+ FX_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: { |
+ FX_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: { |
+ FX_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: { |
+ FX_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; |
+} |
+CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) { |
+ switch (iLineCap) { |
+ case XFA_ATTRIBUTEENUM_Round: |
+ return CFX_GraphStateData::LineCapRound; |
+ case XFA_ATTRIBUTEENUM_Butt: |
+ return CFX_GraphStateData::LineCapButt; |
+ default: |
+ break; |
+ } |
+ return CFX_GraphStateData::LineCapSquare; |
+} |
+class CXFA_ImageRenderer { |
+ public: |
+ CXFA_ImageRenderer(); |
+ ~CXFA_ImageRenderer(); |
+ FX_BOOL Start(CFX_RenderDevice* pDevice, |
+ CFX_DIBSource* pDIBSource, |
+ FX_ARGB bitmap_argb, |
+ int bitmap_alpha, |
+ const CFX_Matrix* pImage2Device, |
+ FX_DWORD flags, |
+ int blendType = FXDIB_BLEND_NORMAL); |
+ FX_BOOL Continue(IFX_Pause* pPause); |
+ |
+ protected: |
+ CFX_RenderDevice* m_pDevice; |
+ int m_Status; |
+ CFX_Matrix m_ImageMatrix; |
+ CFX_DIBSource* m_pDIBSource; |
+ CFX_DIBitmap* m_pCloneConvert; |
+ int m_BitmapAlpha; |
+ FX_ARGB m_FillArgb; |
+ FX_DWORD m_Flags; |
+ CFX_ImageTransformer* m_pTransformer; |
+ void* m_DeviceHandle; |
+ int32_t m_BlendType; |
+ FX_BOOL m_Result; |
+ FX_BOOL m_bPrint; |
+ FX_BOOL StartDIBSource(); |
+ void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, |
+ int left, |
+ int top, |
+ FX_ARGB mask_argb, |
+ int bitmap_alpha, |
+ int blend_mode, |
+ int Transparency); |
+}; |
+CXFA_ImageRenderer::CXFA_ImageRenderer() { |
+ m_pDevice = NULL; |
+ m_Status = 0; |
+ m_pDIBSource = NULL; |
+ m_pCloneConvert = NULL; |
+ m_BitmapAlpha = 255; |
+ m_FillArgb = 0; |
+ m_Flags = 0; |
+ m_pTransformer = NULL; |
+ m_DeviceHandle = NULL; |
+ m_BlendType = FXDIB_BLEND_NORMAL; |
+ m_Result = TRUE; |
+ m_bPrint = FALSE; |
+} |
+CXFA_ImageRenderer::~CXFA_ImageRenderer() { |
+ if (m_pCloneConvert) { |
+ delete m_pCloneConvert; |
+ } |
+ if (m_pTransformer) { |
+ delete m_pTransformer; |
+ } |
+ if (m_DeviceHandle) { |
+ m_pDevice->CancelDIBits(m_DeviceHandle); |
+ } |
+} |
+FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, |
+ CFX_DIBSource* pDIBSource, |
+ FX_ARGB bitmap_argb, |
+ int bitmap_alpha, |
+ const CFX_Matrix* pImage2Device, |
+ FX_DWORD 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(); |
+} |
+FX_BOOL CXFA_ImageRenderer::StartDIBSource() { |
+ if (m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb, |
+ &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, |
+ m_BlendType)) { |
+ if (m_DeviceHandle != NULL) { |
+ m_Status = 3; |
+ return TRUE; |
+ } |
+ return FALSE; |
+ } |
+ CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); |
+ FX_RECT image_rect = image_rect_f.GetOutterRect(); |
+ int dest_width = image_rect.Width(); |
+ 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_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { |
+ m_Result = FALSE; |
+ return FALSE; |
+ } |
+ 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 = new CFX_ImageTransformer; |
+ m_pTransformer->Start(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->StretchDIBits(m_pDIBSource, dest_left, dest_top, dest_width, |
+ dest_height, m_Flags, NULL, m_BlendType)) { |
+ return FALSE; |
+ } |
+ } |
+ if (m_pDIBSource->IsAlphaMask()) { |
+ if (m_BitmapAlpha != 255) { |
+ m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); |
+ } |
+ if (m_pDevice->StretchBitMask(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); |
+ 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); |
+ delete pStretched; |
+ pStretched = NULL; |
+ } |
+ return FALSE; |
+} |
+FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) { |
+ if (m_Status == 2) { |
+ if (m_pTransformer->Continue(pPause)) { |
+ return TRUE; |
+ } |
+ CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach(); |
+ if (pBitmap == NULL) { |
+ 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->m_ResultLeft, |
+ m_pTransformer->m_ResultTop, m_FillArgb); |
+ } else { |
+ if (m_BitmapAlpha != 255) { |
+ pBitmap->MultiplyAlpha(m_BitmapAlpha); |
+ } |
+ m_Result = m_pDevice->SetDIBits(pBitmap, m_pTransformer->m_ResultLeft, |
+ m_pTransformer->m_ResultTop, m_BlendType); |
+ } |
+ delete pBitmap; |
+ return FALSE; |
+ } else if (m_Status == 3) { |
+ return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); |
+ } |
+ return FALSE; |
+} |
+void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, |
+ int left, |
+ int top, |
+ FX_ARGB mask_argb, |
+ int bitmap_alpha, |
+ int blend_mode, |
+ int Transparency) { |
+ if (pDIBitmap == NULL) { |
+ return; |
+ } |
+ FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; |
+ FX_BOOL bGroup = Transparency & 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 { |
+ FX_DWORD 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; |
+ } |
+ } |
+ } |
+ FX_BOOL bBackAlphaRequired = blend_mode && bIsolated; |
+ FX_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->SetDIBits(pDIBitmap, left, top, blend_mode); |
+ } else { |
+ FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), |
+ top + pDIBitmap->GetHeight()); |
+ rect.Intersect(m_pDevice->GetClipBox()); |
+ CFX_DIBitmap* pClone = NULL; |
+ FX_BOOL bClone = FALSE; |
+ if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { |
+ bClone = TRUE; |
+ pClone = m_pDevice->GetBackDrop()->Clone(&rect); |
+ 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->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); |
+ } |
+ if (bClone) { |
+ delete pClone; |
+ } |
+ } |
+ return; |
+ } |
+ if (pDIBitmap->HasAlpha() && |
+ !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { |
+ CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); |
+ if (!pCloneConvert) { |
+ return; |
+ } |
+ CXFA_ImageRenderer imageRender; |
+ FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, |
+ m_BitmapAlpha, &m_ImageMatrix, m_Flags); |
+ while (bRet) { |
+ bRet = imageRender.Continue(NULL); |
+ } |
+ delete pCloneConvert; |
+ return; |
+ } |
+} |
+void XFA_DrawImage(CFX_Graphics* pGS, |
+ const CFX_RectF& rtImage, |
+ CFX_Matrix* pMatrix, |
+ CFX_DIBitmap* pDIBitmap, |
+ int32_t iAspect, |
+ int32_t iImageXDpi, |
+ int32_t iImageYDpi, |
+ int32_t iHorzAlign, |
+ int32_t iVertAlign) { |
+ if (rtImage.IsEmpty()) { |
+ return; |
+ } |
+ if (!pDIBitmap || !pDIBitmap->GetBuffer()) { |
+ return; |
+ } |
+ FX_FLOAT fWidth = |
+ XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi); |
+ FX_FLOAT fHeight = |
+ XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi); |
+ CFX_RectF rtFit; |
+ rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight); |
+ switch (iAspect) { |
+ case XFA_ATTRIBUTEENUM_Fit: { |
+ FX_FLOAT f1 = rtImage.height / rtFit.height; |
+ FX_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_Actual: |
+ break; |
+ case XFA_ATTRIBUTEENUM_Height: { |
+ FX_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: { |
+ FX_FLOAT f1 = rtImage.width / rtFit.width; |
+ rtFit.width = rtImage.width; |
+ rtFit.height = rtFit.height * f1; |
+ } 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(); |
+ pRenderDevice->SaveState(); |
+ CFX_PathData path; |
+ path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); |
+ pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING); |
+ CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); |
+ mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top); |
+ mtImage.Concat(*pMatrix); |
+ CXFA_ImageRenderer imageRender; |
+ FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, |
+ FXDIB_INTERPOL); |
+ while (bRet) { |
+ bRet = imageRender.Continue(NULL); |
+ } |
+ pRenderDevice->RestoreState(); |
+} |
+const static 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 = FXSYS_strlen((FX_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 FX_CHAR* pStr, uint8_t* pOutBuffer) { |
+ if (pStr == NULL) { |
+ return 0; |
+ } |
+ uint8_t* pBuffer = |
+ XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr)); |
+ if (pBuffer == NULL) { |
+ return 0; |
+ } |
+ int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer); |
+ int32_t i = 0, j = 0; |
+ FX_DWORD 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 = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 6) | |
+ ((FX_DWORD)g_inv_base64[pBuffer[i + 1]]); |
+ pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; |
+ j++; |
+ } else { |
+ dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 12) | |
+ ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 6) | |
+ ((FX_DWORD)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 = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 18) | |
+ ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 12) | |
+ ((FX_DWORD)g_inv_base64[pBuffer[i + 2]] << 6) | |
+ ((FX_DWORD)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 FX_CHAR g_base64_chars[] = |
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
+FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { |
+ FX_CHAR* out = NULL; |
+ int i, j; |
+ FX_DWORD limb; |
+ out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5); |
+ for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { |
+ limb = ((FX_DWORD)buf[i] << 16) | ((FX_DWORD)buf[i + 1] << 8) | |
+ ((FX_DWORD)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 = ((FX_DWORD)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 = ((FX_DWORD)buf[i] << 8) | ((FX_DWORD)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 CFX_WideStringC& wsType) { |
+ CFX_WideString wsContentType(wsType); |
+ wsContentType.MakeLower(); |
+ if (wsContentType == FX_WSTRC(L"image/jpg")) { |
+ return FXCODEC_IMAGE_JPG; |
+ } |
+ if (wsContentType == FX_WSTRC(L"image/png")) { |
+ return FXCODEC_IMAGE_PNG; |
+ } |
+ if (wsContentType == FX_WSTRC(L"image/gif")) { |
+ return FXCODEC_IMAGE_GIF; |
+ } |
+ if (wsContentType == FX_WSTRC(L"image/bmp")) { |
+ return FXCODEC_IMAGE_BMP; |
+ } |
+ if (wsContentType == FX_WSTRC(L"image/tif")) { |
+ return FXCODEC_IMAGE_TIF; |
+ } |
+ return FXCODEC_IMAGE_UNKNOWN; |
+} |
+CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, |
+ CXFA_Image* pImage, |
+ FX_BOOL& bNameImage, |
+ int32_t& iImageXDpi, |
+ int32_t& iImageYDpi) { |
+ CFX_WideString wsHref; |
+ pImage->GetHref(wsHref); |
+ CFX_WideString wsImage; |
+ pImage->GetContent(wsImage); |
+ if (wsHref.IsEmpty() && wsImage.IsEmpty()) { |
+ return NULL; |
+ } |
+ CFX_WideString wsContentType; |
+ pImage->GetContentType(wsContentType); |
+ FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType); |
+ CFX_ByteString bsContent; |
+ uint8_t* pImageBuffer = NULL; |
+ IFX_FileRead* pImageFileRead = NULL; |
+ if (wsImage.GetLength() > 0) { |
+ XFA_ATTRIBUTEENUM iEncoding = |
+ (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding(); |
+ if (iEncoding == XFA_ATTRIBUTEENUM_Base64) { |
+ CFX_ByteString bsData = wsImage.UTF8Encode(); |
+ int32_t iLength = bsData.GetLength(); |
+ pImageBuffer = FX_Alloc(uint8_t, iLength); |
+ int32_t iRead = XFA_Base64Decode((const FX_CHAR*)bsData, pImageBuffer); |
+ if (iRead > 0) { |
+ pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead); |
+ } |
+ } else { |
+ bsContent = CFX_ByteString::FromUnicode(wsImage); |
+ pImageFileRead = FX_CreateMemoryStream( |
+ (uint8_t*)(const uint8_t*)bsContent, bsContent.GetLength()); |
+ } |
+ } else { |
+ CFX_WideString wsURL = wsHref; |
+ if (wsURL.Left(7) != FX_WSTRC(L"http://") && |
+ wsURL.Left(6) != FX_WSTRC(L"ftp://")) { |
+ CFX_DIBitmap* pBitmap = |
+ pDoc->GetPDFNamedImage(wsURL, iImageXDpi, iImageYDpi); |
+ if (pBitmap != NULL) { |
+ bNameImage = TRUE; |
+ return pBitmap; |
+ } |
+ } |
+ pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL); |
+ } |
+ if (!pImageFileRead) { |
+ FX_Free(pImageBuffer); |
+ return NULL; |
+ } |
+ bNameImage = FALSE; |
+ CFX_DIBitmap* pBitmap = |
+ XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); |
+ FX_Free(pImageBuffer); |
+ pImageFileRead->Release(); |
+ 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; |
+} |
+CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead, |
+ FXCODEC_IMAGE_TYPE type, |
+ int32_t& iImageXDpi, |
+ int32_t& iImageYDpi) { |
+ CFX_GEModule* pGeModule = CFX_GEModule::Get(); |
+ if (!pGeModule) { |
+ return NULL; |
+ } |
+ CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); |
+ if (!pCodecMgr) { |
+ return NULL; |
+ } |
+ CFX_DIBAttribute dibAttr; |
+ CFX_DIBitmap* pBitmap = NULL; |
+ ICodec_ProgressiveDecoder* pProgressiveDecoder = |
+ pCodecMgr->CreateProgressiveDecoder(); |
+ pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr); |
+ 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 / (FX_FLOAT)100 * 2.54f); |
+ dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_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) { |
+ type = pProgressiveDecoder->GetType(); |
+ int32_t iComponents = pProgressiveDecoder->GetNumComponents(); |
+ int32_t iBpc = pProgressiveDecoder->GetBPC(); |
+ FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); |
+ pBitmap = new CFX_DIBitmap(); |
+ pBitmap->Create(pProgressiveDecoder->GetWidth(), |
+ pProgressiveDecoder->GetHeight(), dibFormat); |
+ pBitmap->Clear(0xffffffff); |
+ int32_t nFrames; |
+ if ((pProgressiveDecoder->GetFrames(nFrames) == |
+ FXCODEC_STATUS_DECODE_READY) && |
+ (nFrames > 0)) { |
+ pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), |
+ pBitmap->GetHeight()); |
+ pProgressiveDecoder->ContinueDecode(); |
+ } |
+ } |
+ delete pProgressiveDecoder; |
+ return pBitmap; |
+} |
+void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) { |
+ if (!mg) { |
+ return; |
+ } |
+ FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; |
+ mg.GetLeftInset(fLeftInset); |
+ mg.GetTopInset(fTopInset); |
+ mg.GetRightInset(fRightInset); |
+ mg.GetBottomInset(fBottomInset); |
+ rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); |
+} |
+CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { |
+ XFA_ELEMENT iType = pLayoutItem->GetFormNode()->GetClassID(); |
+ if (XFA_IsCreateWidget(iType)) { |
+ return static_cast<CXFA_FFWidget*>(pLayoutItem); |
+ } |
+ return nullptr; |
+} |
+FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType) { |
+ return iType == XFA_ELEMENT_Field || iType == XFA_ELEMENT_Draw || |
+ iType == XFA_ELEMENT_Subform || iType == XFA_ELEMENT_ExclGroup; |
+} |
+static void XFA_BOX_GetPath_Arc(CXFA_Box box, |
+ CFX_RectF rtDraw, |
+ CFX_Path& fillPath, |
+ FX_DWORD dwFlags) { |
+ FX_FLOAT a, b; |
+ a = rtDraw.width / 2.0f; |
+ b = rtDraw.height / 2.0f; |
+ if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
+ a = b = std::min(a, b); |
+ } |
+ CFX_PointF center = rtDraw.Center(); |
+ rtDraw.left = center.x - a; |
+ rtDraw.top = center.y - b; |
+ rtDraw.width = a + a; |
+ rtDraw.height = b + b; |
+ FX_FLOAT startAngle = 0, sweepAngle = 360; |
+ FX_BOOL bStart = box.GetStartAngle(startAngle); |
+ FX_BOOL bEnd = box.GetSweepAngle(sweepAngle); |
+ if (!bStart && !bEnd) { |
+ fillPath.AddEllipse(rtDraw); |
+ return; |
+ } |
+ startAngle = -startAngle * FX_PI / 180.0f; |
+ sweepAngle = -sweepAngle * FX_PI / 180.0f; |
+ fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height, |
+ startAngle, sweepAngle); |
+} |
+static void XFA_BOX_GetPath(CXFA_Box box, |
+ const CXFA_StrokeArray& strokes, |
+ CFX_RectF rtWidget, |
+ CFX_Path& path, |
+ int32_t nIndex, |
+ FX_BOOL bStart, |
+ FX_BOOL bCorner) { |
+ FXSYS_assert(nIndex >= 0 && nIndex < 8); |
+ FX_BOOL bInverted, bRound; |
+ FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny, offsetY, offsetX, |
+ offsetEX, offsetEY; |
+ CFX_PointF cpStart, cp, cp1, cp2; |
+ CFX_RectF rtRadius; |
+ int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; |
+ CXFA_Corner corner1 = (CXFA_Node*)strokes[n]; |
+ CXFA_Corner corner2 = (CXFA_Node*)strokes[(n + 2) % 8]; |
+ fRadius1 = bCorner ? corner1.GetRadius() : 0; |
+ fRadius2 = bCorner ? corner2.GetRadius() : 0; |
+ bInverted = corner1.IsInverted(); |
+ offsetY = 0.0f; |
+ offsetX = 0.0f; |
+ bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; |
+ FX_FLOAT halfAfter = 0.0f; |
+ FX_FLOAT halfBefore = 0.0f; |
+ CXFA_Stroke stroke = strokes[nIndex]; |
+ if (stroke.IsCorner()) { |
+ CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; |
+ CXFA_Stroke edgeAfter = strokes[nIndex + 1]; |
+ if (stroke.IsInverted()) { |
+ if (!stroke.SameStyles(edgeBefore)) { |
+ halfBefore = edgeBefore.GetThickness() / 2; |
+ } |
+ if (!stroke.SameStyles(edgeAfter)) { |
+ halfAfter = edgeAfter.GetThickness() / 2; |
+ } |
+ } |
+ } else { |
+ CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8]; |
+ CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8]; |
+ if (!bRound && !bInverted) { |
+ { halfBefore = edgeBefore.GetThickness() / 2; } |
+ { halfAfter = edgeAfter.GetThickness() / 2; } |
+ } |
+ } |
+ offsetEX = 0.0f; |
+ offsetEY = 0.0f; |
+ if (bRound) { |
+ sy = FX_PI / 2; |
+ } |
+ switch (nIndex) { |
+ case 0: |
+ case 1: |
+ cp1 = rtWidget.TopLeft(); |
+ cp2 = rtWidget.TopRight(); |
+ if (nIndex == 0) { |
+ cpStart.x = cp1.x - halfBefore; |
+ cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; |
+ } else { |
+ cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, |
+ offsetEX = halfAfter; |
+ } |
+ vx = 1, vy = 1; |
+ nx = -1, ny = 0; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI / 2 : FX_PI; |
+ } else { |
+ sx = 1, sy = 0; |
+ } |
+ break; |
+ case 2: |
+ case 3: |
+ cp1 = rtWidget.TopRight(); |
+ cp2 = rtWidget.BottomRight(); |
+ if (nIndex == 2) { |
+ cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, |
+ offsetX = halfAfter; |
+ } else { |
+ cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, |
+ offsetEY = halfAfter; |
+ } |
+ vx = -1, vy = 1; |
+ nx = 0, ny = -1; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI : FX_PI * 3 / 2; |
+ } else { |
+ sx = 0, sy = 1; |
+ } |
+ break; |
+ case 4: |
+ case 5: |
+ cp1 = rtWidget.BottomRight(); |
+ cp2 = rtWidget.BottomLeft(); |
+ if (nIndex == 4) { |
+ cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, |
+ offsetY = halfAfter; |
+ } else { |
+ cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, |
+ offsetEX = -halfAfter; |
+ } |
+ vx = -1, vy = -1; |
+ nx = 1, ny = 0; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI * 3 / 2 : 0; |
+ } else { |
+ sx = -1, sy = 0; |
+ } |
+ break; |
+ case 6: |
+ case 7: |
+ cp1 = rtWidget.BottomLeft(); |
+ cp2 = rtWidget.TopLeft(); |
+ if (nIndex == 6) { |
+ cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, |
+ offsetX = -halfAfter; |
+ } else { |
+ cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, |
+ offsetEY = -halfAfter; |
+ } |
+ vx = 1, vy = -1; |
+ nx = 0, ny = 1; |
+ if (bRound) { |
+ sx = bInverted ? 0 : FX_PI / 2; |
+ } else { |
+ sx = 0, sy = -1; |
+ } |
+ break; |
+ } |
+ if (bStart) { |
+ path.MoveTo(cpStart.x, cpStart.y); |
+ } |
+ if (nIndex & 1) { |
+ path.LineTo(cp2.x + fRadius2 * nx + offsetEX, |
+ cp2.y + fRadius2 * ny + offsetEY); |
+ return; |
+ } |
+ if (bRound) { |
+ if (fRadius1 < 0) { |
+ sx -= FX_PI; |
+ } |
+ if (bInverted) { |
+ sy *= -1; |
+ } |
+ rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2, |
+ fRadius1 * 2 * vx - offsetX * 2, |
+ fRadius1 * 2 * vy - offsetY * 2); |
+ rtRadius.Normalize(); |
+ if (bInverted) { |
+ rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); |
+ } |
+ path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx, |
+ sy); |
+ } else { |
+ if (bInverted) { |
+ cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; |
+ } else { |
+ cp = cp1; |
+ } |
+ path.LineTo(cp.x, cp.y); |
+ path.LineTo(cp1.x + fRadius1 * sx + offsetX, |
+ cp1.y + fRadius1 * sy + offsetY); |
+ } |
+} |
+static void XFA_BOX_GetFillPath(CXFA_Box box, |
+ const CXFA_StrokeArray& strokes, |
+ CFX_RectF rtWidget, |
+ CFX_Path& fillPath, |
+ FX_WORD dwFlags) { |
+ if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
+ CXFA_Edge edge = box.GetEdge(0); |
+ FX_FLOAT fThickness = edge.GetThickness(); |
+ if (fThickness < 0) { |
+ fThickness = 0; |
+ } |
+ FX_FLOAT fHalf = fThickness / 2; |
+ int32_t iHand = box.GetHand(); |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.Inflate(fHalf, fHalf); |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.Deflate(fHalf, fHalf); |
+ } |
+ XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags); |
+ return; |
+ } |
+ FX_BOOL bSameStyles = TRUE; |
+ int32_t i; |
+ CXFA_Stroke stroke1 = strokes[0]; |
+ for (i = 1; i < 8; i++) { |
+ CXFA_Stroke stroke2 = strokes[i]; |
+ if (!stroke1.SameStyles(stroke2)) { |
+ bSameStyles = FALSE; |
+ break; |
+ } |
+ stroke1 = stroke2; |
+ } |
+ if (bSameStyles) { |
+ stroke1 = strokes[0]; |
+ for (i = 2; i < 8; i += 2) { |
+ CXFA_Stroke stroke2 = strokes[i]; |
+ if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | |
+ XFA_STROKE_SAMESTYLE_Corner)) { |
+ bSameStyles = FALSE; |
+ break; |
+ } |
+ stroke1 = stroke2; |
+ } |
+ if (bSameStyles) { |
+ stroke1 = strokes[0]; |
+ if (stroke1.IsInverted()) { |
+ bSameStyles = FALSE; |
+ } |
+ if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { |
+ bSameStyles = FALSE; |
+ } |
+ } |
+ } |
+ if (bSameStyles) { |
+ fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, |
+ rtWidget.height); |
+ return; |
+ } |
+ FX_BOOL bInverted, bRound; |
+ FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny; |
+ CFX_PointF cp, cp1, cp2; |
+ CFX_RectF rtRadius; |
+ for (int32_t i = 0; i < 8; i += 2) { |
+ CXFA_Corner corner1 = (CXFA_Node*)strokes[i]; |
+ CXFA_Corner corner2 = (CXFA_Node*)strokes[(i + 2) % 8]; |
+ fRadius1 = corner1.GetRadius(); |
+ fRadius2 = corner2.GetRadius(); |
+ bInverted = corner1.IsInverted(); |
+ bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; |
+ if (bRound) { |
+ sy = FX_PI / 2; |
+ } |
+ switch (i) { |
+ case 0: |
+ cp1 = rtWidget.TopLeft(); |
+ cp2 = rtWidget.TopRight(); |
+ vx = 1, vy = 1; |
+ nx = -1, ny = 0; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI / 2 : FX_PI; |
+ } else { |
+ sx = 1, sy = 0; |
+ } |
+ break; |
+ case 2: |
+ cp1 = rtWidget.TopRight(); |
+ cp2 = rtWidget.BottomRight(); |
+ vx = -1, vy = 1; |
+ nx = 0, ny = -1; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI : FX_PI * 3 / 2; |
+ } else { |
+ sx = 0, sy = 1; |
+ } |
+ break; |
+ case 4: |
+ cp1 = rtWidget.BottomRight(); |
+ cp2 = rtWidget.BottomLeft(); |
+ vx = -1, vy = -1; |
+ nx = 1, ny = 0; |
+ if (bRound) { |
+ sx = bInverted ? FX_PI * 3 / 2 : 0; |
+ } else { |
+ sx = -1, sy = 0; |
+ } |
+ break; |
+ case 6: |
+ cp1 = rtWidget.BottomLeft(); |
+ cp2 = rtWidget.TopLeft(); |
+ vx = 1, vy = -1; |
+ nx = 0, ny = 1; |
+ if (bRound) { |
+ sx = bInverted ? 0 : FX_PI / 2; |
+ } else { |
+ sx = 0, sy = -1; |
+ } |
+ break; |
+ } |
+ if (i == 0) { |
+ fillPath.MoveTo(cp1.x, cp1.y + fRadius1); |
+ } |
+ if (bRound) { |
+ if (fRadius1 < 0) { |
+ sx -= FX_PI; |
+ } |
+ if (bInverted) { |
+ sy *= -1; |
+ } |
+ rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); |
+ rtRadius.Normalize(); |
+ if (bInverted) { |
+ rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); |
+ } |
+ fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, |
+ rtRadius.height, sx, sy); |
+ } else { |
+ if (bInverted) { |
+ cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; |
+ } else { |
+ cp = cp1; |
+ } |
+ fillPath.LineTo(cp.x, cp.y); |
+ fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy); |
+ } |
+ fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny); |
+ } |
+} |
+static void XFA_BOX_Fill_Radial(CXFA_Box box, |
+ CFX_Graphics* pGS, |
+ CFX_Path& fillPath, |
+ CFX_RectF rtFill, |
+ CFX_Matrix* pMatrix) { |
+ CXFA_Fill fill = box.GetFill(); |
+ FX_ARGB crStart, crEnd; |
+ crStart = fill.GetColor(); |
+ int32_t iType = fill.GetRadial(crEnd); |
+ CFX_Shading shading; |
+ if (iType != XFA_ATTRIBUTEENUM_ToEdge) { |
+ FX_ARGB temp = crEnd; |
+ crEnd = crStart; |
+ crStart = temp; |
+ } |
+ shading.CreateRadial(rtFill.Center(), rtFill.Center(), 0, |
+ FXSYS_sqrt(rtFill.Width() * rtFill.Width() + |
+ rtFill.Height() * rtFill.Height()) / |
+ 2, |
+ TRUE, TRUE, crStart, crEnd); |
+ CFX_Color cr(&shading); |
+ pGS->SetFillColor(&cr); |
+ pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
+} |
+static void XFA_BOX_Fill_Pattern(CXFA_Box box, |
+ CFX_Graphics* pGS, |
+ CFX_Path& fillPath, |
+ CFX_RectF rtFill, |
+ CFX_Matrix* pMatrix) { |
+ CXFA_Fill fill = box.GetFill(); |
+ FX_ARGB crStart, crEnd; |
+ crStart = fill.GetColor(); |
+ int32_t iType = fill.GetPattern(crEnd); |
+ int32_t iHatch = FX_HATCHSTYLE_Cross; |
+ switch (iType) { |
+ case XFA_ATTRIBUTEENUM_CrossDiagonal: |
+ iHatch = FX_HATCHSTYLE_DiagonalCross; |
+ break; |
+ case XFA_ATTRIBUTEENUM_DiagonalLeft: |
+ iHatch = FX_HATCHSTYLE_ForwardDiagonal; |
+ break; |
+ case XFA_ATTRIBUTEENUM_DiagonalRight: |
+ iHatch = FX_HATCHSTYLE_BackwardDiagonal; |
+ break; |
+ case XFA_ATTRIBUTEENUM_Horizontal: |
+ iHatch = FX_HATCHSTYLE_Horizontal; |
+ break; |
+ case XFA_ATTRIBUTEENUM_Vertical: |
+ iHatch = FX_HATCHSTYLE_Vertical; |
+ break; |
+ default: |
+ break; |
+ } |
+ CFX_Pattern pattern; |
+ pattern.Create(iHatch, crEnd, crStart); |
+ CFX_Color cr(&pattern); |
+ pGS->SetFillColor(&cr); |
+ pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
+} |
+static void XFA_BOX_Fill_Linear(CXFA_Box box, |
+ CFX_Graphics* pGS, |
+ CFX_Path& fillPath, |
+ CFX_RectF rtFill, |
+ CFX_Matrix* pMatrix) { |
+ CXFA_Fill fill = box.GetFill(); |
+ FX_ARGB crStart, crEnd; |
+ crStart = fill.GetColor(); |
+ int32_t iType = fill.GetLinear(crEnd); |
+ CFX_PointF ptStart, ptEnd; |
+ switch (iType) { |
+ case XFA_ATTRIBUTEENUM_ToRight: |
+ ptStart.Set(rtFill.left, rtFill.top); |
+ ptEnd.Set(rtFill.right(), rtFill.top); |
+ break; |
+ case XFA_ATTRIBUTEENUM_ToBottom: |
+ ptStart.Set(rtFill.left, rtFill.top); |
+ ptEnd.Set(rtFill.left, rtFill.bottom()); |
+ break; |
+ case XFA_ATTRIBUTEENUM_ToLeft: |
+ ptStart.Set(rtFill.right(), rtFill.top); |
+ ptEnd.Set(rtFill.left, rtFill.top); |
+ break; |
+ case XFA_ATTRIBUTEENUM_ToTop: |
+ ptStart.Set(rtFill.left, rtFill.bottom()); |
+ ptEnd.Set(rtFill.left, rtFill.top); |
+ break; |
+ default: |
+ break; |
+ } |
+ CFX_Shading shading; |
+ shading.CreateAxial(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd); |
+ CFX_Color cr(&shading); |
+ pGS->SetFillColor(&cr); |
+ pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
+} |
+static void XFA_BOX_Fill(CXFA_Box box, |
+ const CXFA_StrokeArray& strokes, |
+ CFX_Graphics* pGS, |
+ const CFX_RectF& rtWidget, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwFlags) { |
+ CXFA_Fill fill = box.GetFill(); |
+ if (!fill.IsExistInXML() || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { |
+ return; |
+ } |
+ pGS->SaveGraphState(); |
+ CFX_Path fillPath; |
+ fillPath.Create(); |
+ XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath, |
+ (dwFlags & XFA_DRAWBOX_ForceRound) != 0); |
+ fillPath.Close(); |
+ int32_t eType = fill.GetFillType(); |
+ switch (eType) { |
+ case XFA_ELEMENT_Radial: |
+ XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix); |
+ break; |
+ case XFA_ELEMENT_Pattern: |
+ XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix); |
+ break; |
+ case XFA_ELEMENT_Linear: |
+ XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix); |
+ break; |
+ default: { |
+ FX_ARGB cr; |
+ if (eType == XFA_ELEMENT_Stipple) { |
+ int32_t iRate = fill.GetStipple(cr); |
+ if (iRate == 0) { |
+ iRate = 100; |
+ } |
+ int32_t a = 0; |
+ FX_COLORREF rgb; |
+ ArgbDecode(cr, a, rgb); |
+ cr = ArgbEncode(iRate * a / 100, rgb); |
+ } else { |
+ cr = fill.GetColor(); |
+ } |
+ CFX_Color fillColor(cr); |
+ pGS->SetFillColor(&fillColor); |
+ pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); |
+ } break; |
+ } |
+ pGS->RestoreGraphState(); |
+} |
+static void XFA_BOX_StrokePath(CXFA_Stroke stroke, |
+ CFX_Path* pPath, |
+ CFX_Graphics* pGS, |
+ CFX_Matrix* pMatrix) { |
+ if (!stroke.IsExistInXML() || !stroke.IsVisible()) { |
+ return; |
+ } |
+ FX_FLOAT fThickness = stroke.GetThickness(); |
+ if (fThickness < 0.001f) { |
+ return; |
+ } |
+ pGS->SaveGraphState(); |
+ if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) { |
+ fThickness = 2 * stroke.GetRadius(); |
+ } |
+ pGS->SetLineWidth(fThickness, TRUE); |
+ pGS->SetLineCap(CFX_GraphStateData::LineCapButt); |
+ XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(), |
+ XFA_ATTRIBUTEENUM_Butt); |
+ CFX_Color fxColor(stroke.GetColor()); |
+ pGS->SetStrokeColor(&fxColor); |
+ pGS->StrokePath(pPath, pMatrix); |
+ pGS->RestoreGraphState(); |
+} |
+static void XFA_BOX_StrokeArc(CXFA_Box box, |
+ CFX_Graphics* pGS, |
+ CFX_RectF rtWidget, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwFlags) { |
+ CXFA_Edge edge = box.GetEdge(0); |
+ if (!edge.IsExistInXML() || !edge.IsVisible()) { |
+ return; |
+ } |
+ FX_BOOL bVisible = FALSE; |
+ FX_FLOAT fThickness = 0; |
+ int32_t i3DType = box.Get3DStyle(bVisible, fThickness); |
+ if (i3DType) { |
+ if (bVisible && fThickness >= 0.001f) { |
+ dwFlags |= XFA_DRAWBOX_Lowered3D; |
+ } |
+ } |
+ FX_FLOAT fHalf = edge.GetThickness() / 2; |
+ if (fHalf < 0) { |
+ fHalf = 0; |
+ } |
+ int32_t iHand = box.GetHand(); |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.Inflate(fHalf, fHalf); |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.Deflate(fHalf, fHalf); |
+ } |
+ if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 || |
+ (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) { |
+ if (fHalf < 0.001f) { |
+ return; |
+ } |
+ CFX_Path arcPath; |
+ arcPath.Create(); |
+ XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags); |
+ XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix); |
+ return; |
+ } |
+ pGS->SaveGraphState(); |
+ pGS->SetLineWidth(fHalf); |
+ FX_FLOAT a, b; |
+ a = rtWidget.width / 2.0f; |
+ b = rtWidget.height / 2.0f; |
+ if (dwFlags & XFA_DRAWBOX_ForceRound) { |
+ a = b = std::min(a, b); |
+ } |
+ CFX_PointF center = rtWidget.Center(); |
+ rtWidget.left = center.x - a; |
+ rtWidget.top = center.y - b; |
+ rtWidget.width = a + a; |
+ rtWidget.height = b + b; |
+ FX_FLOAT startAngle = 0, sweepAngle = 360; |
+ startAngle = startAngle * FX_PI / 180.0f; |
+ sweepAngle = -sweepAngle * FX_PI / 180.0f; |
+ CFX_Path arcPath; |
+ arcPath.Create(); |
+ arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
+ 3.0f * FX_PI / 4.0f, FX_PI); |
+ CFX_Color cr(0xFF808080); |
+ pGS->SetStrokeColor(&cr); |
+ pGS->StrokePath(&arcPath, pMatrix); |
+ arcPath.Clear(); |
+ arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
+ -1.0f * FX_PI / 4.0f, FX_PI); |
+ cr.Set(0xFFFFFFFF); |
+ pGS->SetStrokeColor(&cr); |
+ pGS->StrokePath(&arcPath, pMatrix); |
+ rtWidget.Deflate(fHalf, fHalf); |
+ arcPath.Clear(); |
+ arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
+ 3.0f * FX_PI / 4.0f, FX_PI); |
+ cr.Set(0xFF404040); |
+ pGS->SetStrokeColor(&cr); |
+ pGS->StrokePath(&arcPath, pMatrix); |
+ arcPath.Clear(); |
+ arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, |
+ -1.0f * FX_PI / 4.0f, FX_PI); |
+ cr.Set(0xFFC0C0C0); |
+ pGS->SetStrokeColor(&cr); |
+ pGS->StrokePath(&arcPath, pMatrix); |
+ pGS->RestoreGraphState(); |
+} |
+static void XFA_Draw3DRect(CFX_Graphics* pGraphic, |
+ const CFX_RectF& rt, |
+ FX_FLOAT fLineWidth, |
+ CFX_Matrix* pMatrix, |
+ FX_ARGB argbTopLeft, |
+ FX_ARGB argbBottomRight) { |
+ CFX_Color crLT(argbTopLeft); |
+ pGraphic->SetFillColor(&crLT); |
+ FX_FLOAT fBottom = rt.bottom(); |
+ FX_FLOAT fRight = rt.right(); |
+ CFX_Path pathLT; |
+ pathLT.Create(); |
+ pathLT.MoveTo(rt.left, fBottom); |
+ pathLT.LineTo(rt.left, rt.top); |
+ pathLT.LineTo(fRight, rt.top); |
+ pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth); |
+ pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth); |
+ pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); |
+ pathLT.LineTo(rt.left, fBottom); |
+ pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix); |
+ CFX_Color crRB(argbBottomRight); |
+ pGraphic->SetFillColor(&crRB); |
+ CFX_Path pathRB; |
+ pathRB.Create(); |
+ pathRB.MoveTo(fRight, rt.top); |
+ pathRB.LineTo(fRight, fBottom); |
+ pathRB.LineTo(rt.left, fBottom); |
+ pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); |
+ pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth); |
+ pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth); |
+ pathRB.LineTo(fRight, rt.top); |
+ pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix); |
+} |
+static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS, |
+ CFX_RectF rt, |
+ FX_FLOAT fThickness, |
+ CFX_Matrix* pMatrix) { |
+ FX_FLOAT fHalfWidth = fThickness / 2.0f; |
+ CFX_RectF rtInner(rt); |
+ rtInner.Deflate(fHalfWidth, fHalfWidth); |
+ CFX_Color cr(0xFF000000); |
+ pGS->SetFillColor(&cr); |
+ CFX_Path path; |
+ path.Create(); |
+ path.AddRectangle(rt.left, rt.top, rt.width, rt.height); |
+ path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); |
+ pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); |
+ XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0); |
+} |
+static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS, |
+ CFX_RectF rt, |
+ FX_FLOAT fThickness, |
+ CFX_Matrix* pMatrix) { |
+ FX_FLOAT fHalfWidth = fThickness / 2.0f; |
+ CFX_RectF rtInner(rt); |
+ rtInner.Deflate(fHalfWidth, fHalfWidth); |
+ CFX_Color cr(0xFF000000); |
+ pGS->SetFillColor(&cr); |
+ CFX_Path path; |
+ path.Create(); |
+ path.AddRectangle(rt.left, rt.top, rt.width, rt.height); |
+ path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); |
+ pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); |
+ XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); |
+} |
+static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS, |
+ CFX_RectF rt, |
+ FX_FLOAT fThickness, |
+ CFX_Matrix* pMatrix) { |
+ FX_FLOAT fHalfWidth = fThickness / 2.0f; |
+ XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF); |
+ CFX_RectF rtInner(rt); |
+ rtInner.Deflate(fHalfWidth, fHalfWidth); |
+ XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); |
+} |
+static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS, |
+ CFX_RectF rt, |
+ FX_FLOAT fThickness, |
+ CFX_Matrix* pMatrix) { |
+ FX_FLOAT fHalfWidth = fThickness / 2.0f; |
+ XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000); |
+ CFX_RectF rtInner(rt); |
+ rtInner.Deflate(fHalfWidth, fHalfWidth); |
+ XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080); |
+} |
+static void XFA_BOX_Stroke_Rect(CXFA_Box box, |
+ const CXFA_StrokeArray& strokes, |
+ CFX_Graphics* pGS, |
+ CFX_RectF rtWidget, |
+ CFX_Matrix* pMatrix) { |
+ FX_BOOL bVisible = FALSE; |
+ FX_FLOAT fThickness = 0; |
+ int32_t i3DType = box.Get3DStyle(bVisible, fThickness); |
+ if (i3DType) { |
+ if (!bVisible || fThickness < 0.001f) { |
+ return; |
+ } |
+ switch (i3DType) { |
+ case XFA_ATTRIBUTEENUM_Lowered: |
+ XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix); |
+ break; |
+ case XFA_ATTRIBUTEENUM_Raised: |
+ XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix); |
+ break; |
+ case XFA_ATTRIBUTEENUM_Etched: |
+ XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix); |
+ break; |
+ case XFA_ATTRIBUTEENUM_Embossed: |
+ XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix); |
+ break; |
+ } |
+ return; |
+ } |
+ FX_BOOL bClose = FALSE; |
+ FX_BOOL bSameStyles = TRUE; |
+ int32_t i; |
+ CXFA_Stroke stroke1 = strokes[0]; |
+ for (i = 1; i < 8; i++) { |
+ CXFA_Stroke stroke2 = strokes[i]; |
+ if (!stroke1.SameStyles(stroke2)) { |
+ bSameStyles = FALSE; |
+ break; |
+ } |
+ stroke1 = stroke2; |
+ } |
+ if (bSameStyles) { |
+ stroke1 = strokes[0]; |
+ bClose = TRUE; |
+ for (i = 2; i < 8; i += 2) { |
+ CXFA_Stroke stroke2 = strokes[i]; |
+ if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | |
+ XFA_STROKE_SAMESTYLE_Corner)) { |
+ bSameStyles = FALSE; |
+ break; |
+ } |
+ stroke1 = stroke2; |
+ } |
+ if (bSameStyles) { |
+ stroke1 = strokes[0]; |
+ if (stroke1.IsInverted()) { |
+ bSameStyles = FALSE; |
+ } |
+ if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { |
+ bSameStyles = FALSE; |
+ } |
+ } |
+ } |
+ FX_BOOL bStart = TRUE; |
+ CFX_Path path; |
+ path.Create(); |
+ for (i = 0; i < 8; i++) { |
+ CXFA_Stroke stroke1 = strokes[i]; |
+ if ((i % 1) == 0 && stroke1.GetRadius() < 0) { |
+ FX_BOOL bEmpty = path.IsEmpty(); |
+ if (!bEmpty) { |
+ XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); |
+ path.Clear(); |
+ } |
+ bStart = TRUE; |
+ continue; |
+ } |
+ XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles); |
+ CXFA_Stroke stroke2 = strokes[(i + 1) % 8]; |
+ bStart = !stroke1.SameStyles(stroke2); |
+ if (bStart) { |
+ XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); |
+ path.Clear(); |
+ } |
+ } |
+ FX_BOOL bEmpty = path.IsEmpty(); |
+ if (!bEmpty) { |
+ if (bClose) { |
+ path.Close(); |
+ } |
+ XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix); |
+ } |
+} |
+static void XFA_BOX_Stroke(CXFA_Box box, |
+ const CXFA_StrokeArray& strokes, |
+ CFX_Graphics* pGS, |
+ CFX_RectF rtWidget, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwFlags) { |
+ if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { |
+ XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags); |
+ return; |
+ } |
+ FX_BOOL bVisible = FALSE; |
+ for (int32_t j = 0; j < 4; j++) { |
+ bVisible |= strokes[j * 2 + 1].IsVisible(); |
+ if (bVisible) { |
+ break; |
+ } |
+ } |
+ if (!bVisible) { |
+ return; |
+ } |
+ for (int32_t i = 1; i < 8; i += 2) { |
+ CXFA_Edge edge = (CXFA_Node*)strokes[i]; |
+ FX_FLOAT fThickness = edge.GetThickness(); |
+ if (fThickness < 0) { |
+ fThickness = 0; |
+ } |
+ FX_FLOAT fHalf = fThickness / 2; |
+ int32_t iHand = box.GetHand(); |
+ switch (i) { |
+ case 1: |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.top -= fHalf; |
+ rtWidget.height += fHalf; |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.top += fHalf; |
+ rtWidget.height -= fHalf; |
+ } |
+ break; |
+ case 3: |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.width += fHalf; |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.width -= fHalf; |
+ } |
+ break; |
+ case 5: |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.height += fHalf; |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.height -= fHalf; |
+ } |
+ break; |
+ case 7: |
+ if (iHand == XFA_ATTRIBUTEENUM_Left) { |
+ rtWidget.left -= fHalf; |
+ rtWidget.width += fHalf; |
+ } else if (iHand == XFA_ATTRIBUTEENUM_Right) { |
+ rtWidget.left += fHalf; |
+ rtWidget.width -= fHalf; |
+ } |
+ break; |
+ } |
+ } |
+ XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix); |
+} |
+void XFA_DrawBox(CXFA_Box box, |
+ CFX_Graphics* pGS, |
+ const CFX_RectF& rtWidget, |
+ CFX_Matrix* pMatrix, |
+ FX_DWORD dwFlags) { |
+ if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { |
+ return; |
+ } |
+ int32_t iType = box.GetClassID(); |
+ if (iType != XFA_ELEMENT_Arc && iType != XFA_ELEMENT_Border && |
+ iType != XFA_ELEMENT_Rectangle) { |
+ return; |
+ } |
+ CXFA_StrokeArray strokes; |
+ if (!(dwFlags & XFA_DRAWBOX_ForceRound) && iType != XFA_ELEMENT_Arc) { |
+ box.GetStrokes(strokes); |
+ } |
+ XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags); |
+ XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags); |
+} |