| // 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/src/foxitlib.h" |
| #include "xfa/src/fxfa/src/common/xfa_common.h" |
| #include "xfa_ffwidget.h" |
| #include "xfa_ffdraw.h" |
| #include "xfa_fftext.h" |
| #include "xfa_textlayout.h" |
| #include "xfa_ffpageview.h" |
| #include "xfa_ffdoc.h" |
| #include "xfa_ffapp.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, |
| FX_DWORD dwStatus, |
| int32_t iRotate) { |
| 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() == NULL && pItem->GetNext() == NULL) { |
| XFA_RectWidthoutMargin(rtText, mgWidget); |
| } else { |
| FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0; |
| mgWidget.GetLeftInset(fLeftInset); |
| mgWidget.GetRightInset(fRightInset); |
| if (pItem->GetPrev() == NULL) { |
| mgWidget.GetTopInset(fTopInset); |
| } else if (pItem->GetNext() == NULL) { |
| 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 != NULL && !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() == NULL && pItem->GetNext() == NULL) { |
| return TRUE; |
| } |
| pItem = pItem->GetFirst(); |
| while (pItem) { |
| CFX_RectF rtText; |
| pItem->GetRect(rtText); |
| if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { |
| if (pItem->GetPrev() == NULL) { |
| FX_FLOAT fTopInset; |
| mgWidget.GetTopInset(fTopInset); |
| rtText.height -= fTopInset; |
| } else if (pItem->GetNext() == NULL) { |
| 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(FX_DWORD 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 (NULL == wsURLContent) { |
| return FALSE; |
| } |
| SetButtonDown(TRUE); |
| return TRUE; |
| } |
| FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD 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 (NULL == wsURLContent) { |
| return FALSE; |
| } |
| return TRUE; |
| } |
| FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { |
| if (!IsButtonDown()) { |
| return FALSE; |
| } |
| SetButtonDown(FALSE); |
| const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); |
| if (NULL == wsURLContent) { |
| return FALSE; |
| } |
| CXFA_FFDoc* pDoc = GetDoc(); |
| pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE); |
| return TRUE; |
| } |
| FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { |
| CFX_RectF rtBox; |
| GetRectWithoutRotate(rtBox); |
| if (!rtBox.Contains(fx, fy)) { |
| return FWL_WGTHITTEST_Unknown; |
| } |
| if (!GetLinkURLAtPoint(fx, fy)) { |
| return FWL_WGTHITTEST_Unknown; |
| } |
| return FWL_WGTHITTEST_HyperLink; |
| } |
| const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) { |
| CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); |
| if (NULL == pTextLayout) { |
| return NULL; |
| } |
| 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_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j); |
| if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) { |
| return pPiece->pLinkData->GetLinkURL(); |
| } |
| } |
| } |
| return NULL; |
| } |
| void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) { |
| CFX_RectF rtWidget; |
| GetRectWithoutRotate(rtWidget); |
| fx -= rtWidget.left; |
| fy -= rtWidget.top; |
| } |