1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_rectangle.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <math.h>
10*3ac0a46fSAndroid Build Coastguard Worker
11*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
12*3ac0a46fSAndroid Build Coastguard Worker
13*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_node.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/notreached.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/graphics/cfgas_gegraphics.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_corner.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_stroke.h"
20*3ac0a46fSAndroid Build Coastguard Worker
21*3ac0a46fSAndroid Build Coastguard Worker namespace {
22*3ac0a46fSAndroid Build Coastguard Worker
23*3ac0a46fSAndroid Build Coastguard Worker const CXFA_Node::PropertyData kRectanglePropertyData[] = {
24*3ac0a46fSAndroid Build Coastguard Worker {XFA_Element::Edge, 4, {}},
25*3ac0a46fSAndroid Build Coastguard Worker {XFA_Element::Corner, 4, {}},
26*3ac0a46fSAndroid Build Coastguard Worker {XFA_Element::Fill, 1, {}},
27*3ac0a46fSAndroid Build Coastguard Worker };
28*3ac0a46fSAndroid Build Coastguard Worker
29*3ac0a46fSAndroid Build Coastguard Worker const CXFA_Node::AttributeData kRectangleAttributeData[] = {
30*3ac0a46fSAndroid Build Coastguard Worker {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr},
31*3ac0a46fSAndroid Build Coastguard Worker {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr},
32*3ac0a46fSAndroid Build Coastguard Worker {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr},
33*3ac0a46fSAndroid Build Coastguard Worker {XFA_Attribute::Hand, XFA_AttributeType::Enum,
34*3ac0a46fSAndroid Build Coastguard Worker (void*)XFA_AttributeValue::Even},
35*3ac0a46fSAndroid Build Coastguard Worker };
36*3ac0a46fSAndroid Build Coastguard Worker
37*3ac0a46fSAndroid Build Coastguard Worker } // namespace
38*3ac0a46fSAndroid Build Coastguard Worker
39*3ac0a46fSAndroid Build Coastguard Worker // static
FromNode(CXFA_Node * pNode)40*3ac0a46fSAndroid Build Coastguard Worker CXFA_Rectangle* CXFA_Rectangle::FromNode(CXFA_Node* pNode) {
41*3ac0a46fSAndroid Build Coastguard Worker return pNode && pNode->GetElementType() == XFA_Element::Rectangle
42*3ac0a46fSAndroid Build Coastguard Worker ? static_cast<CXFA_Rectangle*>(pNode)
43*3ac0a46fSAndroid Build Coastguard Worker : nullptr;
44*3ac0a46fSAndroid Build Coastguard Worker }
45*3ac0a46fSAndroid Build Coastguard Worker
CXFA_Rectangle(CXFA_Document * doc,XFA_PacketType packet)46*3ac0a46fSAndroid Build Coastguard Worker CXFA_Rectangle::CXFA_Rectangle(CXFA_Document* doc, XFA_PacketType packet)
47*3ac0a46fSAndroid Build Coastguard Worker : CXFA_Box(doc,
48*3ac0a46fSAndroid Build Coastguard Worker packet,
49*3ac0a46fSAndroid Build Coastguard Worker {XFA_XDPPACKET::kTemplate, XFA_XDPPACKET::kForm},
50*3ac0a46fSAndroid Build Coastguard Worker XFA_ObjectType::Node,
51*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Rectangle,
52*3ac0a46fSAndroid Build Coastguard Worker kRectanglePropertyData,
53*3ac0a46fSAndroid Build Coastguard Worker kRectangleAttributeData,
54*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<CJX_Node>(
55*3ac0a46fSAndroid Build Coastguard Worker doc->GetHeap()->GetAllocationHandle(),
56*3ac0a46fSAndroid Build Coastguard Worker this)) {}
57*3ac0a46fSAndroid Build Coastguard Worker
CXFA_Rectangle(CXFA_Document * pDoc,XFA_PacketType ePacket,Mask<XFA_XDPPACKET> validPackets,XFA_ObjectType oType,XFA_Element eType,pdfium::span<const PropertyData> properties,pdfium::span<const AttributeData> attributes,CJX_Object * js_node)58*3ac0a46fSAndroid Build Coastguard Worker CXFA_Rectangle::CXFA_Rectangle(CXFA_Document* pDoc,
59*3ac0a46fSAndroid Build Coastguard Worker XFA_PacketType ePacket,
60*3ac0a46fSAndroid Build Coastguard Worker Mask<XFA_XDPPACKET> validPackets,
61*3ac0a46fSAndroid Build Coastguard Worker XFA_ObjectType oType,
62*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType,
63*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const PropertyData> properties,
64*3ac0a46fSAndroid Build Coastguard Worker pdfium::span<const AttributeData> attributes,
65*3ac0a46fSAndroid Build Coastguard Worker CJX_Object* js_node)
66*3ac0a46fSAndroid Build Coastguard Worker : CXFA_Box(pDoc,
67*3ac0a46fSAndroid Build Coastguard Worker ePacket,
68*3ac0a46fSAndroid Build Coastguard Worker validPackets,
69*3ac0a46fSAndroid Build Coastguard Worker oType,
70*3ac0a46fSAndroid Build Coastguard Worker eType,
71*3ac0a46fSAndroid Build Coastguard Worker properties,
72*3ac0a46fSAndroid Build Coastguard Worker attributes,
73*3ac0a46fSAndroid Build Coastguard Worker js_node) {}
74*3ac0a46fSAndroid Build Coastguard Worker
75*3ac0a46fSAndroid Build Coastguard Worker CXFA_Rectangle::~CXFA_Rectangle() = default;
76*3ac0a46fSAndroid Build Coastguard Worker
GetFillPath(const std::vector<CXFA_Stroke * > & strokes,const CFX_RectF & rtWidget,CFGAS_GEPath * fillPath)77*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::GetFillPath(const std::vector<CXFA_Stroke*>& strokes,
78*3ac0a46fSAndroid Build Coastguard Worker const CFX_RectF& rtWidget,
79*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath* fillPath) {
80*3ac0a46fSAndroid Build Coastguard Worker bool bSameStyles = true;
81*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke1 = strokes[0];
82*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 1; i < 8; i++) {
83*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke2 = strokes[i];
84*3ac0a46fSAndroid Build Coastguard Worker if (!stroke1->SameStyles(stroke2, {})) {
85*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
86*3ac0a46fSAndroid Build Coastguard Worker break;
87*3ac0a46fSAndroid Build Coastguard Worker }
88*3ac0a46fSAndroid Build Coastguard Worker stroke1 = stroke2;
89*3ac0a46fSAndroid Build Coastguard Worker }
90*3ac0a46fSAndroid Build Coastguard Worker
91*3ac0a46fSAndroid Build Coastguard Worker if (bSameStyles) {
92*3ac0a46fSAndroid Build Coastguard Worker stroke1 = strokes[0];
93*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 2; i < 8; i += 2) {
94*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke2 = strokes[i];
95*3ac0a46fSAndroid Build Coastguard Worker if (!stroke1->SameStyles(stroke2,
96*3ac0a46fSAndroid Build Coastguard Worker {CXFA_Stroke::SameStyleOption::kNoPresence,
97*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke::SameStyleOption::kCorner})) {
98*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
99*3ac0a46fSAndroid Build Coastguard Worker break;
100*3ac0a46fSAndroid Build Coastguard Worker }
101*3ac0a46fSAndroid Build Coastguard Worker stroke1 = stroke2;
102*3ac0a46fSAndroid Build Coastguard Worker }
103*3ac0a46fSAndroid Build Coastguard Worker if (bSameStyles) {
104*3ac0a46fSAndroid Build Coastguard Worker stroke1 = strokes[0];
105*3ac0a46fSAndroid Build Coastguard Worker if (stroke1->IsInverted())
106*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
107*3ac0a46fSAndroid Build Coastguard Worker if (stroke1->GetJoinType() != XFA_AttributeValue::Square)
108*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker }
111*3ac0a46fSAndroid Build Coastguard Worker if (bSameStyles) {
112*3ac0a46fSAndroid Build Coastguard Worker fillPath->AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
113*3ac0a46fSAndroid Build Coastguard Worker rtWidget.height);
114*3ac0a46fSAndroid Build Coastguard Worker return;
115*3ac0a46fSAndroid Build Coastguard Worker }
116*3ac0a46fSAndroid Build Coastguard Worker
117*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 0; i < 8; i += 2) {
118*3ac0a46fSAndroid Build Coastguard Worker float sx = 0.0f;
119*3ac0a46fSAndroid Build Coastguard Worker float sy = 0.0f;
120*3ac0a46fSAndroid Build Coastguard Worker float vx = 1.0f;
121*3ac0a46fSAndroid Build Coastguard Worker float vy = 1.0f;
122*3ac0a46fSAndroid Build Coastguard Worker float nx = 1.0f;
123*3ac0a46fSAndroid Build Coastguard Worker float ny = 1.0f;
124*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp1;
125*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp2;
126*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* corner1 = strokes[i];
127*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* corner2 = strokes[(i + 2) % 8];
128*3ac0a46fSAndroid Build Coastguard Worker float fRadius1 = corner1->GetRadius();
129*3ac0a46fSAndroid Build Coastguard Worker float fRadius2 = corner2->GetRadius();
130*3ac0a46fSAndroid Build Coastguard Worker bool bInverted = corner1->IsInverted();
131*3ac0a46fSAndroid Build Coastguard Worker bool bRound = corner1->GetJoinType() == XFA_AttributeValue::Round;
132*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
133*3ac0a46fSAndroid Build Coastguard Worker sy = FXSYS_PI / 2;
134*3ac0a46fSAndroid Build Coastguard Worker }
135*3ac0a46fSAndroid Build Coastguard Worker switch (i) {
136*3ac0a46fSAndroid Build Coastguard Worker case 0:
137*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.TopLeft();
138*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.TopRight();
139*3ac0a46fSAndroid Build Coastguard Worker vx = 1;
140*3ac0a46fSAndroid Build Coastguard Worker vy = 1;
141*3ac0a46fSAndroid Build Coastguard Worker nx = -1;
142*3ac0a46fSAndroid Build Coastguard Worker ny = 0;
143*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
144*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI / 2 : FXSYS_PI;
145*3ac0a46fSAndroid Build Coastguard Worker } else {
146*3ac0a46fSAndroid Build Coastguard Worker sx = 1;
147*3ac0a46fSAndroid Build Coastguard Worker sy = 0;
148*3ac0a46fSAndroid Build Coastguard Worker }
149*3ac0a46fSAndroid Build Coastguard Worker break;
150*3ac0a46fSAndroid Build Coastguard Worker case 2:
151*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.TopRight();
152*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.BottomRight();
153*3ac0a46fSAndroid Build Coastguard Worker vx = -1;
154*3ac0a46fSAndroid Build Coastguard Worker vy = 1;
155*3ac0a46fSAndroid Build Coastguard Worker nx = 0;
156*3ac0a46fSAndroid Build Coastguard Worker ny = -1;
157*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
158*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI : FXSYS_PI * 3 / 2;
159*3ac0a46fSAndroid Build Coastguard Worker } else {
160*3ac0a46fSAndroid Build Coastguard Worker sx = 0;
161*3ac0a46fSAndroid Build Coastguard Worker sy = 1;
162*3ac0a46fSAndroid Build Coastguard Worker }
163*3ac0a46fSAndroid Build Coastguard Worker break;
164*3ac0a46fSAndroid Build Coastguard Worker case 4:
165*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.BottomRight();
166*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.BottomLeft();
167*3ac0a46fSAndroid Build Coastguard Worker vx = -1;
168*3ac0a46fSAndroid Build Coastguard Worker vy = -1;
169*3ac0a46fSAndroid Build Coastguard Worker nx = 1;
170*3ac0a46fSAndroid Build Coastguard Worker ny = 0;
171*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
172*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI * 3 / 2 : 0;
173*3ac0a46fSAndroid Build Coastguard Worker } else {
174*3ac0a46fSAndroid Build Coastguard Worker sx = -1;
175*3ac0a46fSAndroid Build Coastguard Worker sy = 0;
176*3ac0a46fSAndroid Build Coastguard Worker }
177*3ac0a46fSAndroid Build Coastguard Worker break;
178*3ac0a46fSAndroid Build Coastguard Worker case 6:
179*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.BottomLeft();
180*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.TopLeft();
181*3ac0a46fSAndroid Build Coastguard Worker vx = 1;
182*3ac0a46fSAndroid Build Coastguard Worker vy = -1;
183*3ac0a46fSAndroid Build Coastguard Worker nx = 0;
184*3ac0a46fSAndroid Build Coastguard Worker ny = 1;
185*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
186*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? 0 : FXSYS_PI / 2;
187*3ac0a46fSAndroid Build Coastguard Worker } else {
188*3ac0a46fSAndroid Build Coastguard Worker sx = 0;
189*3ac0a46fSAndroid Build Coastguard Worker sy = -1;
190*3ac0a46fSAndroid Build Coastguard Worker }
191*3ac0a46fSAndroid Build Coastguard Worker break;
192*3ac0a46fSAndroid Build Coastguard Worker }
193*3ac0a46fSAndroid Build Coastguard Worker if (i == 0)
194*3ac0a46fSAndroid Build Coastguard Worker fillPath->MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1));
195*3ac0a46fSAndroid Build Coastguard Worker
196*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
197*3ac0a46fSAndroid Build Coastguard Worker if (fRadius1 < 0)
198*3ac0a46fSAndroid Build Coastguard Worker sx -= FXSYS_PI;
199*3ac0a46fSAndroid Build Coastguard Worker if (bInverted)
200*3ac0a46fSAndroid Build Coastguard Worker sy *= -1;
201*3ac0a46fSAndroid Build Coastguard Worker
202*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
203*3ac0a46fSAndroid Build Coastguard Worker rtRadius.Normalize();
204*3ac0a46fSAndroid Build Coastguard Worker if (bInverted)
205*3ac0a46fSAndroid Build Coastguard Worker rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
206*3ac0a46fSAndroid Build Coastguard Worker
207*3ac0a46fSAndroid Build Coastguard Worker fillPath->ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
208*3ac0a46fSAndroid Build Coastguard Worker } else {
209*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp;
210*3ac0a46fSAndroid Build Coastguard Worker if (bInverted) {
211*3ac0a46fSAndroid Build Coastguard Worker cp.x = cp1.x + fRadius1 * vx;
212*3ac0a46fSAndroid Build Coastguard Worker cp.y = cp1.y + fRadius1 * vy;
213*3ac0a46fSAndroid Build Coastguard Worker } else {
214*3ac0a46fSAndroid Build Coastguard Worker cp = cp1;
215*3ac0a46fSAndroid Build Coastguard Worker }
216*3ac0a46fSAndroid Build Coastguard Worker fillPath->LineTo(cp);
217*3ac0a46fSAndroid Build Coastguard Worker fillPath->LineTo(
218*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy));
219*3ac0a46fSAndroid Build Coastguard Worker }
220*3ac0a46fSAndroid Build Coastguard Worker fillPath->LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny));
221*3ac0a46fSAndroid Build Coastguard Worker }
222*3ac0a46fSAndroid Build Coastguard Worker }
223*3ac0a46fSAndroid Build Coastguard Worker
Draw(const std::vector<CXFA_Stroke * > & strokes,CFGAS_GEGraphics * pGS,CFX_RectF rtWidget,const CFX_Matrix & matrix)224*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::Draw(const std::vector<CXFA_Stroke*>& strokes,
225*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEGraphics* pGS,
226*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtWidget,
227*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
228*3ac0a46fSAndroid Build Coastguard Worker bool bVisible = false;
229*3ac0a46fSAndroid Build Coastguard Worker for (int32_t j = 0; j < 4; j++) {
230*3ac0a46fSAndroid Build Coastguard Worker if (strokes[j * 2 + 1]->IsVisible()) {
231*3ac0a46fSAndroid Build Coastguard Worker bVisible = true;
232*3ac0a46fSAndroid Build Coastguard Worker break;
233*3ac0a46fSAndroid Build Coastguard Worker }
234*3ac0a46fSAndroid Build Coastguard Worker }
235*3ac0a46fSAndroid Build Coastguard Worker if (!bVisible)
236*3ac0a46fSAndroid Build Coastguard Worker return;
237*3ac0a46fSAndroid Build Coastguard Worker
238*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 1; i < 8; i += 2) {
239*3ac0a46fSAndroid Build Coastguard Worker float fThickness = fmax(0.0, strokes[i]->GetThickness());
240*3ac0a46fSAndroid Build Coastguard Worker float fHalf = fThickness / 2;
241*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue iHand = GetHand();
242*3ac0a46fSAndroid Build Coastguard Worker switch (i) {
243*3ac0a46fSAndroid Build Coastguard Worker case 1:
244*3ac0a46fSAndroid Build Coastguard Worker if (iHand == XFA_AttributeValue::Left) {
245*3ac0a46fSAndroid Build Coastguard Worker rtWidget.top -= fHalf;
246*3ac0a46fSAndroid Build Coastguard Worker rtWidget.height += fHalf;
247*3ac0a46fSAndroid Build Coastguard Worker } else if (iHand == XFA_AttributeValue::Right) {
248*3ac0a46fSAndroid Build Coastguard Worker rtWidget.top += fHalf;
249*3ac0a46fSAndroid Build Coastguard Worker rtWidget.height -= fHalf;
250*3ac0a46fSAndroid Build Coastguard Worker }
251*3ac0a46fSAndroid Build Coastguard Worker break;
252*3ac0a46fSAndroid Build Coastguard Worker case 3:
253*3ac0a46fSAndroid Build Coastguard Worker if (iHand == XFA_AttributeValue::Left) {
254*3ac0a46fSAndroid Build Coastguard Worker rtWidget.width += fHalf;
255*3ac0a46fSAndroid Build Coastguard Worker } else if (iHand == XFA_AttributeValue::Right) {
256*3ac0a46fSAndroid Build Coastguard Worker rtWidget.width -= fHalf;
257*3ac0a46fSAndroid Build Coastguard Worker }
258*3ac0a46fSAndroid Build Coastguard Worker break;
259*3ac0a46fSAndroid Build Coastguard Worker case 5:
260*3ac0a46fSAndroid Build Coastguard Worker if (iHand == XFA_AttributeValue::Left) {
261*3ac0a46fSAndroid Build Coastguard Worker rtWidget.height += fHalf;
262*3ac0a46fSAndroid Build Coastguard Worker } else if (iHand == XFA_AttributeValue::Right) {
263*3ac0a46fSAndroid Build Coastguard Worker rtWidget.height -= fHalf;
264*3ac0a46fSAndroid Build Coastguard Worker }
265*3ac0a46fSAndroid Build Coastguard Worker break;
266*3ac0a46fSAndroid Build Coastguard Worker case 7:
267*3ac0a46fSAndroid Build Coastguard Worker if (iHand == XFA_AttributeValue::Left) {
268*3ac0a46fSAndroid Build Coastguard Worker rtWidget.left -= fHalf;
269*3ac0a46fSAndroid Build Coastguard Worker rtWidget.width += fHalf;
270*3ac0a46fSAndroid Build Coastguard Worker } else if (iHand == XFA_AttributeValue::Right) {
271*3ac0a46fSAndroid Build Coastguard Worker rtWidget.left += fHalf;
272*3ac0a46fSAndroid Build Coastguard Worker rtWidget.width -= fHalf;
273*3ac0a46fSAndroid Build Coastguard Worker }
274*3ac0a46fSAndroid Build Coastguard Worker break;
275*3ac0a46fSAndroid Build Coastguard Worker }
276*3ac0a46fSAndroid Build Coastguard Worker }
277*3ac0a46fSAndroid Build Coastguard Worker Stroke(strokes, pGS, rtWidget, matrix);
278*3ac0a46fSAndroid Build Coastguard Worker }
279*3ac0a46fSAndroid Build Coastguard Worker
Stroke(const std::vector<CXFA_Stroke * > & strokes,CFGAS_GEGraphics * pGS,CFX_RectF rtWidget,const CFX_Matrix & matrix)280*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::Stroke(const std::vector<CXFA_Stroke*>& strokes,
281*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEGraphics* pGS,
282*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtWidget,
283*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
284*3ac0a46fSAndroid Build Coastguard Worker bool bVisible;
285*3ac0a46fSAndroid Build Coastguard Worker float fThickness;
286*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue i3DType;
287*3ac0a46fSAndroid Build Coastguard Worker std::tie(i3DType, bVisible, fThickness) = Get3DStyle();
288*3ac0a46fSAndroid Build Coastguard Worker if (i3DType != XFA_AttributeValue::Unknown) {
289*3ac0a46fSAndroid Build Coastguard Worker if (!bVisible || fThickness < 0.001f)
290*3ac0a46fSAndroid Build Coastguard Worker return;
291*3ac0a46fSAndroid Build Coastguard Worker
292*3ac0a46fSAndroid Build Coastguard Worker switch (i3DType) {
293*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Lowered:
294*3ac0a46fSAndroid Build Coastguard Worker StrokeLowered(pGS, rtWidget, fThickness, matrix);
295*3ac0a46fSAndroid Build Coastguard Worker break;
296*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Raised:
297*3ac0a46fSAndroid Build Coastguard Worker StrokeRaised(pGS, rtWidget, fThickness, matrix);
298*3ac0a46fSAndroid Build Coastguard Worker break;
299*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Etched:
300*3ac0a46fSAndroid Build Coastguard Worker StrokeEtched(pGS, rtWidget, fThickness, matrix);
301*3ac0a46fSAndroid Build Coastguard Worker break;
302*3ac0a46fSAndroid Build Coastguard Worker case XFA_AttributeValue::Embossed:
303*3ac0a46fSAndroid Build Coastguard Worker StrokeEmbossed(pGS, rtWidget, fThickness, matrix);
304*3ac0a46fSAndroid Build Coastguard Worker break;
305*3ac0a46fSAndroid Build Coastguard Worker default:
306*3ac0a46fSAndroid Build Coastguard Worker NOTREACHED_NORETURN();
307*3ac0a46fSAndroid Build Coastguard Worker }
308*3ac0a46fSAndroid Build Coastguard Worker return;
309*3ac0a46fSAndroid Build Coastguard Worker }
310*3ac0a46fSAndroid Build Coastguard Worker
311*3ac0a46fSAndroid Build Coastguard Worker bool bClose = false;
312*3ac0a46fSAndroid Build Coastguard Worker bool bSameStyles = true;
313*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke1 = strokes[0];
314*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 1; i < 8; i++) {
315*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke2 = strokes[i];
316*3ac0a46fSAndroid Build Coastguard Worker if (!stroke1->SameStyles(stroke2, {})) {
317*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
318*3ac0a46fSAndroid Build Coastguard Worker break;
319*3ac0a46fSAndroid Build Coastguard Worker }
320*3ac0a46fSAndroid Build Coastguard Worker stroke1 = stroke2;
321*3ac0a46fSAndroid Build Coastguard Worker }
322*3ac0a46fSAndroid Build Coastguard Worker if (bSameStyles) {
323*3ac0a46fSAndroid Build Coastguard Worker stroke1 = strokes[0];
324*3ac0a46fSAndroid Build Coastguard Worker bClose = true;
325*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 2; i < 8; i += 2) {
326*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke2 = strokes[i];
327*3ac0a46fSAndroid Build Coastguard Worker if (!stroke1->SameStyles(stroke2,
328*3ac0a46fSAndroid Build Coastguard Worker {CXFA_Stroke::SameStyleOption::kNoPresence,
329*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke::SameStyleOption::kCorner})) {
330*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
331*3ac0a46fSAndroid Build Coastguard Worker break;
332*3ac0a46fSAndroid Build Coastguard Worker }
333*3ac0a46fSAndroid Build Coastguard Worker stroke1 = stroke2;
334*3ac0a46fSAndroid Build Coastguard Worker }
335*3ac0a46fSAndroid Build Coastguard Worker if (bSameStyles) {
336*3ac0a46fSAndroid Build Coastguard Worker stroke1 = strokes[0];
337*3ac0a46fSAndroid Build Coastguard Worker if (stroke1->IsInverted())
338*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
339*3ac0a46fSAndroid Build Coastguard Worker if (stroke1->GetJoinType() != XFA_AttributeValue::Square)
340*3ac0a46fSAndroid Build Coastguard Worker bSameStyles = false;
341*3ac0a46fSAndroid Build Coastguard Worker }
342*3ac0a46fSAndroid Build Coastguard Worker }
343*3ac0a46fSAndroid Build Coastguard Worker
344*3ac0a46fSAndroid Build Coastguard Worker bool bStart = true;
345*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath path;
346*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 0; i < 8; i++) {
347*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke = strokes[i];
348*3ac0a46fSAndroid Build Coastguard Worker if ((i % 1) == 0 && stroke->GetRadius() < 0) {
349*3ac0a46fSAndroid Build Coastguard Worker bool bEmpty = path.IsEmpty();
350*3ac0a46fSAndroid Build Coastguard Worker if (!bEmpty) {
351*3ac0a46fSAndroid Build Coastguard Worker if (stroke)
352*3ac0a46fSAndroid Build Coastguard Worker stroke->Stroke(pGS, path, matrix);
353*3ac0a46fSAndroid Build Coastguard Worker path.Clear();
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker bStart = true;
356*3ac0a46fSAndroid Build Coastguard Worker continue;
357*3ac0a46fSAndroid Build Coastguard Worker }
358*3ac0a46fSAndroid Build Coastguard Worker GetPath(strokes, rtWidget, path, i, bStart, !bSameStyles);
359*3ac0a46fSAndroid Build Coastguard Worker
360*3ac0a46fSAndroid Build Coastguard Worker bStart = !stroke->SameStyles(strokes[(i + 1) % 8], {});
361*3ac0a46fSAndroid Build Coastguard Worker if (bStart) {
362*3ac0a46fSAndroid Build Coastguard Worker if (stroke)
363*3ac0a46fSAndroid Build Coastguard Worker stroke->Stroke(pGS, path, matrix);
364*3ac0a46fSAndroid Build Coastguard Worker path.Clear();
365*3ac0a46fSAndroid Build Coastguard Worker }
366*3ac0a46fSAndroid Build Coastguard Worker }
367*3ac0a46fSAndroid Build Coastguard Worker bool bEmpty = path.IsEmpty();
368*3ac0a46fSAndroid Build Coastguard Worker if (!bEmpty) {
369*3ac0a46fSAndroid Build Coastguard Worker if (bClose) {
370*3ac0a46fSAndroid Build Coastguard Worker path.Close();
371*3ac0a46fSAndroid Build Coastguard Worker }
372*3ac0a46fSAndroid Build Coastguard Worker if (strokes[7])
373*3ac0a46fSAndroid Build Coastguard Worker strokes[7]->Stroke(pGS, path, matrix);
374*3ac0a46fSAndroid Build Coastguard Worker }
375*3ac0a46fSAndroid Build Coastguard Worker }
376*3ac0a46fSAndroid Build Coastguard Worker
StrokeRect(CFGAS_GEGraphics * pGraphic,const CFX_RectF & rt,float fLineWidth,const CFX_Matrix & matrix,FX_ARGB argbTopLeft,FX_ARGB argbBottomRight)377*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::StrokeRect(CFGAS_GEGraphics* pGraphic,
378*3ac0a46fSAndroid Build Coastguard Worker const CFX_RectF& rt,
379*3ac0a46fSAndroid Build Coastguard Worker float fLineWidth,
380*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix,
381*3ac0a46fSAndroid Build Coastguard Worker FX_ARGB argbTopLeft,
382*3ac0a46fSAndroid Build Coastguard Worker FX_ARGB argbBottomRight) {
383*3ac0a46fSAndroid Build Coastguard Worker float fBottom = rt.bottom();
384*3ac0a46fSAndroid Build Coastguard Worker float fRight = rt.right();
385*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath pathLT;
386*3ac0a46fSAndroid Build Coastguard Worker pathLT.MoveTo(CFX_PointF(rt.left, fBottom));
387*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(rt.left, rt.top));
388*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(fRight, rt.top));
389*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
390*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth));
391*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
392*3ac0a46fSAndroid Build Coastguard Worker pathLT.LineTo(CFX_PointF(rt.left, fBottom));
393*3ac0a46fSAndroid Build Coastguard Worker pGraphic->SetFillColor(CFGAS_GEColor(argbTopLeft));
394*3ac0a46fSAndroid Build Coastguard Worker pGraphic->FillPath(pathLT, CFX_FillRenderOptions::FillType::kWinding, matrix);
395*3ac0a46fSAndroid Build Coastguard Worker
396*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath pathRB;
397*3ac0a46fSAndroid Build Coastguard Worker pathRB.MoveTo(CFX_PointF(fRight, rt.top));
398*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(fRight, fBottom));
399*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(rt.left, fBottom));
400*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
401*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth));
402*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
403*3ac0a46fSAndroid Build Coastguard Worker pathRB.LineTo(CFX_PointF(fRight, rt.top));
404*3ac0a46fSAndroid Build Coastguard Worker pGraphic->SetFillColor(CFGAS_GEColor(argbBottomRight));
405*3ac0a46fSAndroid Build Coastguard Worker pGraphic->FillPath(pathRB, CFX_FillRenderOptions::FillType::kWinding, matrix);
406*3ac0a46fSAndroid Build Coastguard Worker }
407*3ac0a46fSAndroid Build Coastguard Worker
StrokeLowered(CFGAS_GEGraphics * pGS,CFX_RectF rt,float fThickness,const CFX_Matrix & matrix)408*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::StrokeLowered(CFGAS_GEGraphics* pGS,
409*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rt,
410*3ac0a46fSAndroid Build Coastguard Worker float fThickness,
411*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
412*3ac0a46fSAndroid Build Coastguard Worker float fHalfWidth = fThickness / 2.0f;
413*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtInner(rt);
414*3ac0a46fSAndroid Build Coastguard Worker rtInner.Deflate(fHalfWidth, fHalfWidth);
415*3ac0a46fSAndroid Build Coastguard Worker
416*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath path;
417*3ac0a46fSAndroid Build Coastguard Worker path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
418*3ac0a46fSAndroid Build Coastguard Worker path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
419*3ac0a46fSAndroid Build Coastguard Worker pGS->SetFillColor(CFGAS_GEColor(0xFF000000));
420*3ac0a46fSAndroid Build Coastguard Worker pGS->FillPath(path, CFX_FillRenderOptions::FillType::kEvenOdd, matrix);
421*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFF808080, 0xFFC0C0C0);
422*3ac0a46fSAndroid Build Coastguard Worker }
423*3ac0a46fSAndroid Build Coastguard Worker
StrokeRaised(CFGAS_GEGraphics * pGS,CFX_RectF rt,float fThickness,const CFX_Matrix & matrix)424*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::StrokeRaised(CFGAS_GEGraphics* pGS,
425*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rt,
426*3ac0a46fSAndroid Build Coastguard Worker float fThickness,
427*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
428*3ac0a46fSAndroid Build Coastguard Worker float fHalfWidth = fThickness / 2.0f;
429*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtInner(rt);
430*3ac0a46fSAndroid Build Coastguard Worker rtInner.Deflate(fHalfWidth, fHalfWidth);
431*3ac0a46fSAndroid Build Coastguard Worker
432*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath path;
433*3ac0a46fSAndroid Build Coastguard Worker path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
434*3ac0a46fSAndroid Build Coastguard Worker path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
435*3ac0a46fSAndroid Build Coastguard Worker pGS->SetFillColor(CFGAS_GEColor(0xFF000000));
436*3ac0a46fSAndroid Build Coastguard Worker pGS->FillPath(path, CFX_FillRenderOptions::FillType::kEvenOdd, matrix);
437*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFFFFFFFF, 0xFF808080);
438*3ac0a46fSAndroid Build Coastguard Worker }
439*3ac0a46fSAndroid Build Coastguard Worker
StrokeEtched(CFGAS_GEGraphics * pGS,CFX_RectF rt,float fThickness,const CFX_Matrix & matrix)440*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::StrokeEtched(CFGAS_GEGraphics* pGS,
441*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rt,
442*3ac0a46fSAndroid Build Coastguard Worker float fThickness,
443*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
444*3ac0a46fSAndroid Build Coastguard Worker float fHalfWidth = fThickness / 2.0f;
445*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rt, fThickness, matrix, 0xFF808080, 0xFFFFFFFF);
446*3ac0a46fSAndroid Build Coastguard Worker
447*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtInner(rt);
448*3ac0a46fSAndroid Build Coastguard Worker rtInner.Deflate(fHalfWidth, fHalfWidth);
449*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFFFFFFFF, 0xFF808080);
450*3ac0a46fSAndroid Build Coastguard Worker }
451*3ac0a46fSAndroid Build Coastguard Worker
StrokeEmbossed(CFGAS_GEGraphics * pGS,CFX_RectF rt,float fThickness,const CFX_Matrix & matrix)452*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::StrokeEmbossed(CFGAS_GEGraphics* pGS,
453*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rt,
454*3ac0a46fSAndroid Build Coastguard Worker float fThickness,
455*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& matrix) {
456*3ac0a46fSAndroid Build Coastguard Worker float fHalfWidth = fThickness / 2.0f;
457*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rt, fThickness, matrix, 0xFF808080, 0xFF000000);
458*3ac0a46fSAndroid Build Coastguard Worker
459*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtInner(rt);
460*3ac0a46fSAndroid Build Coastguard Worker rtInner.Deflate(fHalfWidth, fHalfWidth);
461*3ac0a46fSAndroid Build Coastguard Worker StrokeRect(pGS, rtInner, fHalfWidth, matrix, 0xFF000000, 0xFF808080);
462*3ac0a46fSAndroid Build Coastguard Worker }
463*3ac0a46fSAndroid Build Coastguard Worker
GetPath(const std::vector<CXFA_Stroke * > & strokes,CFX_RectF rtWidget,CFGAS_GEPath & path,int32_t nIndex,bool bStart,bool bCorner)464*3ac0a46fSAndroid Build Coastguard Worker void CXFA_Rectangle::GetPath(const std::vector<CXFA_Stroke*>& strokes,
465*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtWidget,
466*3ac0a46fSAndroid Build Coastguard Worker CFGAS_GEPath& path,
467*3ac0a46fSAndroid Build Coastguard Worker int32_t nIndex,
468*3ac0a46fSAndroid Build Coastguard Worker bool bStart,
469*3ac0a46fSAndroid Build Coastguard Worker bool bCorner) {
470*3ac0a46fSAndroid Build Coastguard Worker DCHECK(nIndex >= 0);
471*3ac0a46fSAndroid Build Coastguard Worker DCHECK(nIndex < 8);
472*3ac0a46fSAndroid Build Coastguard Worker
473*3ac0a46fSAndroid Build Coastguard Worker int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
474*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* corner1 = strokes[n];
475*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* corner2 = strokes[(n + 2) % 8];
476*3ac0a46fSAndroid Build Coastguard Worker float fRadius1 = bCorner ? corner1->GetRadius() : 0.0f;
477*3ac0a46fSAndroid Build Coastguard Worker float fRadius2 = bCorner ? corner2->GetRadius() : 0.0f;
478*3ac0a46fSAndroid Build Coastguard Worker bool bInverted = corner1->IsInverted();
479*3ac0a46fSAndroid Build Coastguard Worker float offsetY = 0.0f;
480*3ac0a46fSAndroid Build Coastguard Worker float offsetX = 0.0f;
481*3ac0a46fSAndroid Build Coastguard Worker bool bRound = corner1->GetJoinType() == XFA_AttributeValue::Round;
482*3ac0a46fSAndroid Build Coastguard Worker float halfAfter = 0.0f;
483*3ac0a46fSAndroid Build Coastguard Worker float halfBefore = 0.0f;
484*3ac0a46fSAndroid Build Coastguard Worker
485*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* stroke = strokes[nIndex];
486*3ac0a46fSAndroid Build Coastguard Worker if (stroke->IsCorner()) {
487*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* strokeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
488*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* strokeAfter = strokes[nIndex + 1];
489*3ac0a46fSAndroid Build Coastguard Worker if (stroke->IsInverted()) {
490*3ac0a46fSAndroid Build Coastguard Worker if (!stroke->SameStyles(strokeBefore, {}))
491*3ac0a46fSAndroid Build Coastguard Worker halfBefore = strokeBefore->GetThickness() / 2;
492*3ac0a46fSAndroid Build Coastguard Worker if (!stroke->SameStyles(strokeAfter, {}))
493*3ac0a46fSAndroid Build Coastguard Worker halfAfter = strokeAfter->GetThickness() / 2;
494*3ac0a46fSAndroid Build Coastguard Worker }
495*3ac0a46fSAndroid Build Coastguard Worker } else {
496*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* strokeBefore = strokes[(nIndex + 8 - 2) % 8];
497*3ac0a46fSAndroid Build Coastguard Worker CXFA_Stroke* strokeAfter = strokes[(nIndex + 2) % 8];
498*3ac0a46fSAndroid Build Coastguard Worker if (!bRound && !bInverted) {
499*3ac0a46fSAndroid Build Coastguard Worker halfBefore = strokeBefore->GetThickness() / 2;
500*3ac0a46fSAndroid Build Coastguard Worker halfAfter = strokeAfter->GetThickness() / 2;
501*3ac0a46fSAndroid Build Coastguard Worker }
502*3ac0a46fSAndroid Build Coastguard Worker }
503*3ac0a46fSAndroid Build Coastguard Worker
504*3ac0a46fSAndroid Build Coastguard Worker float offsetEX = 0.0f;
505*3ac0a46fSAndroid Build Coastguard Worker float offsetEY = 0.0f;
506*3ac0a46fSAndroid Build Coastguard Worker float sx = 0.0f;
507*3ac0a46fSAndroid Build Coastguard Worker float sy = 0.0f;
508*3ac0a46fSAndroid Build Coastguard Worker float vx = 1.0f;
509*3ac0a46fSAndroid Build Coastguard Worker float vy = 1.0f;
510*3ac0a46fSAndroid Build Coastguard Worker float nx = 1.0f;
511*3ac0a46fSAndroid Build Coastguard Worker float ny = 1.0f;
512*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cpStart;
513*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp1;
514*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp2;
515*3ac0a46fSAndroid Build Coastguard Worker if (bRound)
516*3ac0a46fSAndroid Build Coastguard Worker sy = FXSYS_PI / 2;
517*3ac0a46fSAndroid Build Coastguard Worker
518*3ac0a46fSAndroid Build Coastguard Worker switch (nIndex) {
519*3ac0a46fSAndroid Build Coastguard Worker case 0:
520*3ac0a46fSAndroid Build Coastguard Worker case 1:
521*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.TopLeft();
522*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.TopRight();
523*3ac0a46fSAndroid Build Coastguard Worker if (nIndex == 0) {
524*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x - halfBefore;
525*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y + fRadius1;
526*3ac0a46fSAndroid Build Coastguard Worker offsetY = -halfAfter;
527*3ac0a46fSAndroid Build Coastguard Worker } else {
528*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x + fRadius1 - halfBefore;
529*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y;
530*3ac0a46fSAndroid Build Coastguard Worker offsetEX = halfAfter;
531*3ac0a46fSAndroid Build Coastguard Worker }
532*3ac0a46fSAndroid Build Coastguard Worker vx = 1;
533*3ac0a46fSAndroid Build Coastguard Worker vy = 1;
534*3ac0a46fSAndroid Build Coastguard Worker nx = -1;
535*3ac0a46fSAndroid Build Coastguard Worker ny = 0;
536*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
537*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI / 2 : FXSYS_PI;
538*3ac0a46fSAndroid Build Coastguard Worker } else {
539*3ac0a46fSAndroid Build Coastguard Worker sx = 1;
540*3ac0a46fSAndroid Build Coastguard Worker sy = 0;
541*3ac0a46fSAndroid Build Coastguard Worker }
542*3ac0a46fSAndroid Build Coastguard Worker break;
543*3ac0a46fSAndroid Build Coastguard Worker case 2:
544*3ac0a46fSAndroid Build Coastguard Worker case 3:
545*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.TopRight();
546*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.BottomRight();
547*3ac0a46fSAndroid Build Coastguard Worker if (nIndex == 2) {
548*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x - fRadius1;
549*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y - halfBefore;
550*3ac0a46fSAndroid Build Coastguard Worker offsetX = halfAfter;
551*3ac0a46fSAndroid Build Coastguard Worker } else {
552*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x;
553*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y + fRadius1 - halfBefore;
554*3ac0a46fSAndroid Build Coastguard Worker offsetEY = halfAfter;
555*3ac0a46fSAndroid Build Coastguard Worker }
556*3ac0a46fSAndroid Build Coastguard Worker vx = -1;
557*3ac0a46fSAndroid Build Coastguard Worker vy = 1;
558*3ac0a46fSAndroid Build Coastguard Worker nx = 0;
559*3ac0a46fSAndroid Build Coastguard Worker ny = -1;
560*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
561*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI : FXSYS_PI * 3 / 2;
562*3ac0a46fSAndroid Build Coastguard Worker } else {
563*3ac0a46fSAndroid Build Coastguard Worker sx = 0;
564*3ac0a46fSAndroid Build Coastguard Worker sy = 1;
565*3ac0a46fSAndroid Build Coastguard Worker }
566*3ac0a46fSAndroid Build Coastguard Worker break;
567*3ac0a46fSAndroid Build Coastguard Worker case 4:
568*3ac0a46fSAndroid Build Coastguard Worker case 5:
569*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.BottomRight();
570*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.BottomLeft();
571*3ac0a46fSAndroid Build Coastguard Worker if (nIndex == 4) {
572*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x + halfBefore;
573*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y - fRadius1;
574*3ac0a46fSAndroid Build Coastguard Worker offsetY = halfAfter;
575*3ac0a46fSAndroid Build Coastguard Worker } else {
576*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x - fRadius1 + halfBefore;
577*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y;
578*3ac0a46fSAndroid Build Coastguard Worker offsetEX = -halfAfter;
579*3ac0a46fSAndroid Build Coastguard Worker }
580*3ac0a46fSAndroid Build Coastguard Worker vx = -1;
581*3ac0a46fSAndroid Build Coastguard Worker vy = -1;
582*3ac0a46fSAndroid Build Coastguard Worker nx = 1;
583*3ac0a46fSAndroid Build Coastguard Worker ny = 0;
584*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
585*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? FXSYS_PI * 3 / 2 : 0;
586*3ac0a46fSAndroid Build Coastguard Worker } else {
587*3ac0a46fSAndroid Build Coastguard Worker sx = -1;
588*3ac0a46fSAndroid Build Coastguard Worker sy = 0;
589*3ac0a46fSAndroid Build Coastguard Worker }
590*3ac0a46fSAndroid Build Coastguard Worker break;
591*3ac0a46fSAndroid Build Coastguard Worker case 6:
592*3ac0a46fSAndroid Build Coastguard Worker case 7:
593*3ac0a46fSAndroid Build Coastguard Worker cp1 = rtWidget.BottomLeft();
594*3ac0a46fSAndroid Build Coastguard Worker cp2 = rtWidget.TopLeft();
595*3ac0a46fSAndroid Build Coastguard Worker if (nIndex == 6) {
596*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x + fRadius1;
597*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y + halfBefore;
598*3ac0a46fSAndroid Build Coastguard Worker offsetX = -halfAfter;
599*3ac0a46fSAndroid Build Coastguard Worker } else {
600*3ac0a46fSAndroid Build Coastguard Worker cpStart.x = cp1.x;
601*3ac0a46fSAndroid Build Coastguard Worker cpStart.y = cp1.y - fRadius1 + halfBefore;
602*3ac0a46fSAndroid Build Coastguard Worker offsetEY = -halfAfter;
603*3ac0a46fSAndroid Build Coastguard Worker }
604*3ac0a46fSAndroid Build Coastguard Worker vx = 1;
605*3ac0a46fSAndroid Build Coastguard Worker vy = -1;
606*3ac0a46fSAndroid Build Coastguard Worker nx = 0;
607*3ac0a46fSAndroid Build Coastguard Worker ny = 1;
608*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
609*3ac0a46fSAndroid Build Coastguard Worker sx = bInverted ? 0 : FXSYS_PI / 2;
610*3ac0a46fSAndroid Build Coastguard Worker } else {
611*3ac0a46fSAndroid Build Coastguard Worker sx = 0;
612*3ac0a46fSAndroid Build Coastguard Worker sy = -1;
613*3ac0a46fSAndroid Build Coastguard Worker }
614*3ac0a46fSAndroid Build Coastguard Worker break;
615*3ac0a46fSAndroid Build Coastguard Worker }
616*3ac0a46fSAndroid Build Coastguard Worker if (bStart) {
617*3ac0a46fSAndroid Build Coastguard Worker path.MoveTo(cpStart);
618*3ac0a46fSAndroid Build Coastguard Worker }
619*3ac0a46fSAndroid Build Coastguard Worker if (nIndex & 1) {
620*3ac0a46fSAndroid Build Coastguard Worker path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX,
621*3ac0a46fSAndroid Build Coastguard Worker cp2.y + fRadius2 * ny + offsetEY));
622*3ac0a46fSAndroid Build Coastguard Worker return;
623*3ac0a46fSAndroid Build Coastguard Worker }
624*3ac0a46fSAndroid Build Coastguard Worker if (bRound) {
625*3ac0a46fSAndroid Build Coastguard Worker if (fRadius1 < 0)
626*3ac0a46fSAndroid Build Coastguard Worker sx -= FXSYS_PI;
627*3ac0a46fSAndroid Build Coastguard Worker if (bInverted)
628*3ac0a46fSAndroid Build Coastguard Worker sy *= -1;
629*3ac0a46fSAndroid Build Coastguard Worker
630*3ac0a46fSAndroid Build Coastguard Worker CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
631*3ac0a46fSAndroid Build Coastguard Worker fRadius1 * 2 * vx - offsetX * 2,
632*3ac0a46fSAndroid Build Coastguard Worker fRadius1 * 2 * vy - offsetY * 2);
633*3ac0a46fSAndroid Build Coastguard Worker rtRadius.Normalize();
634*3ac0a46fSAndroid Build Coastguard Worker if (bInverted)
635*3ac0a46fSAndroid Build Coastguard Worker rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
636*3ac0a46fSAndroid Build Coastguard Worker
637*3ac0a46fSAndroid Build Coastguard Worker path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
638*3ac0a46fSAndroid Build Coastguard Worker } else {
639*3ac0a46fSAndroid Build Coastguard Worker CFX_PointF cp;
640*3ac0a46fSAndroid Build Coastguard Worker if (bInverted) {
641*3ac0a46fSAndroid Build Coastguard Worker cp.x = cp1.x + fRadius1 * vx;
642*3ac0a46fSAndroid Build Coastguard Worker cp.y = cp1.y + fRadius1 * vy;
643*3ac0a46fSAndroid Build Coastguard Worker } else {
644*3ac0a46fSAndroid Build Coastguard Worker cp = cp1;
645*3ac0a46fSAndroid Build Coastguard Worker }
646*3ac0a46fSAndroid Build Coastguard Worker path.LineTo(cp);
647*3ac0a46fSAndroid Build Coastguard Worker path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX,
648*3ac0a46fSAndroid Build Coastguard Worker cp1.y + fRadius1 * sy + offsetY));
649*3ac0a46fSAndroid Build Coastguard Worker }
650*3ac0a46fSAndroid Build Coastguard Worker }
651