1 // Copyright 2016 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_box.h"
8 
9 #include "xfa/fxfa/parser/cxfa_corner.h"
10 #include "xfa/fxfa/parser/xfa_object.h"
11 
12 namespace {
13 
GetStrokesInternal(CXFA_Node * pNode,CXFA_StrokeArray & strokes,FX_BOOL bNull)14 void GetStrokesInternal(CXFA_Node* pNode,
15                         CXFA_StrokeArray& strokes,
16                         FX_BOOL bNull) {
17   strokes.RemoveAll();
18   if (!pNode)
19     return;
20 
21   strokes.SetSize(8);
22   int32_t i, j;
23   for (i = 0, j = 0; i < 4; i++) {
24     CXFA_Corner corner =
25         CXFA_Corner(pNode->GetProperty(i, XFA_Element::Corner, i == 0));
26     if (corner || i == 0)
27       strokes.SetAt(j, corner);
28     else if (bNull)
29       strokes.SetAt(j, CXFA_Stroke(nullptr));
30     else if (i == 1)
31       strokes.SetAt(j, strokes[0]);
32     else if (i == 2)
33       strokes.SetAt(j, strokes[0]);
34     else
35       strokes.SetAt(j, strokes[2]);
36 
37     j++;
38     CXFA_Edge edge =
39         CXFA_Edge(pNode->GetProperty(i, XFA_Element::Edge, i == 0));
40     if (edge || i == 0)
41       strokes.SetAt(j, edge);
42     else if (bNull)
43       strokes.SetAt(j, CXFA_Stroke(nullptr));
44     else if (i == 1)
45       strokes.SetAt(j, strokes[1]);
46     else if (i == 2)
47       strokes.SetAt(j, strokes[1]);
48     else
49       strokes.SetAt(j, strokes[3]);
50 
51     j++;
52   }
53 }
54 
Style3D(const CXFA_StrokeArray & strokes,CXFA_Stroke & stroke)55 static int32_t Style3D(const CXFA_StrokeArray& strokes, CXFA_Stroke& stroke) {
56   int32_t iCount = strokes.GetSize();
57   if (iCount < 1)
58     return 0;
59 
60   stroke = strokes[0];
61   for (int32_t i = 1; i < iCount; i++) {
62     CXFA_Stroke find = strokes[i];
63     if (!find)
64       continue;
65 
66     if (!stroke)
67       stroke = find;
68     else if (stroke.GetStrokeType() != find.GetStrokeType())
69       stroke = find;
70     break;
71   }
72   int32_t iType = stroke.GetStrokeType();
73   if (iType == XFA_ATTRIBUTEENUM_Lowered || iType == XFA_ATTRIBUTEENUM_Raised ||
74       iType == XFA_ATTRIBUTEENUM_Etched ||
75       iType == XFA_ATTRIBUTEENUM_Embossed) {
76     return iType;
77   }
78   return 0;
79 }
80 
81 }  // namespace
82 
GetHand() const83 int32_t CXFA_Box::GetHand() const {
84   if (!m_pNode)
85     return XFA_ATTRIBUTEENUM_Even;
86   return m_pNode->GetEnum(XFA_ATTRIBUTE_Hand);
87 }
88 
GetPresence() const89 int32_t CXFA_Box::GetPresence() const {
90   if (!m_pNode)
91     return XFA_ATTRIBUTEENUM_Hidden;
92   return m_pNode->GetEnum(XFA_ATTRIBUTE_Presence);
93 }
94 
CountEdges() const95 int32_t CXFA_Box::CountEdges() const {
96   if (!m_pNode)
97     return 0;
98   return m_pNode->CountChildren(XFA_Element::Edge);
99 }
100 
GetEdge(int32_t nIndex) const101 CXFA_Edge CXFA_Box::GetEdge(int32_t nIndex) const {
102   return CXFA_Edge(
103       m_pNode ? m_pNode->GetProperty(nIndex, XFA_Element::Edge, nIndex == 0)
104               : nullptr);
105 }
106 
GetStrokes(CXFA_StrokeArray & strokes) const107 void CXFA_Box::GetStrokes(CXFA_StrokeArray& strokes) const {
108   GetStrokesInternal(m_pNode, strokes, FALSE);
109 }
110 
IsCircular() const111 FX_BOOL CXFA_Box::IsCircular() const {
112   if (!m_pNode)
113     return FALSE;
114   return m_pNode->GetBoolean(XFA_ATTRIBUTE_Circular);
115 }
116 
GetStartAngle(FX_FLOAT & fStartAngle) const117 FX_BOOL CXFA_Box::GetStartAngle(FX_FLOAT& fStartAngle) const {
118   fStartAngle = 0;
119   if (!m_pNode)
120     return FALSE;
121 
122   CXFA_Measurement ms;
123   FX_BOOL bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_StartAngle, ms, FALSE);
124   if (bRet)
125     fStartAngle = ms.GetValue();
126 
127   return bRet;
128 }
129 
GetSweepAngle(FX_FLOAT & fSweepAngle) const130 FX_BOOL CXFA_Box::GetSweepAngle(FX_FLOAT& fSweepAngle) const {
131   fSweepAngle = 360;
132   if (!m_pNode)
133     return FALSE;
134 
135   CXFA_Measurement ms;
136   FX_BOOL bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_SweepAngle, ms, FALSE);
137   if (bRet)
138     fSweepAngle = ms.GetValue();
139 
140   return bRet;
141 }
142 
GetFill(FX_BOOL bModified) const143 CXFA_Fill CXFA_Box::GetFill(FX_BOOL bModified) const {
144   if (!m_pNode)
145     return CXFA_Fill(nullptr);
146 
147   CXFA_Node* pFillNode = m_pNode->GetProperty(0, XFA_Element::Fill, bModified);
148   return CXFA_Fill(pFillNode);
149 }
150 
GetMargin() const151 CXFA_Margin CXFA_Box::GetMargin() const {
152   return CXFA_Margin(m_pNode ? m_pNode->GetChild(0, XFA_Element::Margin)
153                              : nullptr);
154 }
155 
Get3DStyle(FX_BOOL & bVisible,FX_FLOAT & fThickness) const156 int32_t CXFA_Box::Get3DStyle(FX_BOOL& bVisible, FX_FLOAT& fThickness) const {
157   if (IsArc())
158     return 0;
159 
160   CXFA_StrokeArray strokes;
161   GetStrokesInternal(m_pNode, strokes, TRUE);
162   CXFA_Stroke stroke(nullptr);
163   int32_t iType = Style3D(strokes, stroke);
164   if (iType) {
165     bVisible = stroke.IsVisible();
166     fThickness = stroke.GetThickness();
167   }
168   return iType;
169 }
170