blob: cdac507f4199c78a527d60890c2b76ca12983305 [file] [log] [blame]
// 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_fftext.h"
#include "xfa/fgas/graphics/cfgas_gegraphics.h"
#include "xfa/fgas/layout/cfgas_linkuserdata.h"
#include "xfa/fwl/fwl_widgethit.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_textlayout.h"
#include "xfa/fxfa/parser/cxfa_margin.h"
CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}
CXFA_FFText::~CXFA_FFText() = default;
void CXFA_FFText::RenderWidget(CFGAS_GEGraphics* pGS,
const CFX_Matrix& matrix,
HighlightOption highlight) {
if (!HasVisibleStatus())
return;
CFX_Matrix mtRotate = GetRotateMatrix();
mtRotate.Concat(matrix);
CXFA_FFWidget::RenderWidget(pGS, mtRotate, highlight);
CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
if (!pTextLayout)
return;
CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
CFX_RectF rtText = GetRectWithoutRotate();
CXFA_Margin* margin = m_pNode->GetMarginIfExists();
if (margin) {
CXFA_ContentLayoutItem* pItem = GetLayoutItem();
if (!pItem->GetPrev() && !pItem->GetNext()) {
XFA_RectWithoutMargin(&rtText, margin);
} else {
float fTopInset = 0;
float fBottomInset = 0;
if (!pItem->GetPrev())
fTopInset = margin->GetTopInset();
else if (!pItem->GetNext())
fBottomInset = margin->GetBottomInset();
rtText.Deflate(margin->GetLeftInset(), fTopInset, margin->GetRightInset(),
fBottomInset);
}
}
CFX_Matrix mt(1, 0, 0, 1, rtText.left, rtText.top);
CFX_RectF rtClip = mtRotate.TransformRect(rtText);
mt.Concat(mtRotate);
pTextLayout->DrawString(pRenderDevice, mt, rtClip,
GetLayoutItem()->GetIndex());
}
bool CXFA_FFText::IsLoaded() {
CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
return pTextLayout && !pTextLayout->HasBlock();
}
bool CXFA_FFText::PerformLayout() {
CXFA_FFWidget::PerformLayout();
CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
if (!pTextLayout)
return false;
if (!pTextLayout->HasBlock())
return true;
pTextLayout->ClearBlocks();
CXFA_ContentLayoutItem* pItem = GetLayoutItem();
if (!pItem->GetPrev() && !pItem->GetNext())
return true;
pItem = pItem->GetFirst();
while (pItem) {
CFX_RectF rtText = pItem->GetAbsoluteRect();
CXFA_Margin* margin = m_pNode->GetMarginIfExists();
if (margin) {
if (!pItem->GetPrev())
rtText.height -= margin->GetTopInset();
else if (!pItem->GetNext())
rtText.height -= margin->GetBottomInset();
}
pTextLayout->ItemBlocks(rtText, pItem->GetIndex());
pItem = pItem->GetNext();
}
pTextLayout->ResetHasBlock();
return true;
}
bool CXFA_FFText::AcceptsFocusOnButtonDown(
Mask<XFA_FWL_KeyFlag> dwFlags,
const CFX_PointF& point,
CFWL_MessageMouse::MouseCommand command) {
return command == CFWL_MessageMouse::MouseCommand::kLeftButtonDown &&
GetRectWithoutRotate().Contains(point) &&
!GetLinkURLAtPoint(point).IsEmpty();
}
bool CXFA_FFText::OnLButtonDown(Mask<XFA_FWL_KeyFlag> dwFlags,
const CFX_PointF& point) {
SetButtonDown(true);
return true;
}
bool CXFA_FFText::OnMouseMove(Mask<XFA_FWL_KeyFlag> dwFlags,
const CFX_PointF& point) {
return GetRectWithoutRotate().Contains(point) &&
!GetLinkURLAtPoint(point).IsEmpty();
}
bool CXFA_FFText::OnLButtonUp(Mask<XFA_FWL_KeyFlag> dwFlags,
const CFX_PointF& point) {
if (!IsButtonDown())
return false;
SetButtonDown(false);
WideString wsURLContent = GetLinkURLAtPoint(point);
if (wsURLContent.IsEmpty())
return false;
GetDoc()->GotoURL(wsURLContent);
return true;
}
FWL_WidgetHit CXFA_FFText::HitTest(const CFX_PointF& point) {
if (GetRectWithoutRotate().Contains(point) &&
!GetLinkURLAtPoint(point).IsEmpty()) {
return FWL_WidgetHit::HyperLink;
}
return FWL_WidgetHit::Unknown;
}
WideString CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) {
CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
if (!pTextLayout)
return WideString();
CFX_RectF rect = GetRectWithoutRotate();
return pTextLayout->GetLinkURLAtPoint(point - rect.TopLeft());
}