LibreOffice Module oox (master) 1
linepropertiescontext.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
24#include <oox/token/namespaces.hxx>
25#include <oox/token/tokens.hxx>
27
28using namespace ::oox::core;
29using namespace ::com::sun::star::uno;
30using namespace ::com::sun::star::xml::sax;
31
32// CT_LineProperties
33
34namespace oox::drawingml {
35
36LinePropertiesContext::LinePropertiesContext( ContextHandler2Helper const & rParent, const AttributeList& rAttribs,
37 LineProperties& rLineProperties, model::LineStyle* pLineStyle) noexcept
38 : ContextHandler2(rParent)
39 , mpLineStyle(pLineStyle)
40 , mrLineProperties(rLineProperties)
41{
42 mrLineProperties.moLineWidth = rAttribs.getInteger( XML_w );
43 mrLineProperties.moLineCompound = rAttribs.getToken( XML_cmpd );
44 mrLineProperties.moLineCap = rAttribs.getToken( XML_cap );
45
46 if (mpLineStyle)
47 {
48 mpLineStyle->mnWidth = rAttribs.getInteger(XML_w, 0);
49
50 switch (rAttribs.getToken(XML_cap, XML_TOKEN_INVALID))
51 {
52 case XML_rnd: mpLineStyle->meCapType = model::CapType::Round; break;
53 case XML_sq: mpLineStyle->meCapType = model::CapType::Square; break;
54 case XML_flat: mpLineStyle->meCapType = model::CapType::Flat; break;
55 default:
56 mpLineStyle->meCapType = model::CapType::Unset; break;
57 }
58
59 switch (rAttribs.getToken(XML_cmpd, XML_TOKEN_INVALID))
60 {
61 case XML_sng: mpLineStyle->meCompoundLineType = model::CompoundLineType::Single; break;
62 case XML_dbl: mpLineStyle->meCompoundLineType = model::CompoundLineType::Double; break;
63 case XML_thickThin: mpLineStyle->meCompoundLineType = model::CompoundLineType::ThickThin_Double; break;
64 case XML_thinThick: mpLineStyle->meCompoundLineType = model::CompoundLineType::ThinThick_Double; break;
65 case XML_tri: mpLineStyle->meCompoundLineType = model::CompoundLineType::Triple; break;
66 default:
67 mpLineStyle->meCompoundLineType = model::CompoundLineType::Unset; break;
68 }
69
70 switch (rAttribs.getToken(XML_algn, XML_TOKEN_INVALID))
71 {
72 case XML_ctr: mpLineStyle->mePenAlignment = model::PenAlignmentType::Center; break;
73 case XML_in: mpLineStyle->mePenAlignment = model::PenAlignmentType::Inset; break;
74 default:
75 mpLineStyle->mePenAlignment = model::PenAlignmentType::Unset; break;
76 }
77 }
78}
79
81{
82}
83
85{
86 switch( nElement )
87 {
88 // LineFillPropertiesGroup
89 case A_TOKEN( noFill ):
90 case A_TOKEN( solidFill ):
91 case A_TOKEN( gradFill ):
92 case A_TOKEN( pattFill ):
93 {
94 model::FillStyle* pFillStyle = nullptr;
95 if (mpLineStyle)
96 {
97 pFillStyle = &mpLineStyle->maLineFillStyle;
98 }
99 return FillPropertiesContext::createFillContext(*this, nElement, rAttribs, mrLineProperties.maLineFill, pFillStyle);
100 }
101 break;
102
103 // LineDashPropertiesGroup
104 case A_TOKEN( prstDash ): // CT_PresetLineDashProperties
105 {
106 mrLineProperties.moPresetDash = rAttribs.getToken( XML_val );
107
108 if (mpLineStyle)
109 {
110 auto& rLineDash = mpLineStyle->maLineDash;
111 switch (rAttribs.getToken(XML_val, XML_TOKEN_INVALID))
112 {
113 case XML_solid: rLineDash.mePresetType = model::PresetDashType::Solid; break;
114 case XML_dot: rLineDash.mePresetType = model::PresetDashType::Dot; break;
115 case XML_dash: rLineDash.mePresetType = model::PresetDashType::Dash; break;
116 case XML_lgDash: rLineDash.mePresetType = model::PresetDashType::LargeDash; break;
117 case XML_dashDot: rLineDash.mePresetType = model::PresetDashType::DashDot; break;
118 case XML_lgDashDot: rLineDash.mePresetType = model::PresetDashType::LargeDashDot; break;
119 case XML_lgDashDotDot: rLineDash.mePresetType = model::PresetDashType::LargeDashDotDot; break;
120 case XML_sysDash: rLineDash.mePresetType = model::PresetDashType::SystemDash; break;
121 case XML_sysDot: rLineDash.mePresetType = model::PresetDashType::SystemDot; break;
122 case XML_sysDashDot: rLineDash.mePresetType = model::PresetDashType::SystemDashDot; break;
123 case XML_sysDashDotDot: rLineDash.mePresetType = model::PresetDashType::SystemDashDotDot; break;
124 default:
125 rLineDash.mePresetType = model::PresetDashType::Unset; break;
126 }
127 }
128 }
129 break;
130 case A_TOKEN( custDash ): // CT_DashStopList
131 return this;
132 case A_TOKEN( ds ):
133 {
134 // 'a:ds' has 2 attributes : 'd' and 'sp'
135 // both are of type 'a:ST_PositivePercentage'
136 // according to the specs Office will read percentages formatted with a trailing percent sign
137 // or formatted as 1000th of a percent without a trailing percent sign, but only write percentages
138 // as 1000th's of a percent without a trailing percent sign.
139 // The code below takes care of both scenarios by converting to '1000th of a percent' always
140 OUString aStr;
141 sal_Int32 nDashLength = 0;
142 aStr = rAttribs.getStringDefaulted( XML_d);
143 if ( aStr.endsWith("%") )
144 {
145 // Ends with a '%'
146 aStr = aStr.copy(0, aStr.getLength() - 1);
147 aStr = aStr.trim();
148 nDashLength = aStr.toInt32();
149
150 // Convert to 1000th of a percent
151 nDashLength *= 1000;
152 }
153 else
154 {
155 nDashLength = rAttribs.getInteger( XML_d, 0 );
156 }
157
158 sal_Int32 nSpaceLength = 0;
159 aStr = rAttribs.getStringDefaulted( XML_sp);
160 if ( aStr.endsWith("%") )
161 {
162 // Ends with a '%'
163 aStr = aStr.copy(0, aStr.getLength() - 1);
164 aStr = aStr.trim();
165 nSpaceLength = aStr.toInt32();
166
167 // Convert to 1000th of a percent
168 nSpaceLength *= 1000;
169 }
170 else
171 {
172 nSpaceLength = rAttribs.getInteger( XML_sp, 0 );
173 }
174
175 mrLineProperties.maCustomDash.emplace_back( nDashLength, nSpaceLength );
176
177 if (mpLineStyle)
178 {
179 mpLineStyle->maLineDash.maCustomList.push_back({ nDashLength, nSpaceLength });
180 }
181 }
182 break;
183
184 // LineJoinPropertiesGroup
185 case A_TOKEN( round ):
186 case A_TOKEN( bevel ):
187 case A_TOKEN( miter ):
188 {
189 sal_Int32 nToken = getBaseToken(nElement);
191
192 if (mpLineStyle)
193 {
194 switch (nToken)
195 {
199 default:
201 }
202 if (nToken == XML_miter)
203 {
204 sal_Int32 nMiterLimit = rAttribs.getInteger(XML_lim, 0);
205 mpLineStyle->maLineJoin.mnMiterLimit = nMiterLimit;
206 }
207 }
208 }
209 break;
210
211 case A_TOKEN( headEnd ): // CT_LineEndProperties
212 case A_TOKEN( tailEnd ): // CT_LineEndProperties
213 { // ST_LineEndType
214 bool bTailEnd = nElement == A_TOKEN( tailEnd );
216 rArrowProps.moArrowType = rAttribs.getToken( XML_type );
217 rArrowProps.moArrowWidth = rAttribs.getToken( XML_w );
218 rArrowProps.moArrowLength = rAttribs.getToken( XML_len );
219
220 if (mpLineStyle)
221 {
223 switch (rAttribs.getToken(XML_type, XML_none))
224 {
225 case XML_triangle: eLineEndType = model::LineEndType::Triangle; break;
226 case XML_stealth: eLineEndType = model::LineEndType::Stealth; break;
227 case XML_diamond: eLineEndType = model::LineEndType::Diamond; break;
228 case XML_oval: eLineEndType = model::LineEndType::Oval; break;
229 case XML_arrow: eLineEndType = model::LineEndType::Arrow; break;
230 default:
231 case XML_none: eLineEndType = model::LineEndType::None; break;
232 }
233
235 switch (rAttribs.getToken(XML_len, XML_TOKEN_INVALID))
236 {
237 case XML_sm: eLineEndLength = model::LineEndLength::Small; break;
238 case XML_med: eLineEndLength = model::LineEndLength::Medium; break;
239 case XML_lg: eLineEndLength = model::LineEndLength::Large; break;
240 default:
241 break;
242 }
243
245 switch (rAttribs.getToken(XML_w, XML_TOKEN_INVALID))
246 {
247 case XML_sm: eLineEndWidth = model::LineEndWidth::Small; break;
248 case XML_med: eLineEndWidth = model::LineEndWidth::Medium; break;
249 case XML_lg: eLineEndWidth = model::LineEndWidth::Large; break;
250 default:
251 break;
252 }
253
254 if (nElement == A_TOKEN(tailEnd))
255 {
256 mpLineStyle->maTailEnd.meType = eLineEndType;
257 mpLineStyle->maTailEnd.meLength = eLineEndLength;
258 mpLineStyle->maTailEnd.meWidth = eLineEndWidth;
259 }
260 else if (nElement == A_TOKEN(headEnd))
261 {
262 mpLineStyle->maHeadEnd.meType = eLineEndType;
263 mpLineStyle->maHeadEnd.meLength = eLineEndLength;
264 mpLineStyle->maHeadEnd.meWidth = eLineEndWidth;
265 }
266 }
267 }
268 break;
269 }
270 return nullptr;
271}
272
273}
274
275/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
FillStyle maLineFillStyle
LineDash maLineDash
LineJoin maLineJoin
Provides access to attribute values of an element.
OUString getStringDefaulted(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute, returns an empty string if attribute not present...
std::optional< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
Returns the 32-bit signed integer value of the specified attribute (decimal).
std::optional< sal_Int32 > getToken(sal_Int32 nAttrToken) const
Returns the token identifier of the value of the specified attribute.
::oox::core::ContextHandlerRef createFillContext(::oox::core::ContextHandler2Helper const &rParent, sal_Int32 nElement, const ::oox::AttributeList &rAttribs, FillProperties &rFillProps, model::FillStyle *pFillStyle)
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
LinePropertiesContext(::oox::core::ContextHandler2Helper const &rParent, const ::oox::AttributeList &rAttributes, LineProperties &rLineProperties, model::LineStyle *pLineStyle=nullptr) noexcept
aStr
XML_none
XML_type
XML_TOKEN_INVALID
DefTokenId nToken
std::vector< DashStop > maCustomList
PresetDashType mePresetType
LineEndWidth meWidth
LineEndLength meLength
LineEndType meType
sal_Int32 mnMiterLimit
LineJoinType meType
std::optional< sal_Int32 > moArrowLength
std::optional< sal_Int32 > moArrowType
std::optional< sal_Int32 > moArrowWidth
FillProperties maLineFill
End line arrow style.
LineArrowProperties maStartArrow
std::optional< sal_Int32 > moLineJoint
Line cap (OOXML token).
LineArrowProperties maEndArrow
Start line arrow style.
std::optional< sal_Int32 > moPresetDash
Line width (EMUs).
DashStopVector maCustomDash
Line fill (solid, gradient, ...).