| OLD | NEW |
| (Empty) |
| 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/fxfa/app/xfa_ffwidget.h" | |
| 8 | |
| 9 #include <algorithm> | |
| 10 | |
| 11 #include "core/include/fpdfapi/fpdf_page.h" | |
| 12 #include "core/include/fxcodec/fx_codec.h" | |
| 13 #include "xfa/include/fxgraphics/fx_graphics.h" | |
| 14 #include "xfa/src/fxfa/app/xfa_ffapp.h" | |
| 15 #include "xfa/src/fxfa/app/xfa_ffdoc.h" | |
| 16 #include "xfa/src/fxfa/app/xfa_ffdocview.h" | |
| 17 #include "xfa/src/fxfa/app/xfa_ffpageview.h" | |
| 18 #include "xfa/src/fxfa/app/xfa_textlayout.h" | |
| 19 | |
| 20 CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView, | |
| 21 CXFA_WidgetAcc* pDataAcc) | |
| 22 : CXFA_ContentLayoutItem(pDataAcc->GetNode()), | |
| 23 m_pPageView(pPageView), | |
| 24 m_pDataAcc(pDataAcc) { | |
| 25 m_rtWidget.Set(0, 0, 0, 0); | |
| 26 } | |
| 27 CXFA_FFWidget::~CXFA_FFWidget() {} | |
| 28 IXFA_PageView* CXFA_FFWidget::GetPageView() { | |
| 29 return m_pPageView; | |
| 30 } | |
| 31 void CXFA_FFWidget::SetPageView(IXFA_PageView* pPageView) { | |
| 32 m_pPageView = static_cast<CXFA_FFPageView*>(pPageView); | |
| 33 } | |
| 34 void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) { | |
| 35 if ((m_dwStatus & XFA_WIDGETSTATUS_RectCached) == 0) { | |
| 36 m_dwStatus |= XFA_WIDGETSTATUS_RectCached; | |
| 37 GetRect(m_rtWidget); | |
| 38 } | |
| 39 rtWidget = m_rtWidget; | |
| 40 } | |
| 41 CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() { | |
| 42 m_dwStatus |= XFA_WIDGETSTATUS_RectCached; | |
| 43 GetRect(m_rtWidget); | |
| 44 return m_rtWidget; | |
| 45 } | |
| 46 void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) { | |
| 47 GetWidgetRect(rtWidget); | |
| 48 FX_FLOAT fValue = 0; | |
| 49 switch (m_pDataAcc->GetRotate()) { | |
| 50 case 90: | |
| 51 rtWidget.top = rtWidget.bottom(); | |
| 52 fValue = rtWidget.width; | |
| 53 rtWidget.width = rtWidget.height; | |
| 54 rtWidget.height = fValue; | |
| 55 break; | |
| 56 case 180: | |
| 57 rtWidget.left = rtWidget.right(); | |
| 58 rtWidget.top = rtWidget.bottom(); | |
| 59 break; | |
| 60 case 270: | |
| 61 rtWidget.left = rtWidget.right(); | |
| 62 fValue = rtWidget.width; | |
| 63 rtWidget.width = rtWidget.height; | |
| 64 rtWidget.height = fValue; | |
| 65 break; | |
| 66 } | |
| 67 } | |
| 68 FX_DWORD CXFA_FFWidget::GetStatus() { | |
| 69 return m_dwStatus; | |
| 70 } | |
| 71 | |
| 72 void CXFA_FFWidget::ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved) { | |
| 73 m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; | |
| 74 } | |
| 75 | |
| 76 FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox, | |
| 77 FX_DWORD dwStatus, | |
| 78 FX_BOOL bDrawFocus) { | |
| 79 if (bDrawFocus) | |
| 80 return FALSE; | |
| 81 if (m_pPageView) | |
| 82 m_pPageView->GetPageViewRect(rtBox); | |
| 83 return TRUE; | |
| 84 } | |
| 85 | |
| 86 CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() { | |
| 87 return m_pDataAcc; | |
| 88 } | |
| 89 FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) { | |
| 90 if (CXFA_Assist assist = m_pDataAcc->GetAssist()) { | |
| 91 if (CXFA_ToolTip toolTip = assist.GetToolTip()) { | |
| 92 return toolTip.GetTip(wsToolTip); | |
| 93 } | |
| 94 } | |
| 95 return GetCaptionText(wsToolTip); | |
| 96 } | |
| 97 void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS, | |
| 98 CFX_Matrix* pMatrix, | |
| 99 FX_DWORD dwStatus, | |
| 100 int32_t iRotate) { | |
| 101 if (!IsMatchVisibleStatus(dwStatus)) { | |
| 102 return; | |
| 103 } | |
| 104 CXFA_Border border = m_pDataAcc->GetBorder(); | |
| 105 if (border) { | |
| 106 CFX_RectF rtBorder; | |
| 107 GetRectWithoutRotate(rtBorder); | |
| 108 CXFA_Margin margin = border.GetMargin(); | |
| 109 if (margin) { | |
| 110 XFA_RectWidthoutMargin(rtBorder, margin); | |
| 111 } | |
| 112 rtBorder.Normalize(); | |
| 113 DrawBorder(pGS, border, rtBorder, pMatrix); | |
| 114 } | |
| 115 } | |
| 116 FX_BOOL CXFA_FFWidget::IsLoaded() { | |
| 117 return m_pPageView != NULL; | |
| 118 } | |
| 119 FX_BOOL CXFA_FFWidget::LoadWidget() { | |
| 120 PerformLayout(); | |
| 121 return TRUE; | |
| 122 } | |
| 123 void CXFA_FFWidget::UnloadWidget() {} | |
| 124 FX_BOOL CXFA_FFWidget::PerformLayout() { | |
| 125 ReCacheWidgetRect(); | |
| 126 return TRUE; | |
| 127 } | |
| 128 FX_BOOL CXFA_FFWidget::UpdateFWLData() { | |
| 129 return FALSE; | |
| 130 } | |
| 131 void CXFA_FFWidget::UpdateWidgetProperty() {} | |
| 132 void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS, | |
| 133 CXFA_Box box, | |
| 134 const CFX_RectF& rtBorder, | |
| 135 CFX_Matrix* pMatrix, | |
| 136 FX_DWORD dwFlags) { | |
| 137 XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags); | |
| 138 } | |
| 139 void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) { | |
| 140 if (!pRect) { | |
| 141 CFX_RectF rtWidget; | |
| 142 GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); | |
| 143 rtWidget.Inflate(2, 2); | |
| 144 GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget, | |
| 145 XFA_INVALIDATE_CurrentPage); | |
| 146 } else { | |
| 147 GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect, | |
| 148 XFA_INVALIDATE_CurrentPage); | |
| 149 } | |
| 150 } | |
| 151 void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) { | |
| 152 CFX_RectF rtWidget; | |
| 153 if (pRect) { | |
| 154 rtWidget = *pRect; | |
| 155 } else { | |
| 156 GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); | |
| 157 rtWidget.Inflate(2, 2); | |
| 158 } | |
| 159 m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); | |
| 160 } | |
| 161 FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) { | |
| 162 CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout(); | |
| 163 if (!pCapTextlayout) { | |
| 164 return FALSE; | |
| 165 } | |
| 166 pCapTextlayout->GetText(wsCap); | |
| 167 return TRUE; | |
| 168 } | |
| 169 FX_BOOL CXFA_FFWidget::IsFocused() { | |
| 170 return m_dwStatus & XFA_WIDGETSTATUS_Focused; | |
| 171 } | |
| 172 FX_BOOL CXFA_FFWidget::OnMouseEnter() { | |
| 173 return FALSE; | |
| 174 } | |
| 175 FX_BOOL CXFA_FFWidget::OnMouseExit() { | |
| 176 return FALSE; | |
| 177 } | |
| 178 FX_BOOL CXFA_FFWidget::OnLButtonDown(FX_DWORD dwFlags, | |
| 179 FX_FLOAT fx, | |
| 180 FX_FLOAT fy) { | |
| 181 return FALSE; | |
| 182 } | |
| 183 FX_BOOL CXFA_FFWidget::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
| 184 return FALSE; | |
| 185 } | |
| 186 FX_BOOL CXFA_FFWidget::OnLButtonDblClk(FX_DWORD dwFlags, | |
| 187 FX_FLOAT fx, | |
| 188 FX_FLOAT fy) { | |
| 189 return FALSE; | |
| 190 } | |
| 191 FX_BOOL CXFA_FFWidget::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
| 192 return FALSE; | |
| 193 } | |
| 194 FX_BOOL CXFA_FFWidget::OnMouseWheel(FX_DWORD dwFlags, | |
| 195 int16_t zDelta, | |
| 196 FX_FLOAT fx, | |
| 197 FX_FLOAT fy) { | |
| 198 return FALSE; | |
| 199 } | |
| 200 FX_BOOL CXFA_FFWidget::OnRButtonDown(FX_DWORD dwFlags, | |
| 201 FX_FLOAT fx, | |
| 202 FX_FLOAT fy) { | |
| 203 return FALSE; | |
| 204 } | |
| 205 FX_BOOL CXFA_FFWidget::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
| 206 return FALSE; | |
| 207 } | |
| 208 FX_BOOL CXFA_FFWidget::OnRButtonDblClk(FX_DWORD dwFlags, | |
| 209 FX_FLOAT fx, | |
| 210 FX_FLOAT fy) { | |
| 211 return FALSE; | |
| 212 } | |
| 213 | |
| 214 FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { | |
| 215 CXFA_FFWidget* pParent = GetParent(); | |
| 216 if (pParent && !pParent->IsAncestorOf(pOldWidget)) { | |
| 217 pParent->OnSetFocus(pOldWidget); | |
| 218 } | |
| 219 m_dwStatus |= XFA_WIDGETSTATUS_Focused; | |
| 220 CXFA_EventParam eParam; | |
| 221 eParam.m_eType = XFA_EVENT_Enter; | |
| 222 eParam.m_pTarget = m_pDataAcc; | |
| 223 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam); | |
| 224 return TRUE; | |
| 225 } | |
| 226 FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { | |
| 227 m_dwStatus &= ~XFA_WIDGETSTATUS_Focused; | |
| 228 EventKillFocus(); | |
| 229 if (pNewWidget) { | |
| 230 CXFA_FFWidget* pParent = GetParent(); | |
| 231 if (pParent && !pParent->IsAncestorOf(pNewWidget)) { | |
| 232 pParent->OnKillFocus(pNewWidget); | |
| 233 } | |
| 234 } | |
| 235 return TRUE; | |
| 236 } | |
| 237 FX_BOOL CXFA_FFWidget::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { | |
| 238 return FALSE; | |
| 239 } | |
| 240 FX_BOOL CXFA_FFWidget::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { | |
| 241 return FALSE; | |
| 242 } | |
| 243 FX_BOOL CXFA_FFWidget::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) { | |
| 244 return FALSE; | |
| 245 } | |
| 246 FX_DWORD CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
| 247 return FALSE; | |
| 248 } | |
| 249 FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) { | |
| 250 return FALSE; | |
| 251 } | |
| 252 void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) { | |
| 253 CFX_Matrix mt; | |
| 254 GetRotateMatrix(mt); | |
| 255 if (mt.IsIdentity()) { | |
| 256 return; | |
| 257 } | |
| 258 CFX_Matrix mtReverse; | |
| 259 mtReverse.SetReverse(mt); | |
| 260 mtReverse.TransformPoint(fx, fy); | |
| 261 } | |
| 262 static void XFA_GetMatrix(CFX_Matrix& m, | |
| 263 int32_t iRotate, | |
| 264 int32_t at, | |
| 265 const CFX_RectF& rt) { | |
| 266 if (!iRotate) { | |
| 267 return; | |
| 268 } | |
| 269 FX_FLOAT fAnchorX, fAnchorY; | |
| 270 switch (at) { | |
| 271 case XFA_ATTRIBUTEENUM_TopLeft: | |
| 272 fAnchorX = rt.left, fAnchorY = rt.top; | |
| 273 break; | |
| 274 case XFA_ATTRIBUTEENUM_TopCenter: | |
| 275 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top; | |
| 276 break; | |
| 277 case XFA_ATTRIBUTEENUM_TopRight: | |
| 278 fAnchorX = rt.right(), fAnchorY = rt.top; | |
| 279 break; | |
| 280 case XFA_ATTRIBUTEENUM_MiddleLeft: | |
| 281 fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2; | |
| 282 break; | |
| 283 case XFA_ATTRIBUTEENUM_MiddleCenter: | |
| 284 fAnchorX = (rt.left + rt.right()) / 2, | |
| 285 fAnchorY = (rt.top + rt.bottom()) / 2; | |
| 286 break; | |
| 287 case XFA_ATTRIBUTEENUM_MiddleRight: | |
| 288 fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2; | |
| 289 break; | |
| 290 case XFA_ATTRIBUTEENUM_BottomLeft: | |
| 291 fAnchorX = rt.left, fAnchorY = rt.bottom(); | |
| 292 break; | |
| 293 case XFA_ATTRIBUTEENUM_BottomCenter: | |
| 294 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom(); | |
| 295 break; | |
| 296 case XFA_ATTRIBUTEENUM_BottomRight: | |
| 297 fAnchorX = rt.right(), fAnchorY = rt.bottom(); | |
| 298 break; | |
| 299 } | |
| 300 switch (iRotate) { | |
| 301 case 90: | |
| 302 m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY, | |
| 303 m.f = fAnchorX + fAnchorY; | |
| 304 break; | |
| 305 case 180: | |
| 306 m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2, | |
| 307 m.f = fAnchorY * 2; | |
| 308 break; | |
| 309 case 270: | |
| 310 m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY, | |
| 311 m.f = fAnchorY - fAnchorX; | |
| 312 break; | |
| 313 } | |
| 314 } | |
| 315 void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) { | |
| 316 mt.Set(1, 0, 0, 1, 0, 0); | |
| 317 int32_t iRotate = m_pDataAcc->GetRotate(); | |
| 318 if (!iRotate) { | |
| 319 return; | |
| 320 } | |
| 321 CFX_RectF rcWidget; | |
| 322 GetRectWithoutRotate(rcWidget); | |
| 323 XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft; | |
| 324 XFA_GetMatrix(mt, iRotate, at, rcWidget); | |
| 325 } | |
| 326 FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() { | |
| 327 CFX_RectF rtLayout; | |
| 328 GetRectWithoutRotate(rtLayout); | |
| 329 return rtLayout.width < 0.1f && rtLayout.height < 0.1f; | |
| 330 } | |
| 331 CXFA_FFWidget* CXFA_FFWidget::GetParent() { | |
| 332 CXFA_Node* pParentNode = | |
| 333 m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent); | |
| 334 if (pParentNode) { | |
| 335 CXFA_WidgetAcc* pParentWidgetAcc = | |
| 336 (CXFA_WidgetAcc*)pParentNode->GetWidgetData(); | |
| 337 if (pParentWidgetAcc) { | |
| 338 return pParentWidgetAcc->GetNextWidget(NULL); | |
| 339 } | |
| 340 } | |
| 341 return NULL; | |
| 342 } | |
| 343 FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { | |
| 344 if (!pWidget) { | |
| 345 return FALSE; | |
| 346 } | |
| 347 CXFA_Node* pNode = m_pDataAcc->GetNode(); | |
| 348 CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode(); | |
| 349 while (pChildNode) { | |
| 350 if (pChildNode == pNode) { | |
| 351 return TRUE; | |
| 352 } | |
| 353 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent); | |
| 354 } | |
| 355 return FALSE; | |
| 356 } | |
| 357 FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) { | |
| 358 CFX_RectF rtWidget; | |
| 359 GetWidgetRect(rtWidget); | |
| 360 if (rtWidget.Contains(fx, fy)) { | |
| 361 return TRUE; | |
| 362 } | |
| 363 return FALSE; | |
| 364 } | |
| 365 CXFA_FFDocView* CXFA_FFWidget::GetDocView() { | |
| 366 return m_pDocView; | |
| 367 } | |
| 368 CXFA_FFDoc* CXFA_FFWidget::GetDoc() { | |
| 369 return (CXFA_FFDoc*)m_pDocView->GetDoc(); | |
| 370 } | |
| 371 CXFA_FFApp* CXFA_FFWidget::GetApp() { | |
| 372 return GetDoc()->GetApp(); | |
| 373 } | |
| 374 IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { | |
| 375 return GetApp()->GetAppProvider(); | |
| 376 } | |
| 377 void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) { | |
| 378 fMinWidth = fMaxWidth = 0; | |
| 379 FX_FLOAT fWidth = 0; | |
| 380 if (m_pDataAcc->GetWidth(fWidth)) { | |
| 381 fMinWidth = fMaxWidth = fWidth; | |
| 382 } else { | |
| 383 m_pDataAcc->GetMinWidth(fMinWidth); | |
| 384 m_pDataAcc->GetMaxWidth(fMaxWidth); | |
| 385 } | |
| 386 } | |
| 387 void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) { | |
| 388 fMinHeight = fMaxHeight = 0; | |
| 389 FX_FLOAT fHeight = 0; | |
| 390 if (m_pDataAcc->GetHeight(fHeight)) { | |
| 391 fMinHeight = fMaxHeight = fHeight; | |
| 392 } else { | |
| 393 m_pDataAcc->GetMinHeight(fMinHeight); | |
| 394 m_pDataAcc->GetMaxHeight(fMaxHeight); | |
| 395 } | |
| 396 } | |
| 397 FX_BOOL CXFA_FFWidget::IsMatchVisibleStatus(FX_DWORD dwStatus) { | |
| 398 return m_dwStatus & XFA_WIDGETSTATUS_Visible; | |
| 399 } | |
| 400 void CXFA_FFWidget::EventKillFocus() { | |
| 401 if (m_dwStatus & XFA_WIDGETSTATUS_Access) { | |
| 402 m_dwStatus &= ~XFA_WIDGETSTATUS_Access; | |
| 403 return; | |
| 404 } | |
| 405 CXFA_EventParam eParam; | |
| 406 eParam.m_eType = XFA_EVENT_Exit; | |
| 407 eParam.m_pTarget = m_pDataAcc; | |
| 408 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam); | |
| 409 } | |
| 410 FX_BOOL CXFA_FFWidget::IsButtonDown() { | |
| 411 return (m_dwStatus & XFA_WIDGETSTATUS_ButtonDown) != 0; | |
| 412 } | |
| 413 void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) { | |
| 414 bSet ? m_dwStatus |= XFA_WIDGETSTATUS_ButtonDown | |
| 415 : m_dwStatus &= ~XFA_WIDGETSTATUS_ButtonDown; | |
| 416 } | |
| 417 int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, | |
| 418 int32_t iStrokeType, | |
| 419 int32_t iCapType) { | |
| 420 switch (iStrokeType) { | |
| 421 case XFA_ATTRIBUTEENUM_DashDot: { | |
| 422 FX_FLOAT dashArray[] = {4, 1, 2, 1}; | |
| 423 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
| 424 dashArray[1] = 2; | |
| 425 dashArray[3] = 2; | |
| 426 } | |
| 427 pGraphics->SetLineDash(0, dashArray, 4); | |
| 428 return FX_DASHSTYLE_DashDot; | |
| 429 } | |
| 430 case XFA_ATTRIBUTEENUM_DashDotDot: { | |
| 431 FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; | |
| 432 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
| 433 dashArray[1] = 2; | |
| 434 dashArray[3] = 2; | |
| 435 dashArray[5] = 2; | |
| 436 } | |
| 437 pGraphics->SetLineDash(0, dashArray, 6); | |
| 438 return FX_DASHSTYLE_DashDotDot; | |
| 439 } | |
| 440 case XFA_ATTRIBUTEENUM_Dashed: { | |
| 441 FX_FLOAT dashArray[] = {5, 1}; | |
| 442 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
| 443 dashArray[1] = 2; | |
| 444 } | |
| 445 pGraphics->SetLineDash(0, dashArray, 2); | |
| 446 return FX_DASHSTYLE_Dash; | |
| 447 } | |
| 448 case XFA_ATTRIBUTEENUM_Dotted: { | |
| 449 FX_FLOAT dashArray[] = {2, 1}; | |
| 450 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
| 451 dashArray[1] = 2; | |
| 452 } | |
| 453 pGraphics->SetLineDash(0, dashArray, 2); | |
| 454 return FX_DASHSTYLE_Dot; | |
| 455 } | |
| 456 default: | |
| 457 break; | |
| 458 } | |
| 459 pGraphics->SetLineDash(FX_DASHSTYLE_Solid); | |
| 460 return FX_DASHSTYLE_Solid; | |
| 461 } | |
| 462 CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) { | |
| 463 switch (iLineCap) { | |
| 464 case XFA_ATTRIBUTEENUM_Round: | |
| 465 return CFX_GraphStateData::LineCapRound; | |
| 466 case XFA_ATTRIBUTEENUM_Butt: | |
| 467 return CFX_GraphStateData::LineCapButt; | |
| 468 default: | |
| 469 break; | |
| 470 } | |
| 471 return CFX_GraphStateData::LineCapSquare; | |
| 472 } | |
| 473 class CXFA_ImageRenderer { | |
| 474 public: | |
| 475 CXFA_ImageRenderer(); | |
| 476 ~CXFA_ImageRenderer(); | |
| 477 FX_BOOL Start(CFX_RenderDevice* pDevice, | |
| 478 CFX_DIBSource* pDIBSource, | |
| 479 FX_ARGB bitmap_argb, | |
| 480 int bitmap_alpha, | |
| 481 const CFX_Matrix* pImage2Device, | |
| 482 FX_DWORD flags, | |
| 483 int blendType = FXDIB_BLEND_NORMAL); | |
| 484 FX_BOOL Continue(IFX_Pause* pPause); | |
| 485 | |
| 486 protected: | |
| 487 CFX_RenderDevice* m_pDevice; | |
| 488 int m_Status; | |
| 489 CFX_Matrix m_ImageMatrix; | |
| 490 CFX_DIBSource* m_pDIBSource; | |
| 491 CFX_DIBitmap* m_pCloneConvert; | |
| 492 int m_BitmapAlpha; | |
| 493 FX_ARGB m_FillArgb; | |
| 494 FX_DWORD m_Flags; | |
| 495 CFX_ImageTransformer* m_pTransformer; | |
| 496 void* m_DeviceHandle; | |
| 497 int32_t m_BlendType; | |
| 498 FX_BOOL m_Result; | |
| 499 FX_BOOL m_bPrint; | |
| 500 FX_BOOL StartDIBSource(); | |
| 501 void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, | |
| 502 int left, | |
| 503 int top, | |
| 504 FX_ARGB mask_argb, | |
| 505 int bitmap_alpha, | |
| 506 int blend_mode, | |
| 507 int Transparency); | |
| 508 }; | |
| 509 CXFA_ImageRenderer::CXFA_ImageRenderer() { | |
| 510 m_pDevice = NULL; | |
| 511 m_Status = 0; | |
| 512 m_pDIBSource = NULL; | |
| 513 m_pCloneConvert = NULL; | |
| 514 m_BitmapAlpha = 255; | |
| 515 m_FillArgb = 0; | |
| 516 m_Flags = 0; | |
| 517 m_pTransformer = NULL; | |
| 518 m_DeviceHandle = NULL; | |
| 519 m_BlendType = FXDIB_BLEND_NORMAL; | |
| 520 m_Result = TRUE; | |
| 521 m_bPrint = FALSE; | |
| 522 } | |
| 523 CXFA_ImageRenderer::~CXFA_ImageRenderer() { | |
| 524 if (m_pCloneConvert) { | |
| 525 delete m_pCloneConvert; | |
| 526 } | |
| 527 if (m_pTransformer) { | |
| 528 delete m_pTransformer; | |
| 529 } | |
| 530 if (m_DeviceHandle) { | |
| 531 m_pDevice->CancelDIBits(m_DeviceHandle); | |
| 532 } | |
| 533 } | |
| 534 FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, | |
| 535 CFX_DIBSource* pDIBSource, | |
| 536 FX_ARGB bitmap_argb, | |
| 537 int bitmap_alpha, | |
| 538 const CFX_Matrix* pImage2Device, | |
| 539 FX_DWORD flags, | |
| 540 int blendType) { | |
| 541 m_pDevice = pDevice; | |
| 542 m_pDIBSource = pDIBSource; | |
| 543 m_FillArgb = bitmap_argb; | |
| 544 m_BitmapAlpha = bitmap_alpha; | |
| 545 m_ImageMatrix = *pImage2Device; | |
| 546 m_Flags = flags; | |
| 547 m_BlendType = blendType; | |
| 548 return StartDIBSource(); | |
| 549 } | |
| 550 FX_BOOL CXFA_ImageRenderer::StartDIBSource() { | |
| 551 if (m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb, | |
| 552 &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, | |
| 553 m_BlendType)) { | |
| 554 if (m_DeviceHandle) { | |
| 555 m_Status = 3; | |
| 556 return TRUE; | |
| 557 } | |
| 558 return FALSE; | |
| 559 } | |
| 560 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
| 561 FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
| 562 int dest_width = image_rect.Width(); | |
| 563 int dest_height = image_rect.Height(); | |
| 564 if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || | |
| 565 (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { | |
| 566 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
| 567 m_Result = FALSE; | |
| 568 return FALSE; | |
| 569 } | |
| 570 CFX_DIBSource* pDib = m_pDIBSource; | |
| 571 if (m_pDIBSource->HasAlpha() && | |
| 572 !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) && | |
| 573 !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { | |
| 574 m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb); | |
| 575 if (!m_pCloneConvert) { | |
| 576 m_Result = FALSE; | |
| 577 return FALSE; | |
| 578 } | |
| 579 pDib = m_pCloneConvert; | |
| 580 } | |
| 581 FX_RECT clip_box = m_pDevice->GetClipBox(); | |
| 582 clip_box.Intersect(image_rect); | |
| 583 m_Status = 2; | |
| 584 m_pTransformer = new CFX_ImageTransformer; | |
| 585 m_pTransformer->Start(pDib, &m_ImageMatrix, m_Flags, &clip_box); | |
| 586 return TRUE; | |
| 587 } | |
| 588 if (m_ImageMatrix.a < 0) { | |
| 589 dest_width = -dest_width; | |
| 590 } | |
| 591 if (m_ImageMatrix.d > 0) { | |
| 592 dest_height = -dest_height; | |
| 593 } | |
| 594 int dest_left, dest_top; | |
| 595 dest_left = dest_width > 0 ? image_rect.left : image_rect.right; | |
| 596 dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
| 597 if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { | |
| 598 if (m_pDevice->StretchDIBits(m_pDIBSource, dest_left, dest_top, dest_width, | |
| 599 dest_height, m_Flags, NULL, m_BlendType)) { | |
| 600 return FALSE; | |
| 601 } | |
| 602 } | |
| 603 if (m_pDIBSource->IsAlphaMask()) { | |
| 604 if (m_BitmapAlpha != 255) { | |
| 605 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
| 606 } | |
| 607 if (m_pDevice->StretchBitMask(m_pDIBSource, dest_left, dest_top, dest_width, | |
| 608 dest_height, m_FillArgb, m_Flags)) { | |
| 609 return FALSE; | |
| 610 } | |
| 611 } | |
| 612 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
| 613 m_Result = FALSE; | |
| 614 return TRUE; | |
| 615 } | |
| 616 FX_RECT clip_box = m_pDevice->GetClipBox(); | |
| 617 FX_RECT dest_rect = clip_box; | |
| 618 dest_rect.Intersect(image_rect); | |
| 619 FX_RECT dest_clip( | |
| 620 dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, | |
| 621 dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); | |
| 622 CFX_DIBitmap* pStretched = | |
| 623 m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); | |
| 624 if (pStretched) { | |
| 625 CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb, | |
| 626 m_BitmapAlpha, m_BlendType, FALSE); | |
| 627 delete pStretched; | |
| 628 pStretched = NULL; | |
| 629 } | |
| 630 return FALSE; | |
| 631 } | |
| 632 FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) { | |
| 633 if (m_Status == 2) { | |
| 634 if (m_pTransformer->Continue(pPause)) { | |
| 635 return TRUE; | |
| 636 } | |
| 637 CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach(); | |
| 638 if (pBitmap == NULL) { | |
| 639 return FALSE; | |
| 640 } | |
| 641 if (pBitmap->IsAlphaMask()) { | |
| 642 if (m_BitmapAlpha != 255) { | |
| 643 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
| 644 } | |
| 645 m_Result = m_pDevice->SetBitMask(pBitmap, m_pTransformer->m_ResultLeft, | |
| 646 m_pTransformer->m_ResultTop, m_FillArgb); | |
| 647 } else { | |
| 648 if (m_BitmapAlpha != 255) { | |
| 649 pBitmap->MultiplyAlpha(m_BitmapAlpha); | |
| 650 } | |
| 651 m_Result = m_pDevice->SetDIBits(pBitmap, m_pTransformer->m_ResultLeft, | |
| 652 m_pTransformer->m_ResultTop, m_BlendType); | |
| 653 } | |
| 654 delete pBitmap; | |
| 655 return FALSE; | |
| 656 } else if (m_Status == 3) { | |
| 657 return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); | |
| 658 } | |
| 659 return FALSE; | |
| 660 } | |
| 661 void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, | |
| 662 int left, | |
| 663 int top, | |
| 664 FX_ARGB mask_argb, | |
| 665 int bitmap_alpha, | |
| 666 int blend_mode, | |
| 667 int Transparency) { | |
| 668 if (pDIBitmap == NULL) { | |
| 669 return; | |
| 670 } | |
| 671 FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; | |
| 672 FX_BOOL bGroup = Transparency & PDFTRANS_GROUP; | |
| 673 if (blend_mode == FXDIB_BLEND_NORMAL) { | |
| 674 if (!pDIBitmap->IsAlphaMask()) { | |
| 675 if (bitmap_alpha < 255) { | |
| 676 pDIBitmap->MultiplyAlpha(bitmap_alpha); | |
| 677 } | |
| 678 if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { | |
| 679 return; | |
| 680 } | |
| 681 } else { | |
| 682 FX_DWORD fill_argb = (mask_argb); | |
| 683 if (bitmap_alpha < 255) { | |
| 684 ((uint8_t*)&fill_argb)[3] = | |
| 685 ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; | |
| 686 } | |
| 687 if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { | |
| 688 return; | |
| 689 } | |
| 690 } | |
| 691 } | |
| 692 FX_BOOL bBackAlphaRequired = blend_mode && bIsolated; | |
| 693 FX_BOOL bGetBackGround = | |
| 694 ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || | |
| 695 (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && | |
| 696 (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); | |
| 697 if (bGetBackGround) { | |
| 698 if (bIsolated || !bGroup) { | |
| 699 if (pDIBitmap->IsAlphaMask()) { | |
| 700 return; | |
| 701 } | |
| 702 m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode); | |
| 703 } else { | |
| 704 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), | |
| 705 top + pDIBitmap->GetHeight()); | |
| 706 rect.Intersect(m_pDevice->GetClipBox()); | |
| 707 CFX_DIBitmap* pClone = NULL; | |
| 708 FX_BOOL bClone = FALSE; | |
| 709 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { | |
| 710 bClone = TRUE; | |
| 711 pClone = m_pDevice->GetBackDrop()->Clone(&rect); | |
| 712 CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); | |
| 713 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
| 714 pForeBitmap, rect.left, rect.top); | |
| 715 left = left >= 0 ? 0 : left; | |
| 716 top = top >= 0 ? 0 : top; | |
| 717 if (!pDIBitmap->IsAlphaMask()) | |
| 718 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
| 719 pDIBitmap, left, top, blend_mode); | |
| 720 else | |
| 721 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
| 722 pDIBitmap, mask_argb, left, top, blend_mode); | |
| 723 } else { | |
| 724 pClone = pDIBitmap; | |
| 725 } | |
| 726 if (m_pDevice->GetBackDrop()) { | |
| 727 m_pDevice->SetDIBits(pClone, rect.left, rect.top); | |
| 728 } else { | |
| 729 if (pDIBitmap->IsAlphaMask()) { | |
| 730 return; | |
| 731 } | |
| 732 m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); | |
| 733 } | |
| 734 if (bClone) { | |
| 735 delete pClone; | |
| 736 } | |
| 737 } | |
| 738 return; | |
| 739 } | |
| 740 if (pDIBitmap->HasAlpha() && | |
| 741 !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { | |
| 742 CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); | |
| 743 if (!pCloneConvert) { | |
| 744 return; | |
| 745 } | |
| 746 CXFA_ImageRenderer imageRender; | |
| 747 FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, | |
| 748 m_BitmapAlpha, &m_ImageMatrix, m_Flags); | |
| 749 while (bRet) { | |
| 750 bRet = imageRender.Continue(NULL); | |
| 751 } | |
| 752 delete pCloneConvert; | |
| 753 return; | |
| 754 } | |
| 755 } | |
| 756 void XFA_DrawImage(CFX_Graphics* pGS, | |
| 757 const CFX_RectF& rtImage, | |
| 758 CFX_Matrix* pMatrix, | |
| 759 CFX_DIBitmap* pDIBitmap, | |
| 760 int32_t iAspect, | |
| 761 int32_t iImageXDpi, | |
| 762 int32_t iImageYDpi, | |
| 763 int32_t iHorzAlign, | |
| 764 int32_t iVertAlign) { | |
| 765 if (rtImage.IsEmpty()) { | |
| 766 return; | |
| 767 } | |
| 768 if (!pDIBitmap || !pDIBitmap->GetBuffer()) { | |
| 769 return; | |
| 770 } | |
| 771 FX_FLOAT fWidth = | |
| 772 XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi); | |
| 773 FX_FLOAT fHeight = | |
| 774 XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi); | |
| 775 CFX_RectF rtFit; | |
| 776 rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight); | |
| 777 switch (iAspect) { | |
| 778 case XFA_ATTRIBUTEENUM_Fit: { | |
| 779 FX_FLOAT f1 = rtImage.height / rtFit.height; | |
| 780 FX_FLOAT f2 = rtImage.width / rtFit.width; | |
| 781 f1 = std::min(f1, f2); | |
| 782 rtFit.height = rtFit.height * f1; | |
| 783 rtFit.width = rtFit.width * f1; | |
| 784 } break; | |
| 785 case XFA_ATTRIBUTEENUM_Actual: | |
| 786 break; | |
| 787 case XFA_ATTRIBUTEENUM_Height: { | |
| 788 FX_FLOAT f1 = rtImage.height / rtFit.height; | |
| 789 rtFit.height = rtImage.height; | |
| 790 rtFit.width = f1 * rtFit.width; | |
| 791 } break; | |
| 792 case XFA_ATTRIBUTEENUM_None: | |
| 793 rtFit.height = rtImage.height; | |
| 794 rtFit.width = rtImage.width; | |
| 795 break; | |
| 796 case XFA_ATTRIBUTEENUM_Width: { | |
| 797 FX_FLOAT f1 = rtImage.width / rtFit.width; | |
| 798 rtFit.width = rtImage.width; | |
| 799 rtFit.height = rtFit.height * f1; | |
| 800 } break; | |
| 801 } | |
| 802 if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) { | |
| 803 rtFit.left += (rtImage.width - rtFit.width) / 2; | |
| 804 } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) { | |
| 805 rtFit.left = rtImage.right() - rtFit.width; | |
| 806 } | |
| 807 if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) { | |
| 808 rtFit.top += (rtImage.height - rtFit.height) / 2; | |
| 809 } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) { | |
| 810 rtFit.top = rtImage.bottom() - rtImage.height; | |
| 811 } | |
| 812 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); | |
| 813 pRenderDevice->SaveState(); | |
| 814 CFX_PathData path; | |
| 815 path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); | |
| 816 pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING); | |
| 817 CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); | |
| 818 mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top); | |
| 819 mtImage.Concat(*pMatrix); | |
| 820 CXFA_ImageRenderer imageRender; | |
| 821 FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, | |
| 822 FXDIB_INTERPOL); | |
| 823 while (bRet) { | |
| 824 bRet = imageRender.Continue(NULL); | |
| 825 } | |
| 826 pRenderDevice->RestoreState(); | |
| 827 } | |
| 828 | |
| 829 static const uint8_t g_inv_base64[128] = { | |
| 830 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | |
| 831 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | |
| 832 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, | |
| 833 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, | |
| 834 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | |
| 835 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, | |
| 836 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, | |
| 837 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | |
| 838 49, 50, 51, 255, 255, 255, 255, 255, | |
| 839 }; | |
| 840 | |
| 841 static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { | |
| 842 uint8_t* pCP; | |
| 843 int32_t i = 0, j = 0; | |
| 844 if (iLen == 0) { | |
| 845 iLen = FXSYS_strlen((FX_CHAR*)pStr); | |
| 846 } | |
| 847 pCP = FX_Alloc(uint8_t, iLen + 1); | |
| 848 for (; i < iLen; i++) { | |
| 849 if ((pStr[i] & 128) == 0) { | |
| 850 if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { | |
| 851 pCP[j++] = pStr[i]; | |
| 852 } | |
| 853 } | |
| 854 } | |
| 855 pCP[j] = '\0'; | |
| 856 return pCP; | |
| 857 } | |
| 858 static int32_t XFA_Base64Decode(const FX_CHAR* pStr, uint8_t* pOutBuffer) { | |
| 859 if (pStr == NULL) { | |
| 860 return 0; | |
| 861 } | |
| 862 uint8_t* pBuffer = | |
| 863 XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr)); | |
| 864 if (pBuffer == NULL) { | |
| 865 return 0; | |
| 866 } | |
| 867 int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer); | |
| 868 int32_t i = 0, j = 0; | |
| 869 FX_DWORD dwLimb = 0; | |
| 870 for (; i + 3 < iLen; i += 4) { | |
| 871 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || | |
| 872 pBuffer[i + 3] == '=') { | |
| 873 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { | |
| 874 break; | |
| 875 } | |
| 876 if (pBuffer[i + 2] == '=') { | |
| 877 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 6) | | |
| 878 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]]); | |
| 879 pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; | |
| 880 j++; | |
| 881 } else { | |
| 882 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 12) | | |
| 883 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 6) | | |
| 884 ((FX_DWORD)g_inv_base64[pBuffer[i + 2]]); | |
| 885 pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; | |
| 886 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; | |
| 887 j += 2; | |
| 888 } | |
| 889 } else { | |
| 890 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 18) | | |
| 891 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 12) | | |
| 892 ((FX_DWORD)g_inv_base64[pBuffer[i + 2]] << 6) | | |
| 893 ((FX_DWORD)g_inv_base64[pBuffer[i + 3]]); | |
| 894 pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; | |
| 895 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; | |
| 896 pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; | |
| 897 j += 3; | |
| 898 } | |
| 899 } | |
| 900 FX_Free(pBuffer); | |
| 901 return j; | |
| 902 } | |
| 903 static FX_CHAR g_base64_chars[] = | |
| 904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 905 FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { | |
| 906 FX_CHAR* out = NULL; | |
| 907 int i, j; | |
| 908 FX_DWORD limb; | |
| 909 out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5); | |
| 910 for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { | |
| 911 limb = ((FX_DWORD)buf[i] << 16) | ((FX_DWORD)buf[i + 1] << 8) | | |
| 912 ((FX_DWORD)buf[i + 2]); | |
| 913 out[j] = g_base64_chars[(limb >> 18) & 63]; | |
| 914 out[j + 1] = g_base64_chars[(limb >> 12) & 63]; | |
| 915 out[j + 2] = g_base64_chars[(limb >> 6) & 63]; | |
| 916 out[j + 3] = g_base64_chars[(limb)&63]; | |
| 917 } | |
| 918 switch (buf_len - i) { | |
| 919 case 0: | |
| 920 break; | |
| 921 case 1: | |
| 922 limb = ((FX_DWORD)buf[i]); | |
| 923 out[j++] = g_base64_chars[(limb >> 2) & 63]; | |
| 924 out[j++] = g_base64_chars[(limb << 4) & 63]; | |
| 925 out[j++] = '='; | |
| 926 out[j++] = '='; | |
| 927 break; | |
| 928 case 2: | |
| 929 limb = ((FX_DWORD)buf[i] << 8) | ((FX_DWORD)buf[i + 1]); | |
| 930 out[j++] = g_base64_chars[(limb >> 10) & 63]; | |
| 931 out[j++] = g_base64_chars[(limb >> 4) & 63]; | |
| 932 out[j++] = g_base64_chars[(limb << 2) & 63]; | |
| 933 out[j++] = '='; | |
| 934 break; | |
| 935 default: | |
| 936 break; | |
| 937 } | |
| 938 out[j] = '\0'; | |
| 939 return out; | |
| 940 } | |
| 941 FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideStringC& wsType) { | |
| 942 CFX_WideString wsContentType(wsType); | |
| 943 wsContentType.MakeLower(); | |
| 944 if (wsContentType == FX_WSTRC(L"image/jpg")) { | |
| 945 return FXCODEC_IMAGE_JPG; | |
| 946 } | |
| 947 if (wsContentType == FX_WSTRC(L"image/png")) { | |
| 948 return FXCODEC_IMAGE_PNG; | |
| 949 } | |
| 950 if (wsContentType == FX_WSTRC(L"image/gif")) { | |
| 951 return FXCODEC_IMAGE_GIF; | |
| 952 } | |
| 953 if (wsContentType == FX_WSTRC(L"image/bmp")) { | |
| 954 return FXCODEC_IMAGE_BMP; | |
| 955 } | |
| 956 if (wsContentType == FX_WSTRC(L"image/tif")) { | |
| 957 return FXCODEC_IMAGE_TIF; | |
| 958 } | |
| 959 return FXCODEC_IMAGE_UNKNOWN; | |
| 960 } | |
| 961 CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, | |
| 962 CXFA_Image* pImage, | |
| 963 FX_BOOL& bNameImage, | |
| 964 int32_t& iImageXDpi, | |
| 965 int32_t& iImageYDpi) { | |
| 966 CFX_WideString wsHref; | |
| 967 pImage->GetHref(wsHref); | |
| 968 CFX_WideString wsImage; | |
| 969 pImage->GetContent(wsImage); | |
| 970 if (wsHref.IsEmpty() && wsImage.IsEmpty()) { | |
| 971 return NULL; | |
| 972 } | |
| 973 CFX_WideString wsContentType; | |
| 974 pImage->GetContentType(wsContentType); | |
| 975 FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType); | |
| 976 CFX_ByteString bsContent; | |
| 977 uint8_t* pImageBuffer = NULL; | |
| 978 IFX_FileRead* pImageFileRead = NULL; | |
| 979 if (wsImage.GetLength() > 0) { | |
| 980 XFA_ATTRIBUTEENUM iEncoding = | |
| 981 (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding(); | |
| 982 if (iEncoding == XFA_ATTRIBUTEENUM_Base64) { | |
| 983 CFX_ByteString bsData = wsImage.UTF8Encode(); | |
| 984 int32_t iLength = bsData.GetLength(); | |
| 985 pImageBuffer = FX_Alloc(uint8_t, iLength); | |
| 986 int32_t iRead = XFA_Base64Decode((const FX_CHAR*)bsData, pImageBuffer); | |
| 987 if (iRead > 0) { | |
| 988 pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead); | |
| 989 } | |
| 990 } else { | |
| 991 bsContent = CFX_ByteString::FromUnicode(wsImage); | |
| 992 pImageFileRead = FX_CreateMemoryStream( | |
| 993 (uint8_t*)(const uint8_t*)bsContent, bsContent.GetLength()); | |
| 994 } | |
| 995 } else { | |
| 996 CFX_WideString wsURL = wsHref; | |
| 997 if (wsURL.Left(7) != FX_WSTRC(L"http://") && | |
| 998 wsURL.Left(6) != FX_WSTRC(L"ftp://")) { | |
| 999 CFX_DIBitmap* pBitmap = | |
| 1000 pDoc->GetPDFNamedImage(wsURL, iImageXDpi, iImageYDpi); | |
| 1001 if (pBitmap) { | |
| 1002 bNameImage = TRUE; | |
| 1003 return pBitmap; | |
| 1004 } | |
| 1005 } | |
| 1006 pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL); | |
| 1007 } | |
| 1008 if (!pImageFileRead) { | |
| 1009 FX_Free(pImageBuffer); | |
| 1010 return NULL; | |
| 1011 } | |
| 1012 bNameImage = FALSE; | |
| 1013 CFX_DIBitmap* pBitmap = | |
| 1014 XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); | |
| 1015 FX_Free(pImageBuffer); | |
| 1016 pImageFileRead->Release(); | |
| 1017 return pBitmap; | |
| 1018 } | |
| 1019 static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, | |
| 1020 int32_t iComponents, | |
| 1021 int32_t iBitsPerComponent) { | |
| 1022 FXDIB_Format dibFormat = FXDIB_Argb; | |
| 1023 switch (type) { | |
| 1024 case FXCODEC_IMAGE_BMP: | |
| 1025 case FXCODEC_IMAGE_JPG: | |
| 1026 case FXCODEC_IMAGE_TIF: { | |
| 1027 dibFormat = FXDIB_Rgb32; | |
| 1028 int32_t bpp = iComponents * iBitsPerComponent; | |
| 1029 if (bpp <= 24) { | |
| 1030 dibFormat = FXDIB_Rgb; | |
| 1031 } | |
| 1032 } break; | |
| 1033 case FXCODEC_IMAGE_PNG: | |
| 1034 default: | |
| 1035 break; | |
| 1036 } | |
| 1037 return dibFormat; | |
| 1038 } | |
| 1039 CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead, | |
| 1040 FXCODEC_IMAGE_TYPE type, | |
| 1041 int32_t& iImageXDpi, | |
| 1042 int32_t& iImageYDpi) { | |
| 1043 CFX_GEModule* pGeModule = CFX_GEModule::Get(); | |
| 1044 if (!pGeModule) { | |
| 1045 return NULL; | |
| 1046 } | |
| 1047 CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); | |
| 1048 if (!pCodecMgr) { | |
| 1049 return NULL; | |
| 1050 } | |
| 1051 CFX_DIBAttribute dibAttr; | |
| 1052 CFX_DIBitmap* pBitmap = NULL; | |
| 1053 ICodec_ProgressiveDecoder* pProgressiveDecoder = | |
| 1054 pCodecMgr->CreateProgressiveDecoder(); | |
| 1055 pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr); | |
| 1056 switch (dibAttr.m_wDPIUnit) { | |
| 1057 case FXCODEC_RESUNIT_CENTIMETER: | |
| 1058 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); | |
| 1059 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); | |
| 1060 break; | |
| 1061 case FXCODEC_RESUNIT_METER: | |
| 1062 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (FX_FLOAT)100 * 2.54f); | |
| 1063 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_FLOAT)100 * 2.54f); | |
| 1064 break; | |
| 1065 default: | |
| 1066 break; | |
| 1067 } | |
| 1068 iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); | |
| 1069 iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); | |
| 1070 if (pProgressiveDecoder->GetWidth() > 0 && | |
| 1071 pProgressiveDecoder->GetHeight() > 0) { | |
| 1072 type = pProgressiveDecoder->GetType(); | |
| 1073 int32_t iComponents = pProgressiveDecoder->GetNumComponents(); | |
| 1074 int32_t iBpc = pProgressiveDecoder->GetBPC(); | |
| 1075 FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); | |
| 1076 pBitmap = new CFX_DIBitmap(); | |
| 1077 pBitmap->Create(pProgressiveDecoder->GetWidth(), | |
| 1078 pProgressiveDecoder->GetHeight(), dibFormat); | |
| 1079 pBitmap->Clear(0xffffffff); | |
| 1080 int32_t nFrames; | |
| 1081 if ((pProgressiveDecoder->GetFrames(nFrames) == | |
| 1082 FXCODEC_STATUS_DECODE_READY) && | |
| 1083 (nFrames > 0)) { | |
| 1084 pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), | |
| 1085 pBitmap->GetHeight()); | |
| 1086 pProgressiveDecoder->ContinueDecode(); | |
| 1087 } | |
| 1088 } | |
| 1089 delete pProgressiveDecoder; | |
| 1090 return pBitmap; | |
| 1091 } | |
| 1092 void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) { | |
| 1093 if (!mg) { | |
| 1094 return; | |
| 1095 } | |
| 1096 FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; | |
| 1097 mg.GetLeftInset(fLeftInset); | |
| 1098 mg.GetTopInset(fTopInset); | |
| 1099 mg.GetRightInset(fRightInset); | |
| 1100 mg.GetBottomInset(fBottomInset); | |
| 1101 rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); | |
| 1102 } | |
| 1103 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { | |
| 1104 XFA_ELEMENT iType = pLayoutItem->GetFormNode()->GetClassID(); | |
| 1105 if (XFA_IsCreateWidget(iType)) { | |
| 1106 return static_cast<CXFA_FFWidget*>(pLayoutItem); | |
| 1107 } | |
| 1108 return nullptr; | |
| 1109 } | |
| 1110 FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType) { | |
| 1111 return iType == XFA_ELEMENT_Field || iType == XFA_ELEMENT_Draw || | |
| 1112 iType == XFA_ELEMENT_Subform || iType == XFA_ELEMENT_ExclGroup; | |
| 1113 } | |
| 1114 static void XFA_BOX_GetPath_Arc(CXFA_Box box, | |
| 1115 CFX_RectF rtDraw, | |
| 1116 CFX_Path& fillPath, | |
| 1117 FX_DWORD dwFlags) { | |
| 1118 FX_FLOAT a, b; | |
| 1119 a = rtDraw.width / 2.0f; | |
| 1120 b = rtDraw.height / 2.0f; | |
| 1121 if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
| 1122 a = b = std::min(a, b); | |
| 1123 } | |
| 1124 CFX_PointF center = rtDraw.Center(); | |
| 1125 rtDraw.left = center.x - a; | |
| 1126 rtDraw.top = center.y - b; | |
| 1127 rtDraw.width = a + a; | |
| 1128 rtDraw.height = b + b; | |
| 1129 FX_FLOAT startAngle = 0, sweepAngle = 360; | |
| 1130 FX_BOOL bStart = box.GetStartAngle(startAngle); | |
| 1131 FX_BOOL bEnd = box.GetSweepAngle(sweepAngle); | |
| 1132 if (!bStart && !bEnd) { | |
| 1133 fillPath.AddEllipse(rtDraw); | |
| 1134 return; | |
| 1135 } | |
| 1136 startAngle = -startAngle * FX_PI / 180.0f; | |
| 1137 sweepAngle = -sweepAngle * FX_PI / 180.0f; | |
| 1138 fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height, | |
| 1139 startAngle, sweepAngle); | |
| 1140 } | |
| 1141 static void XFA_BOX_GetPath(CXFA_Box box, | |
| 1142 const CXFA_StrokeArray& strokes, | |
| 1143 CFX_RectF rtWidget, | |
| 1144 CFX_Path& path, | |
| 1145 int32_t nIndex, | |
| 1146 FX_BOOL bStart, | |
| 1147 FX_BOOL bCorner) { | |
| 1148 FXSYS_assert(nIndex >= 0 && nIndex < 8); | |
| 1149 FX_BOOL bInverted, bRound; | |
| 1150 FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny, offsetY, offsetX, | |
| 1151 offsetEX, offsetEY; | |
| 1152 CFX_PointF cpStart, cp, cp1, cp2; | |
| 1153 CFX_RectF rtRadius; | |
| 1154 int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; | |
| 1155 CXFA_Corner corner1(strokes[n].GetNode()); | |
| 1156 CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode()); | |
| 1157 fRadius1 = bCorner ? corner1.GetRadius() : 0; | |
| 1158 fRadius2 = bCorner ? corner2.GetRadius() : 0; | |
| 1159 bInverted = corner1.IsInverted(); | |
| 1160 offsetY = 0.0f; | |
| 1161 offsetX = 0.0f; | |
| 1162 bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; | |
| 1163 FX_FLOAT halfAfter = 0.0f; | |
| 1164 FX_FLOAT halfBefore = 0.0f; | |
| 1165 CXFA_Stroke stroke = strokes[nIndex]; | |
| 1166 if (stroke.IsCorner()) { | |
| 1167 CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; | |
| 1168 CXFA_Stroke edgeAfter = strokes[nIndex + 1]; | |
| 1169 if (stroke.IsInverted()) { | |
| 1170 if (!stroke.SameStyles(edgeBefore)) { | |
| 1171 halfBefore = edgeBefore.GetThickness() / 2; | |
| 1172 } | |
| 1173 if (!stroke.SameStyles(edgeAfter)) { | |
| 1174 halfAfter = edgeAfter.GetThickness() / 2; | |
| 1175 } | |
| 1176 } | |
| 1177 } else { | |
| 1178 CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8]; | |
| 1179 CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8]; | |
| 1180 if (!bRound && !bInverted) { | |
| 1181 { halfBefore = edgeBefore.GetThickness() / 2; } | |
| 1182 { halfAfter = edgeAfter.GetThickness() / 2; } | |
| 1183 } | |
| 1184 } | |
| 1185 offsetEX = 0.0f; | |
| 1186 offsetEY = 0.0f; | |
| 1187 if (bRound) { | |
| 1188 sy = FX_PI / 2; | |
| 1189 } | |
| 1190 switch (nIndex) { | |
| 1191 case 0: | |
| 1192 case 1: | |
| 1193 cp1 = rtWidget.TopLeft(); | |
| 1194 cp2 = rtWidget.TopRight(); | |
| 1195 if (nIndex == 0) { | |
| 1196 cpStart.x = cp1.x - halfBefore; | |
| 1197 cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; | |
| 1198 } else { | |
| 1199 cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, | |
| 1200 offsetEX = halfAfter; | |
| 1201 } | |
| 1202 vx = 1, vy = 1; | |
| 1203 nx = -1, ny = 0; | |
| 1204 if (bRound) { | |
| 1205 sx = bInverted ? FX_PI / 2 : FX_PI; | |
| 1206 } else { | |
| 1207 sx = 1, sy = 0; | |
| 1208 } | |
| 1209 break; | |
| 1210 case 2: | |
| 1211 case 3: | |
| 1212 cp1 = rtWidget.TopRight(); | |
| 1213 cp2 = rtWidget.BottomRight(); | |
| 1214 if (nIndex == 2) { | |
| 1215 cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, | |
| 1216 offsetX = halfAfter; | |
| 1217 } else { | |
| 1218 cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, | |
| 1219 offsetEY = halfAfter; | |
| 1220 } | |
| 1221 vx = -1, vy = 1; | |
| 1222 nx = 0, ny = -1; | |
| 1223 if (bRound) { | |
| 1224 sx = bInverted ? FX_PI : FX_PI * 3 / 2; | |
| 1225 } else { | |
| 1226 sx = 0, sy = 1; | |
| 1227 } | |
| 1228 break; | |
| 1229 case 4: | |
| 1230 case 5: | |
| 1231 cp1 = rtWidget.BottomRight(); | |
| 1232 cp2 = rtWidget.BottomLeft(); | |
| 1233 if (nIndex == 4) { | |
| 1234 cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, | |
| 1235 offsetY = halfAfter; | |
| 1236 } else { | |
| 1237 cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, | |
| 1238 offsetEX = -halfAfter; | |
| 1239 } | |
| 1240 vx = -1, vy = -1; | |
| 1241 nx = 1, ny = 0; | |
| 1242 if (bRound) { | |
| 1243 sx = bInverted ? FX_PI * 3 / 2 : 0; | |
| 1244 } else { | |
| 1245 sx = -1, sy = 0; | |
| 1246 } | |
| 1247 break; | |
| 1248 case 6: | |
| 1249 case 7: | |
| 1250 cp1 = rtWidget.BottomLeft(); | |
| 1251 cp2 = rtWidget.TopLeft(); | |
| 1252 if (nIndex == 6) { | |
| 1253 cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, | |
| 1254 offsetX = -halfAfter; | |
| 1255 } else { | |
| 1256 cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, | |
| 1257 offsetEY = -halfAfter; | |
| 1258 } | |
| 1259 vx = 1, vy = -1; | |
| 1260 nx = 0, ny = 1; | |
| 1261 if (bRound) { | |
| 1262 sx = bInverted ? 0 : FX_PI / 2; | |
| 1263 } else { | |
| 1264 sx = 0, sy = -1; | |
| 1265 } | |
| 1266 break; | |
| 1267 } | |
| 1268 if (bStart) { | |
| 1269 path.MoveTo(cpStart.x, cpStart.y); | |
| 1270 } | |
| 1271 if (nIndex & 1) { | |
| 1272 path.LineTo(cp2.x + fRadius2 * nx + offsetEX, | |
| 1273 cp2.y + fRadius2 * ny + offsetEY); | |
| 1274 return; | |
| 1275 } | |
| 1276 if (bRound) { | |
| 1277 if (fRadius1 < 0) { | |
| 1278 sx -= FX_PI; | |
| 1279 } | |
| 1280 if (bInverted) { | |
| 1281 sy *= -1; | |
| 1282 } | |
| 1283 rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2, | |
| 1284 fRadius1 * 2 * vx - offsetX * 2, | |
| 1285 fRadius1 * 2 * vy - offsetY * 2); | |
| 1286 rtRadius.Normalize(); | |
| 1287 if (bInverted) { | |
| 1288 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); | |
| 1289 } | |
| 1290 path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx, | |
| 1291 sy); | |
| 1292 } else { | |
| 1293 if (bInverted) { | |
| 1294 cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; | |
| 1295 } else { | |
| 1296 cp = cp1; | |
| 1297 } | |
| 1298 path.LineTo(cp.x, cp.y); | |
| 1299 path.LineTo(cp1.x + fRadius1 * sx + offsetX, | |
| 1300 cp1.y + fRadius1 * sy + offsetY); | |
| 1301 } | |
| 1302 } | |
| 1303 static void XFA_BOX_GetFillPath(CXFA_Box box, | |
| 1304 const CXFA_StrokeArray& strokes, | |
| 1305 CFX_RectF rtWidget, | |
| 1306 CFX_Path& fillPath, | |
| 1307 FX_WORD dwFlags) { | |
| 1308 if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
| 1309 CXFA_Edge edge = box.GetEdge(0); | |
| 1310 FX_FLOAT fThickness = edge.GetThickness(); | |
| 1311 if (fThickness < 0) { | |
| 1312 fThickness = 0; | |
| 1313 } | |
| 1314 FX_FLOAT fHalf = fThickness / 2; | |
| 1315 int32_t iHand = box.GetHand(); | |
| 1316 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1317 rtWidget.Inflate(fHalf, fHalf); | |
| 1318 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1319 rtWidget.Deflate(fHalf, fHalf); | |
| 1320 } | |
| 1321 XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags); | |
| 1322 return; | |
| 1323 } | |
| 1324 FX_BOOL bSameStyles = TRUE; | |
| 1325 int32_t i; | |
| 1326 CXFA_Stroke stroke1 = strokes[0]; | |
| 1327 for (i = 1; i < 8; i++) { | |
| 1328 CXFA_Stroke stroke2 = strokes[i]; | |
| 1329 if (!stroke1.SameStyles(stroke2)) { | |
| 1330 bSameStyles = FALSE; | |
| 1331 break; | |
| 1332 } | |
| 1333 stroke1 = stroke2; | |
| 1334 } | |
| 1335 if (bSameStyles) { | |
| 1336 stroke1 = strokes[0]; | |
| 1337 for (i = 2; i < 8; i += 2) { | |
| 1338 CXFA_Stroke stroke2 = strokes[i]; | |
| 1339 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | | |
| 1340 XFA_STROKE_SAMESTYLE_Corner)) { | |
| 1341 bSameStyles = FALSE; | |
| 1342 break; | |
| 1343 } | |
| 1344 stroke1 = stroke2; | |
| 1345 } | |
| 1346 if (bSameStyles) { | |
| 1347 stroke1 = strokes[0]; | |
| 1348 if (stroke1.IsInverted()) { | |
| 1349 bSameStyles = FALSE; | |
| 1350 } | |
| 1351 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { | |
| 1352 bSameStyles = FALSE; | |
| 1353 } | |
| 1354 } | |
| 1355 } | |
| 1356 if (bSameStyles) { | |
| 1357 fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, | |
| 1358 rtWidget.height); | |
| 1359 return; | |
| 1360 } | |
| 1361 FX_BOOL bInverted, bRound; | |
| 1362 FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny; | |
| 1363 CFX_PointF cp, cp1, cp2; | |
| 1364 CFX_RectF rtRadius; | |
| 1365 for (int32_t i = 0; i < 8; i += 2) { | |
| 1366 CXFA_Corner corner1(strokes[i].GetNode()); | |
| 1367 CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode()); | |
| 1368 fRadius1 = corner1.GetRadius(); | |
| 1369 fRadius2 = corner2.GetRadius(); | |
| 1370 bInverted = corner1.IsInverted(); | |
| 1371 bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; | |
| 1372 if (bRound) { | |
| 1373 sy = FX_PI / 2; | |
| 1374 } | |
| 1375 switch (i) { | |
| 1376 case 0: | |
| 1377 cp1 = rtWidget.TopLeft(); | |
| 1378 cp2 = rtWidget.TopRight(); | |
| 1379 vx = 1, vy = 1; | |
| 1380 nx = -1, ny = 0; | |
| 1381 if (bRound) { | |
| 1382 sx = bInverted ? FX_PI / 2 : FX_PI; | |
| 1383 } else { | |
| 1384 sx = 1, sy = 0; | |
| 1385 } | |
| 1386 break; | |
| 1387 case 2: | |
| 1388 cp1 = rtWidget.TopRight(); | |
| 1389 cp2 = rtWidget.BottomRight(); | |
| 1390 vx = -1, vy = 1; | |
| 1391 nx = 0, ny = -1; | |
| 1392 if (bRound) { | |
| 1393 sx = bInverted ? FX_PI : FX_PI * 3 / 2; | |
| 1394 } else { | |
| 1395 sx = 0, sy = 1; | |
| 1396 } | |
| 1397 break; | |
| 1398 case 4: | |
| 1399 cp1 = rtWidget.BottomRight(); | |
| 1400 cp2 = rtWidget.BottomLeft(); | |
| 1401 vx = -1, vy = -1; | |
| 1402 nx = 1, ny = 0; | |
| 1403 if (bRound) { | |
| 1404 sx = bInverted ? FX_PI * 3 / 2 : 0; | |
| 1405 } else { | |
| 1406 sx = -1, sy = 0; | |
| 1407 } | |
| 1408 break; | |
| 1409 case 6: | |
| 1410 cp1 = rtWidget.BottomLeft(); | |
| 1411 cp2 = rtWidget.TopLeft(); | |
| 1412 vx = 1, vy = -1; | |
| 1413 nx = 0, ny = 1; | |
| 1414 if (bRound) { | |
| 1415 sx = bInverted ? 0 : FX_PI / 2; | |
| 1416 } else { | |
| 1417 sx = 0, sy = -1; | |
| 1418 } | |
| 1419 break; | |
| 1420 } | |
| 1421 if (i == 0) { | |
| 1422 fillPath.MoveTo(cp1.x, cp1.y + fRadius1); | |
| 1423 } | |
| 1424 if (bRound) { | |
| 1425 if (fRadius1 < 0) { | |
| 1426 sx -= FX_PI; | |
| 1427 } | |
| 1428 if (bInverted) { | |
| 1429 sy *= -1; | |
| 1430 } | |
| 1431 rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); | |
| 1432 rtRadius.Normalize(); | |
| 1433 if (bInverted) { | |
| 1434 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); | |
| 1435 } | |
| 1436 fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, | |
| 1437 rtRadius.height, sx, sy); | |
| 1438 } else { | |
| 1439 if (bInverted) { | |
| 1440 cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; | |
| 1441 } else { | |
| 1442 cp = cp1; | |
| 1443 } | |
| 1444 fillPath.LineTo(cp.x, cp.y); | |
| 1445 fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy); | |
| 1446 } | |
| 1447 fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny); | |
| 1448 } | |
| 1449 } | |
| 1450 static void XFA_BOX_Fill_Radial(CXFA_Box box, | |
| 1451 CFX_Graphics* pGS, | |
| 1452 CFX_Path& fillPath, | |
| 1453 CFX_RectF rtFill, | |
| 1454 CFX_Matrix* pMatrix) { | |
| 1455 CXFA_Fill fill = box.GetFill(); | |
| 1456 FX_ARGB crStart, crEnd; | |
| 1457 crStart = fill.GetColor(); | |
| 1458 int32_t iType = fill.GetRadial(crEnd); | |
| 1459 CFX_Shading shading; | |
| 1460 if (iType != XFA_ATTRIBUTEENUM_ToEdge) { | |
| 1461 FX_ARGB temp = crEnd; | |
| 1462 crEnd = crStart; | |
| 1463 crStart = temp; | |
| 1464 } | |
| 1465 shading.CreateRadial(rtFill.Center(), rtFill.Center(), 0, | |
| 1466 FXSYS_sqrt(rtFill.Width() * rtFill.Width() + | |
| 1467 rtFill.Height() * rtFill.Height()) / | |
| 1468 2, | |
| 1469 TRUE, TRUE, crStart, crEnd); | |
| 1470 CFX_Color cr(&shading); | |
| 1471 pGS->SetFillColor(&cr); | |
| 1472 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
| 1473 } | |
| 1474 static void XFA_BOX_Fill_Pattern(CXFA_Box box, | |
| 1475 CFX_Graphics* pGS, | |
| 1476 CFX_Path& fillPath, | |
| 1477 CFX_RectF rtFill, | |
| 1478 CFX_Matrix* pMatrix) { | |
| 1479 CXFA_Fill fill = box.GetFill(); | |
| 1480 FX_ARGB crStart, crEnd; | |
| 1481 crStart = fill.GetColor(); | |
| 1482 int32_t iType = fill.GetPattern(crEnd); | |
| 1483 int32_t iHatch = FX_HATCHSTYLE_Cross; | |
| 1484 switch (iType) { | |
| 1485 case XFA_ATTRIBUTEENUM_CrossDiagonal: | |
| 1486 iHatch = FX_HATCHSTYLE_DiagonalCross; | |
| 1487 break; | |
| 1488 case XFA_ATTRIBUTEENUM_DiagonalLeft: | |
| 1489 iHatch = FX_HATCHSTYLE_ForwardDiagonal; | |
| 1490 break; | |
| 1491 case XFA_ATTRIBUTEENUM_DiagonalRight: | |
| 1492 iHatch = FX_HATCHSTYLE_BackwardDiagonal; | |
| 1493 break; | |
| 1494 case XFA_ATTRIBUTEENUM_Horizontal: | |
| 1495 iHatch = FX_HATCHSTYLE_Horizontal; | |
| 1496 break; | |
| 1497 case XFA_ATTRIBUTEENUM_Vertical: | |
| 1498 iHatch = FX_HATCHSTYLE_Vertical; | |
| 1499 break; | |
| 1500 default: | |
| 1501 break; | |
| 1502 } | |
| 1503 CFX_Pattern pattern; | |
| 1504 pattern.Create(iHatch, crEnd, crStart); | |
| 1505 CFX_Color cr(&pattern); | |
| 1506 pGS->SetFillColor(&cr); | |
| 1507 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
| 1508 } | |
| 1509 static void XFA_BOX_Fill_Linear(CXFA_Box box, | |
| 1510 CFX_Graphics* pGS, | |
| 1511 CFX_Path& fillPath, | |
| 1512 CFX_RectF rtFill, | |
| 1513 CFX_Matrix* pMatrix) { | |
| 1514 CXFA_Fill fill = box.GetFill(); | |
| 1515 FX_ARGB crStart = fill.GetColor(); | |
| 1516 FX_ARGB crEnd; | |
| 1517 int32_t iType = fill.GetLinear(crEnd); | |
| 1518 CFX_PointF ptStart; | |
| 1519 CFX_PointF ptEnd; | |
| 1520 switch (iType) { | |
| 1521 case XFA_ATTRIBUTEENUM_ToRight: | |
| 1522 ptStart = CFX_PointF(rtFill.left, rtFill.top); | |
| 1523 ptEnd = CFX_PointF(rtFill.right(), rtFill.top); | |
| 1524 break; | |
| 1525 case XFA_ATTRIBUTEENUM_ToBottom: | |
| 1526 ptStart = CFX_PointF(rtFill.left, rtFill.top); | |
| 1527 ptEnd = CFX_PointF(rtFill.left, rtFill.bottom()); | |
| 1528 break; | |
| 1529 case XFA_ATTRIBUTEENUM_ToLeft: | |
| 1530 ptStart = CFX_PointF(rtFill.right(), rtFill.top); | |
| 1531 ptEnd = CFX_PointF(rtFill.left, rtFill.top); | |
| 1532 break; | |
| 1533 case XFA_ATTRIBUTEENUM_ToTop: | |
| 1534 ptStart = CFX_PointF(rtFill.left, rtFill.bottom()); | |
| 1535 ptEnd = CFX_PointF(rtFill.left, rtFill.top); | |
| 1536 break; | |
| 1537 default: | |
| 1538 break; | |
| 1539 } | |
| 1540 CFX_Shading shading; | |
| 1541 shading.CreateAxial(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd); | |
| 1542 CFX_Color cr(&shading); | |
| 1543 pGS->SetFillColor(&cr); | |
| 1544 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
| 1545 } | |
| 1546 static void XFA_BOX_Fill(CXFA_Box box, | |
| 1547 const CXFA_StrokeArray& strokes, | |
| 1548 CFX_Graphics* pGS, | |
| 1549 const CFX_RectF& rtWidget, | |
| 1550 CFX_Matrix* pMatrix, | |
| 1551 FX_DWORD dwFlags) { | |
| 1552 CXFA_Fill fill = box.GetFill(); | |
| 1553 if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { | |
| 1554 return; | |
| 1555 } | |
| 1556 pGS->SaveGraphState(); | |
| 1557 CFX_Path fillPath; | |
| 1558 fillPath.Create(); | |
| 1559 XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath, | |
| 1560 (dwFlags & XFA_DRAWBOX_ForceRound) != 0); | |
| 1561 fillPath.Close(); | |
| 1562 int32_t eType = fill.GetFillType(); | |
| 1563 switch (eType) { | |
| 1564 case XFA_ELEMENT_Radial: | |
| 1565 XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix); | |
| 1566 break; | |
| 1567 case XFA_ELEMENT_Pattern: | |
| 1568 XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix); | |
| 1569 break; | |
| 1570 case XFA_ELEMENT_Linear: | |
| 1571 XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix); | |
| 1572 break; | |
| 1573 default: { | |
| 1574 FX_ARGB cr; | |
| 1575 if (eType == XFA_ELEMENT_Stipple) { | |
| 1576 int32_t iRate = fill.GetStipple(cr); | |
| 1577 if (iRate == 0) { | |
| 1578 iRate = 100; | |
| 1579 } | |
| 1580 int32_t a = 0; | |
| 1581 FX_COLORREF rgb; | |
| 1582 ArgbDecode(cr, a, rgb); | |
| 1583 cr = ArgbEncode(iRate * a / 100, rgb); | |
| 1584 } else { | |
| 1585 cr = fill.GetColor(); | |
| 1586 } | |
| 1587 CFX_Color fillColor(cr); | |
| 1588 pGS->SetFillColor(&fillColor); | |
| 1589 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
| 1590 } break; | |
| 1591 } | |
| 1592 pGS->RestoreGraphState(); | |
| 1593 } | |
| 1594 static void XFA_BOX_StrokePath(CXFA_Stroke stroke, | |
| 1595 CFX_Path* pPath, | |
| 1596 CFX_Graphics* pGS, | |
| 1597 CFX_Matrix* pMatrix) { | |
| 1598 if (!stroke || !stroke.IsVisible()) { | |
| 1599 return; | |
| 1600 } | |
| 1601 FX_FLOAT fThickness = stroke.GetThickness(); | |
| 1602 if (fThickness < 0.001f) { | |
| 1603 return; | |
| 1604 } | |
| 1605 pGS->SaveGraphState(); | |
| 1606 if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) { | |
| 1607 fThickness = 2 * stroke.GetRadius(); | |
| 1608 } | |
| 1609 pGS->SetLineWidth(fThickness, TRUE); | |
| 1610 pGS->SetLineCap(CFX_GraphStateData::LineCapButt); | |
| 1611 XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(), | |
| 1612 XFA_ATTRIBUTEENUM_Butt); | |
| 1613 CFX_Color fxColor(stroke.GetColor()); | |
| 1614 pGS->SetStrokeColor(&fxColor); | |
| 1615 pGS->StrokePath(pPath, pMatrix); | |
| 1616 pGS->RestoreGraphState(); | |
| 1617 } | |
| 1618 static void XFA_BOX_StrokeArc(CXFA_Box box, | |
| 1619 CFX_Graphics* pGS, | |
| 1620 CFX_RectF rtWidget, | |
| 1621 CFX_Matrix* pMatrix, | |
| 1622 FX_DWORD dwFlags) { | |
| 1623 CXFA_Edge edge = box.GetEdge(0); | |
| 1624 if (!edge || !edge.IsVisible()) { | |
| 1625 return; | |
| 1626 } | |
| 1627 FX_BOOL bVisible = FALSE; | |
| 1628 FX_FLOAT fThickness = 0; | |
| 1629 int32_t i3DType = box.Get3DStyle(bVisible, fThickness); | |
| 1630 if (i3DType) { | |
| 1631 if (bVisible && fThickness >= 0.001f) { | |
| 1632 dwFlags |= XFA_DRAWBOX_Lowered3D; | |
| 1633 } | |
| 1634 } | |
| 1635 FX_FLOAT fHalf = edge.GetThickness() / 2; | |
| 1636 if (fHalf < 0) { | |
| 1637 fHalf = 0; | |
| 1638 } | |
| 1639 int32_t iHand = box.GetHand(); | |
| 1640 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1641 rtWidget.Inflate(fHalf, fHalf); | |
| 1642 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1643 rtWidget.Deflate(fHalf, fHalf); | |
| 1644 } | |
| 1645 if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 || | |
| 1646 (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) { | |
| 1647 if (fHalf < 0.001f) { | |
| 1648 return; | |
| 1649 } | |
| 1650 CFX_Path arcPath; | |
| 1651 arcPath.Create(); | |
| 1652 XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags); | |
| 1653 XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix); | |
| 1654 return; | |
| 1655 } | |
| 1656 pGS->SaveGraphState(); | |
| 1657 pGS->SetLineWidth(fHalf); | |
| 1658 FX_FLOAT a, b; | |
| 1659 a = rtWidget.width / 2.0f; | |
| 1660 b = rtWidget.height / 2.0f; | |
| 1661 if (dwFlags & XFA_DRAWBOX_ForceRound) { | |
| 1662 a = b = std::min(a, b); | |
| 1663 } | |
| 1664 CFX_PointF center = rtWidget.Center(); | |
| 1665 rtWidget.left = center.x - a; | |
| 1666 rtWidget.top = center.y - b; | |
| 1667 rtWidget.width = a + a; | |
| 1668 rtWidget.height = b + b; | |
| 1669 FX_FLOAT startAngle = 0, sweepAngle = 360; | |
| 1670 startAngle = startAngle * FX_PI / 180.0f; | |
| 1671 sweepAngle = -sweepAngle * FX_PI / 180.0f; | |
| 1672 CFX_Path arcPath; | |
| 1673 arcPath.Create(); | |
| 1674 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
| 1675 3.0f * FX_PI / 4.0f, FX_PI); | |
| 1676 CFX_Color cr(0xFF808080); | |
| 1677 pGS->SetStrokeColor(&cr); | |
| 1678 pGS->StrokePath(&arcPath, pMatrix); | |
| 1679 arcPath.Clear(); | |
| 1680 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
| 1681 -1.0f * FX_PI / 4.0f, FX_PI); | |
| 1682 cr.Set(0xFFFFFFFF); | |
| 1683 pGS->SetStrokeColor(&cr); | |
| 1684 pGS->StrokePath(&arcPath, pMatrix); | |
| 1685 rtWidget.Deflate(fHalf, fHalf); | |
| 1686 arcPath.Clear(); | |
| 1687 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
| 1688 3.0f * FX_PI / 4.0f, FX_PI); | |
| 1689 cr.Set(0xFF404040); | |
| 1690 pGS->SetStrokeColor(&cr); | |
| 1691 pGS->StrokePath(&arcPath, pMatrix); | |
| 1692 arcPath.Clear(); | |
| 1693 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
| 1694 -1.0f * FX_PI / 4.0f, FX_PI); | |
| 1695 cr.Set(0xFFC0C0C0); | |
| 1696 pGS->SetStrokeColor(&cr); | |
| 1697 pGS->StrokePath(&arcPath, pMatrix); | |
| 1698 pGS->RestoreGraphState(); | |
| 1699 } | |
| 1700 static void XFA_Draw3DRect(CFX_Graphics* pGraphic, | |
| 1701 const CFX_RectF& rt, | |
| 1702 FX_FLOAT fLineWidth, | |
| 1703 CFX_Matrix* pMatrix, | |
| 1704 FX_ARGB argbTopLeft, | |
| 1705 FX_ARGB argbBottomRight) { | |
| 1706 CFX_Color crLT(argbTopLeft); | |
| 1707 pGraphic->SetFillColor(&crLT); | |
| 1708 FX_FLOAT fBottom = rt.bottom(); | |
| 1709 FX_FLOAT fRight = rt.right(); | |
| 1710 CFX_Path pathLT; | |
| 1711 pathLT.Create(); | |
| 1712 pathLT.MoveTo(rt.left, fBottom); | |
| 1713 pathLT.LineTo(rt.left, rt.top); | |
| 1714 pathLT.LineTo(fRight, rt.top); | |
| 1715 pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth); | |
| 1716 pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth); | |
| 1717 pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); | |
| 1718 pathLT.LineTo(rt.left, fBottom); | |
| 1719 pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix); | |
| 1720 CFX_Color crRB(argbBottomRight); | |
| 1721 pGraphic->SetFillColor(&crRB); | |
| 1722 CFX_Path pathRB; | |
| 1723 pathRB.Create(); | |
| 1724 pathRB.MoveTo(fRight, rt.top); | |
| 1725 pathRB.LineTo(fRight, fBottom); | |
| 1726 pathRB.LineTo(rt.left, fBottom); | |
| 1727 pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); | |
| 1728 pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth); | |
| 1729 pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth); | |
| 1730 pathRB.LineTo(fRight, rt.top); | |
| 1731 pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix); | |
| 1732 } | |
| 1733 static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS, | |
| 1734 CFX_RectF rt, | |
| 1735 FX_FLOAT fThickness, | |
| 1736 CFX_Matrix* pMatrix) { | |
| 1737 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
| 1738 CFX_RectF rtInner(rt); | |
| 1739 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
| 1740 CFX_Color cr(0xFF000000); | |
| 1741 pGS->SetFillColor(&cr); | |
| 1742 CFX_Path path; | |
| 1743 path.Create(); | |
| 1744 path.AddRectangle(rt.left, rt.top, rt.width, rt.height); | |
| 1745 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); | |
| 1746 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); | |
| 1747 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0); | |
| 1748 } | |
| 1749 static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS, | |
| 1750 CFX_RectF rt, | |
| 1751 FX_FLOAT fThickness, | |
| 1752 CFX_Matrix* pMatrix) { | |
| 1753 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
| 1754 CFX_RectF rtInner(rt); | |
| 1755 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
| 1756 CFX_Color cr(0xFF000000); | |
| 1757 pGS->SetFillColor(&cr); | |
| 1758 CFX_Path path; | |
| 1759 path.Create(); | |
| 1760 path.AddRectangle(rt.left, rt.top, rt.width, rt.height); | |
| 1761 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); | |
| 1762 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); | |
| 1763 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); | |
| 1764 } | |
| 1765 static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS, | |
| 1766 CFX_RectF rt, | |
| 1767 FX_FLOAT fThickness, | |
| 1768 CFX_Matrix* pMatrix) { | |
| 1769 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
| 1770 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF); | |
| 1771 CFX_RectF rtInner(rt); | |
| 1772 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
| 1773 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); | |
| 1774 } | |
| 1775 static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS, | |
| 1776 CFX_RectF rt, | |
| 1777 FX_FLOAT fThickness, | |
| 1778 CFX_Matrix* pMatrix) { | |
| 1779 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
| 1780 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000); | |
| 1781 CFX_RectF rtInner(rt); | |
| 1782 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
| 1783 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080); | |
| 1784 } | |
| 1785 static void XFA_BOX_Stroke_Rect(CXFA_Box box, | |
| 1786 const CXFA_StrokeArray& strokes, | |
| 1787 CFX_Graphics* pGS, | |
| 1788 CFX_RectF rtWidget, | |
| 1789 CFX_Matrix* pMatrix) { | |
| 1790 FX_BOOL bVisible = FALSE; | |
| 1791 FX_FLOAT fThickness = 0; | |
| 1792 int32_t i3DType = box.Get3DStyle(bVisible, fThickness); | |
| 1793 if (i3DType) { | |
| 1794 if (!bVisible || fThickness < 0.001f) { | |
| 1795 return; | |
| 1796 } | |
| 1797 switch (i3DType) { | |
| 1798 case XFA_ATTRIBUTEENUM_Lowered: | |
| 1799 XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix); | |
| 1800 break; | |
| 1801 case XFA_ATTRIBUTEENUM_Raised: | |
| 1802 XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix); | |
| 1803 break; | |
| 1804 case XFA_ATTRIBUTEENUM_Etched: | |
| 1805 XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix); | |
| 1806 break; | |
| 1807 case XFA_ATTRIBUTEENUM_Embossed: | |
| 1808 XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix); | |
| 1809 break; | |
| 1810 } | |
| 1811 return; | |
| 1812 } | |
| 1813 FX_BOOL bClose = FALSE; | |
| 1814 FX_BOOL bSameStyles = TRUE; | |
| 1815 int32_t i; | |
| 1816 CXFA_Stroke stroke1 = strokes[0]; | |
| 1817 for (i = 1; i < 8; i++) { | |
| 1818 CXFA_Stroke stroke2 = strokes[i]; | |
| 1819 if (!stroke1.SameStyles(stroke2)) { | |
| 1820 bSameStyles = FALSE; | |
| 1821 break; | |
| 1822 } | |
| 1823 stroke1 = stroke2; | |
| 1824 } | |
| 1825 if (bSameStyles) { | |
| 1826 stroke1 = strokes[0]; | |
| 1827 bClose = TRUE; | |
| 1828 for (i = 2; i < 8; i += 2) { | |
| 1829 CXFA_Stroke stroke2 = strokes[i]; | |
| 1830 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | | |
| 1831 XFA_STROKE_SAMESTYLE_Corner)) { | |
| 1832 bSameStyles = FALSE; | |
| 1833 break; | |
| 1834 } | |
| 1835 stroke1 = stroke2; | |
| 1836 } | |
| 1837 if (bSameStyles) { | |
| 1838 stroke1 = strokes[0]; | |
| 1839 if (stroke1.IsInverted()) { | |
| 1840 bSameStyles = FALSE; | |
| 1841 } | |
| 1842 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { | |
| 1843 bSameStyles = FALSE; | |
| 1844 } | |
| 1845 } | |
| 1846 } | |
| 1847 FX_BOOL bStart = TRUE; | |
| 1848 CFX_Path path; | |
| 1849 path.Create(); | |
| 1850 for (i = 0; i < 8; i++) { | |
| 1851 CXFA_Stroke stroke1 = strokes[i]; | |
| 1852 if ((i % 1) == 0 && stroke1.GetRadius() < 0) { | |
| 1853 FX_BOOL bEmpty = path.IsEmpty(); | |
| 1854 if (!bEmpty) { | |
| 1855 XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); | |
| 1856 path.Clear(); | |
| 1857 } | |
| 1858 bStart = TRUE; | |
| 1859 continue; | |
| 1860 } | |
| 1861 XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles); | |
| 1862 CXFA_Stroke stroke2 = strokes[(i + 1) % 8]; | |
| 1863 bStart = !stroke1.SameStyles(stroke2); | |
| 1864 if (bStart) { | |
| 1865 XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); | |
| 1866 path.Clear(); | |
| 1867 } | |
| 1868 } | |
| 1869 FX_BOOL bEmpty = path.IsEmpty(); | |
| 1870 if (!bEmpty) { | |
| 1871 if (bClose) { | |
| 1872 path.Close(); | |
| 1873 } | |
| 1874 XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix); | |
| 1875 } | |
| 1876 } | |
| 1877 static void XFA_BOX_Stroke(CXFA_Box box, | |
| 1878 const CXFA_StrokeArray& strokes, | |
| 1879 CFX_Graphics* pGS, | |
| 1880 CFX_RectF rtWidget, | |
| 1881 CFX_Matrix* pMatrix, | |
| 1882 FX_DWORD dwFlags) { | |
| 1883 if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
| 1884 XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags); | |
| 1885 return; | |
| 1886 } | |
| 1887 bool bVisible = false; | |
| 1888 for (int32_t j = 0; j < 4; j++) { | |
| 1889 if (strokes[j * 2 + 1].IsVisible()) { | |
| 1890 bVisible = true; | |
| 1891 break; | |
| 1892 } | |
| 1893 } | |
| 1894 if (!bVisible) { | |
| 1895 return; | |
| 1896 } | |
| 1897 for (int32_t i = 1; i < 8; i += 2) { | |
| 1898 CXFA_Edge edge(strokes[i].GetNode()); | |
| 1899 FX_FLOAT fThickness = edge.GetThickness(); | |
| 1900 if (fThickness < 0) { | |
| 1901 fThickness = 0; | |
| 1902 } | |
| 1903 FX_FLOAT fHalf = fThickness / 2; | |
| 1904 int32_t iHand = box.GetHand(); | |
| 1905 switch (i) { | |
| 1906 case 1: | |
| 1907 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1908 rtWidget.top -= fHalf; | |
| 1909 rtWidget.height += fHalf; | |
| 1910 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1911 rtWidget.top += fHalf; | |
| 1912 rtWidget.height -= fHalf; | |
| 1913 } | |
| 1914 break; | |
| 1915 case 3: | |
| 1916 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1917 rtWidget.width += fHalf; | |
| 1918 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1919 rtWidget.width -= fHalf; | |
| 1920 } | |
| 1921 break; | |
| 1922 case 5: | |
| 1923 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1924 rtWidget.height += fHalf; | |
| 1925 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1926 rtWidget.height -= fHalf; | |
| 1927 } | |
| 1928 break; | |
| 1929 case 7: | |
| 1930 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
| 1931 rtWidget.left -= fHalf; | |
| 1932 rtWidget.width += fHalf; | |
| 1933 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
| 1934 rtWidget.left += fHalf; | |
| 1935 rtWidget.width -= fHalf; | |
| 1936 } | |
| 1937 break; | |
| 1938 } | |
| 1939 } | |
| 1940 XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix); | |
| 1941 } | |
| 1942 void XFA_DrawBox(CXFA_Box box, | |
| 1943 CFX_Graphics* pGS, | |
| 1944 const CFX_RectF& rtWidget, | |
| 1945 CFX_Matrix* pMatrix, | |
| 1946 FX_DWORD dwFlags) { | |
| 1947 if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { | |
| 1948 return; | |
| 1949 } | |
| 1950 int32_t iType = box.GetClassID(); | |
| 1951 if (iType != XFA_ELEMENT_Arc && iType != XFA_ELEMENT_Border && | |
| 1952 iType != XFA_ELEMENT_Rectangle) { | |
| 1953 return; | |
| 1954 } | |
| 1955 CXFA_StrokeArray strokes; | |
| 1956 if (!(dwFlags & XFA_DRAWBOX_ForceRound) && iType != XFA_ELEMENT_Arc) { | |
| 1957 box.GetStrokes(strokes); | |
| 1958 } | |
| 1959 XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags); | |
| 1960 XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags); | |
| 1961 } | |
| OLD | NEW |