// 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/app/xfa_fftext.h" #include "xfa/fwl/core/fwl_widgetdef.h" #include "xfa/fxfa/app/xfa_ffdraw.h" #include "xfa/fxfa/app/xfa_textlayout.h" #include "xfa/fxfa/include/xfa_ffapp.h" #include "xfa/fxfa/include/xfa_ffdoc.h" #include "xfa/fxfa/include/xfa_ffpageview.h" #include "xfa/fxfa/include/xfa_ffwidget.h" #include "xfa/fxgraphics/include/cfx_graphics.h" CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc) : CXFA_FFDraw(pPageView, pDataAcc) {} CXFA_FFText::~CXFA_FFText() {} void CXFA_FFText::RenderWidget(CFX_Graphics* pGS, CFX_Matrix* pMatrix, uint32_t dwStatus) { if (!IsMatchVisibleStatus(dwStatus)) { return; } { CFX_Matrix mtRotate; GetRotateMatrix(mtRotate); if (pMatrix) { mtRotate.Concat(*pMatrix); } CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); if (pTextLayout) { CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); CFX_RectF rtText; GetRectWithoutRotate(rtText); if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { CXFA_LayoutItem* pItem = this; if (!pItem->GetPrev() && !pItem->GetNext()) { XFA_RectWidthoutMargin(rtText, mgWidget); } else { FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0; mgWidget.GetLeftInset(fLeftInset); mgWidget.GetRightInset(fRightInset); if (!pItem->GetPrev()) { mgWidget.GetTopInset(fTopInset); } else if (!pItem->GetNext()) { mgWidget.GetBottomInset(fBottomInset); } rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); } } CFX_Matrix mt; mt.Set(1, 0, 0, 1, rtText.left, rtText.top); CFX_RectF rtClip = rtText; mtRotate.TransformRect(rtClip); mt.Concat(mtRotate); pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex()); } } } FX_BOOL CXFA_FFText::IsLoaded() { CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); return pTextLayout && !pTextLayout->m_bHasBlock; } FX_BOOL CXFA_FFText::PerformLayout() { CXFA_FFDraw::PerformLayout(); CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); if (!pTextLayout) { return FALSE; } if (!pTextLayout->m_bHasBlock) { return TRUE; } pTextLayout->m_Blocks.RemoveAll(); CXFA_LayoutItem* pItem = this; if (!pItem->GetPrev() && !pItem->GetNext()) { return TRUE; } pItem = pItem->GetFirst(); while (pItem) { CFX_RectF rtText; pItem->GetRect(rtText); if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { if (!pItem->GetPrev()) { FX_FLOAT fTopInset; mgWidget.GetTopInset(fTopInset); rtText.height -= fTopInset; } else if (!pItem->GetNext()) { FX_FLOAT fBottomInset; mgWidget.GetBottomInset(fBottomInset); rtText.height -= fBottomInset; } } pTextLayout->ItemBlocks(rtText, pItem->GetIndex()); pItem = pItem->GetNext(); } pTextLayout->m_bHasBlock = FALSE; return TRUE; } FX_BOOL CXFA_FFText::OnLButtonDown(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) { CFX_RectF rtBox; GetRectWithoutRotate(rtBox); if (!rtBox.Contains(fx, fy)) { return FALSE; } const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); if (!wsURLContent) { return FALSE; } SetButtonDown(TRUE); return TRUE; } FX_BOOL CXFA_FFText::OnMouseMove(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) { CFX_RectF rtBox; GetRectWithoutRotate(rtBox); if (!rtBox.Contains(fx, fy)) { return FALSE; } const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); if (!wsURLContent) { return FALSE; } return TRUE; } FX_BOOL CXFA_FFText::OnLButtonUp(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) { if (!IsButtonDown()) { return FALSE; } SetButtonDown(FALSE); const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); if (!wsURLContent) { return FALSE; } CXFA_FFDoc* pDoc = GetDoc(); pDoc->GetDocProvider()->GotoURL(pDoc, wsURLContent, FALSE); return TRUE; } FWL_WidgetHit CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { CFX_RectF rtBox; GetRectWithoutRotate(rtBox); if (!rtBox.Contains(fx, fy)) return FWL_WidgetHit::Unknown; if (!GetLinkURLAtPoint(fx, fy)) return FWL_WidgetHit::Unknown; return FWL_WidgetHit::HyperLink; } const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) { CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); if (!pTextLayout) { return nullptr; } FX_FLOAT x(fx), y(fy); FWLToClient(x, y); const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines(); int32_t iCount = pPieceLines->GetSize(); for (int32_t i = 0; i < iCount; i++) { CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i); int32_t iPieces = pPieceLine->m_textPieces.GetSize(); for (int32_t j = 0; j < iPieces; j++) { XFA_TextPiece* pPiece = pPieceLine->m_textPieces.GetAt(j); if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) { return pPiece->pLinkData->GetLinkURL(); } } } return nullptr; } void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) { CFX_RectF rtWidget; GetRectWithoutRotate(rtWidget); fx -= rtWidget.left; fy -= rtWidget.top; }