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/cxfa_ffline.h"
8 
9 #include "xfa/fxfa/parser/cxfa_edge.h"
10 #include "xfa/fxfa/parser/cxfa_line.h"
11 #include "xfa/fxfa/parser/cxfa_value.h"
12 #include "xfa/fxgraphics/cxfa_gecolor.h"
13 #include "xfa/fxgraphics/cxfa_gepath.h"
14 #include "xfa/fxgraphics/cxfa_graphics.h"
15 
16 namespace {
17 
LineCapToFXGE(XFA_AttributeValue iLineCap)18 CFX_GraphStateData::LineCap LineCapToFXGE(XFA_AttributeValue iLineCap) {
19   switch (iLineCap) {
20     case XFA_AttributeValue::Round:
21       return CFX_GraphStateData::LineCapRound;
22     case XFA_AttributeValue::Butt:
23       return CFX_GraphStateData::LineCapButt;
24     default:
25       break;
26   }
27   return CFX_GraphStateData::LineCapSquare;
28 }
29 
30 }  // namespace
31 
CXFA_FFLine(CXFA_Node * pNode)32 CXFA_FFLine::CXFA_FFLine(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}
33 
~CXFA_FFLine()34 CXFA_FFLine::~CXFA_FFLine() {}
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(CXFA_Graphics * pGS,const CFX_Matrix & matrix,HighlightOption highlight)85 void CXFA_FFLine::RenderWidget(CXFA_Graphics* 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   CXFA_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   pGS->SaveGraphState();
131   pGS->SetLineWidth(fLineWidth);
132   pGS->EnableActOnDash();
133   XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap);
134 
135   pGS->SetStrokeColor(CXFA_GEColor(lineColor));
136   pGS->SetLineCap(LineCapToFXGE(iCap));
137   pGS->StrokePath(&linePath, &mtRotate);
138   pGS->RestoreGraphState();
139 }
140