1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "xfa/src/foxitlib.h" 8 #include "xfa/src/fxfa/src/common/xfa_common.h" 9 #include "xfa_ffwidget.h" 10 #include "xfa_ffdraw.h" 11 #include "xfa_fftext.h" 12 #include "xfa_textlayout.h" 13 #include "xfa_ffpageview.h" 14 #include "xfa_ffdoc.h" 15 #include "xfa_ffapp.h" 16 CXFA_FFText::CXFA_FFText(CXFA_FFPageView* pPageView, CXFA_WidgetAcc* pDataAcc) 17 : CXFA_FFDraw(pPageView, pDataAcc) {} 18 CXFA_FFText::~CXFA_FFText() {} 19 void CXFA_FFText::RenderWidget(CFX_Graphics* pGS, 20 CFX_Matrix* pMatrix, 21 FX_DWORD dwStatus, 22 int32_t iRotate) { 23 if (!IsMatchVisibleStatus(dwStatus)) { 24 return; 25 } 26 { 27 CFX_Matrix mtRotate; 28 GetRotateMatrix(mtRotate); 29 if (pMatrix) { 30 mtRotate.Concat(*pMatrix); 31 } 32 CXFA_FFWidget::RenderWidget(pGS, &mtRotate, dwStatus); 33 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); 34 if (pTextLayout) { 35 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); 36 CFX_RectF rtText; 37 GetRectWithoutRotate(rtText); 38 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { 39 CXFA_LayoutItem* pItem = this; 40 if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) { 41 XFA_RectWidthoutMargin(rtText, mgWidget); 42 } else { 43 FX_FLOAT fLeftInset, fRightInset, fTopInset = 0, fBottomInset = 0; 44 mgWidget.GetLeftInset(fLeftInset); 45 mgWidget.GetRightInset(fRightInset); 46 if (pItem->GetPrev() == NULL) { 47 mgWidget.GetTopInset(fTopInset); 48 } else if (pItem->GetNext() == NULL) { 49 mgWidget.GetBottomInset(fBottomInset); 50 } 51 rtText.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); 52 } 53 } 54 CFX_Matrix mt; 55 mt.Set(1, 0, 0, 1, rtText.left, rtText.top); 56 CFX_RectF rtClip = rtText; 57 mtRotate.TransformRect(rtClip); 58 mt.Concat(mtRotate); 59 pTextLayout->DrawString(pRenderDevice, mt, rtClip, GetIndex()); 60 } 61 } 62 } 63 FX_BOOL CXFA_FFText::IsLoaded() { 64 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); 65 return pTextLayout != NULL && !pTextLayout->m_bHasBlock; 66 } 67 FX_BOOL CXFA_FFText::PerformLayout() { 68 CXFA_FFDraw::PerformLayout(); 69 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); 70 if (!pTextLayout) { 71 return FALSE; 72 } 73 if (!pTextLayout->m_bHasBlock) { 74 return TRUE; 75 } 76 pTextLayout->m_Blocks.RemoveAll(); 77 CXFA_LayoutItem* pItem = this; 78 if (pItem->GetPrev() == NULL && pItem->GetNext() == NULL) { 79 return TRUE; 80 } 81 pItem = pItem->GetFirst(); 82 while (pItem) { 83 CFX_RectF rtText; 84 pItem->GetRect(rtText); 85 if (CXFA_Margin mgWidget = m_pDataAcc->GetMargin()) { 86 if (pItem->GetPrev() == NULL) { 87 FX_FLOAT fTopInset; 88 mgWidget.GetTopInset(fTopInset); 89 rtText.height -= fTopInset; 90 } else if (pItem->GetNext() == NULL) { 91 FX_FLOAT fBottomInset; 92 mgWidget.GetBottomInset(fBottomInset); 93 rtText.height -= fBottomInset; 94 } 95 } 96 pTextLayout->ItemBlocks(rtText, pItem->GetIndex()); 97 pItem = pItem->GetNext(); 98 } 99 pTextLayout->m_bHasBlock = FALSE; 100 return TRUE; 101 } 102 FX_BOOL CXFA_FFText::OnLButtonDown(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { 103 CFX_RectF rtBox; 104 GetRectWithoutRotate(rtBox); 105 if (!rtBox.Contains(fx, fy)) { 106 return FALSE; 107 } 108 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); 109 if (NULL == wsURLContent) { 110 return FALSE; 111 } 112 SetButtonDown(TRUE); 113 return TRUE; 114 } 115 FX_BOOL CXFA_FFText::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { 116 CFX_RectF rtBox; 117 GetRectWithoutRotate(rtBox); 118 if (!rtBox.Contains(fx, fy)) { 119 return FALSE; 120 } 121 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); 122 if (NULL == wsURLContent) { 123 return FALSE; 124 } 125 return TRUE; 126 } 127 FX_BOOL CXFA_FFText::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { 128 if (!IsButtonDown()) { 129 return FALSE; 130 } 131 SetButtonDown(FALSE); 132 const FX_WCHAR* wsURLContent = GetLinkURLAtPoint(fx, fy); 133 if (NULL == wsURLContent) { 134 return FALSE; 135 } 136 CXFA_FFDoc* pDoc = GetDoc(); 137 pDoc->GetDocProvider()->GotoURL(pDoc, CFX_WideStringC(wsURLContent), FALSE); 138 return TRUE; 139 } 140 FX_DWORD CXFA_FFText::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { 141 CFX_RectF rtBox; 142 GetRectWithoutRotate(rtBox); 143 if (!rtBox.Contains(fx, fy)) { 144 return FWL_WGTHITTEST_Unknown; 145 } 146 if (!GetLinkURLAtPoint(fx, fy)) { 147 return FWL_WGTHITTEST_Unknown; 148 } 149 return FWL_WGTHITTEST_HyperLink; 150 } 151 const FX_WCHAR* CXFA_FFText::GetLinkURLAtPoint(FX_FLOAT fx, FX_FLOAT fy) { 152 CXFA_TextLayout* pTextLayout = m_pDataAcc->GetTextLayout(); 153 if (NULL == pTextLayout) { 154 return NULL; 155 } 156 FX_FLOAT x(fx), y(fy); 157 FWLToClient(x, y); 158 const CXFA_PieceLineArray* pPieceLines = pTextLayout->GetPieceLines(); 159 int32_t iCount = pPieceLines->GetSize(); 160 for (int32_t i = 0; i < iCount; i++) { 161 CXFA_PieceLine* pPieceLine = pPieceLines->GetAt(i); 162 int32_t iPieces = pPieceLine->m_textPieces.GetSize(); 163 for (int32_t j = 0; j < iPieces; j++) { 164 XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j); 165 if (pPiece->pLinkData && pPiece->rtPiece.Contains(x, y)) { 166 return pPiece->pLinkData->GetLinkURL(); 167 } 168 } 169 } 170 return NULL; 171 } 172 void CXFA_FFText::FWLToClient(FX_FLOAT& fx, FX_FLOAT& fy) { 173 CFX_RectF rtWidget; 174 GetRectWithoutRotate(rtWidget); 175 fx -= rtWidget.left; 176 fy -= rtWidget.top; 177 } 178