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