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