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
20 #include <TransGradientStyle.hxx>
21
22 #include <com/sun/star/awt/Gradient.hpp>
23
24 #include <sax/tools/converter.hxx>
25 #include <comphelper/documentconstants.hxx>
26
27 #include <xmloff/namespacemap.hxx>
28 #include <xmloff/xmluconv.hxx>
29 #include <xmloff/xmlnamespace.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include <rtl/ustring.hxx>
32 #include <sal/log.hxx>
33 #include <tools/color.hxx>
34 #include <xmloff/xmltkmap.hxx>
35 #include <xmloff/xmlexp.hxx>
36 #include <xmloff/xmlimp.hxx>
37 #include <xmloff/xmlement.hxx>
38
39 using namespace ::com::sun::star;
40
41 using namespace ::xmloff::token;
42
43 SvXMLEnumMapEntry<awt::GradientStyle> const pXML_GradientStyle_Enum[] =
44 {
45 { XML_LINEAR, awt::GradientStyle_LINEAR },
46 { XML_GRADIENTSTYLE_AXIAL, awt::GradientStyle_AXIAL },
47 { XML_GRADIENTSTYLE_RADIAL, awt::GradientStyle_RADIAL },
48 { XML_GRADIENTSTYLE_ELLIPSOID, awt::GradientStyle_ELLIPTICAL },
49 { XML_GRADIENTSTYLE_SQUARE, awt::GradientStyle_SQUARE },
50 { XML_GRADIENTSTYLE_RECTANGULAR, awt::GradientStyle_RECT },
51 { XML_TOKEN_INVALID, awt::GradientStyle(0) }
52 };
53
54 // Import
55
XMLTransGradientStyleImport(SvXMLImport & rImp)56 XMLTransGradientStyleImport::XMLTransGradientStyleImport( SvXMLImport& rImp )
57 : rImport(rImp)
58 {
59 }
60
~XMLTransGradientStyleImport()61 XMLTransGradientStyleImport::~XMLTransGradientStyleImport()
62 {
63 }
64
importXML(const uno::Reference<xml::sax::XFastAttributeList> & xAttrList,uno::Any & rValue,OUString & rStrName)65 void XMLTransGradientStyleImport::importXML(
66 const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
67 uno::Any& rValue,
68 OUString& rStrName )
69 {
70 OUString aDisplayName;
71
72 awt::Gradient aGradient;
73 aGradient.XOffset = 0;
74 aGradient.YOffset = 0;
75 aGradient.StartIntensity = 100;
76 aGradient.EndIntensity = 100;
77 aGradient.Angle = 0;
78 aGradient.Border = 0;
79
80 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
81 {
82 sal_Int32 nTmpValue;
83
84 switch( aIter.getToken() )
85 {
86 case XML_ELEMENT(DRAW, XML_NAME):
87 {
88 rStrName = aIter.toString();
89 }
90 break;
91 case XML_ELEMENT(DRAW, XML_DISPLAY_NAME):
92 {
93 aDisplayName = aIter.toString();
94 }
95 break;
96 case XML_ELEMENT(DRAW, XML_STYLE):
97 {
98 SvXMLUnitConverter::convertEnum( aGradient.Style, aIter.toView(), pXML_GradientStyle_Enum );
99 }
100 break;
101 case XML_ELEMENT(DRAW, XML_CX):
102 ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
103 aGradient.XOffset = sal::static_int_cast< sal_Int16 >(nTmpValue);
104 break;
105 case XML_ELEMENT(DRAW, XML_CY):
106 ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
107 aGradient.YOffset = sal::static_int_cast< sal_Int16 >(nTmpValue);
108 break;
109 case XML_ELEMENT(DRAW, XML_START):
110 {
111 sal_Int32 aStartTransparency;
112 ::sax::Converter::convertPercent( aStartTransparency, aIter.toView() );
113
114 sal_uInt8 n = sal::static_int_cast< sal_uInt8 >(
115 ( (100 - aStartTransparency) * 255 ) / 100 );
116
117 Color aColor( n, n, n );
118 aGradient.StartColor = static_cast<sal_Int32>( aColor );
119 }
120 break;
121 case XML_ELEMENT(DRAW, XML_END):
122 {
123 sal_Int32 aEndTransparency;
124 ::sax::Converter::convertPercent( aEndTransparency, aIter.toView() );
125
126 sal_uInt8 n = sal::static_int_cast< sal_uInt8 >(
127 ( (100 - aEndTransparency) * 255 ) / 100 );
128
129 Color aColor( n, n, n );
130 aGradient.EndColor = static_cast<sal_Int32>( aColor );
131 }
132 break;
133 case XML_ELEMENT(DRAW, XML_GRADIENT_ANGLE):
134 {
135 auto const cmp12(rImport.GetODFVersion().compareTo(u"" ODFVER_012_TEXT));
136 bool const bSuccess =
137 ::sax::Converter::convertAngle(aGradient.Angle, aIter.toView(),
138 // tdf#89475 try to detect borked OOo angles
139 (cmp12 < 0) || (cmp12 == 0
140 && (rImport.isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_7x)
141 // also for AOO 4.x, assume there won't ever be a 4.2
142 || rImport.getGeneratorVersion() == SvXMLImport::AOO_4x)));
143 SAL_INFO_IF(!bSuccess, "xmloff.style", "failed to import draw:angle");
144 }
145 break;
146 case XML_ELEMENT(DRAW, XML_BORDER):
147 ::sax::Converter::convertPercent( nTmpValue, aIter.toView() );
148 aGradient.Border = sal::static_int_cast< sal_Int16 >(nTmpValue);
149 break;
150
151 default:
152 XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
153 }
154 }
155
156 rValue <<= aGradient;
157
158 if( !aDisplayName.isEmpty() )
159 {
160 rImport.AddStyleDisplayName( XmlStyleFamily::SD_GRADIENT_ID, rStrName,
161 aDisplayName );
162 rStrName = aDisplayName;
163 }
164 }
165
166 // Export
167
XMLTransGradientStyleExport(SvXMLExport & rExp)168 XMLTransGradientStyleExport::XMLTransGradientStyleExport( SvXMLExport& rExp )
169 : rExport(rExp)
170 {
171 }
172
~XMLTransGradientStyleExport()173 XMLTransGradientStyleExport::~XMLTransGradientStyleExport()
174 {
175 }
176
exportXML(const OUString & rStrName,const uno::Any & rValue)177 void XMLTransGradientStyleExport::exportXML(
178 const OUString& rStrName,
179 const uno::Any& rValue )
180 {
181 awt::Gradient aGradient;
182
183 if( rStrName.isEmpty() )
184 return;
185
186 if( !(rValue >>= aGradient) )
187 return;
188
189 OUString aStrValue;
190 OUStringBuffer aOut;
191
192 // Style
193 if( !SvXMLUnitConverter::convertEnum( aOut, aGradient.Style, pXML_GradientStyle_Enum ) )
194 return;
195
196 // Name
197 bool bEncoded = false;
198 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
199 rExport.EncodeStyleName( rStrName,
200 &bEncoded ) );
201 if( bEncoded )
202 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
203 rStrName );
204
205 aStrValue = aOut.makeStringAndClear();
206 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE, aStrValue );
207
208 // Center x/y
209 if( aGradient.Style != awt::GradientStyle_LINEAR &&
210 aGradient.Style != awt::GradientStyle_AXIAL )
211 {
212 ::sax::Converter::convertPercent(aOut, aGradient.XOffset);
213 aStrValue = aOut.makeStringAndClear();
214 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CX, aStrValue );
215
216 ::sax::Converter::convertPercent(aOut, aGradient.YOffset);
217 aStrValue = aOut.makeStringAndClear();
218 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_CY, aStrValue );
219 }
220
221 // Transparency start
222 Color aColor(ColorTransparency, aGradient.StartColor);
223 sal_Int32 aStartValue = 100 - static_cast<sal_Int32>(((aColor.GetRed() + 1) * 100) / 255);
224 ::sax::Converter::convertPercent( aOut, aStartValue );
225 aStrValue = aOut.makeStringAndClear();
226 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_START, aStrValue );
227
228 // Transparency end
229 aColor = Color(ColorTransparency, aGradient.EndColor);
230 sal_Int32 aEndValue = 100 - static_cast<sal_Int32>(((aColor.GetRed() + 1) * 100) / 255);
231 ::sax::Converter::convertPercent( aOut, aEndValue );
232 aStrValue = aOut.makeStringAndClear();
233 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_END, aStrValue );
234
235 // Angle
236 if( aGradient.Style != awt::GradientStyle_RADIAL )
237 {
238 ::sax::Converter::convertAngle(aOut, aGradient.Angle, rExport.getSaneDefaultVersion());
239 aStrValue = aOut.makeStringAndClear();
240 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_GRADIENT_ANGLE, aStrValue );
241 }
242
243 // Border
244 ::sax::Converter::convertPercent( aOut, aGradient.Border );
245 aStrValue = aOut.makeStringAndClear();
246 rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_BORDER, aStrValue );
247
248 // Do Write
249 SvXMLElementExport rElem( rExport,
250 XML_NAMESPACE_DRAW, XML_OPACITY,
251 true, false );
252 }
253
254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
255