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