/src/libmwaw/src/lib/MWAWGraphicStyle.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | /* This header contains code specific to a pict mac file |
35 | | */ |
36 | | #include <string.h> |
37 | | |
38 | | #include <iomanip> |
39 | | #include <iostream> |
40 | | #include <sstream> |
41 | | #include <string> |
42 | | |
43 | | #include <librevenge/librevenge.h> |
44 | | #include <libmwaw/libmwaw.hxx> |
45 | | |
46 | | #include "libmwaw_internal.hxx" |
47 | | |
48 | | #include "MWAWFontConverter.hxx" |
49 | | #include "MWAWPictBitmap.hxx" |
50 | | |
51 | | #include "MWAWGraphicStyle.hxx" |
52 | | |
53 | | //////////////////////////////////////////////////////////// |
54 | | // arrow |
55 | | //////////////////////////////////////////////////////////// |
56 | | void MWAWGraphicStyle::Arrow::addTo(librevenge::RVNGPropertyList &propList, std::string const &type) const |
57 | 1.26M | { |
58 | 1.26M | if (isEmpty()) |
59 | 0 | return; |
60 | 1.26M | if (type!="start" && type!="end") { |
61 | 0 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::Arrow::addTo: oops, find unexpected type\n")); |
62 | 0 | return; |
63 | 0 | } |
64 | 1.26M | std::stringstream s, s2; |
65 | 1.26M | s << "draw:marker-" << type << "-path"; |
66 | 1.26M | propList.insert(s.str().c_str(), m_path.c_str()); |
67 | 1.26M | s.str(""); |
68 | 1.26M | s << "draw:marker-" << type << "-viewbox"; |
69 | 1.26M | s2 << m_viewBox[0][0] << " " << m_viewBox[0][1] << " " << m_viewBox[1][0] << " " << m_viewBox[1][1]; |
70 | 1.26M | propList.insert(s.str().c_str(), s2.str().c_str()); |
71 | 1.26M | s.str(""); |
72 | 1.26M | s << "draw:marker-" << type << "-center"; |
73 | 1.26M | propList.insert(s.str().c_str(), m_isCentered); |
74 | 1.26M | s.str(""); |
75 | 1.26M | s << "draw:marker-" << type << "-width"; |
76 | 1.26M | propList.insert(s.str().c_str(), double(m_width), librevenge::RVNG_POINT); |
77 | 1.26M | } |
78 | | |
79 | | //////////////////////////////////////////////////////////// |
80 | | // pattern |
81 | | //////////////////////////////////////////////////////////// |
82 | | MWAWGraphicStyle::Pattern::~Pattern() |
83 | 786M | { |
84 | 786M | } |
85 | | |
86 | | bool MWAWGraphicStyle::Pattern::getUniqueColor(MWAWColor &col) const |
87 | 63.0M | { |
88 | 63.0M | if (empty() || !m_picture.isEmpty() || m_data.empty()) return false; |
89 | 33.5M | if (m_colors[0]==m_colors[1]) { |
90 | 3.70M | col = m_colors[0]; |
91 | 3.70M | return true; |
92 | 3.70M | } |
93 | 29.8M | unsigned char def=m_data[0]; |
94 | 29.8M | if (def!=0 && def!=0xFF) return false; |
95 | 62.6M | for (size_t c=1; c < m_data.size(); ++c) |
96 | 55.4M | if (m_data[c]!=def) return false; |
97 | 7.16M | col = m_colors[def ? 1 : 0]; |
98 | 7.16M | return true; |
99 | 10.5M | } |
100 | | |
101 | | bool MWAWGraphicStyle::Pattern::getAverageColor(MWAWColor &color) const |
102 | 50.6M | { |
103 | 50.6M | if (empty()) return false; |
104 | 21.7M | if (!m_picture.isEmpty()) { |
105 | 537k | color=m_pictureAverageColor; |
106 | 537k | return true; |
107 | 537k | } |
108 | 21.1M | if (m_data.empty()) return false; |
109 | 21.1M | if (m_colors[0]==m_colors[1]) { |
110 | 192k | color = m_colors[0]; |
111 | 192k | return true; |
112 | 192k | } |
113 | 21.0M | int numOne=0, numZero=0; |
114 | 168M | for (auto data : m_data) { |
115 | 1.51G | for (int depl=1, b=0; b < 8; ++b, depl*=2) { |
116 | 1.34G | if (data & depl) |
117 | 426M | numOne++; |
118 | 917M | else |
119 | 917M | numZero++; |
120 | 1.34G | } |
121 | 168M | } |
122 | 21.0M | if (!numOne && !numZero) return false; |
123 | 21.0M | float percent=float(numOne)/float(numOne+numZero); |
124 | 21.0M | color = MWAWColor::barycenter(1.f-percent,m_colors[0],percent,m_colors[1]); |
125 | 21.0M | return true; |
126 | 21.0M | } |
127 | | |
128 | | bool MWAWGraphicStyle::Pattern::getBinary(MWAWEmbeddedObject &picture) const |
129 | 3.15M | { |
130 | 3.15M | if (empty()) { |
131 | 0 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::Pattern::getBinary: called on invalid pattern\n")); |
132 | 0 | return false; |
133 | 0 | } |
134 | 3.15M | if (!m_picture.isEmpty()) { |
135 | 622k | picture=m_picture; |
136 | 622k | return true; |
137 | 622k | } |
138 | | /* We create a indexed bitmap to obtain a final binary data. |
139 | | |
140 | | But it will probably better to recode that differently |
141 | | */ |
142 | 2.53M | MWAWPictBitmapIndexed bitmap(m_dim); |
143 | 2.53M | std::vector<MWAWColor> colors; |
144 | 2.53M | for (auto const &color : m_colors) |
145 | 5.07M | colors.push_back(color); |
146 | 2.53M | bitmap.setColors(colors); |
147 | 2.53M | int numBytesByLines = m_dim[0]/8; |
148 | 2.53M | unsigned char const *ptr = &m_data[0]; |
149 | 2.53M | std::vector<int> rowValues(static_cast<size_t>(m_dim[0])); |
150 | 22.8M | for (int h=0; h < m_dim[1]; ++h) { |
151 | 20.2M | size_t i=0; |
152 | 40.5M | for (int b=0; b < numBytesByLines; ++b) { |
153 | 20.2M | unsigned char c=*(ptr++); |
154 | 20.2M | unsigned char depl=0x80; |
155 | 182M | for (int byt=0; byt<8; ++byt) { |
156 | 162M | rowValues[i++] = (c&depl) ? 1 : 0; |
157 | 162M | depl=static_cast<unsigned char>(depl>>1); |
158 | 162M | } |
159 | 20.2M | } |
160 | 20.2M | bitmap.setRow(h, &rowValues[0]); |
161 | 20.2M | } |
162 | 2.53M | return bitmap.getBinary(picture); |
163 | 3.15M | } |
164 | | |
165 | | //////////////////////////////////////////////////////////// |
166 | | // gradient |
167 | | //////////////////////////////////////////////////////////// |
168 | | bool MWAWGraphicStyle::Gradient::getAverageColor(MWAWColor &color) const |
169 | 0 | { |
170 | 0 | if (m_stopList.empty()) |
171 | 0 | return false; |
172 | 0 | if (m_stopList.size()==1) { |
173 | 0 | color=m_stopList[0].m_color; |
174 | 0 | return true; |
175 | 0 | } |
176 | | // fixme: check the offset are sorted and use then to compute a better barycenter |
177 | 0 | unsigned n[]= {0,0,0,0}; |
178 | 0 | for (auto const &st : m_stopList) { |
179 | 0 | n[0]+=st.m_color.getRed(); |
180 | 0 | n[1]+=st.m_color.getGreen(); |
181 | 0 | n[2]+=st.m_color.getBlue(); |
182 | 0 | n[3]+=st.m_color.getAlpha(); |
183 | 0 | } |
184 | 0 | color=MWAWColor((unsigned char)(n[0]/(unsigned)(m_stopList.size())), |
185 | 0 | (unsigned char)(n[1]/(unsigned)(m_stopList.size())), |
186 | 0 | (unsigned char)(n[2]/(unsigned)(m_stopList.size())), |
187 | 0 | (unsigned char)(n[3]/(unsigned)(m_stopList.size()))); |
188 | 0 | return true; |
189 | 0 | } |
190 | | |
191 | | void MWAWGraphicStyle::Gradient::addTo(librevenge::RVNGPropertyList &propList) const |
192 | 514k | { |
193 | 514k | if (!hasGradient()) return; |
194 | 514k | propList.insert("draw:fill", "gradient"); |
195 | 514k | switch (m_type) { |
196 | 11.9k | case G_Axial: |
197 | 11.9k | propList.insert("draw:style", "axial"); |
198 | 11.9k | break; |
199 | 48.4k | case G_Radial: |
200 | 48.4k | propList.insert("draw:style", "radial"); |
201 | 48.4k | break; |
202 | 59.7k | case G_Rectangular: |
203 | 59.7k | propList.insert("draw:style", "rectangular"); |
204 | 59.7k | break; |
205 | 0 | case G_Square: |
206 | 0 | propList.insert("draw:style", "square"); |
207 | 0 | break; |
208 | 0 | case G_Ellipsoid: |
209 | 0 | propList.insert("draw:style", "ellipsoid"); |
210 | 0 | break; |
211 | 394k | case G_Linear: |
212 | 394k | case G_None: |
213 | | #if !defined(__clang__) |
214 | | default: |
215 | | #endif |
216 | 394k | propList.insert("draw:style", "linear"); |
217 | 394k | break; |
218 | 514k | } |
219 | 514k | if (m_stopList.size()==2 &&m_stopList[0].m_offset <= 0 && |
220 | 434k | m_stopList[1].m_offset >=1) { |
221 | 434k | size_t first=(m_type==G_Linear || m_type==G_Axial) ? 0 : 1; |
222 | 434k | propList.insert("draw:start-color",m_stopList[first].m_color.str().c_str()); |
223 | 434k | propList.insert("librevenge:start-opacity", double(m_stopList[first].m_opacity), librevenge::RVNG_PERCENT); |
224 | 434k | propList.insert("draw:end-color",m_stopList[1-first].m_color.str().c_str()); |
225 | 434k | propList.insert("librevenge:end-opacity", double(m_stopList[1-first].m_opacity), librevenge::RVNG_PERCENT); |
226 | 434k | } |
227 | 80.3k | else { |
228 | 80.3k | librevenge::RVNGPropertyListVector gradient; |
229 | 223k | for (auto const &gr :m_stopList) { |
230 | 223k | librevenge::RVNGPropertyList grad; |
231 | 223k | grad.insert("svg:offset", double(gr.m_offset), librevenge::RVNG_PERCENT); |
232 | 223k | grad.insert("svg:stop-color", gr.m_color.str().c_str()); |
233 | 223k | grad.insert("svg:stop-opacity", double(gr.m_opacity), librevenge::RVNG_PERCENT); |
234 | 223k | gradient.append(grad); |
235 | 223k | } |
236 | 80.3k | propList.insert("svg:linearGradient", gradient); |
237 | 80.3k | } |
238 | 514k | propList.insert("draw:angle", double(m_angle), librevenge::RVNG_GENERIC); |
239 | 514k | propList.insert("draw:border", double(m_border), librevenge::RVNG_PERCENT); |
240 | 514k | if (m_type != G_Linear) { |
241 | 120k | propList.insert("svg:cx", double(m_percentCenter[0]), librevenge::RVNG_PERCENT); |
242 | 120k | propList.insert("svg:cy", double(m_percentCenter[1]), librevenge::RVNG_PERCENT); |
243 | 120k | } |
244 | 514k | if (m_type == G_Radial) |
245 | 48.4k | propList.insert("svg:r", double(m_radius), librevenge::RVNG_PERCENT); // checkme |
246 | 514k | } |
247 | | |
248 | | //////////////////////////////////////////////////////////// |
249 | | // hatch |
250 | | //////////////////////////////////////////////////////////// |
251 | | void MWAWGraphicStyle::Hatch::addTo(librevenge::RVNGPropertyList &propList) const |
252 | 0 | { |
253 | 0 | if (!hasHatch()) return; |
254 | 0 | propList.insert("draw:fill", "hatch"); |
255 | 0 | if (int(m_type)>=1 && int(m_type)<4) { |
256 | 0 | char const *wh[]= {"single", "double", "triple"}; |
257 | 0 | propList.insert("draw:style", wh[int(m_type)-1]); |
258 | 0 | } |
259 | 0 | else { |
260 | 0 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::Hatch::addTo: unknown hash type %d\n", int(m_type))); |
261 | 0 | } |
262 | 0 | propList.insert("draw:color", m_color.str().c_str()); |
263 | 0 | propList.insert("draw:distance", double(m_distance), librevenge::RVNG_INCH); |
264 | 0 | if (m_rotation<0 || m_rotation>0) propList.insert("draw:rotation", double(m_rotation), librevenge::RVNG_GENERIC); |
265 | 0 | } |
266 | | |
267 | | //////////////////////////////////////////////////////////// |
268 | | // style |
269 | | //////////////////////////////////////////////////////////// |
270 | | MWAWGraphicStyle::~MWAWGraphicStyle() |
271 | 614M | { |
272 | 614M | } |
273 | | |
274 | | void MWAWGraphicStyle::setBorders(int wh, MWAWBorder const &border) |
275 | 792k | { |
276 | 792k | int const allBits = libmwaw::LeftBit|libmwaw::RightBit|libmwaw::TopBit|libmwaw::BottomBit; |
277 | 792k | if (wh & (~allBits)) { |
278 | 0 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::setBorders: unknown borders\n")); |
279 | 0 | return; |
280 | 0 | } |
281 | 792k | size_t numData = 4; |
282 | 792k | if (m_bordersList.size() < numData) { |
283 | 772k | MWAWBorder emptyBorder; |
284 | 772k | emptyBorder.m_style = MWAWBorder::None; |
285 | 772k | m_bordersList.resize(numData, emptyBorder); |
286 | 772k | } |
287 | 792k | if (wh & libmwaw::LeftBit) m_bordersList[libmwaw::Left] = border; |
288 | 792k | if (wh & libmwaw::RightBit) m_bordersList[libmwaw::Right] = border; |
289 | 792k | if (wh & libmwaw::TopBit) m_bordersList[libmwaw::Top] = border; |
290 | 792k | if (wh & libmwaw::BottomBit) m_bordersList[libmwaw::Bottom] = border; |
291 | 792k | } |
292 | | |
293 | | void MWAWGraphicStyle::addTo(librevenge::RVNGPropertyList &list, bool only1D) const |
294 | 26.0M | { |
295 | 26.0M | if (!hasLine()) |
296 | 16.8M | list.insert("draw:stroke", "none"); |
297 | 9.17M | else if (m_lineDashWidth.size()>=2) { |
298 | 126k | int nDots1=0, nDots2=0; |
299 | 126k | float size1=0, size2=0, totalGap=0.0; |
300 | 335k | for (size_t c=0; c+1 < m_lineDashWidth.size();) { |
301 | 241k | float sz=m_lineDashWidth[c++]; |
302 | 241k | if (nDots2 && (sz<size2||sz>size2)) { |
303 | 32.8k | static bool first=true; |
304 | 32.8k | if (first) { |
305 | 28 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::addTo: can not set some dash\n")); |
306 | 28 | first = false; |
307 | 28 | } |
308 | 32.8k | break; |
309 | 32.8k | } |
310 | 208k | if (nDots2) |
311 | 13.7k | nDots2++; |
312 | 194k | else if (!nDots1 || (sz>=size1 && sz <= size1)) { |
313 | 132k | nDots1++; |
314 | 132k | size1=sz; |
315 | 132k | } |
316 | 62.1k | else { |
317 | 62.1k | nDots2=1; |
318 | 62.1k | size2=sz; |
319 | 62.1k | } |
320 | 208k | totalGap += m_lineDashWidth[c++]; |
321 | 208k | } |
322 | 126k | list.insert("draw:stroke", "dash"); |
323 | 126k | list.insert("draw:dots1", nDots1); |
324 | 126k | list.insert("draw:dots1-length", double(size1), librevenge::RVNG_POINT); |
325 | 126k | if (nDots2) { |
326 | 62.1k | list.insert("draw:dots2", nDots2); |
327 | 62.1k | list.insert("draw:dots2-length", double(size2), librevenge::RVNG_POINT); |
328 | 62.1k | } |
329 | 126k | const double distance = ((nDots1 + nDots2) > 0) ? double(totalGap)/double(nDots1+nDots2) : double(totalGap); |
330 | 126k | list.insert("draw:distance", distance, librevenge::RVNG_POINT);; |
331 | 126k | } |
332 | 9.04M | else |
333 | 9.04M | list.insert("draw:stroke", "solid"); |
334 | 26.0M | list.insert("svg:stroke-color", m_lineColor.str().c_str()); |
335 | 26.0M | list.insert("svg:stroke-width", double(m_lineWidth),librevenge::RVNG_POINT); |
336 | | |
337 | 26.0M | if (m_lineOpacity < 1) |
338 | 393k | list.insert("svg:stroke-opacity", double(m_lineOpacity), librevenge::RVNG_PERCENT); |
339 | 26.0M | switch (m_lineCap) { |
340 | 95 | case C_Round: |
341 | 95 | list.insert("svg:stroke-linecap", "round"); |
342 | 95 | break; |
343 | 30 | case C_Square: |
344 | 30 | list.insert("svg:stroke-linecap", "square"); |
345 | 30 | break; |
346 | 26.0M | case C_Butt: |
347 | | #if !defined(__clang__) |
348 | | default: |
349 | | #endif |
350 | 26.0M | break; |
351 | 26.0M | } |
352 | 26.0M | switch (m_lineJoin) { |
353 | 88 | case J_Round: |
354 | 88 | list.insert("draw:stroke-linejoin", "round"); |
355 | 88 | break; |
356 | 154 | case J_Bevel: |
357 | 154 | list.insert("draw:stroke-linejoin", "bevel"); |
358 | 154 | break; |
359 | 26.0M | case J_Miter: |
360 | | #if !defined(__clang__) |
361 | | default: |
362 | | #endif |
363 | 26.0M | break; |
364 | 26.0M | } |
365 | | // alignment |
366 | 26.0M | switch (m_verticalAlignment) { |
367 | 0 | case V_AlignTop: |
368 | 0 | list.insert("draw:textarea-vertical-align", "top"); |
369 | 0 | break; |
370 | 0 | case V_AlignCenter: |
371 | 0 | list.insert("draw:textarea-vertical-align", "middle"); |
372 | 0 | break; |
373 | 0 | case V_AlignBottom: |
374 | 0 | list.insert("draw:textarea-vertical-align", "bottom"); |
375 | 0 | break; |
376 | 0 | case V_AlignJustify: |
377 | 0 | list.insert("draw:textarea-vertical-align", "justify"); |
378 | 0 | break; |
379 | 26.0M | case V_AlignDefault: |
380 | 26.0M | break; // default |
381 | | #if !defined(__clang__) |
382 | | default: |
383 | | #endif |
384 | 0 | MWAW_DEBUG_MSG(("MWAWStyle::addTo: called with unknown valign=%d\n", m_verticalAlignment)); |
385 | 26.0M | } |
386 | 26.0M | if (!m_arrows[0].isEmpty()) m_arrows[0].addTo(list,"start"); |
387 | 26.0M | if (!m_arrows[1].isEmpty()) m_arrows[1].addTo(list,"end"); |
388 | 26.0M | if (hasShadow()) { |
389 | 41.6k | list.insert("draw:shadow", "visible"); |
390 | 41.6k | list.insert("draw:shadow-color", m_shadowColor.str().c_str()); |
391 | 41.6k | list.insert("draw:shadow-opacity", double(m_shadowOpacity), librevenge::RVNG_PERCENT); |
392 | | // in cm |
393 | 41.6k | list.insert("draw:shadow-offset-x", double(m_shadowOffset[0])/72.*2.54, librevenge::RVNG_GENERIC); // cm |
394 | 41.6k | list.insert("draw:shadow-offset-y", double(m_shadowOffset[1])/72.*2.54, librevenge::RVNG_GENERIC); // cm |
395 | 41.6k | } |
396 | 26.0M | if (m_doNotPrint) |
397 | 0 | list.insert("style:print-content", false); |
398 | 26.0M | if (only1D || !hasSurface()) { |
399 | 16.5M | list.insert("draw:fill", "none"); |
400 | 16.5M | return; |
401 | 16.5M | } |
402 | 9.51M | list.insert("svg:fill-rule", m_fillRuleEvenOdd ? "evenodd" : "nonzero"); |
403 | 9.51M | if (hasGradient()) |
404 | 514k | m_gradient.addTo(list); |
405 | 9.00M | else if (hasHatch()) { |
406 | 0 | m_hatch.addTo(list); |
407 | 0 | if (hasSurfaceColor()) { |
408 | 0 | list.insert("draw:fill-color", m_surfaceColor.str().c_str()); |
409 | 0 | list.insert("draw:opacity", double(m_surfaceOpacity), librevenge::RVNG_PERCENT); |
410 | 0 | list.insert("draw:fill-hatch-solid", true); |
411 | 0 | } |
412 | 0 | } |
413 | 9.00M | else { |
414 | 9.00M | bool done = false; |
415 | 9.00M | MWAWColor surfaceColor=m_surfaceColor; |
416 | 9.00M | float surfaceOpacity = m_surfaceOpacity; |
417 | 9.00M | if (hasPattern()) { |
418 | 3.17M | MWAWColor col; |
419 | 3.17M | if (m_pattern.getUniqueColor(col)) { |
420 | | // no need to create a uniform pattern |
421 | 20.4k | surfaceColor = col; |
422 | 20.4k | surfaceOpacity = 1; |
423 | 20.4k | } |
424 | 3.15M | else { |
425 | 3.15M | MWAWEmbeddedObject picture; |
426 | 3.15M | if (m_pattern.getBinary(picture) && !picture.m_dataList.empty() && !picture.m_dataList[0].empty()) { |
427 | 3.15M | list.insert("draw:fill", "bitmap"); |
428 | 3.15M | list.insert("draw:fill-image", picture.m_dataList[0].getBase64Data()); |
429 | 3.15M | list.insert("draw:fill-image-width", m_pattern.m_dim[0], librevenge::RVNG_POINT); |
430 | 3.15M | list.insert("draw:fill-image-height", m_pattern.m_dim[1], librevenge::RVNG_POINT); |
431 | 3.15M | list.insert("draw:fill-image-ref-point-x",0, librevenge::RVNG_POINT); |
432 | 3.15M | list.insert("draw:fill-image-ref-point-y",0, librevenge::RVNG_POINT); |
433 | 3.15M | if (surfaceOpacity<1) |
434 | 56 | list.insert("draw:opacity", double(surfaceOpacity), librevenge::RVNG_PERCENT); |
435 | 3.15M | list.insert("librevenge:mime-type", picture.m_typeList.empty() ? "image/pict" : picture.m_typeList[0].c_str()); |
436 | 3.15M | done = true; |
437 | 3.15M | } |
438 | 0 | else { |
439 | 0 | MWAW_DEBUG_MSG(("MWAWGraphicStyle::addTo: can not set the pattern\n")); |
440 | 0 | } |
441 | 3.15M | } |
442 | 3.17M | } |
443 | 9.00M | if (!done) { |
444 | 5.84M | list.insert("draw:fill", "solid"); |
445 | 5.84M | list.insert("draw:fill-color", surfaceColor.str().c_str()); |
446 | 5.84M | list.insert("draw:opacity", double(surfaceOpacity), librevenge::RVNG_PERCENT); |
447 | 5.84M | } |
448 | 9.00M | } |
449 | 9.51M | } |
450 | | |
451 | | void MWAWGraphicStyle::addFrameTo(librevenge::RVNGPropertyList &list) const |
452 | 7.24M | { |
453 | 7.24M | if (m_backgroundOpacity>=0) { |
454 | 3.91M | if (m_backgroundOpacity>0) |
455 | 955k | list.insert("fo:background-color", m_backgroundColor.str().c_str()); |
456 | 3.91M | if (m_backgroundOpacity<1) |
457 | 2.96M | list.insert("style:background-transparency", 1.-double(m_backgroundOpacity), librevenge::RVNG_PERCENT); |
458 | 3.91M | } |
459 | 7.24M | if (hasBorders()) { |
460 | 570k | if (hasSameBorders()) |
461 | 569k | m_bordersList[0].addTo(list, ""); |
462 | 1.11k | else { |
463 | 5.55k | for (size_t c = 0; c < m_bordersList.size(); c++) { |
464 | 4.44k | if (c >= 4) break; |
465 | 4.44k | switch (c) { |
466 | 1.11k | case libmwaw::Left: |
467 | 1.11k | m_bordersList[c].addTo(list, "left"); |
468 | 1.11k | break; |
469 | 1.11k | case libmwaw::Right: |
470 | 1.11k | m_bordersList[c].addTo(list, "right"); |
471 | 1.11k | break; |
472 | 1.11k | case libmwaw::Top: |
473 | 1.11k | m_bordersList[c].addTo(list, "top"); |
474 | 1.11k | break; |
475 | 1.11k | case libmwaw::Bottom: |
476 | 1.11k | m_bordersList[c].addTo(list, "bottom"); |
477 | 1.11k | break; |
478 | | #if !defined(__clang__) |
479 | | default: |
480 | | MWAW_DEBUG_MSG(("MWAWGraphicStyle::addFrameTo: can not send %d border\n",int(c))); |
481 | | break; |
482 | | #endif |
483 | 4.44k | } |
484 | 4.44k | } |
485 | 1.11k | } |
486 | 570k | } |
487 | 7.24M | if (hasShadow()) { |
488 | 69.4k | list.insert("draw:shadow", "visible"); |
489 | 69.4k | list.insert("draw:shadow-color", m_shadowColor.str().c_str()); |
490 | 69.4k | list.insert("draw:shadow-opacity", double(m_shadowOpacity), librevenge::RVNG_PERCENT); |
491 | | // in cm |
492 | 69.4k | list.insert("draw:shadow-offset-x", double(m_shadowOffset[0])/72.*2.54, librevenge::RVNG_GENERIC); // cm |
493 | 69.4k | list.insert("draw:shadow-offset-y", double(m_shadowOffset[1])/72.*2.54, librevenge::RVNG_GENERIC); // cm |
494 | 69.4k | } |
495 | 7.24M | if (!m_frameName.empty()) |
496 | 77.7k | list.insert("librevenge:frame-name",m_frameName.c_str()); |
497 | 7.24M | } |
498 | | |
499 | | int MWAWGraphicStyle::cmp(MWAWGraphicStyle const &a) const |
500 | 0 | { |
501 | 0 | if (m_lineWidth < a.m_lineWidth) return -1; |
502 | 0 | if (m_lineWidth > a.m_lineWidth) return 1; |
503 | 0 | if (m_lineCap < a.m_lineCap) return -1; |
504 | 0 | if (m_lineCap > a.m_lineCap) return 1; |
505 | 0 | if (m_lineJoin < a.m_lineJoin) return -1; |
506 | 0 | if (m_lineJoin > a.m_lineJoin) return 1; |
507 | 0 | if (m_lineOpacity < a.m_lineOpacity) return -1; |
508 | 0 | if (m_lineOpacity > a.m_lineOpacity) return 1; |
509 | 0 | if (m_lineColor < a.m_lineColor) return -1; |
510 | 0 | if (m_lineColor > a.m_lineColor) return 1; |
511 | | |
512 | 0 | if (m_lineDashWidth.size() < a.m_lineDashWidth.size()) return -1; |
513 | 0 | if (m_lineDashWidth.size() > a.m_lineDashWidth.size()) return 1; |
514 | 0 | for (size_t d=0; d < m_lineDashWidth.size(); ++d) { |
515 | 0 | if (m_lineDashWidth[d] > a.m_lineDashWidth[d]) return -1; |
516 | 0 | if (m_lineDashWidth[d] < a.m_lineDashWidth[d]) return 1; |
517 | 0 | } |
518 | 0 | for (int i=0; i<2; ++i) { |
519 | 0 | if (m_arrows[i]!=a.m_arrows[i]) |
520 | 0 | return m_arrows[i]<a.m_arrows[i] ? -1 : 1; |
521 | 0 | if (m_flip[i]!=a.m_flip[i]) |
522 | 0 | return m_flip[i] ? 1 : -1; |
523 | 0 | } |
524 | | |
525 | 0 | if (m_fillRuleEvenOdd != a.m_fillRuleEvenOdd) return m_fillRuleEvenOdd ? 1: -1; |
526 | | |
527 | 0 | if (m_surfaceColor < a.m_surfaceColor) return -1; |
528 | 0 | if (m_surfaceColor > a.m_surfaceColor) return 1; |
529 | 0 | if (m_surfaceOpacity < a.m_surfaceOpacity) return -1; |
530 | 0 | if (m_surfaceOpacity > a.m_surfaceOpacity) return 1; |
531 | | |
532 | 0 | if (m_shadowColor < a.m_shadowColor) return -1; |
533 | 0 | if (m_shadowColor > a.m_shadowColor) return 1; |
534 | 0 | if (m_shadowOpacity < a.m_shadowOpacity) return -1; |
535 | 0 | if (m_shadowOpacity > a.m_shadowOpacity) return 1; |
536 | 0 | int diff=m_shadowOffset.cmp(a.m_shadowOffset); |
537 | 0 | if (diff) return diff; |
538 | | |
539 | 0 | diff = m_pattern.cmp(a.m_pattern); |
540 | 0 | if (diff) return diff; |
541 | 0 | diff = m_gradient.cmp(a.m_gradient); |
542 | 0 | if (diff) return diff; |
543 | 0 | diff = m_hatch.cmp(a.m_hatch); |
544 | 0 | if (diff) return diff; |
545 | | |
546 | 0 | size_t numBorders=m_bordersList.size(); |
547 | 0 | if (a.m_bordersList.size()>numBorders) |
548 | 0 | numBorders=a.m_bordersList.size(); |
549 | 0 | for (size_t b=0; b<numBorders; ++b) { |
550 | 0 | bool empty=b>=m_bordersList.size() || m_bordersList[b].isEmpty(); |
551 | 0 | bool aEmpty=b>=a.m_bordersList.size() || a.m_bordersList[b].isEmpty(); |
552 | 0 | if (empty!=aEmpty) return empty ? 1 : -1; |
553 | 0 | diff=m_bordersList[b].compare(a.m_bordersList[b]); |
554 | 0 | if (diff) return diff; |
555 | 0 | } |
556 | 0 | if (m_backgroundColor < a.m_backgroundColor) return -1; |
557 | 0 | if (m_backgroundColor > a.m_backgroundColor) return 1; |
558 | 0 | if (m_backgroundOpacity < a.m_backgroundOpacity) return -1; |
559 | 0 | if (m_backgroundOpacity > a.m_backgroundOpacity) return 1; |
560 | 0 | if (m_frameName < a.m_frameName) return -1; |
561 | 0 | if (m_frameName > a.m_frameName) return 1; |
562 | 0 | if (m_frameNextName < a.m_frameNextName) return -1; |
563 | 0 | if (m_frameNextName > a.m_frameNextName) return 1; |
564 | 0 | if (m_verticalAlignment < a.m_verticalAlignment) return -1; |
565 | 0 | if (m_verticalAlignment > a.m_verticalAlignment) return 1; |
566 | | |
567 | 0 | if (m_rotate < a.m_rotate) return -1; |
568 | 0 | if (m_rotate > a.m_rotate) return 1; |
569 | 0 | return 0; |
570 | 0 | } |
571 | | |
572 | | std::ostream &operator<<(std::ostream &o, MWAWGraphicStyle const &st) |
573 | 0 | { |
574 | 0 | if (st.m_rotate<0 || st.m_rotate>0) |
575 | 0 | o << "rot=" << st.m_rotate << ","; |
576 | 0 | if (st.m_flip[0]) o << "flipX,"; |
577 | 0 | if (st.m_flip[1]) o << "flipY,"; |
578 | 0 | o << "line=["; |
579 | 0 | if (st.m_lineWidth<1 || st.m_lineWidth>1) |
580 | 0 | o << "width=" << st.m_lineWidth << ","; |
581 | 0 | if (!st.m_lineDashWidth.empty()) { |
582 | 0 | o << "dash=["; |
583 | 0 | for (auto w : st.m_lineDashWidth) |
584 | 0 | o << w << ","; |
585 | 0 | o << "],"; |
586 | 0 | } |
587 | 0 | switch (st.m_lineCap) { |
588 | 0 | case MWAWGraphicStyle::C_Square: |
589 | 0 | o << "cap=square,"; |
590 | 0 | break; |
591 | 0 | case MWAWGraphicStyle::C_Round: |
592 | 0 | o << "cap=round,"; |
593 | 0 | break; |
594 | 0 | case MWAWGraphicStyle::C_Butt: |
595 | | #if !defined(__clang__) |
596 | | default: |
597 | | #endif |
598 | 0 | break; |
599 | 0 | } |
600 | 0 | switch (st.m_lineJoin) { |
601 | 0 | case MWAWGraphicStyle::J_Bevel: |
602 | 0 | o << "join=bevel,"; |
603 | 0 | break; |
604 | 0 | case MWAWGraphicStyle::J_Round: |
605 | 0 | o << "join=round,"; |
606 | 0 | break; |
607 | 0 | case MWAWGraphicStyle::J_Miter: |
608 | | #if !defined(__clang__) |
609 | | default: |
610 | | #endif |
611 | 0 | break; |
612 | 0 | } |
613 | 0 | if (st.m_lineOpacity<1) |
614 | 0 | o << "opacity=" << st.m_lineOpacity << ","; |
615 | 0 | if (!st.m_lineColor.isBlack()) |
616 | 0 | o << "color=" << st.m_lineColor << ","; |
617 | 0 | if (!st.m_arrows[0].isEmpty()) o << "arrow[start]=[" << st.m_arrows[0] << "],"; |
618 | 0 | if (!st.m_arrows[1].isEmpty()) o << "arrow[end]=[" << st.m_arrows[1] << "],"; |
619 | 0 | o << "],"; |
620 | 0 | if (st.hasSurfaceColor()) { |
621 | 0 | o << "surf=["; |
622 | 0 | if (!st.m_surfaceColor.isWhite()) |
623 | 0 | o << "color=" << st.m_surfaceColor << ","; |
624 | 0 | if (st.m_surfaceOpacity > 0) |
625 | 0 | o << "opacity=" << st.m_surfaceOpacity << ","; |
626 | 0 | o << "],"; |
627 | 0 | if (st.m_fillRuleEvenOdd) |
628 | 0 | o << "fill[evenOdd],"; |
629 | 0 | } |
630 | 0 | if (st.hasPattern()) |
631 | 0 | o << "pattern=[" << st.m_pattern << "],"; |
632 | 0 | if (st.hasGradient()) |
633 | 0 | o << "grad=[" << st.m_gradient << "],"; |
634 | 0 | if (st.hasHatch()) |
635 | 0 | o << "hatch=[" << st.m_hatch << "],"; |
636 | 0 | if (st.hasShadow()) { |
637 | 0 | o << "shadow=["; |
638 | 0 | if (!st.m_shadowColor.isBlack()) |
639 | 0 | o << "color=" << st.m_shadowColor << ","; |
640 | 0 | if (st.m_shadowOpacity > 0) |
641 | 0 | o << "opacity=" << st.m_shadowOpacity << ","; |
642 | 0 | o << "offset=" << st.m_shadowOffset << ","; |
643 | 0 | o << "],"; |
644 | 0 | } |
645 | 0 | if (st.hasBorders()) { |
646 | 0 | for (size_t i = 0; i < st.m_bordersList.size(); i++) { |
647 | 0 | if (st.m_bordersList[i].m_style == MWAWBorder::None) |
648 | 0 | continue; |
649 | 0 | o << "bord"; |
650 | 0 | if (i < 4) { |
651 | 0 | static char const* const wh[] = { "L", "R", "T", "B"}; |
652 | 0 | o << wh[i]; |
653 | 0 | } |
654 | 0 | else o << "[#wh=" << i << "]"; |
655 | 0 | o << "=" << st.m_bordersList[i] << ","; |
656 | 0 | } |
657 | 0 | } |
658 | 0 | if (!st.m_backgroundColor.isWhite()) |
659 | 0 | o << "background[color]=" << st.m_backgroundColor << ","; |
660 | 0 | if (st.m_backgroundOpacity>=0) |
661 | 0 | o << "background[opacity]=" << 100.f *st.m_backgroundOpacity << "%,"; |
662 | 0 | if (!st.m_frameName.empty()) |
663 | 0 | o << "frame[name]=" << st.m_frameName << ","; |
664 | 0 | if (!st.m_frameNextName.empty()) |
665 | 0 | o << "frame[linkedto]=" << st.m_frameNextName << ","; |
666 | 0 | o << st.m_extra; |
667 | 0 | return o; |
668 | 0 | } |
669 | | |
670 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |