// Copyright 2016 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fxfa/parser/cxfa_box.h" #include "xfa/fxfa/parser/cxfa_corner.h" #include "xfa/fxfa/parser/cxfa_measurement.h" #include "xfa/fxfa/parser/xfa_object.h" namespace { void GetStrokesInternal(CXFA_Node* pNode, std::vector<CXFA_Stroke>* strokes, bool bNull) { strokes->clear(); if (!pNode) return; strokes->resize(8); int32_t i, j; for (i = 0, j = 0; i < 4; i++) { CXFA_Corner corner = CXFA_Corner(pNode->GetProperty(i, XFA_Element::Corner, i == 0)); if (corner || i == 0) { (*strokes)[j] = corner; } else if (!bNull) { if (i == 1 || i == 2) (*strokes)[j] = (*strokes)[0]; else (*strokes)[j] = (*strokes)[2]; } j++; CXFA_Edge edge = CXFA_Edge(pNode->GetProperty(i, XFA_Element::Edge, i == 0)); if (edge || i == 0) { (*strokes)[j] = edge; } else if (!bNull) { if (i == 1 || i == 2) (*strokes)[j] = (*strokes)[1]; else (*strokes)[j] = (*strokes)[3]; } j++; } } static int32_t Style3D(const std::vector<CXFA_Stroke>& strokes, CXFA_Stroke& stroke) { if (strokes.empty()) return 0; stroke = strokes[0]; for (size_t i = 1; i < strokes.size(); i++) { CXFA_Stroke find = strokes[i]; if (!find) continue; if (!stroke) stroke = find; else if (stroke.GetStrokeType() != find.GetStrokeType()) stroke = find; break; } int32_t iType = stroke.GetStrokeType(); if (iType == XFA_ATTRIBUTEENUM_Lowered || iType == XFA_ATTRIBUTEENUM_Raised || iType == XFA_ATTRIBUTEENUM_Etched || iType == XFA_ATTRIBUTEENUM_Embossed) { return iType; } return 0; } } // namespace int32_t CXFA_Box::GetHand() const { if (!m_pNode) return XFA_ATTRIBUTEENUM_Even; return m_pNode->GetEnum(XFA_ATTRIBUTE_Hand); } int32_t CXFA_Box::GetPresence() const { if (!m_pNode) return XFA_ATTRIBUTEENUM_Hidden; return m_pNode->GetEnum(XFA_ATTRIBUTE_Presence); } int32_t CXFA_Box::CountEdges() const { if (!m_pNode) return 0; return m_pNode->CountChildren(XFA_Element::Edge); } CXFA_Edge CXFA_Box::GetEdge(int32_t nIndex) const { return CXFA_Edge( m_pNode ? m_pNode->GetProperty(nIndex, XFA_Element::Edge, nIndex == 0) : nullptr); } void CXFA_Box::GetStrokes(std::vector<CXFA_Stroke>* strokes) const { GetStrokesInternal(m_pNode, strokes, false); } bool CXFA_Box::IsCircular() const { if (!m_pNode) return false; return m_pNode->GetBoolean(XFA_ATTRIBUTE_Circular); } bool CXFA_Box::GetStartAngle(FX_FLOAT& fStartAngle) const { fStartAngle = 0; if (!m_pNode) return false; CXFA_Measurement ms; bool bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_StartAngle, ms, false); if (bRet) fStartAngle = ms.GetValue(); return bRet; } bool CXFA_Box::GetSweepAngle(FX_FLOAT& fSweepAngle) const { fSweepAngle = 360; if (!m_pNode) return false; CXFA_Measurement ms; bool bRet = m_pNode->TryMeasure(XFA_ATTRIBUTE_SweepAngle, ms, false); if (bRet) fSweepAngle = ms.GetValue(); return bRet; } CXFA_Fill CXFA_Box::GetFill(bool bModified) const { if (!m_pNode) return CXFA_Fill(nullptr); CXFA_Node* pFillNode = m_pNode->GetProperty(0, XFA_Element::Fill, bModified); return CXFA_Fill(pFillNode); } CXFA_Margin CXFA_Box::GetMargin() const { return CXFA_Margin(m_pNode ? m_pNode->GetChild(0, XFA_Element::Margin) : nullptr); } int32_t CXFA_Box::Get3DStyle(bool& bVisible, FX_FLOAT& fThickness) const { if (IsArc()) return 0; std::vector<CXFA_Stroke> strokes; GetStrokesInternal(m_pNode, &strokes, true); CXFA_Stroke stroke(nullptr); int32_t iType = Style3D(strokes, stroke); if (iType) { bVisible = stroke.IsVisible(); fThickness = stroke.GetThickness(); } return iType; }