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/cxfa_ffline.h"
8
9 #include "third_party/base/notreached.h"
10 #include "xfa/fgas/graphics/cfgas_gecolor.h"
11 #include "xfa/fgas/graphics/cfgas_gegraphics.h"
12 #include "xfa/fgas/graphics/cfgas_gepath.h"
13 #include "xfa/fxfa/parser/cxfa_edge.h"
14 #include "xfa/fxfa/parser/cxfa_line.h"
15 #include "xfa/fxfa/parser/cxfa_value.h"
16
17 namespace {
18
LineCapToFXGE(XFA_AttributeValue iLineCap)19 CFX_GraphStateData::LineCap LineCapToFXGE(XFA_AttributeValue iLineCap) {
20 switch (iLineCap) {
21 case XFA_AttributeValue::Round:
22 return CFX_GraphStateData::LineCap::kRound;
23 case XFA_AttributeValue::Butt:
24 return CFX_GraphStateData::LineCap::kButt;
25 default:
26 return CFX_GraphStateData::LineCap::kSquare;
27 }
28 }
29
30 } // namespace
31
CXFA_FFLine(CXFA_Node * pNode)32 CXFA_FFLine::CXFA_FFLine(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}
33
34 CXFA_FFLine::~CXFA_FFLine() = default;
35
GetRectFromHand(CFX_RectF & rect,XFA_AttributeValue iHand,float fLineWidth)36 void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect,
37 XFA_AttributeValue iHand,
38 float fLineWidth) {
39 float fHalfWidth = fLineWidth / 2.0f;
40 if (rect.height < 1.0f) {
41 switch (iHand) {
42 case XFA_AttributeValue::Left:
43 rect.top -= fHalfWidth;
44 break;
45 case XFA_AttributeValue::Right:
46 rect.top += fHalfWidth;
47 break;
48 case XFA_AttributeValue::Even:
49 break;
50 default:
51 NOTREACHED();
52 break;
53 }
54 } else if (rect.width < 1.0f) {
55 switch (iHand) {
56 case XFA_AttributeValue::Left:
57 rect.left += fHalfWidth;
58 break;
59 case XFA_AttributeValue::Right:
60 rect.left += fHalfWidth;
61 break;
62 case XFA_AttributeValue::Even:
63 break;
64 default:
65 NOTREACHED();
66 break;
67 }
68 } else {
69 switch (iHand) {
70 case XFA_AttributeValue::Left:
71 rect.Inflate(fHalfWidth, fHalfWidth);
72 break;
73 case XFA_AttributeValue::Right:
74 rect.Deflate(fHalfWidth, fHalfWidth);
75 break;
76 case XFA_AttributeValue::Even:
77 break;
78 default:
79 NOTREACHED();
80 break;
81 }
82 }
83 }
84
RenderWidget(CFGAS_GEGraphics * pGS,const CFX_Matrix & matrix,HighlightOption highlight)85 void CXFA_FFLine::RenderWidget(CFGAS_GEGraphics* pGS,
86 const CFX_Matrix& matrix,
87 HighlightOption highlight) {
88 if (!HasVisibleStatus())
89 return;
90
91 CXFA_Value* value = m_pNode->GetFormValueIfExists();
92 if (!value)
93 return;
94
95 FX_ARGB lineColor = 0xFF000000;
96 float fLineWidth = 1.0f;
97 XFA_AttributeValue iStrokeType = XFA_AttributeValue::Unknown;
98 XFA_AttributeValue iCap = XFA_AttributeValue::Unknown;
99 CXFA_Line* line = value->GetLineIfExists();
100 if (line) {
101 CXFA_Edge* edge = line->GetEdgeIfExists();
102 if (edge && !edge->IsVisible())
103 return;
104
105 if (edge) {
106 lineColor = edge->GetColor();
107 iStrokeType = edge->GetStrokeType();
108 fLineWidth = edge->GetThickness();
109 iCap = edge->GetCapType();
110 }
111 }
112
113 CFX_Matrix mtRotate = GetRotateMatrix();
114 mtRotate.Concat(matrix);
115
116 CFX_RectF rtLine = GetRectWithoutRotate();
117 CXFA_Margin* margin = m_pNode->GetMarginIfExists();
118 XFA_RectWithoutMargin(&rtLine, margin);
119
120 GetRectFromHand(rtLine, line ? line->GetHand() : XFA_AttributeValue::Left,
121 fLineWidth);
122 CFGAS_GEPath linePath;
123 if (line && line->GetSlope() && rtLine.right() > 0.0f &&
124 rtLine.bottom() > 0.0f) {
125 linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft());
126 } else {
127 linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight());
128 }
129
130 CFGAS_GEGraphics::StateRestorer restorer(pGS);
131 pGS->SetLineWidth(fLineWidth);
132 pGS->EnableActOnDash();
133 XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap);
134
135 pGS->SetStrokeColor(CFGAS_GEColor(lineColor));
136 pGS->SetLineCap(LineCapToFXGE(iCap));
137 pGS->StrokePath(linePath, mtRotate);
138 }
139