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.
165 lines
4.8 KiB
165 lines
4.8 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_fftext.h"
|
|
|
|
#include "xfa/fgas/layout/cfx_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_pieceline.h"
|
|
#include "xfa/fxfa/cxfa_textlayout.h"
|
|
#include "xfa/fxfa/cxfa_textpiece.h"
|
|
#include "xfa/fxfa/parser/cxfa_margin.h"
|
|
#include "xfa/fxgraphics/cxfa_graphics.h"
|
|
|
|
CXFA_FFText::CXFA_FFText(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}
|
|
|
|
CXFA_FFText::~CXFA_FFText() {}
|
|
|
|
void CXFA_FFText::RenderWidget(CXFA_Graphics* 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->GetRect(false);
|
|
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(uint32_t dwFlags,
|
|
const CFX_PointF& point,
|
|
FWL_MouseCommand command) {
|
|
if (command != FWL_MouseCommand::LeftButtonDown)
|
|
return false;
|
|
|
|
if (!GetRectWithoutRotate().Contains(point))
|
|
return false;
|
|
|
|
const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
|
|
if (!wsURLContent)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_FFText::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
|
|
SetButtonDown(true);
|
|
return true;
|
|
}
|
|
|
|
bool CXFA_FFText::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
|
|
return GetRectWithoutRotate().Contains(point) && !!GetLinkURLAtPoint(point);
|
|
}
|
|
|
|
bool CXFA_FFText::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
|
|
if (!IsButtonDown())
|
|
return false;
|
|
|
|
SetButtonDown(false);
|
|
const wchar_t* wsURLContent = GetLinkURLAtPoint(point);
|
|
if (!wsURLContent)
|
|
return false;
|
|
|
|
CXFA_FFDoc* pDoc = GetDoc();
|
|
pDoc->GetDocEnvironment()->GotoURL(pDoc, wsURLContent);
|
|
return true;
|
|
}
|
|
|
|
FWL_WidgetHit CXFA_FFText::HitTest(const CFX_PointF& point) {
|
|
if (!GetRectWithoutRotate().Contains(point))
|
|
return FWL_WidgetHit::Unknown;
|
|
if (!GetLinkURLAtPoint(point))
|
|
return FWL_WidgetHit::Unknown;
|
|
return FWL_WidgetHit::HyperLink;
|
|
}
|
|
|
|
const wchar_t* CXFA_FFText::GetLinkURLAtPoint(const CFX_PointF& point) {
|
|
CXFA_TextLayout* pTextLayout = m_pNode->GetTextLayout();
|
|
if (!pTextLayout)
|
|
return nullptr;
|
|
|
|
CFX_RectF rect = GetRectWithoutRotate();
|
|
for (const auto& pPieceLine : *pTextLayout->GetPieceLines()) {
|
|
for (const auto& pPiece : pPieceLine->m_textPieces) {
|
|
if (pPiece->pLinkData &&
|
|
pPiece->rtPiece.Contains(point - rect.TopLeft())) {
|
|
return pPiece->pLinkData->GetLinkURL();
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|