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