You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
693 lines
18 KiB
693 lines
18 KiB
// 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 "xfa/fxfa/cxfa_ffwidget.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "core/fxcodec/fx_codec.h"
|
|
#include "core/fxcodec/progressivedecoder.h"
|
|
#include "core/fxcrt/maybe_owned.h"
|
|
#include "core/fxge/cfx_pathdata.h"
|
|
#include "core/fxge/cfx_renderdevice.h"
|
|
#include "core/fxge/dib/cfx_dibitmap.h"
|
|
#include "xfa/fwl/fwl_widgethit.h"
|
|
#include "xfa/fxfa/cxfa_eventparam.h"
|
|
#include "xfa/fxfa/cxfa_ffapp.h"
|
|
#include "xfa/fxfa/cxfa_ffdoc.h"
|
|
#include "xfa/fxfa/cxfa_ffdocview.h"
|
|
#include "xfa/fxfa/cxfa_ffpageview.h"
|
|
#include "xfa/fxfa/cxfa_ffwidgethandler.h"
|
|
#include "xfa/fxfa/cxfa_imagerenderer.h"
|
|
#include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
|
|
#include "xfa/fxfa/parser/cxfa_border.h"
|
|
#include "xfa/fxfa/parser/cxfa_box.h"
|
|
#include "xfa/fxfa/parser/cxfa_edge.h"
|
|
#include "xfa/fxfa/parser/cxfa_image.h"
|
|
#include "xfa/fxfa/parser/cxfa_margin.h"
|
|
#include "xfa/fxfa/parser/cxfa_node.h"
|
|
#include "xfa/fxgraphics/cxfa_graphics.h"
|
|
|
|
namespace {
|
|
|
|
FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
|
|
int32_t iComponents,
|
|
int32_t iBitsPerComponent) {
|
|
FXDIB_Format dibFormat = FXDIB_Argb;
|
|
switch (type) {
|
|
case FXCODEC_IMAGE_JPG:
|
|
#ifdef PDF_ENABLE_XFA_BMP
|
|
case FXCODEC_IMAGE_BMP:
|
|
#endif // PDF_ENABLE_XFA_BMP
|
|
#ifdef PDF_ENABLE_XFA_TIFF
|
|
case FXCODEC_IMAGE_TIFF:
|
|
#endif // PDF_ENABLE_XFA_TIFF
|
|
{
|
|
dibFormat = FXDIB_Rgb32;
|
|
int32_t bpp = iComponents * iBitsPerComponent;
|
|
if (bpp <= 24) {
|
|
dibFormat = FXDIB_Rgb;
|
|
}
|
|
} break;
|
|
#ifdef PDF_ENABLE_XFA_PNG
|
|
case FXCODEC_IMAGE_PNG:
|
|
#endif // PDF_ENABLE_XFA_PNG
|
|
default:
|
|
break;
|
|
}
|
|
return dibFormat;
|
|
}
|
|
|
|
bool IsFXCodecErrorStatus(FXCODEC_STATUS status) {
|
|
return (status == FXCODEC_STATUS_ERROR ||
|
|
status == FXCODEC_STATUS_ERR_MEMORY ||
|
|
status == FXCODEC_STATUS_ERR_READ ||
|
|
status == FXCODEC_STATUS_ERR_FLUSH ||
|
|
status == FXCODEC_STATUS_ERR_FORMAT ||
|
|
status == FXCODEC_STATUS_ERR_PARAMS);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void XFA_DrawImage(CXFA_Graphics* pGS,
|
|
const CFX_RectF& rtImage,
|
|
const CFX_Matrix& matrix,
|
|
const RetainPtr<CFX_DIBitmap>& pDIBitmap,
|
|
XFA_AttributeValue iAspect,
|
|
const CFX_Size& dpi,
|
|
XFA_AttributeValue iHorzAlign,
|
|
XFA_AttributeValue iVertAlign) {
|
|
if (rtImage.IsEmpty())
|
|
return;
|
|
if (!pDIBitmap || !pDIBitmap->GetBuffer())
|
|
return;
|
|
|
|
CFX_RectF rtFit(rtImage.TopLeft(),
|
|
XFA_UnitPx2Pt(pDIBitmap->GetWidth(), dpi.width),
|
|
XFA_UnitPx2Pt(pDIBitmap->GetHeight(), dpi.height));
|
|
switch (iAspect) {
|
|
case XFA_AttributeValue::Fit: {
|
|
float f1 = rtImage.height / rtFit.height;
|
|
float f2 = rtImage.width / rtFit.width;
|
|
f1 = std::min(f1, f2);
|
|
rtFit.height = rtFit.height * f1;
|
|
rtFit.width = rtFit.width * f1;
|
|
break;
|
|
}
|
|
case XFA_AttributeValue::Height: {
|
|
float f1 = rtImage.height / rtFit.height;
|
|
rtFit.height = rtImage.height;
|
|
rtFit.width = f1 * rtFit.width;
|
|
break;
|
|
}
|
|
case XFA_AttributeValue::None:
|
|
rtFit.height = rtImage.height;
|
|
rtFit.width = rtImage.width;
|
|
break;
|
|
case XFA_AttributeValue::Width: {
|
|
float f1 = rtImage.width / rtFit.width;
|
|
rtFit.width = rtImage.width;
|
|
rtFit.height = rtFit.height * f1;
|
|
break;
|
|
}
|
|
case XFA_AttributeValue::Actual:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (iHorzAlign == XFA_AttributeValue::Center)
|
|
rtFit.left += (rtImage.width - rtFit.width) / 2;
|
|
else if (iHorzAlign == XFA_AttributeValue::Right)
|
|
rtFit.left = rtImage.right() - rtFit.width;
|
|
|
|
if (iVertAlign == XFA_AttributeValue::Middle)
|
|
rtFit.top += (rtImage.height - rtFit.height) / 2;
|
|
else if (iVertAlign == XFA_AttributeValue::Bottom)
|
|
rtFit.top = rtImage.bottom() - rtImage.height;
|
|
|
|
CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
|
|
CFX_RenderDevice::StateRestorer restorer(pRenderDevice);
|
|
CFX_PathData path;
|
|
path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
|
|
pRenderDevice->SetClip_PathFill(&path, &matrix, FXFILL_WINDING);
|
|
|
|
CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
|
|
mtImage.Concat(
|
|
CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top));
|
|
mtImage.Concat(matrix);
|
|
|
|
CXFA_ImageRenderer imageRender(pRenderDevice, pDIBitmap, &mtImage);
|
|
if (!imageRender.Start()) {
|
|
return;
|
|
}
|
|
while (imageRender.Continue())
|
|
continue;
|
|
}
|
|
|
|
RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
|
|
const RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
|
|
FXCODEC_IMAGE_TYPE type,
|
|
int32_t& iImageXDpi,
|
|
int32_t& iImageYDpi) {
|
|
auto* pCodecMgr = fxcodec::ModuleMgr::GetInstance();
|
|
std::unique_ptr<ProgressiveDecoder> pProgressiveDecoder =
|
|
pCodecMgr->CreateProgressiveDecoder();
|
|
|
|
CFX_DIBAttribute dibAttr;
|
|
pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
|
|
switch (dibAttr.m_wDPIUnit) {
|
|
case FXCODEC_RESUNIT_CENTIMETER:
|
|
dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f);
|
|
dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
|
|
break;
|
|
case FXCODEC_RESUNIT_METER:
|
|
dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f);
|
|
dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
|
|
iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
|
|
if (pProgressiveDecoder->GetWidth() <= 0 ||
|
|
pProgressiveDecoder->GetHeight() <= 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
type = pProgressiveDecoder->GetType();
|
|
int32_t iComponents = pProgressiveDecoder->GetNumComponents();
|
|
int32_t iBpc = pProgressiveDecoder->GetBPC();
|
|
FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
|
|
RetainPtr<CFX_DIBitmap> pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
|
|
pBitmap->Create(pProgressiveDecoder->GetWidth(),
|
|
pProgressiveDecoder->GetHeight(), dibFormat);
|
|
pBitmap->Clear(0xffffffff);
|
|
|
|
size_t nFrames;
|
|
FXCODEC_STATUS status;
|
|
std::tie(status, nFrames) = pProgressiveDecoder->GetFrames();
|
|
if (status != FXCODEC_STATUS_DECODE_READY || nFrames == 0) {
|
|
pBitmap = nullptr;
|
|
return pBitmap;
|
|
}
|
|
|
|
status = pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
|
|
pBitmap->GetHeight());
|
|
if (IsFXCodecErrorStatus(status)) {
|
|
pBitmap = nullptr;
|
|
return pBitmap;
|
|
}
|
|
|
|
while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
|
|
status = pProgressiveDecoder->ContinueDecode();
|
|
if (IsFXCodecErrorStatus(status)) {
|
|
pBitmap = nullptr;
|
|
return pBitmap;
|
|
}
|
|
}
|
|
|
|
return pBitmap;
|
|
}
|
|
|
|
void XFA_RectWithoutMargin(CFX_RectF* rt, const CXFA_Margin* margin) {
|
|
if (!margin)
|
|
return;
|
|
|
|
rt->Deflate(margin->GetLeftInset(), margin->GetTopInset(),
|
|
margin->GetRightInset(), margin->GetBottomInset());
|
|
}
|
|
|
|
CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
|
|
if (!pLayoutItem->GetFormNode()->HasCreatedUIWidget())
|
|
return nullptr;
|
|
|
|
return GetFFWidget(ToContentLayoutItem(pLayoutItem));
|
|
}
|
|
|
|
CXFA_CalcData::CXFA_CalcData() = default;
|
|
|
|
CXFA_CalcData::~CXFA_CalcData() = default;
|
|
|
|
CXFA_FFWidget::CXFA_FFWidget(CXFA_Node* node) : m_pNode(node) {}
|
|
|
|
CXFA_FFWidget::~CXFA_FFWidget() = default;
|
|
|
|
const CFWL_App* CXFA_FFWidget::GetFWLApp() {
|
|
return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
|
|
}
|
|
|
|
CXFA_FFWidget* CXFA_FFWidget::GetNextFFWidget() const {
|
|
return GetFFWidget(GetLayoutItem()->GetNext());
|
|
}
|
|
|
|
const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
|
|
if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_RectCached))
|
|
RecacheWidgetRect();
|
|
return m_rtWidget;
|
|
}
|
|
|
|
const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
|
|
GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_RectCached);
|
|
m_rtWidget = GetLayoutItem()->GetRect(false);
|
|
return m_rtWidget;
|
|
}
|
|
|
|
CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() {
|
|
CFX_RectF rtWidget = GetWidgetRect();
|
|
float fValue = 0;
|
|
switch (m_pNode->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;
|
|
}
|
|
return rtWidget;
|
|
}
|
|
|
|
void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) {
|
|
GetLayoutItem()->ClearStatusBits(dwRemoved);
|
|
GetLayoutItem()->SetStatusBits(dwAdded);
|
|
}
|
|
|
|
CXFA_FFField* CXFA_FFWidget::AsField() {
|
|
return nullptr;
|
|
}
|
|
|
|
CFX_RectF CXFA_FFWidget::GetBBox(FocusOption focus) {
|
|
if (focus == kDrawFocus || !m_pPageView)
|
|
return CFX_RectF();
|
|
return m_pPageView->GetPageViewRect();
|
|
}
|
|
|
|
void CXFA_FFWidget::RenderWidget(CXFA_Graphics* pGS,
|
|
const CFX_Matrix& matrix,
|
|
HighlightOption highlight) {
|
|
if (!HasVisibleStatus())
|
|
return;
|
|
|
|
CXFA_Border* border = m_pNode->GetBorderIfExists();
|
|
if (!border)
|
|
return;
|
|
|
|
CFX_RectF rtBorder = GetRectWithoutRotate();
|
|
CXFA_Margin* margin = border->GetMarginIfExists();
|
|
XFA_RectWithoutMargin(&rtBorder, margin);
|
|
rtBorder.Normalize();
|
|
DrawBorder(pGS, border, rtBorder, matrix);
|
|
}
|
|
|
|
bool CXFA_FFWidget::IsLoaded() {
|
|
return !!m_pPageView;
|
|
}
|
|
|
|
bool CXFA_FFWidget::LoadWidget() {
|
|
PerformLayout();
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_FFWidget::PerformLayout() {
|
|
RecacheWidgetRect();
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_FFWidget::UpdateFWLData() {
|
|
return false;
|
|
}
|
|
|
|
void CXFA_FFWidget::UpdateWidgetProperty() {}
|
|
|
|
bool CXFA_FFWidget::HasEventUnderHandler(XFA_EVENTTYPE eEventType,
|
|
CXFA_FFWidgetHandler* pHandler) {
|
|
CXFA_Node* pNode = GetNode();
|
|
return pNode->IsWidgetReady() && pHandler->HasEvent(pNode, eEventType);
|
|
}
|
|
|
|
bool CXFA_FFWidget::ProcessEventUnderHandler(CXFA_EventParam* params,
|
|
CXFA_FFWidgetHandler* pHandler) {
|
|
CXFA_Node* pNode = GetNode();
|
|
if (!pNode->IsWidgetReady())
|
|
return false;
|
|
|
|
params->m_pTarget = pNode;
|
|
return pHandler->ProcessEvent(pNode, params) == XFA_EventError::kSuccess;
|
|
}
|
|
|
|
void CXFA_FFWidget::DrawBorder(CXFA_Graphics* pGS,
|
|
CXFA_Box* box,
|
|
const CFX_RectF& rtBorder,
|
|
const CFX_Matrix& matrix) {
|
|
if (box)
|
|
box->Draw(pGS, rtBorder, matrix, false);
|
|
}
|
|
|
|
void CXFA_FFWidget::DrawBorderWithFlag(CXFA_Graphics* pGS,
|
|
CXFA_Box* box,
|
|
const CFX_RectF& rtBorder,
|
|
const CFX_Matrix& matrix,
|
|
bool forceRound) {
|
|
if (box)
|
|
box->Draw(pGS, rtBorder, matrix, forceRound);
|
|
}
|
|
|
|
void CXFA_FFWidget::InvalidateRect() {
|
|
CFX_RectF rtWidget = GetBBox(kDoNotDrawFocus);
|
|
rtWidget.Inflate(2, 2);
|
|
m_pDocView->InvalidateRect(m_pPageView.Get(), rtWidget);
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnMouseEnter() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnMouseExit() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::AcceptsFocusOnButtonDown(uint32_t dwFlags,
|
|
const CFX_PointF& point,
|
|
FWL_MouseCommand command) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags,
|
|
int16_t zDelta,
|
|
const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
|
|
// OnSetFocus event may remove this widget.
|
|
ObservedPtr<CXFA_FFWidget> pWatched(this);
|
|
CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
|
|
if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
|
|
if (!pParent->OnSetFocus(pOldWidget))
|
|
return false;
|
|
}
|
|
if (!pWatched)
|
|
return false;
|
|
|
|
GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused);
|
|
|
|
CXFA_EventParam eParam;
|
|
eParam.m_eType = XFA_EVENT_Enter;
|
|
eParam.m_pTarget = m_pNode.Get();
|
|
m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Enter, &eParam);
|
|
|
|
return !!pWatched;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
|
|
// OnKillFocus event may remove these widgets.
|
|
ObservedPtr<CXFA_FFWidget> pWatched(this);
|
|
ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
|
|
GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
|
|
EventKillFocus();
|
|
if (!pWatched)
|
|
return false;
|
|
|
|
if (!pNewWidget)
|
|
return true;
|
|
|
|
if (!pNewWatched)
|
|
return false;
|
|
|
|
// OnKillFocus event may remove |pNewWidget|.
|
|
CXFA_FFWidget* pParent = GetFFWidget(ToContentLayoutItem(GetParent()));
|
|
if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
|
|
if (!pParent->OnKillFocus(pNewWidget))
|
|
return false;
|
|
}
|
|
return pWatched && pNewWatched;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) {
|
|
return false;
|
|
}
|
|
|
|
FWL_WidgetHit CXFA_FFWidget::HitTest(const CFX_PointF& point) {
|
|
return FWL_WidgetHit::Unknown;
|
|
}
|
|
|
|
bool CXFA_FFWidget::OnSetCursor(const CFX_PointF& point) {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanUndo() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanRedo() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::Undo() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::Redo() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanCopy() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanCut() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanPaste() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanSelectAll() {
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanDelete() {
|
|
return CanCut();
|
|
}
|
|
|
|
bool CXFA_FFWidget::CanDeSelect() {
|
|
return CanCopy();
|
|
}
|
|
|
|
Optional<WideString> CXFA_FFWidget::Copy() {
|
|
return {};
|
|
}
|
|
|
|
Optional<WideString> CXFA_FFWidget::Cut() {
|
|
return {};
|
|
}
|
|
|
|
bool CXFA_FFWidget::Paste(const WideString& wsPaste) {
|
|
return false;
|
|
}
|
|
|
|
void CXFA_FFWidget::SelectAll() {}
|
|
|
|
void CXFA_FFWidget::Delete() {}
|
|
|
|
void CXFA_FFWidget::DeSelect() {}
|
|
|
|
WideString CXFA_FFWidget::GetText() {
|
|
return WideString();
|
|
}
|
|
|
|
FormFieldType CXFA_FFWidget::GetFormFieldType() {
|
|
return FormFieldType::kXFA;
|
|
}
|
|
|
|
CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) {
|
|
CFX_Matrix mt = GetRotateMatrix();
|
|
if (mt.IsIdentity())
|
|
return point;
|
|
|
|
return mt.GetInverse().Transform(point);
|
|
}
|
|
|
|
CFX_Matrix CXFA_FFWidget::GetRotateMatrix() {
|
|
int32_t iRotate = m_pNode->GetRotate();
|
|
if (!iRotate)
|
|
return CFX_Matrix();
|
|
|
|
CFX_RectF rcWidget = GetRectWithoutRotate();
|
|
CFX_Matrix mt;
|
|
switch (iRotate) {
|
|
case 90:
|
|
mt.a = 0;
|
|
mt.b = -1;
|
|
mt.c = 1;
|
|
mt.d = 0;
|
|
mt.e = rcWidget.left - rcWidget.top;
|
|
mt.f = rcWidget.left + rcWidget.top;
|
|
break;
|
|
case 180:
|
|
mt.a = -1;
|
|
mt.b = 0;
|
|
mt.c = 0;
|
|
mt.d = -1;
|
|
mt.e = rcWidget.left * 2;
|
|
mt.f = rcWidget.top * 2;
|
|
break;
|
|
case 270:
|
|
mt.a = 0;
|
|
mt.b = 1;
|
|
mt.c = -1;
|
|
mt.d = 0;
|
|
mt.e = rcWidget.left + rcWidget.top;
|
|
mt.f = rcWidget.top - rcWidget.left;
|
|
break;
|
|
}
|
|
return mt;
|
|
}
|
|
|
|
void CXFA_FFWidget::DisplayCaret(bool bVisible, const CFX_RectF* pRtAnchor) {
|
|
IXFA_DocEnvironment* pDocEnvironment = GetDoc()->GetDocEnvironment();
|
|
if (!pDocEnvironment)
|
|
return;
|
|
|
|
pDocEnvironment->DisplayCaret(this, bVisible, pRtAnchor);
|
|
}
|
|
|
|
void CXFA_FFWidget::GetBorderColorAndThickness(FX_ARGB* cr, float* fWidth) {
|
|
ASSERT(GetNode()->IsWidgetReady());
|
|
CXFA_Border* borderUI = GetNode()->GetUIBorder();
|
|
if (!borderUI)
|
|
return;
|
|
|
|
CXFA_Edge* edge = borderUI->GetEdgeIfExists(0);
|
|
if (!edge)
|
|
return;
|
|
|
|
*cr = edge->GetColor();
|
|
*fWidth = edge->GetThickness();
|
|
}
|
|
|
|
bool CXFA_FFWidget::IsLayoutRectEmpty() {
|
|
CFX_RectF rtLayout = GetRectWithoutRotate();
|
|
return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
|
|
}
|
|
|
|
CXFA_LayoutItem* CXFA_FFWidget::GetParent() {
|
|
CXFA_Node* pParentNode = m_pNode->GetParent();
|
|
if (!pParentNode)
|
|
return nullptr;
|
|
|
|
CXFA_LayoutProcessor* layout = GetDocView()->GetXFALayout();
|
|
return layout->GetLayoutItem(pParentNode);
|
|
}
|
|
|
|
bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
|
|
if (!pWidget)
|
|
return false;
|
|
|
|
CXFA_Node* pChildNode = pWidget->GetNode();
|
|
while (pChildNode) {
|
|
if (pChildNode == m_pNode)
|
|
return true;
|
|
|
|
pChildNode = pChildNode->GetParent();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) {
|
|
return GetWidgetRect().Contains(point);
|
|
}
|
|
|
|
CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
|
|
return m_pDocView->GetDoc();
|
|
}
|
|
|
|
CXFA_FFApp* CXFA_FFWidget::GetApp() {
|
|
return GetDoc()->GetApp();
|
|
}
|
|
|
|
IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() {
|
|
return GetApp()->GetAppProvider();
|
|
}
|
|
|
|
bool CXFA_FFWidget::HasVisibleStatus() const {
|
|
return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible);
|
|
}
|
|
|
|
void CXFA_FFWidget::EventKillFocus() {
|
|
CXFA_ContentLayoutItem* pItem = GetLayoutItem();
|
|
if (pItem->TestStatusBits(XFA_WidgetStatus_Access)) {
|
|
pItem->ClearStatusBits(XFA_WidgetStatus_Access);
|
|
return;
|
|
}
|
|
CXFA_EventParam eParam;
|
|
eParam.m_eType = XFA_EVENT_Exit;
|
|
eParam.m_pTarget = m_pNode.Get();
|
|
m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Exit, &eParam);
|
|
}
|
|
|
|
bool CXFA_FFWidget::IsButtonDown() {
|
|
return GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_ButtonDown);
|
|
}
|
|
|
|
void CXFA_FFWidget::SetButtonDown(bool bSet) {
|
|
CXFA_ContentLayoutItem* pItem = GetLayoutItem();
|
|
if (bSet)
|
|
pItem->SetStatusBits(XFA_WidgetStatus_ButtonDown);
|
|
else
|
|
pItem->ClearStatusBits(XFA_WidgetStatus_ButtonDown);
|
|
}
|