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_NORETURN();
52 }
53 } else if (rect.width < 1.0f) {
54 switch (iHand) {
55 case XFA_AttributeValue::Left:
56 rect.left += fHalfWidth;
57 break;
58 case XFA_AttributeValue::Right:
59 rect.left += fHalfWidth;
60 break;
61 case XFA_AttributeValue::Even:
62 break;
63 default:
64 NOTREACHED_NORETURN();
65 }
66 } else {
67 switch (iHand) {
68 case XFA_AttributeValue::Left:
69 rect.Inflate(fHalfWidth, fHalfWidth);
70 break;
71 case XFA_AttributeValue::Right:
72 rect.Deflate(fHalfWidth, fHalfWidth);
73 break;
74 case XFA_AttributeValue::Even:
75 break;
76 default:
77 NOTREACHED_NORETURN();
78 }
79 }
80 }
81
RenderWidget(CFGAS_GEGraphics * pGS,const CFX_Matrix & matrix,HighlightOption highlight)82 void CXFA_FFLine::RenderWidget(CFGAS_GEGraphics* pGS,
83 const CFX_Matrix& matrix,
84 HighlightOption highlight) {
85 if (!HasVisibleStatus())
86 return;
87
88 CXFA_Value* value = m_pNode->GetFormValueIfExists();
89 if (!value)
90 return;
91
92 FX_ARGB lineColor = 0xFF000000;
93 float fLineWidth = 1.0f;
94 XFA_AttributeValue iStrokeType = XFA_AttributeValue::Unknown;
95 XFA_AttributeValue iCap = XFA_AttributeValue::Unknown;
96 CXFA_Line* line = value->GetLineIfExists();
97 if (line) {
98 CXFA_Edge* edge = line->GetEdgeIfExists();
99 if (edge && !edge->IsVisible())
100 return;
101
102 if (edge) {
103 lineColor = edge->GetColor();
104 iStrokeType = edge->GetStrokeType();
105 fLineWidth = edge->GetThickness();
106 iCap = edge->GetCapType();
107 }
108 }
109
110 CFX_Matrix mtRotate = GetRotateMatrix();
111 mtRotate.Concat(matrix);
112
113 CFX_RectF rtLine = GetRectWithoutRotate();
114 CXFA_Margin* margin = m_pNode->GetMarginIfExists();
115 XFA_RectWithoutMargin(&rtLine, margin);
116
117 GetRectFromHand(rtLine, line ? line->GetHand() : XFA_AttributeValue::Left,
118 fLineWidth);
119 CFGAS_GEPath linePath;
120 if (line && line->GetSlope() && rtLine.right() > 0.0f &&
121 rtLine.bottom() > 0.0f) {
122 linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft());
123 } else {
124 linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight());
125 }
126
127 CFGAS_GEGraphics::StateRestorer restorer(pGS);
128 pGS->SetLineWidth(fLineWidth);
129 pGS->EnableActOnDash();
130 XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap);
131
132 pGS->SetStrokeColor(CFGAS_GEColor(lineColor));
133 pGS->SetLineCap(LineCapToFXGE(iCap));
134 pGS->StrokePath(linePath, mtRotate);
135 }
136