1 // Copyright 2017 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/parser/cxfa_fill.h"
8 
9 #include "fxjs/xfa/cjx_node.h"
10 #include "xfa/fxfa/parser/cxfa_color.h"
11 #include "xfa/fxfa/parser/cxfa_document.h"
12 #include "xfa/fxfa/parser/cxfa_linear.h"
13 #include "xfa/fxfa/parser/cxfa_node.h"
14 #include "xfa/fxfa/parser/cxfa_pattern.h"
15 #include "xfa/fxfa/parser/cxfa_radial.h"
16 #include "xfa/fxfa/parser/cxfa_stipple.h"
17 
18 namespace {
19 
20 const CXFA_Node::PropertyData kFillPropertyData[] = {
21     {XFA_Element::Pattern, 1, XFA_PROPERTYFLAG_OneOf},
22     {XFA_Element::Solid, 1,
23      XFA_PROPERTYFLAG_OneOf | XFA_PROPERTYFLAG_DefaultOneOf},
24     {XFA_Element::Stipple, 1, XFA_PROPERTYFLAG_OneOf},
25     {XFA_Element::Color, 1, 0},
26     {XFA_Element::Linear, 1, XFA_PROPERTYFLAG_OneOf},
27     {XFA_Element::Extras, 1, 0},
28     {XFA_Element::Radial, 1, XFA_PROPERTYFLAG_OneOf},
29 };
30 
31 const CXFA_Node::AttributeData kFillAttributeData[] = {
32     {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr},
33     {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr},
34     {XFA_Attribute::Presence, XFA_AttributeType::Enum,
35      (void*)XFA_AttributeValue::Visible},
36     {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr},
37 };
38 
39 }  // namespace
40 
CXFA_Fill(CXFA_Document * doc,XFA_PacketType packet)41 CXFA_Fill::CXFA_Fill(CXFA_Document* doc, XFA_PacketType packet)
42     : CXFA_Node(doc,
43                 packet,
44                 (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form),
45                 XFA_ObjectType::Node,
46                 XFA_Element::Fill,
47                 kFillPropertyData,
48                 kFillAttributeData,
49                 cppgc::MakeGarbageCollected<CJX_Node>(
50                     doc->GetHeap()->GetAllocationHandle(),
51                     this)) {}
52 
53 CXFA_Fill::~CXFA_Fill() = default;
54 
IsVisible()55 bool CXFA_Fill::IsVisible() {
56   return JSObject()
57              ->TryEnum(XFA_Attribute::Presence, true)
58              .value_or(XFA_AttributeValue::Visible) ==
59          XFA_AttributeValue::Visible;
60 }
61 
SetColor(FX_ARGB color)62 void CXFA_Fill::SetColor(FX_ARGB color) {
63   CXFA_Color* pColor =
64       JSObject()->GetOrCreateProperty<CXFA_Color>(0, XFA_Element::Color);
65   if (!pColor)
66     return;
67 
68   pColor->SetValue(color);
69 }
70 
GetColor(bool bText)71 FX_ARGB CXFA_Fill::GetColor(bool bText) {
72   CXFA_Color* pColor = GetChild<CXFA_Color>(0, XFA_Element::Color, false);
73   if (!pColor)
74     return bText ? 0xFF000000 : 0xFFFFFFFF;
75   return pColor->GetValueOrDefault(bText ? 0xFF000000 : 0xFFFFFFFF);
76 }
77 
GetType() const78 XFA_Element CXFA_Fill::GetType() const {
79   CXFA_Node* pChild = GetFirstChild();
80   while (pChild) {
81     XFA_Element eType = pChild->GetElementType();
82     if (eType != XFA_Element::Color && eType != XFA_Element::Extras)
83       return eType;
84 
85     pChild = pChild->GetNextSibling();
86   }
87   return XFA_Element::Solid;
88 }
89 
Draw(CFGAS_GEGraphics * pGS,CFGAS_GEPath * fillPath,const CFX_RectF & rtWidget,const CFX_Matrix & matrix)90 void CXFA_Fill::Draw(CFGAS_GEGraphics* pGS,
91                      CFGAS_GEPath* fillPath,
92                      const CFX_RectF& rtWidget,
93                      const CFX_Matrix& matrix) {
94   pGS->SaveGraphState();
95 
96   switch (GetType()) {
97     case XFA_Element::Radial:
98       DrawRadial(pGS, fillPath, rtWidget, matrix);
99       break;
100     case XFA_Element::Pattern:
101       DrawPattern(pGS, fillPath, rtWidget, matrix);
102       break;
103     case XFA_Element::Linear:
104       DrawLinear(pGS, fillPath, rtWidget, matrix);
105       break;
106     case XFA_Element::Stipple:
107       DrawStipple(pGS, fillPath, rtWidget, matrix);
108       break;
109     default:
110       pGS->SetFillColor(CFGAS_GEColor(GetColor(false)));
111       pGS->FillPath(fillPath, CFX_FillRenderOptions::FillType::kWinding,
112                     &matrix);
113       break;
114   }
115 
116   pGS->RestoreGraphState();
117 }
118 
DrawStipple(CFGAS_GEGraphics * pGS,CFGAS_GEPath * fillPath,const CFX_RectF & rtWidget,const CFX_Matrix & matrix)119 void CXFA_Fill::DrawStipple(CFGAS_GEGraphics* pGS,
120                             CFGAS_GEPath* fillPath,
121                             const CFX_RectF& rtWidget,
122                             const CFX_Matrix& matrix) {
123   CXFA_Stipple* stipple =
124       JSObject()->GetOrCreateProperty<CXFA_Stipple>(0, XFA_Element::Stipple);
125   if (stipple)
126     stipple->Draw(pGS, fillPath, rtWidget, matrix);
127 }
128 
DrawRadial(CFGAS_GEGraphics * pGS,CFGAS_GEPath * fillPath,const CFX_RectF & rtWidget,const CFX_Matrix & matrix)129 void CXFA_Fill::DrawRadial(CFGAS_GEGraphics* pGS,
130                            CFGAS_GEPath* fillPath,
131                            const CFX_RectF& rtWidget,
132                            const CFX_Matrix& matrix) {
133   CXFA_Radial* radial =
134       JSObject()->GetOrCreateProperty<CXFA_Radial>(0, XFA_Element::Radial);
135   if (radial)
136     radial->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix);
137 }
138 
DrawLinear(CFGAS_GEGraphics * pGS,CFGAS_GEPath * fillPath,const CFX_RectF & rtWidget,const CFX_Matrix & matrix)139 void CXFA_Fill::DrawLinear(CFGAS_GEGraphics* pGS,
140                            CFGAS_GEPath* fillPath,
141                            const CFX_RectF& rtWidget,
142                            const CFX_Matrix& matrix) {
143   CXFA_Linear* linear =
144       JSObject()->GetOrCreateProperty<CXFA_Linear>(0, XFA_Element::Linear);
145   if (linear)
146     linear->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix);
147 }
148 
DrawPattern(CFGAS_GEGraphics * pGS,CFGAS_GEPath * fillPath,const CFX_RectF & rtWidget,const CFX_Matrix & matrix)149 void CXFA_Fill::DrawPattern(CFGAS_GEGraphics* pGS,
150                             CFGAS_GEPath* fillPath,
151                             const CFX_RectF& rtWidget,
152                             const CFX_Matrix& matrix) {
153   CXFA_Pattern* pattern =
154       JSObject()->GetOrCreateProperty<CXFA_Pattern>(0, XFA_Element::Pattern);
155   if (pattern)
156     pattern->Draw(pGS, fillPath, GetColor(false), rtWidget, matrix);
157 }
158