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 18 CFX_GraphStateData::LineCap LineCapToFXGE(XFA_AttributeEnum iLineCap) { 19 switch (iLineCap) { 20 case XFA_AttributeEnum::Round: 21 return CFX_GraphStateData::LineCapRound; 22 case XFA_AttributeEnum::Butt: 23 return CFX_GraphStateData::LineCapButt; 24 default: 25 break; 26 } 27 return CFX_GraphStateData::LineCapSquare; 28 } 29 30 } // namespace 31 32 CXFA_FFLine::CXFA_FFLine(CXFA_Node* pNode) : CXFA_FFDraw(pNode) {} 33 34 CXFA_FFLine::~CXFA_FFLine() {} 35 36 void CXFA_FFLine::GetRectFromHand(CFX_RectF& rect, 37 XFA_AttributeEnum iHand, 38 float fLineWidth) { 39 float fHalfWidth = fLineWidth / 2.0f; 40 if (rect.height < 1.0f) { 41 switch (iHand) { 42 case XFA_AttributeEnum::Left: 43 rect.top -= fHalfWidth; 44 break; 45 case XFA_AttributeEnum::Right: 46 rect.top += fHalfWidth; 47 case XFA_AttributeEnum::Even: 48 break; 49 default: 50 NOTREACHED(); 51 break; 52 } 53 } else if (rect.width < 1.0f) { 54 switch (iHand) { 55 case XFA_AttributeEnum::Left: 56 rect.left += fHalfWidth; 57 break; 58 case XFA_AttributeEnum::Right: 59 rect.left += fHalfWidth; 60 break; 61 case XFA_AttributeEnum::Even: 62 break; 63 default: 64 NOTREACHED(); 65 break; 66 } 67 } else { 68 switch (iHand) { 69 case XFA_AttributeEnum::Left: 70 rect.Inflate(fHalfWidth, fHalfWidth); 71 break; 72 case XFA_AttributeEnum::Right: 73 rect.Deflate(fHalfWidth, fHalfWidth); 74 break; 75 case XFA_AttributeEnum::Even: 76 break; 77 default: 78 NOTREACHED(); 79 break; 80 } 81 } 82 } 83 84 void CXFA_FFLine::RenderWidget(CXFA_Graphics* pGS, 85 const CFX_Matrix& matrix, 86 uint32_t dwStatus) { 87 if (!IsMatchVisibleStatus(dwStatus)) 88 return; 89 90 CXFA_Value* value = m_pNode->GetFormValueIfExists(); 91 if (!value) 92 return; 93 94 FX_ARGB lineColor = 0xFF000000; 95 float fLineWidth = 1.0f; 96 XFA_AttributeEnum iStrokeType = XFA_AttributeEnum::Unknown; 97 XFA_AttributeEnum iCap = XFA_AttributeEnum::Unknown; 98 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 if (margin) 119 XFA_RectWithoutMargin(rtLine, margin); 120 121 GetRectFromHand(rtLine, line ? line->GetHand() : XFA_AttributeEnum::Left, 122 fLineWidth); 123 CXFA_GEPath linePath; 124 if (line && line->GetSlope() && rtLine.right() > 0.0f && 125 rtLine.bottom() > 0.0f) { 126 linePath.AddLine(rtLine.TopRight(), rtLine.BottomLeft()); 127 } else { 128 linePath.AddLine(rtLine.TopLeft(), rtLine.BottomRight()); 129 } 130 131 pGS->SaveGraphState(); 132 pGS->SetLineWidth(fLineWidth); 133 pGS->EnableActOnDash(); 134 XFA_StrokeTypeSetLineDash(pGS, iStrokeType, iCap); 135 136 pGS->SetStrokeColor(CXFA_GEColor(lineColor)); 137 pGS->SetLineCap(LineCapToFXGE(iCap)); 138 pGS->StrokePath(&linePath, &mtRotate); 139 pGS->RestoreGraphState(); 140 } 141