/src/libfreehand/src/lib/FHCollector.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libfreehand 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 | | |
10 | | #include <algorithm> |
11 | | #include <cassert> |
12 | | #include <string.h> |
13 | | #include <librevenge/librevenge.h> |
14 | | #include "FHCollector.h" |
15 | | #include "FHConstants.h" |
16 | | #include "libfreehand_utils.h" |
17 | | |
18 | | #ifndef M_PI |
19 | | #define M_PI 3.14159265358979323846 |
20 | | #endif |
21 | | |
22 | | #ifndef DUMP_CONTENTS |
23 | | #define DUMP_CONTENTS 0 |
24 | | #endif |
25 | | #ifndef DUMP_BINARY_OBJECTS |
26 | | #define DUMP_BINARY_OBJECTS 0 |
27 | | #endif |
28 | | #ifndef DEBUG_BOUNDING_BOX |
29 | | #define DEBUG_BOUNDING_BOX 0 |
30 | | #endif |
31 | | #ifndef DUMP_TILE_FILLS |
32 | | #define DUMP_TILE_FILLS 0 |
33 | | #endif |
34 | | #ifndef DUMP_CLIP_GROUPS |
35 | | #define DUMP_CLIP_GROUPS 0 |
36 | | #endif |
37 | | |
38 | | #define FH_UNINITIALIZED(pI) \ |
39 | 1.90k | FH_ALMOST_ZERO(pI.m_minX) && FH_ALMOST_ZERO(pI.m_minY) && FH_ALMOST_ZERO(pI.m_maxY) && FH_ALMOST_ZERO(pI.m_maxX) |
40 | | |
41 | | namespace |
42 | | { |
43 | | bool isTiff(const unsigned char *buffer, unsigned long size) |
44 | 0 | { |
45 | 0 | if (size < 4) |
46 | 0 | return false; |
47 | 0 | if (buffer[0] == 0x49 && buffer[1] == 0x49 && buffer[2] == 0x2a && buffer[3] == 0x00) |
48 | 0 | return true; |
49 | 0 | if (buffer[0] == 0x4d && buffer[1] == 0x4d && buffer[2] == 0x00 && buffer[3] == 0x2a) |
50 | 0 | return true; |
51 | 0 | return false; |
52 | 0 | } |
53 | | |
54 | | bool isBmp(const unsigned char *buffer, unsigned long size) |
55 | 0 | { |
56 | 0 | if (size < 6) |
57 | 0 | return false; |
58 | 0 | if (buffer[0] != 0x42) |
59 | 0 | return false; |
60 | 0 | if (buffer[1] != 0x4d) |
61 | 0 | return false; |
62 | 0 | unsigned bufferSize = ((unsigned long)buffer[2] + ((unsigned long)buffer[3] << 8) + ((unsigned long)buffer[4] << 8) + ((unsigned long)buffer[5] << 8)); |
63 | 0 | if (bufferSize != size) |
64 | 0 | return false; |
65 | 0 | return true; |
66 | 0 | } |
67 | | |
68 | | bool isJpeg(const unsigned char *buffer, unsigned long size) |
69 | 0 | { |
70 | 0 | if (size < 4) |
71 | 0 | return false; |
72 | 0 | if (buffer[0] != 0xff) |
73 | 0 | return false; |
74 | 0 | if (buffer[1] != 0xd8) |
75 | 0 | return false; |
76 | 0 | if (buffer[size-2] != 0xff) |
77 | 0 | return false; |
78 | 0 | if (buffer[size-1] != 0xd9) |
79 | 0 | return false; |
80 | 0 | return true; |
81 | 0 | } |
82 | | |
83 | | bool isPng(const unsigned char *buffer, unsigned long size) |
84 | 0 | { |
85 | 0 | if (size < 8) |
86 | 0 | return false; |
87 | 0 | if (buffer[0] != 0x89) |
88 | 0 | return false; |
89 | 0 | if (buffer[1] != 0x50) |
90 | 0 | return false; |
91 | 0 | if (buffer[2] != 0x4e) |
92 | 0 | return false; |
93 | 0 | if (buffer[3] != 0x47) |
94 | 0 | return false; |
95 | 0 | if (buffer[4] != 0x0d) |
96 | 0 | return false; |
97 | 0 | if (buffer[5] != 0x0a) |
98 | 0 | return false; |
99 | 0 | if (buffer[6] != 0x1a) |
100 | 0 | return false; |
101 | 0 | if (buffer[7] != 0x0a) |
102 | 0 | return false; |
103 | 0 | return true; |
104 | 0 | } |
105 | | |
106 | | librevenge::RVNGString _getColorString(const libfreehand::FHRGBColor &color) |
107 | 345k | { |
108 | 345k | librevenge::RVNGString colorString; |
109 | 345k | colorString.sprintf("#%.2x%.2x%.2x", color.m_red >> 8, color.m_green >> 8, color.m_blue >> 8); |
110 | 345k | return colorString; |
111 | 345k | } |
112 | | |
113 | | static void _composePath(librevenge::RVNGPropertyListVector &path, bool isClosed) |
114 | 129k | { |
115 | 129k | bool firstPoint = true; |
116 | 129k | bool wasMove = false; |
117 | 129k | double initialX = 0.0; |
118 | 129k | double initialY = 0.0; |
119 | 129k | double previousX = 0.0; |
120 | 129k | double previousY = 0.0; |
121 | 129k | double x = 0.0; |
122 | 129k | double y = 0.0; |
123 | 129k | std::vector<librevenge::RVNGPropertyList> tmpPath; |
124 | | |
125 | 129k | librevenge::RVNGPropertyListVector::Iter i(path); |
126 | 900k | for (i.rewind(); i.next();) |
127 | 771k | { |
128 | 771k | if (!i()["librevenge:path-action"]) |
129 | 0 | continue; |
130 | 771k | if (i()["svg:x"] && i()["svg:y"]) |
131 | 771k | { |
132 | 771k | bool ignoreM = false; |
133 | 771k | x = i()["svg:x"]->getDouble(); |
134 | 771k | y = i()["svg:y"]->getDouble(); |
135 | 771k | if (firstPoint) |
136 | 129k | { |
137 | 129k | initialX = x; |
138 | 129k | initialY = y; |
139 | 129k | firstPoint = false; |
140 | 129k | wasMove = true; |
141 | 129k | } |
142 | 641k | else if (i()["librevenge:path-action"]->getStr() == "M") |
143 | 263 | { |
144 | 263 | if (FH_ALMOST_ZERO(previousX - x) && FH_ALMOST_ZERO(previousY - y)) |
145 | 13 | ignoreM = true; |
146 | 250 | else |
147 | 250 | { |
148 | 250 | if (!tmpPath.empty()) |
149 | 250 | { |
150 | 250 | if (!wasMove) |
151 | 250 | { |
152 | 250 | if ((FH_ALMOST_ZERO(initialX - previousX) && FH_ALMOST_ZERO(initialY - previousY)) || isClosed) |
153 | 225 | { |
154 | 225 | librevenge::RVNGPropertyList node; |
155 | 225 | node.insert("librevenge:path-action", "Z"); |
156 | 225 | tmpPath.push_back(node); |
157 | 225 | } |
158 | 250 | } |
159 | 0 | else |
160 | 0 | tmpPath.pop_back(); |
161 | 250 | } |
162 | 250 | } |
163 | | |
164 | 263 | if (!ignoreM) |
165 | 250 | { |
166 | 250 | initialX = x; |
167 | 250 | initialY = y; |
168 | 250 | wasMove = true; |
169 | 250 | } |
170 | | |
171 | 263 | } |
172 | 641k | else |
173 | 641k | wasMove = false; |
174 | | |
175 | 771k | if (!ignoreM) |
176 | 771k | { |
177 | 771k | tmpPath.push_back(i()); |
178 | 771k | previousX = x; |
179 | 771k | previousY = y; |
180 | 771k | } |
181 | | |
182 | 771k | } |
183 | 0 | else if (i()["librevenge:path-action"]->getStr() == "Z") |
184 | 0 | { |
185 | 0 | if (tmpPath.back()["librevenge:path-action"] && tmpPath.back()["librevenge:path-action"]->getStr() != "Z") |
186 | 0 | tmpPath.push_back(i()); |
187 | 0 | } |
188 | 771k | } |
189 | 129k | if (!tmpPath.empty()) |
190 | 129k | { |
191 | 129k | if (!wasMove) |
192 | 129k | { |
193 | 129k | if ((FH_ALMOST_ZERO(initialX - previousX) && FH_ALMOST_ZERO(initialY - previousY)) || isClosed) |
194 | 70.7k | { |
195 | 70.7k | if (tmpPath.back()["librevenge:path-action"] && tmpPath.back()["librevenge:path-action"]->getStr() != "Z") |
196 | 70.7k | { |
197 | 70.7k | librevenge::RVNGPropertyList closedPath; |
198 | 70.7k | closedPath.insert("librevenge:path-action", "Z"); |
199 | 70.7k | tmpPath.push_back(closedPath); |
200 | 70.7k | } |
201 | 70.7k | } |
202 | 129k | } |
203 | 49 | else |
204 | 49 | tmpPath.pop_back(); |
205 | 129k | } |
206 | 129k | if (!tmpPath.empty()) |
207 | 129k | { |
208 | 129k | path.clear(); |
209 | 971k | for (std::vector<librevenge::RVNGPropertyList>::const_iterator iter = tmpPath.begin(); iter != tmpPath.end(); ++iter) |
210 | 841k | path.append(*iter); |
211 | 129k | } |
212 | 129k | } |
213 | | |
214 | | class ObjectRecursionGuard |
215 | | { |
216 | | public: |
217 | | ObjectRecursionGuard(std::deque<unsigned> &objectStack, const unsigned id) |
218 | 745k | : m_objectStack(objectStack) |
219 | 745k | , m_id(id) |
220 | 745k | { |
221 | 745k | m_objectStack.push_front(m_id); |
222 | 745k | } |
223 | | |
224 | | ~ObjectRecursionGuard() |
225 | 745k | { |
226 | 745k | assert(!m_objectStack.empty()); |
227 | 745k | assert(m_objectStack.front() == m_id); |
228 | 745k | m_objectStack.pop_front(); |
229 | 745k | } |
230 | | |
231 | | private: |
232 | | std::deque<unsigned> &m_objectStack; |
233 | | const unsigned m_id; |
234 | | }; |
235 | | |
236 | | } |
237 | | |
238 | | libfreehand::FHCollector::FHCollector() : |
239 | 8.17k | m_pageInfo(), m_fhTail(), m_block(), m_transforms(), m_paths(), m_strings(), m_names(), m_lists(), |
240 | 8.17k | m_layers(), m_groups(), m_clipGroups(), m_currentTransforms(), m_fakeTransforms(), m_compositePaths(), |
241 | 8.17k | m_pathTexts(), m_tStrings(), m_fonts(), m_tEffects(), m_paragraphs(), m_tabs(), m_textBloks(), m_textObjects(), m_charProperties(), |
242 | 8.17k | m_paragraphProperties(), m_rgbColors(), m_basicFills(), m_propertyLists(), |
243 | 8.17k | m_basicLines(), m_customProcs(), m_patternLines(), m_displayTexts(), m_graphicStyles(), |
244 | 8.17k | m_attributeHolders(), m_data(), m_dataLists(), m_images(), m_multiColorLists(), m_linearFills(), |
245 | 8.17k | m_tints(), m_lensFills(), m_radialFills(), m_newBlends(), m_filterAttributeHolders(), m_opacityFilters(), |
246 | 8.17k | m_shadowFilters(), m_glowFilters(), m_tileFills(), m_symbolClasses(), m_symbolInstances(), m_patternFills(), |
247 | 8.17k | m_linePatterns(), m_arrowPaths(), |
248 | 8.17k | m_strokeId(0), m_fillId(0), m_contentId(0), m_textBoxNumberId(0), m_visitedObjects() |
249 | 8.17k | { |
250 | 8.17k | } |
251 | | |
252 | | libfreehand::FHCollector::~FHCollector() |
253 | 8.17k | { |
254 | 8.17k | } |
255 | | |
256 | | void libfreehand::FHCollector::collectPageInfo(const FHPageInfo &pageInfo) |
257 | 4.20k | { |
258 | 4.20k | m_pageInfo = pageInfo; |
259 | 4.20k | } |
260 | | |
261 | | void libfreehand::FHCollector::collectString(unsigned recordId, const librevenge::RVNGString &str) |
262 | 88.1k | { |
263 | 88.1k | m_strings[recordId] = str; |
264 | 88.1k | } |
265 | | |
266 | | void libfreehand::FHCollector::collectName(unsigned recordId, const librevenge::RVNGString &name) |
267 | 49.5k | { |
268 | 49.5k | m_names[name] = recordId; |
269 | 49.5k | if (name == "stroke") |
270 | 1.58k | m_strokeId = recordId; |
271 | 49.5k | if (name == "fill") |
272 | 1.46k | m_fillId = recordId; |
273 | 49.5k | if (name == "contents") |
274 | 1.05k | m_contentId = recordId; |
275 | 49.5k | } |
276 | | |
277 | | void libfreehand::FHCollector::collectPath(unsigned recordId, const libfreehand::FHPath &path) |
278 | 443k | { |
279 | 443k | m_paths[recordId] = path; |
280 | 443k | } |
281 | | |
282 | | void libfreehand::FHCollector::collectXform(unsigned recordId, |
283 | | double m11, double m21, double m12, double m22, double m13, double m23) |
284 | 86.5k | { |
285 | 86.5k | m_transforms[recordId] = FHTransform(m11, m21, m12, m22, m13, m23); |
286 | 86.5k | } |
287 | | |
288 | | void libfreehand::FHCollector::collectFHTail(unsigned /* recordId */, const FHTail &fhTail) |
289 | 3.54k | { |
290 | 3.54k | m_fhTail = fhTail; |
291 | 3.54k | } |
292 | | |
293 | | void libfreehand::FHCollector::collectBlock(unsigned recordId, const libfreehand::FHBlock &block) |
294 | 5.65k | { |
295 | 5.65k | if (m_block.first && m_block.first != recordId) |
296 | 3.43k | { |
297 | 3.43k | FH_DEBUG_MSG(("FHCollector::collectBlock -- WARNING: Several \"Block\" records in the file\n")); |
298 | 3.43k | } |
299 | 5.65k | m_block = std::make_pair(recordId, block); |
300 | 5.65k | } |
301 | | |
302 | | void libfreehand::FHCollector::collectList(unsigned recordId, const libfreehand::FHList &lst) |
303 | 108k | { |
304 | 108k | m_lists[recordId] = lst; |
305 | 108k | } |
306 | | |
307 | | void libfreehand::FHCollector::collectLayer(unsigned recordId, const libfreehand::FHLayer &layer) |
308 | 13.4k | { |
309 | 13.4k | m_layers[recordId] = layer; |
310 | 13.4k | } |
311 | | |
312 | | void libfreehand::FHCollector::collectGroup(unsigned recordId, const libfreehand::FHGroup &group) |
313 | 34.2k | { |
314 | 34.2k | m_groups[recordId] = group; |
315 | 34.2k | } |
316 | | |
317 | | void libfreehand::FHCollector::collectClipGroup(unsigned recordId, const libfreehand::FHGroup &group) |
318 | 1.14k | { |
319 | 1.14k | m_clipGroups[recordId] = group; |
320 | 1.14k | } |
321 | | |
322 | | void libfreehand::FHCollector::collectCompositePath(unsigned recordId, const libfreehand::FHCompositePath &compositePath) |
323 | 2.99k | { |
324 | 2.99k | m_compositePaths[recordId] = compositePath; |
325 | 2.99k | } |
326 | | |
327 | | void libfreehand::FHCollector::collectPathText(unsigned recordId, const libfreehand::FHPathText &pathText) |
328 | 3.53k | { |
329 | 3.53k | m_pathTexts[recordId] = pathText; |
330 | 3.53k | } |
331 | | |
332 | | void libfreehand::FHCollector::collectTString(unsigned recordId, const std::vector<unsigned> &elements) |
333 | 21.3k | { |
334 | 21.3k | m_tStrings[recordId] = elements; |
335 | 21.3k | } |
336 | | |
337 | | void libfreehand::FHCollector::collectAGDFont(unsigned recordId, const FHAGDFont &font) |
338 | 2.79k | { |
339 | 2.79k | m_fonts[recordId] = font; |
340 | 2.79k | } |
341 | | |
342 | | void libfreehand::FHCollector::collectTEffect(unsigned recordId, const FHTEffect &tEffect) |
343 | 61.3k | { |
344 | 61.3k | m_tEffects[recordId] = tEffect; |
345 | 61.3k | } |
346 | | |
347 | | void libfreehand::FHCollector::collectParagraph(unsigned recordId, const FHParagraph ¶graph) |
348 | 26.2k | { |
349 | 26.2k | m_paragraphs[recordId] = paragraph; |
350 | 26.2k | } |
351 | | |
352 | | void libfreehand::FHCollector::collectTabTable(unsigned recordId, const std::vector<FHTab> &tabs) |
353 | 7.68k | { |
354 | 7.68k | if (tabs.empty()) return; |
355 | 321 | m_tabs[recordId] = tabs; |
356 | 321 | } |
357 | | |
358 | | void libfreehand::FHCollector::collectTextBlok(unsigned recordId, const std::vector<unsigned short> &characters) |
359 | 26.5k | { |
360 | 26.5k | m_textBloks[recordId] = characters; |
361 | 26.5k | } |
362 | | |
363 | | void libfreehand::FHCollector::collectTextObject(unsigned recordId, const FHTextObject &textObject) |
364 | 22.2k | { |
365 | 22.2k | m_textObjects[recordId] = textObject; |
366 | 22.2k | } |
367 | | |
368 | | void libfreehand::FHCollector::collectCharProps(unsigned recordId, const FHCharProperties &charProps) |
369 | 34.7k | { |
370 | 34.7k | m_charProperties[recordId] = charProps; |
371 | 34.7k | } |
372 | | |
373 | | void libfreehand::FHCollector::collectParagraphProps(unsigned recordId, const FHParagraphProperties ¶graphProps) |
374 | 60.1k | { |
375 | 60.1k | m_paragraphProperties[recordId] = paragraphProps; |
376 | 60.1k | } |
377 | | |
378 | | void libfreehand::FHCollector::collectColor(unsigned recordId, const FHRGBColor &color) |
379 | 36.6k | { |
380 | 36.6k | m_rgbColors[recordId] = color; |
381 | 36.6k | } |
382 | | |
383 | | void libfreehand::FHCollector::collectTintColor(unsigned recordId, const FHTintColor &color) |
384 | 2.28k | { |
385 | 2.28k | m_tints[recordId] = color; |
386 | 2.28k | } |
387 | | |
388 | | void libfreehand::FHCollector::collectBasicFill(unsigned recordId, const FHBasicFill &fill) |
389 | 8.63k | { |
390 | 8.63k | m_basicFills[recordId] = fill; |
391 | 8.63k | } |
392 | | |
393 | | void libfreehand::FHCollector::collectBasicLine(unsigned recordId, const FHBasicLine &line) |
394 | 15.5k | { |
395 | 15.5k | m_basicLines[recordId] = line; |
396 | 15.5k | } |
397 | | |
398 | | void libfreehand::FHCollector::collectCustomProc(unsigned recordId, const FHCustomProc &line) |
399 | 2.79k | { |
400 | 2.79k | m_customProcs[recordId] = line; |
401 | 2.79k | } |
402 | | |
403 | | void libfreehand::FHCollector::collectPatternLine(unsigned recordId, const FHPatternLine &line) |
404 | 2.69k | { |
405 | 2.69k | m_patternLines[recordId] = line; |
406 | 2.69k | } |
407 | | |
408 | | void libfreehand::FHCollector::collectTileFill(unsigned recordId, const FHTileFill &fill) |
409 | 935 | { |
410 | 935 | m_tileFills[recordId] = fill; |
411 | 935 | } |
412 | | |
413 | | void libfreehand::FHCollector::collectPatternFill(unsigned recordId, const FHPatternFill &fill) |
414 | 3.91k | { |
415 | 3.91k | m_patternFills[recordId] = fill; |
416 | 3.91k | } |
417 | | |
418 | | void libfreehand::FHCollector::collectLinePattern(unsigned recordId, const FHLinePattern &line) |
419 | 21.9k | { |
420 | 21.9k | m_linePatterns[recordId] = line; |
421 | 21.9k | } |
422 | | |
423 | | void libfreehand::FHCollector::collectArrowPath(unsigned recordId, const FHPath &path) |
424 | 12.4k | { |
425 | | // osnola: useme |
426 | 12.4k | m_arrowPaths[recordId] = path; |
427 | 12.4k | } |
428 | | |
429 | | void libfreehand::FHCollector::collectPropList(unsigned recordId, const FHPropList &propertyList) |
430 | 241k | { |
431 | 241k | m_propertyLists[recordId] = propertyList; |
432 | 241k | } |
433 | | |
434 | | void libfreehand::FHCollector::collectDisplayText(unsigned recordId, const FHDisplayText &displayText) |
435 | 42.2k | { |
436 | 42.2k | m_displayTexts[recordId] = displayText; |
437 | 42.2k | } |
438 | | |
439 | | void libfreehand::FHCollector::collectGraphicStyle(unsigned recordId, const FHGraphicStyle &graphicStyle) |
440 | 34.7k | { |
441 | 34.7k | m_graphicStyles[recordId] = graphicStyle; |
442 | 34.7k | } |
443 | | |
444 | | void libfreehand::FHCollector::collectAttributeHolder(unsigned recordId, const FHAttributeHolder &attributeHolder) |
445 | 33.5k | { |
446 | 33.5k | m_attributeHolders[recordId] = attributeHolder; |
447 | 33.5k | } |
448 | | |
449 | | void libfreehand::FHCollector::collectFilterAttributeHolder(unsigned recordId, const FHFilterAttributeHolder &filterAttributeHolder) |
450 | 5.39k | { |
451 | 5.39k | m_filterAttributeHolders[recordId] = filterAttributeHolder; |
452 | 5.39k | } |
453 | | |
454 | | void libfreehand::FHCollector::collectData(unsigned recordId, const librevenge::RVNGBinaryData &data) |
455 | 1.08k | { |
456 | 1.08k | m_data[recordId] = data; |
457 | 1.08k | } |
458 | | |
459 | | void libfreehand::FHCollector::collectDataList(unsigned recordId, const FHDataList &list) |
460 | 271 | { |
461 | 271 | m_dataLists[recordId] = list; |
462 | 271 | } |
463 | | |
464 | | void libfreehand::FHCollector::collectImage(unsigned recordId, const FHImageImport &image) |
465 | 1.80k | { |
466 | 1.80k | m_images[recordId] = image; |
467 | 1.80k | } |
468 | | |
469 | | void libfreehand::FHCollector::collectMultiColorList(unsigned recordId, const std::vector<FHColorStop> &colorStops) |
470 | 2.58k | { |
471 | 2.58k | m_multiColorLists[recordId] = colorStops; |
472 | 2.58k | } |
473 | | |
474 | | void libfreehand::FHCollector::collectLinearFill(unsigned recordId, const FHLinearFill &fill) |
475 | 7.96k | { |
476 | 7.96k | m_linearFills[recordId] = fill; |
477 | 7.96k | } |
478 | | |
479 | | void libfreehand::FHCollector::collectLensFill(unsigned recordId, const FHLensFill &fill) |
480 | 630 | { |
481 | 630 | m_lensFills[recordId] = fill; |
482 | 630 | } |
483 | | |
484 | | void libfreehand::FHCollector::collectRadialFill(unsigned recordId, const FHRadialFill &fill) |
485 | 7.45k | { |
486 | 7.45k | m_radialFills[recordId] = fill; |
487 | 7.45k | } |
488 | | |
489 | | void libfreehand::FHCollector::collectNewBlend(unsigned recordId, const FHNewBlend &newBlend) |
490 | 2.99k | { |
491 | 2.99k | m_newBlends[recordId] = newBlend; |
492 | 2.99k | } |
493 | | |
494 | | void libfreehand::FHCollector::collectOpacityFilter(unsigned recordId, double opacity) |
495 | 3.71k | { |
496 | 3.71k | m_opacityFilters[recordId] = opacity; |
497 | 3.71k | } |
498 | | |
499 | | void libfreehand::FHCollector::collectFWShadowFilter(unsigned recordId, const FWShadowFilter &filter) |
500 | 3.43k | { |
501 | 3.43k | m_shadowFilters[recordId] = filter; |
502 | 3.43k | } |
503 | | |
504 | | void libfreehand::FHCollector::collectFWGlowFilter(unsigned recordId, const FWGlowFilter &filter) |
505 | 3.44k | { |
506 | 3.44k | m_glowFilters[recordId] = filter; |
507 | 3.44k | } |
508 | | |
509 | | void libfreehand::FHCollector::collectSymbolClass(unsigned recordId, const FHSymbolClass &symbolClass) |
510 | 73.1k | { |
511 | 73.1k | m_symbolClasses[recordId] = symbolClass; |
512 | 73.1k | } |
513 | | |
514 | | void libfreehand::FHCollector::collectSymbolInstance(unsigned recordId, const FHSymbolInstance &symbolInstance) |
515 | 14.1k | { |
516 | 14.1k | m_symbolInstances[recordId] = symbolInstance; |
517 | 14.1k | } |
518 | | |
519 | | void libfreehand::FHCollector::_normalizePath(libfreehand::FHPath &path) |
520 | 130k | { |
521 | 130k | FHTransform trafo(1.0, 0.0, 0.0, -1.0, - m_pageInfo.m_minX, m_pageInfo.m_maxY); |
522 | 130k | path.transform(trafo); |
523 | 130k | } |
524 | | |
525 | | void libfreehand::FHCollector::_normalizePoint(double &x, double &y) |
526 | 172k | { |
527 | 172k | FHTransform trafo(1.0, 0.0, 0.0, -1.0, - m_pageInfo.m_minX, m_pageInfo.m_maxY); |
528 | 172k | trafo.applyToPoint(x, y); |
529 | 172k | } |
530 | | |
531 | | void libfreehand::FHCollector::_getBBofPath(const FHPath *path, libfreehand::FHBoundingBox &bBox) |
532 | 2.24k | { |
533 | 2.24k | if (!path || path->empty()) |
534 | 893 | return; |
535 | | |
536 | 1.35k | FHPath fhPath(*path); |
537 | 1.35k | unsigned short xform = fhPath.getXFormId(); |
538 | | |
539 | 1.35k | if (xform) |
540 | 242 | { |
541 | 242 | const FHTransform *trafo = _findTransform(xform); |
542 | 242 | if (trafo) |
543 | 0 | fhPath.transform(*trafo); |
544 | 242 | } |
545 | 1.35k | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
546 | 2.86k | while (!groupTransforms.empty()) |
547 | 1.51k | { |
548 | 1.51k | fhPath.transform(groupTransforms.top()); |
549 | 1.51k | groupTransforms.pop(); |
550 | 1.51k | } |
551 | 1.35k | _normalizePath(fhPath); |
552 | 1.75k | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
553 | 403 | { |
554 | 403 | fhPath.transform(*iter); |
555 | 403 | } |
556 | | |
557 | 1.35k | FHBoundingBox tmpBBox; |
558 | 1.35k | fhPath.getBoundingBox(tmpBBox.m_xmin, tmpBBox.m_ymin, tmpBBox.m_xmax, tmpBBox.m_ymax); |
559 | 1.35k | bBox.merge(tmpBBox); |
560 | 1.35k | } |
561 | | |
562 | | void libfreehand::FHCollector::_getBBofGroup(const FHGroup *group, libfreehand::FHBoundingBox &bBox) |
563 | 2.24k | { |
564 | 2.24k | if (!group) |
565 | 2.24k | return; |
566 | | |
567 | 0 | if (group->m_xFormId) |
568 | 0 | { |
569 | 0 | const FHTransform *trafo = _findTransform(group->m_xFormId); |
570 | 0 | if (trafo) |
571 | 0 | m_currentTransforms.push(*trafo); |
572 | 0 | else |
573 | 0 | m_currentTransforms.push(libfreehand::FHTransform()); |
574 | 0 | } |
575 | 0 | else |
576 | 0 | m_currentTransforms.push(libfreehand::FHTransform()); |
577 | |
|
578 | 0 | const std::vector<unsigned> *elements = _findListElements(group->m_elementsId); |
579 | 0 | if (!elements) |
580 | 0 | { |
581 | 0 | FH_DEBUG_MSG(("ERROR: The pointed element list does not exist\n")); |
582 | 0 | return; |
583 | 0 | } |
584 | | |
585 | 0 | for (unsigned int element : *elements) |
586 | 0 | { |
587 | 0 | FHBoundingBox tmpBBox; |
588 | 0 | _getBBofSomething(element, tmpBBox); |
589 | 0 | bBox.merge(tmpBBox); |
590 | 0 | } |
591 | |
|
592 | 0 | if (!m_currentTransforms.empty()) |
593 | 0 | m_currentTransforms.pop(); |
594 | 0 | } |
595 | | |
596 | | void libfreehand::FHCollector::_getBBofClipGroup(const FHGroup *group, libfreehand::FHBoundingBox &bBox) |
597 | 2.24k | { |
598 | 2.24k | if (!group) |
599 | 2.24k | return; |
600 | | |
601 | 0 | if (group->m_xFormId) |
602 | 0 | { |
603 | 0 | const FHTransform *trafo = _findTransform(group->m_xFormId); |
604 | 0 | if (trafo) |
605 | 0 | m_currentTransforms.push(*trafo); |
606 | 0 | else |
607 | 0 | m_currentTransforms.push(libfreehand::FHTransform()); |
608 | 0 | } |
609 | 0 | else |
610 | 0 | m_currentTransforms.push(libfreehand::FHTransform()); |
611 | |
|
612 | 0 | const std::vector<unsigned> *elements = _findListElements(group->m_elementsId); |
613 | 0 | if (!elements) |
614 | 0 | { |
615 | 0 | FH_DEBUG_MSG(("ERROR: The pointed element list does not exist\n")); |
616 | 0 | return; |
617 | 0 | } |
618 | | |
619 | 0 | auto iterVec = elements->begin(); |
620 | 0 | FHBoundingBox tmpBBox; |
621 | 0 | _getBBofSomething(*iterVec, tmpBBox); |
622 | 0 | bBox.merge(tmpBBox); |
623 | |
|
624 | 0 | if (!m_currentTransforms.empty()) |
625 | 0 | m_currentTransforms.pop(); |
626 | 0 | } |
627 | | |
628 | | void libfreehand::FHCollector::_getBBofCompositePath(const FHCompositePath *compositePath, libfreehand::FHBoundingBox &bBox) |
629 | 2.24k | { |
630 | 2.24k | if (!compositePath) |
631 | 2.24k | return; |
632 | | |
633 | 0 | const std::vector<unsigned> *elements = _findListElements(compositePath->m_elementsId); |
634 | 0 | if (elements && !elements->empty()) |
635 | 0 | { |
636 | 0 | libfreehand::FHPath fhPath; |
637 | 0 | auto iter = elements->begin(); |
638 | 0 | const libfreehand::FHPath *path = _findPath(*(iter++)); |
639 | 0 | if (path) |
640 | 0 | { |
641 | 0 | fhPath = *path; |
642 | 0 | if (!fhPath.getGraphicStyleId()) |
643 | 0 | fhPath.setGraphicStyleId(compositePath->m_graphicStyleId); |
644 | 0 | } |
645 | |
|
646 | 0 | for (; iter != elements->end(); ++iter) |
647 | 0 | { |
648 | 0 | path = _findPath(*iter); |
649 | 0 | if (path) |
650 | 0 | { |
651 | 0 | fhPath.appendPath(*path); |
652 | 0 | if (!fhPath.getGraphicStyleId()) |
653 | 0 | fhPath.setGraphicStyleId(compositePath->m_graphicStyleId); |
654 | 0 | } |
655 | 0 | } |
656 | 0 | FHBoundingBox tmpBBox; |
657 | 0 | _getBBofPath(&fhPath, tmpBBox); |
658 | 0 | bBox.merge(tmpBBox); |
659 | 0 | } |
660 | 0 | } |
661 | | |
662 | | void libfreehand::FHCollector::_getBBofPathText(const FHPathText *pathText, libfreehand::FHBoundingBox &bBox) |
663 | 2.24k | { |
664 | 2.24k | if (!pathText) |
665 | 2.24k | return; |
666 | | |
667 | 0 | _getBBofDisplayText(_findDisplayText(pathText->m_displayTextId),bBox); |
668 | 0 | } |
669 | | |
670 | | void libfreehand::FHCollector::_getBBofTextObject(const FHTextObject *textObject, libfreehand::FHBoundingBox &bBox) |
671 | 2.24k | { |
672 | 2.24k | if (!textObject) |
673 | 1.52k | return; |
674 | | |
675 | 723 | double xa = textObject->m_startX; |
676 | 723 | double ya = textObject->m_startY; |
677 | 723 | double xb = textObject->m_startX + textObject->m_width; |
678 | 723 | double yb = textObject->m_startY + textObject->m_height; |
679 | 723 | double xc = xa; |
680 | 723 | double yc = yb; |
681 | 723 | double xd = xb; |
682 | 723 | double yd = ya; |
683 | 723 | unsigned xFormId = textObject->m_xFormId; |
684 | 723 | if (xFormId) |
685 | 692 | { |
686 | 692 | const FHTransform *trafo = _findTransform(xFormId); |
687 | 692 | if (trafo) |
688 | 610 | { |
689 | 610 | trafo->applyToPoint(xa, ya); |
690 | 610 | trafo->applyToPoint(xb, yb); |
691 | 610 | trafo->applyToPoint(xc, yc); |
692 | 610 | trafo->applyToPoint(xd, yd); |
693 | 610 | } |
694 | 692 | } |
695 | 723 | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
696 | 1.44k | while (!groupTransforms.empty()) |
697 | 721 | { |
698 | 721 | groupTransforms.top().applyToPoint(xa, ya); |
699 | 721 | groupTransforms.top().applyToPoint(xb, yb); |
700 | 721 | groupTransforms.top().applyToPoint(xc, yc); |
701 | 721 | groupTransforms.top().applyToPoint(xd, yd); |
702 | 721 | groupTransforms.pop(); |
703 | 721 | } |
704 | 723 | _normalizePoint(xa, ya); |
705 | 723 | _normalizePoint(xb, yb); |
706 | 723 | _normalizePoint(xc, yc); |
707 | 723 | _normalizePoint(xd, yd); |
708 | | |
709 | 723 | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
710 | 0 | { |
711 | 0 | iter->applyToPoint(xa, ya); |
712 | 0 | iter->applyToPoint(xb, yb); |
713 | 0 | iter->applyToPoint(xc, yc); |
714 | 0 | iter->applyToPoint(xd, yd); |
715 | 0 | } |
716 | | |
717 | 723 | FHBoundingBox tmpBBox; |
718 | 723 | if (xa < tmpBBox.m_xmin) tmpBBox.m_xmin = xa; |
719 | 723 | if (xb < tmpBBox.m_xmin) tmpBBox.m_xmin = xb; |
720 | 723 | if (xc < tmpBBox.m_xmin) tmpBBox.m_xmin = xc; |
721 | 723 | if (xd < tmpBBox.m_xmin) tmpBBox.m_xmin = xd; |
722 | | |
723 | 723 | if (xa > tmpBBox.m_xmax) tmpBBox.m_xmax = xa; |
724 | 723 | if (xb > tmpBBox.m_xmax) tmpBBox.m_xmax = xb; |
725 | 723 | if (xc > tmpBBox.m_xmax) tmpBBox.m_xmax = xc; |
726 | 723 | if (xd > tmpBBox.m_xmax) tmpBBox.m_xmax = xd; |
727 | | |
728 | 723 | if (ya < tmpBBox.m_ymin) tmpBBox.m_ymin = ya; |
729 | 723 | if (yb < tmpBBox.m_ymin) tmpBBox.m_ymin = yb; |
730 | 723 | if (yc < tmpBBox.m_ymin) tmpBBox.m_ymin = yc; |
731 | 723 | if (yd < tmpBBox.m_ymin) tmpBBox.m_ymin = yd; |
732 | | |
733 | 723 | if (ya > tmpBBox.m_ymax) tmpBBox.m_ymax = ya; |
734 | 723 | if (yb > tmpBBox.m_ymax) tmpBBox.m_ymax = yb; |
735 | 723 | if (yc > tmpBBox.m_ymax) tmpBBox.m_ymax = yc; |
736 | 723 | if (yd > tmpBBox.m_ymax) tmpBBox.m_ymax = yd; |
737 | 723 | bBox.merge(tmpBBox); |
738 | 723 | } |
739 | | |
740 | | void libfreehand::FHCollector::_getBBofDisplayText(const FHDisplayText *displayText, libfreehand::FHBoundingBox &bBox) |
741 | 2.24k | { |
742 | 2.24k | if (!displayText) |
743 | 2.24k | return; |
744 | | |
745 | 0 | double xa = displayText->m_startX; |
746 | 0 | double ya = displayText->m_startY; |
747 | 0 | double xb = displayText->m_startX + displayText->m_width; |
748 | 0 | double yb = displayText->m_startY + displayText->m_height; |
749 | 0 | double xc = xa; |
750 | 0 | double yc = yb; |
751 | 0 | double xd = xb; |
752 | 0 | double yd = ya; |
753 | 0 | unsigned xFormId = displayText->m_xFormId; |
754 | 0 | if (xFormId) |
755 | 0 | { |
756 | 0 | const FHTransform *trafo = _findTransform(xFormId); |
757 | 0 | if (trafo) |
758 | 0 | { |
759 | 0 | trafo->applyToPoint(xa, ya); |
760 | 0 | trafo->applyToPoint(xb, yb); |
761 | 0 | trafo->applyToPoint(xc, yc); |
762 | 0 | trafo->applyToPoint(xd, yd); |
763 | 0 | } |
764 | 0 | } |
765 | 0 | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
766 | 0 | while (!groupTransforms.empty()) |
767 | 0 | { |
768 | 0 | groupTransforms.top().applyToPoint(xa, ya); |
769 | 0 | groupTransforms.top().applyToPoint(xb, yb); |
770 | 0 | groupTransforms.top().applyToPoint(xc, yc); |
771 | 0 | groupTransforms.top().applyToPoint(xd, yd); |
772 | 0 | groupTransforms.pop(); |
773 | 0 | } |
774 | 0 | _normalizePoint(xa, ya); |
775 | 0 | _normalizePoint(xb, yb); |
776 | 0 | _normalizePoint(xc, yc); |
777 | 0 | _normalizePoint(xd, yd); |
778 | |
|
779 | 0 | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
780 | 0 | { |
781 | 0 | iter->applyToPoint(xa, ya); |
782 | 0 | iter->applyToPoint(xb, yb); |
783 | 0 | iter->applyToPoint(xc, yc); |
784 | 0 | iter->applyToPoint(xd, yd); |
785 | 0 | } |
786 | |
|
787 | 0 | FHBoundingBox tmpBBox; |
788 | 0 | if (xa < tmpBBox.m_xmin) tmpBBox.m_xmin = xa; |
789 | 0 | if (xb < tmpBBox.m_xmin) tmpBBox.m_xmin = xb; |
790 | 0 | if (xc < tmpBBox.m_xmin) tmpBBox.m_xmin = xc; |
791 | 0 | if (xd < tmpBBox.m_xmin) tmpBBox.m_xmin = xd; |
792 | |
|
793 | 0 | if (xa > tmpBBox.m_xmax) tmpBBox.m_xmax = xa; |
794 | 0 | if (xb > tmpBBox.m_xmax) tmpBBox.m_xmax = xb; |
795 | 0 | if (xc > tmpBBox.m_xmax) tmpBBox.m_xmax = xc; |
796 | 0 | if (xd > tmpBBox.m_xmax) tmpBBox.m_xmax = xd; |
797 | |
|
798 | 0 | if (ya < tmpBBox.m_ymin) tmpBBox.m_ymin = ya; |
799 | 0 | if (yb < tmpBBox.m_ymin) tmpBBox.m_ymin = yb; |
800 | 0 | if (yc < tmpBBox.m_ymin) tmpBBox.m_ymin = yc; |
801 | 0 | if (yd < tmpBBox.m_ymin) tmpBBox.m_ymin = yd; |
802 | |
|
803 | 0 | if (ya > tmpBBox.m_ymax) tmpBBox.m_ymax = ya; |
804 | 0 | if (yb > tmpBBox.m_ymax) tmpBBox.m_ymax = yb; |
805 | 0 | if (yc > tmpBBox.m_ymax) tmpBBox.m_ymax = yc; |
806 | 0 | if (yd > tmpBBox.m_ymax) tmpBBox.m_ymax = yd; |
807 | 0 | bBox.merge(tmpBBox); |
808 | 0 | } |
809 | | |
810 | | void libfreehand::FHCollector::_getBBofImageImport(const FHImageImport *image, libfreehand::FHBoundingBox &bBox) |
811 | 2.24k | { |
812 | 2.24k | if (!image) |
813 | 2.24k | return; |
814 | | |
815 | 0 | double xa = image->m_startX; |
816 | 0 | double ya = image->m_startY; |
817 | 0 | double xb = image->m_startX + image->m_width; |
818 | 0 | double yb = image->m_startY + image->m_height; |
819 | 0 | double xc = xa; |
820 | 0 | double yc = yb; |
821 | 0 | double xd = xb; |
822 | 0 | double yd = ya; |
823 | 0 | unsigned xFormId = image->m_xFormId; |
824 | 0 | if (xFormId) |
825 | 0 | { |
826 | 0 | const FHTransform *trafo = _findTransform(xFormId); |
827 | 0 | if (trafo) |
828 | 0 | { |
829 | 0 | trafo->applyToPoint(xa, ya); |
830 | 0 | trafo->applyToPoint(xb, yb); |
831 | 0 | trafo->applyToPoint(xc, yc); |
832 | 0 | trafo->applyToPoint(xd, yd); |
833 | 0 | } |
834 | 0 | } |
835 | 0 | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
836 | 0 | while (!groupTransforms.empty()) |
837 | 0 | { |
838 | 0 | groupTransforms.top().applyToPoint(xa, ya); |
839 | 0 | groupTransforms.top().applyToPoint(xb, yb); |
840 | 0 | groupTransforms.top().applyToPoint(xc, yc); |
841 | 0 | groupTransforms.top().applyToPoint(xd, yd); |
842 | 0 | groupTransforms.pop(); |
843 | 0 | } |
844 | 0 | _normalizePoint(xa, ya); |
845 | 0 | _normalizePoint(xb, yb); |
846 | 0 | _normalizePoint(xc, yc); |
847 | 0 | _normalizePoint(xd, yd); |
848 | |
|
849 | 0 | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
850 | 0 | { |
851 | 0 | iter->applyToPoint(xa, ya); |
852 | 0 | iter->applyToPoint(xb, yb); |
853 | 0 | iter->applyToPoint(xc, yc); |
854 | 0 | iter->applyToPoint(xd, yd); |
855 | 0 | } |
856 | |
|
857 | 0 | FHBoundingBox tmpBBox; |
858 | 0 | if (xa < tmpBBox.m_xmin) tmpBBox.m_xmin = xa; |
859 | 0 | if (xb < tmpBBox.m_xmin) tmpBBox.m_xmin = xb; |
860 | 0 | if (xc < tmpBBox.m_xmin) tmpBBox.m_xmin = xc; |
861 | 0 | if (xd < tmpBBox.m_xmin) tmpBBox.m_xmin = xd; |
862 | |
|
863 | 0 | if (xa > tmpBBox.m_xmax) tmpBBox.m_xmax = xa; |
864 | 0 | if (xb > tmpBBox.m_xmax) tmpBBox.m_xmax = xb; |
865 | 0 | if (xc > tmpBBox.m_xmax) tmpBBox.m_xmax = xc; |
866 | 0 | if (xd > tmpBBox.m_xmax) tmpBBox.m_xmax = xd; |
867 | |
|
868 | 0 | if (ya < tmpBBox.m_ymin) tmpBBox.m_ymin = ya; |
869 | 0 | if (yb < tmpBBox.m_ymin) tmpBBox.m_ymin = yb; |
870 | 0 | if (yc < tmpBBox.m_ymin) tmpBBox.m_ymin = yc; |
871 | 0 | if (yd < tmpBBox.m_ymin) tmpBBox.m_ymin = yd; |
872 | |
|
873 | 0 | if (ya > tmpBBox.m_ymax) tmpBBox.m_ymax = ya; |
874 | 0 | if (yb > tmpBBox.m_ymax) tmpBBox.m_ymax = yb; |
875 | 0 | if (yc > tmpBBox.m_ymax) tmpBBox.m_ymax = yc; |
876 | 0 | if (yd > tmpBBox.m_ymax) tmpBBox.m_ymax = yd; |
877 | 0 | bBox.merge(tmpBBox); |
878 | 0 | } |
879 | | |
880 | | void libfreehand::FHCollector::_getBBofNewBlend(const FHNewBlend * /* newBlend */, libfreehand::FHBoundingBox & /* bBox */) |
881 | 2.24k | { |
882 | 2.24k | } |
883 | | |
884 | | void libfreehand::FHCollector::_getBBofSymbolInstance(const FHSymbolInstance *symbolInstance, libfreehand::FHBoundingBox &bBox) |
885 | 2.24k | { |
886 | 2.24k | if (!symbolInstance) |
887 | 2.24k | return; |
888 | | |
889 | 0 | m_currentTransforms.push(symbolInstance->m_xForm); |
890 | |
|
891 | 0 | const FHSymbolClass *symbolClass = _findSymbolClass(symbolInstance->m_symbolClassId); |
892 | 0 | if (symbolClass) |
893 | 0 | { |
894 | 0 | FHBoundingBox tmpBBox; |
895 | 0 | _getBBofSomething(symbolClass->m_groupId, tmpBBox); |
896 | 0 | bBox.merge(tmpBBox); |
897 | 0 | } |
898 | |
|
899 | 0 | if (!m_currentTransforms.empty()) |
900 | 0 | m_currentTransforms.pop(); |
901 | 0 | } |
902 | | |
903 | | void libfreehand::FHCollector::_getBBofSomething(unsigned somethingId, libfreehand::FHBoundingBox &bBox) |
904 | 2.24k | { |
905 | 2.24k | if (!somethingId) |
906 | 0 | return; |
907 | | |
908 | 2.24k | FHBoundingBox tmpBBox; |
909 | 2.24k | _getBBofGroup(_findGroup(somethingId), tmpBBox); |
910 | 2.24k | _getBBofClipGroup(_findClipGroup(somethingId), tmpBBox); |
911 | 2.24k | _getBBofPathText(_findPathText(somethingId), tmpBBox); |
912 | 2.24k | _getBBofPath(_findPath(somethingId), tmpBBox); |
913 | 2.24k | _getBBofCompositePath(_findCompositePath(somethingId), tmpBBox); |
914 | 2.24k | _getBBofTextObject(_findTextObject(somethingId), tmpBBox); |
915 | 2.24k | _getBBofDisplayText(_findDisplayText(somethingId), tmpBBox); |
916 | 2.24k | _getBBofImageImport(_findImageImport(somethingId), tmpBBox); |
917 | 2.24k | _getBBofNewBlend(_findNewBlend(somethingId), tmpBBox); |
918 | 2.24k | _getBBofSymbolInstance(_findSymbolInstance(somethingId), tmpBBox); |
919 | 2.24k | bBox.merge(tmpBBox); |
920 | 2.24k | } |
921 | | |
922 | | |
923 | | void libfreehand::FHCollector::_outputPath(const libfreehand::FHPath *path, librevenge::RVNGDrawingInterface *painter) |
924 | 223k | { |
925 | 223k | if (!painter || !path || path->empty()) |
926 | 94.0k | return; |
927 | | |
928 | 129k | FHPath fhPath(*path); |
929 | 129k | librevenge::RVNGPropertyList propList; |
930 | 129k | _appendStrokeProperties(propList, fhPath.getGraphicStyleId()); |
931 | 129k | _appendFillProperties(propList, fhPath.getGraphicStyleId()); |
932 | 129k | unsigned contentId = _findContentId(fhPath.getGraphicStyleId()); |
933 | 129k | if (fhPath.getEvenOdd()) |
934 | 0 | propList.insert("svg:fill-rule", "evenodd"); |
935 | | |
936 | 129k | unsigned short xform = fhPath.getXFormId(); |
937 | | |
938 | 129k | if (xform) |
939 | 18.8k | { |
940 | 18.8k | const FHTransform *trafo = _findTransform(xform); |
941 | 18.8k | if (trafo) |
942 | 17.3k | fhPath.transform(*trafo); |
943 | 18.8k | } |
944 | 129k | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
945 | 325k | while (!groupTransforms.empty()) |
946 | 195k | { |
947 | 195k | fhPath.transform(groupTransforms.top()); |
948 | 195k | groupTransforms.pop(); |
949 | 195k | } |
950 | 129k | _normalizePath(fhPath); |
951 | | |
952 | 132k | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
953 | 3.02k | { |
954 | 3.02k | fhPath.transform(*iter); |
955 | 3.02k | } |
956 | | |
957 | 129k | librevenge::RVNGPropertyListVector propVec; |
958 | 129k | fhPath.writeOut(propVec); |
959 | 129k | if (propList["draw:fill"] && propList["draw:fill"]->getStr() != "none") |
960 | 9.18k | _composePath(propVec, true); |
961 | 120k | else |
962 | 120k | _composePath(propVec, fhPath.isClosed()); |
963 | 129k | librevenge::RVNGPropertyList pList; |
964 | 129k | pList.insert("svg:d", propVec); |
965 | 129k | if (contentId) |
966 | 10.6k | painter->openGroup(librevenge::RVNGPropertyList()); |
967 | 129k | painter->setStyle(propList); |
968 | 129k | painter->drawPath(pList); |
969 | 129k | if (contentId) |
970 | 10.6k | { |
971 | 10.6k | FHBoundingBox bBox; |
972 | 10.6k | fhPath.getBoundingBox(bBox.m_xmin, bBox.m_ymin, bBox.m_xmax, bBox.m_ymax); |
973 | 10.6k | FHTransform trafo(1.0, 0.0, 0.0, 1.0, - bBox.m_xmin, - bBox.m_ymin); |
974 | 10.6k | m_fakeTransforms.push_back(trafo); |
975 | 10.6k | librevenge::RVNGStringVector svgOutput; |
976 | 10.6k | librevenge::RVNGSVGDrawingGenerator generator(svgOutput, ""); |
977 | 10.6k | propList.clear(); |
978 | 10.6k | propList.insert("svg:width", bBox.m_xmax - bBox.m_xmin); |
979 | 10.6k | propList.insert("svg:height", bBox.m_ymax - bBox.m_ymin); |
980 | 10.6k | generator.startPage(propList); |
981 | 10.6k | _outputSomething(contentId, &generator); |
982 | 10.6k | generator.endPage(); |
983 | 10.6k | if (!svgOutput.empty() && svgOutput[0].size() > 140) // basically empty svg if it is not fullfilled |
984 | 10.6k | { |
985 | 10.6k | const char *header = |
986 | 10.6k | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"; |
987 | 10.6k | librevenge::RVNGBinaryData output((const unsigned char *)header, strlen(header)); |
988 | 10.6k | output.append((unsigned char *)svgOutput[0].cstr(), strlen(svgOutput[0].cstr())); |
989 | | #if DUMP_CONTENTS |
990 | | { |
991 | | librevenge::RVNGString filename; |
992 | | filename.sprintf("fhcontents%.4x.svg", contentId); |
993 | | FILE *f = fopen(filename.cstr(), "wb"); |
994 | | if (f) |
995 | | { |
996 | | const unsigned char *tmpBuffer = output.getDataBuffer(); |
997 | | for (unsigned long k = 0; k < output.size(); k++) |
998 | | fprintf(f, "%c",tmpBuffer[k]); |
999 | | fclose(f); |
1000 | | } |
1001 | | } |
1002 | | #endif |
1003 | 10.6k | propList.clear(); |
1004 | 10.6k | propList.insert("draw:stroke", "none"); |
1005 | 10.6k | propList.insert("draw:fill", "bitmap"); |
1006 | 10.6k | propList.insert("librevenge:mime-type", "image/svg+xml"); |
1007 | 10.6k | propList.insert("style:repeat", "stretch"); |
1008 | 10.6k | propList.insert("draw:fill-image", output); |
1009 | 10.6k | painter->setStyle(propList); |
1010 | 10.6k | painter->drawPath(pList); |
1011 | 10.6k | } |
1012 | 10.6k | if (!m_fakeTransforms.empty()) |
1013 | 10.6k | m_fakeTransforms.pop_back(); |
1014 | 10.6k | painter->closeGroup(); |
1015 | 10.6k | } |
1016 | | #if DEBUG_BOUNDING_BOX |
1017 | | { |
1018 | | librevenge::RVNGPropertyList rectangleProps; |
1019 | | rectangleProps.insert("draw:fill", "none"); |
1020 | | rectangleProps.insert("draw:stroke", "solid"); |
1021 | | painter->setStyle(rectangleProps); |
1022 | | double xmin, ymin, xmax, ymax; |
1023 | | fhPath.getBoundingBox(xmin, ymin, xmax, ymax); |
1024 | | librevenge::RVNGPropertyList rectangleList; |
1025 | | rectangleList.insert("svg:x", xmin); |
1026 | | rectangleList.insert("svg:y", ymin); |
1027 | | rectangleList.insert("svg:width", xmax - xmin); |
1028 | | rectangleList.insert("svg:height", ymax - ymin); |
1029 | | painter->drawRectangle(rectangleList); |
1030 | | } |
1031 | | #endif |
1032 | 129k | } |
1033 | | |
1034 | | void libfreehand::FHCollector::_outputSomething(unsigned somethingId, librevenge::RVNGDrawingInterface *painter) |
1035 | 228k | { |
1036 | 228k | if (!painter || !somethingId) |
1037 | 5.12k | return; |
1038 | 223k | if (find(m_visitedObjects.begin(), m_visitedObjects.end(), somethingId) != m_visitedObjects.end()) |
1039 | 482 | return; |
1040 | | |
1041 | 223k | const ObjectRecursionGuard guard(m_visitedObjects, somethingId); |
1042 | | |
1043 | 223k | _outputGroup(_findGroup(somethingId), painter); |
1044 | 223k | _outputClipGroup(_findClipGroup(somethingId), painter); |
1045 | 223k | _outputPathText(_findPathText(somethingId), painter); |
1046 | 223k | _outputPath(_findPath(somethingId), painter); |
1047 | 223k | _outputCompositePath(_findCompositePath(somethingId), painter); |
1048 | 223k | _outputTextObject(_findTextObject(somethingId), painter); |
1049 | 223k | _outputDisplayText(_findDisplayText(somethingId), painter); |
1050 | 223k | _outputImageImport(_findImageImport(somethingId), painter); |
1051 | 223k | _outputNewBlend(_findNewBlend(somethingId), painter); |
1052 | 223k | _outputSymbolInstance(_findSymbolInstance(somethingId), painter); |
1053 | 223k | } |
1054 | | |
1055 | | void libfreehand::FHCollector::_outputGroup(const libfreehand::FHGroup *group, librevenge::RVNGDrawingInterface *painter) |
1056 | 223k | { |
1057 | 223k | if (!painter || !group) |
1058 | 203k | return; |
1059 | | |
1060 | 19.7k | if (group->m_xFormId) |
1061 | 91 | { |
1062 | 91 | const FHTransform *trafo = _findTransform(group->m_xFormId); |
1063 | 91 | if (trafo) |
1064 | 4 | m_currentTransforms.push(*trafo); |
1065 | 87 | else |
1066 | 87 | m_currentTransforms.push(libfreehand::FHTransform()); |
1067 | 91 | } |
1068 | 19.6k | else |
1069 | 19.6k | m_currentTransforms.push(libfreehand::FHTransform()); |
1070 | | |
1071 | 19.7k | const std::vector<unsigned> *elements = _findListElements(group->m_elementsId); |
1072 | 19.7k | if (!elements) |
1073 | 151 | { |
1074 | 151 | FH_DEBUG_MSG(("ERROR: The pointed element list does not exist\n")); |
1075 | 151 | return; |
1076 | 151 | } |
1077 | | |
1078 | 19.6k | if (!elements->empty()) |
1079 | 19.5k | { |
1080 | 19.5k | painter->openGroup(librevenge::RVNGPropertyList()); |
1081 | 19.5k | for (unsigned int element : *elements) |
1082 | 174k | _outputSomething(element, painter); |
1083 | 19.5k | painter->closeGroup(); |
1084 | 19.5k | } |
1085 | | |
1086 | 19.6k | if (!m_currentTransforms.empty()) |
1087 | 19.6k | m_currentTransforms.pop(); |
1088 | 19.6k | } |
1089 | | |
1090 | | void libfreehand::FHCollector::_outputClipGroup(const libfreehand::FHGroup *group, librevenge::RVNGDrawingInterface *painter) |
1091 | 223k | { |
1092 | 223k | if (!painter || !group) |
1093 | 223k | return; |
1094 | | |
1095 | 84 | const std::vector<unsigned> *elements = _findListElements(group->m_elementsId); |
1096 | 84 | if (!elements) |
1097 | 0 | { |
1098 | 0 | FH_DEBUG_MSG(("ERROR: The pointed element list does not exist\n")); |
1099 | 0 | return; |
1100 | 0 | } |
1101 | | |
1102 | 84 | if (!elements->empty()) |
1103 | 84 | { |
1104 | 84 | auto iter = elements->begin(); |
1105 | 84 | const FHPath *path = _findPath(*iter); |
1106 | 84 | if (!path) |
1107 | 0 | _outputGroup(group, painter); |
1108 | 84 | else |
1109 | 84 | { |
1110 | 84 | if (group->m_xFormId) |
1111 | 0 | { |
1112 | 0 | const FHTransform *trafo = _findTransform(group->m_xFormId); |
1113 | 0 | if (trafo) |
1114 | 0 | m_currentTransforms.push(*trafo); |
1115 | 0 | else |
1116 | 0 | m_currentTransforms.push(libfreehand::FHTransform()); |
1117 | 0 | } |
1118 | 84 | else |
1119 | 84 | m_currentTransforms.push(libfreehand::FHTransform()); |
1120 | | |
1121 | 84 | librevenge::RVNGPropertyList propList; |
1122 | 84 | FHPath fhPath(*path); |
1123 | 84 | _appendStrokeProperties(propList, fhPath.getGraphicStyleId()); |
1124 | 84 | _appendFillProperties(propList, fhPath.getGraphicStyleId()); |
1125 | 84 | if (fhPath.getEvenOdd()) |
1126 | 0 | propList.insert("svg:fill-rule", "evenodd"); |
1127 | 84 | unsigned short xform = fhPath.getXFormId(); |
1128 | | |
1129 | 84 | if (xform) |
1130 | 0 | { |
1131 | 0 | const FHTransform *trafo = _findTransform(xform); |
1132 | 0 | if (trafo) |
1133 | 0 | fhPath.transform(*trafo); |
1134 | 0 | } |
1135 | 84 | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
1136 | 357 | while (!groupTransforms.empty()) |
1137 | 273 | { |
1138 | 273 | fhPath.transform(groupTransforms.top()); |
1139 | 273 | groupTransforms.pop(); |
1140 | 273 | } |
1141 | 84 | _normalizePath(fhPath); |
1142 | | |
1143 | 156 | for (std::vector<FHTransform>::const_iterator iterVec = m_fakeTransforms.begin(); iterVec != m_fakeTransforms.end(); ++iterVec) |
1144 | 72 | { |
1145 | 72 | fhPath.transform(*iterVec); |
1146 | 72 | } |
1147 | | |
1148 | 84 | if (!m_currentTransforms.empty()) |
1149 | 84 | m_currentTransforms.pop(); |
1150 | | |
1151 | 84 | librevenge::RVNGPropertyListVector propVec; |
1152 | 84 | fhPath.writeOut(propVec); |
1153 | 84 | _composePath(propVec, true); |
1154 | 84 | librevenge::RVNGPropertyList pList; |
1155 | 84 | pList.insert("svg:d", propVec); |
1156 | | |
1157 | | |
1158 | 84 | FHBoundingBox bBox; |
1159 | 84 | fhPath.getBoundingBox(bBox.m_xmin, bBox.m_ymin, bBox.m_xmax, bBox.m_ymax); |
1160 | 84 | FHTransform trafo(1.0, 0.0, 0.0, 1.0, - bBox.m_xmin, - bBox.m_ymin); |
1161 | 84 | m_fakeTransforms.push_back(trafo); |
1162 | 84 | librevenge::RVNGStringVector svgOutput; |
1163 | 84 | librevenge::RVNGSVGDrawingGenerator generator(svgOutput, ""); |
1164 | 84 | propList.clear(); |
1165 | 84 | propList.insert("svg:width", bBox.m_xmax - bBox.m_xmin); |
1166 | 84 | propList.insert("svg:height", bBox.m_ymax - bBox.m_ymin); |
1167 | 84 | generator.startPage(propList); |
1168 | 84 | _outputGroup(group, &generator); |
1169 | 84 | generator.endPage(); |
1170 | 84 | if (!svgOutput.empty() && svgOutput[0].size() > 140) // basically empty svg if it is not fullfilled |
1171 | 84 | { |
1172 | 84 | const char *header = |
1173 | 84 | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"; |
1174 | 84 | librevenge::RVNGBinaryData output((const unsigned char *)header, strlen(header)); |
1175 | 84 | output.append((unsigned char *)svgOutput[0].cstr(), strlen(svgOutput[0].cstr())); |
1176 | | #if DUMP_CLIP_GROUPS |
1177 | | { |
1178 | | librevenge::RVNGString filename; |
1179 | | filename.sprintf("freehandclipgroup%.4x.svg", group->m_elementsId); |
1180 | | FILE *f = fopen(filename.cstr(), "wb"); |
1181 | | if (f) |
1182 | | { |
1183 | | const unsigned char *tmpBuffer = output.getDataBuffer(); |
1184 | | for (unsigned long k = 0; k < output.size(); k++) |
1185 | | fprintf(f, "%c",tmpBuffer[k]); |
1186 | | fclose(f); |
1187 | | } |
1188 | | } |
1189 | | #endif |
1190 | 84 | propList.insert("draw:stroke", "none"); |
1191 | 84 | propList.insert("draw:fill", "bitmap"); |
1192 | 84 | propList.insert("librevenge:mime-type", "image/svg+xml"); |
1193 | 84 | propList.insert("style:repeat", "stretch"); |
1194 | 84 | propList.insert("draw:fill-image", output); |
1195 | 84 | painter->setStyle(propList); |
1196 | 84 | painter->drawPath(pList); |
1197 | 84 | } |
1198 | 84 | if (!m_fakeTransforms.empty()) |
1199 | 84 | m_fakeTransforms.pop_back(); |
1200 | 84 | } |
1201 | 84 | } |
1202 | 84 | } |
1203 | | |
1204 | | void libfreehand::FHCollector::_outputPathText(const libfreehand::FHPathText *pathText, librevenge::RVNGDrawingInterface *painter) |
1205 | 223k | { |
1206 | 223k | if (!painter || !pathText) |
1207 | 223k | return; |
1208 | | |
1209 | 189 | _outputDisplayText(_findDisplayText(pathText->m_displayTextId), painter); |
1210 | 189 | } |
1211 | | |
1212 | | void libfreehand::FHCollector::_outputNewBlend(const libfreehand::FHNewBlend *newBlend, librevenge::RVNGDrawingInterface *painter) |
1213 | 223k | { |
1214 | 223k | if (!painter || !newBlend) |
1215 | 223k | return; |
1216 | | |
1217 | 12 | m_currentTransforms.push(libfreehand::FHTransform()); |
1218 | | |
1219 | 12 | painter->openGroup(librevenge::RVNGPropertyList()); |
1220 | 12 | const std::vector<unsigned> *elements1 = _findListElements(newBlend->m_list1Id); |
1221 | 12 | if (elements1 && !elements1->empty()) |
1222 | 12 | { |
1223 | 12 | for (unsigned int iterVec : *elements1) |
1224 | 24 | _outputSomething(iterVec, painter); |
1225 | 12 | } |
1226 | 12 | const std::vector<unsigned> *elements2 = _findListElements(newBlend->m_list2Id); |
1227 | 12 | if (elements2 && !elements2->empty()) |
1228 | 12 | { |
1229 | 12 | for (unsigned int iterVec : *elements2) |
1230 | 12 | _outputSomething(iterVec, painter); |
1231 | 12 | } |
1232 | 12 | const std::vector<unsigned> *elements3 = _findListElements(newBlend->m_list3Id); |
1233 | 12 | if (elements3 && !elements3->empty()) |
1234 | 12 | { |
1235 | 12 | for (unsigned int iterVec : *elements3) |
1236 | 12 | _outputSomething(iterVec, painter); |
1237 | 12 | } |
1238 | 12 | painter->closeGroup(); |
1239 | | |
1240 | 12 | if (!m_currentTransforms.empty()) |
1241 | 12 | m_currentTransforms.pop(); |
1242 | 12 | } |
1243 | | |
1244 | | void libfreehand::FHCollector::_outputSymbolInstance(const libfreehand::FHSymbolInstance *symbolInstance, librevenge::RVNGDrawingInterface *painter) |
1245 | 223k | { |
1246 | 223k | if (!painter || !symbolInstance) |
1247 | 223k | return; |
1248 | | |
1249 | 0 | m_currentTransforms.push(symbolInstance->m_xForm); |
1250 | |
|
1251 | 0 | const FHSymbolClass *symbolClass = _findSymbolClass(symbolInstance->m_symbolClassId); |
1252 | 0 | if (symbolClass) |
1253 | 0 | { |
1254 | 0 | _outputSomething(symbolClass->m_groupId, painter); |
1255 | 0 | } |
1256 | |
|
1257 | 0 | if (!m_currentTransforms.empty()) |
1258 | 0 | m_currentTransforms.pop(); |
1259 | 0 | } |
1260 | | |
1261 | | void libfreehand::FHCollector::outputDrawing(librevenge::RVNGDrawingInterface *painter) |
1262 | 4.20k | { |
1263 | | |
1264 | | #if DUMP_BINARY_OBJECTS |
1265 | | for (std::map<unsigned, FHImageImport>::const_iterator iterImage = m_images.begin(); iterImage != m_images.end(); ++iterImage) |
1266 | | { |
1267 | | librevenge::RVNGBinaryData data = getImageData(iterImage->second.m_dataListId); |
1268 | | librevenge::RVNGString filename; |
1269 | | filename.sprintf("freehanddump%.4x.%s", iterImage->first, iterImage->second.m_format.empty() ? "bin" : iterImage->second.m_format.cstr()); |
1270 | | FILE *f = fopen(filename.cstr(), "wb"); |
1271 | | if (f) |
1272 | | { |
1273 | | const unsigned char *tmpBuffer = data.getDataBuffer(); |
1274 | | for (unsigned long k = 0; k < data.size(); k++) |
1275 | | fprintf(f, "%c",tmpBuffer[k]); |
1276 | | fclose(f); |
1277 | | } |
1278 | | } |
1279 | | #endif |
1280 | | |
1281 | 4.20k | if (!painter) |
1282 | 0 | return; |
1283 | | |
1284 | 4.20k | if (!m_fhTail.m_blockId || m_fhTail.m_blockId != m_block.first) |
1285 | 3.34k | { |
1286 | 3.34k | FH_DEBUG_MSG(("WARNING: FHTail points to an invalid Block ID\n")); |
1287 | 3.34k | m_fhTail.m_blockId = m_block.first; |
1288 | 3.34k | } |
1289 | 4.20k | if (!m_fhTail.m_blockId) |
1290 | 2.29k | { |
1291 | 2.29k | FH_DEBUG_MSG(("ERROR: Block record is absent from this file\n")); |
1292 | 2.29k | return; |
1293 | 2.29k | } |
1294 | | |
1295 | 1.90k | if (FH_UNINITIALIZED(m_pageInfo)) |
1296 | 1.52k | m_pageInfo = m_fhTail.m_pageInfo; |
1297 | | |
1298 | 1.90k | painter->startDocument(librevenge::RVNGPropertyList()); |
1299 | 1.90k | librevenge::RVNGPropertyList propList; |
1300 | 1.90k | propList.insert("svg:height", m_pageInfo.m_maxY - m_pageInfo.m_minY); |
1301 | 1.90k | propList.insert("svg:width", m_pageInfo.m_maxX - m_pageInfo.m_minX); |
1302 | 1.90k | painter->startPage(propList); |
1303 | | |
1304 | 1.90k | unsigned layerListId = m_block.second.m_layerListId; |
1305 | | |
1306 | 1.90k | const std::vector<unsigned> *elements = _findListElements(layerListId); |
1307 | 1.90k | if (elements) |
1308 | 1.73k | { |
1309 | 1.73k | for (unsigned int element : *elements) |
1310 | 9.29k | { |
1311 | 9.29k | _outputLayer(element, painter); |
1312 | 9.29k | } |
1313 | 1.73k | } |
1314 | 1.90k | painter->endPage(); |
1315 | 1.90k | painter->endDocument(); |
1316 | 1.90k | } |
1317 | | |
1318 | | void libfreehand::FHCollector::_outputLayer(unsigned layerId, librevenge::RVNGDrawingInterface *painter) |
1319 | 9.29k | { |
1320 | 9.29k | if (!painter) |
1321 | 0 | return; |
1322 | | |
1323 | 9.29k | std::map<unsigned, FHLayer>::const_iterator layerIter = m_layers.find(layerId); |
1324 | 9.29k | if (layerIter == m_layers.end()) |
1325 | 4.88k | { |
1326 | 4.88k | FH_DEBUG_MSG(("ERROR: Could not find the referenced layer\n")); |
1327 | 4.88k | return; |
1328 | 4.88k | } |
1329 | | |
1330 | 4.41k | if (layerIter->second.m_visibility != 3) |
1331 | 2.39k | return; |
1332 | | |
1333 | 2.01k | unsigned layerElementsListId = layerIter->second.m_elementsId; |
1334 | 2.01k | if (!layerElementsListId) |
1335 | 3 | { |
1336 | 3 | FH_DEBUG_MSG(("ERROR: Layer points to invalid element list\n")); |
1337 | 3 | return; |
1338 | 3 | } |
1339 | | |
1340 | 2.01k | const std::vector<unsigned> *elements = _findListElements(layerElementsListId); |
1341 | 2.01k | if (!elements) |
1342 | 21 | { |
1343 | 21 | FH_DEBUG_MSG(("ERROR: The pointed element list does not exist\n")); |
1344 | 21 | return; |
1345 | 21 | } |
1346 | | |
1347 | 1.99k | for (unsigned int element : *elements) |
1348 | 41.6k | _outputSomething(element, painter); |
1349 | 1.99k | } |
1350 | | |
1351 | | void libfreehand::FHCollector::_outputCompositePath(const libfreehand::FHCompositePath *compositePath, librevenge::RVNGDrawingInterface *painter) |
1352 | 223k | { |
1353 | 223k | if (!painter || !compositePath) |
1354 | 223k | return; |
1355 | | |
1356 | 322 | const std::vector<unsigned> *elements = _findListElements(compositePath->m_elementsId); |
1357 | 322 | if (elements && !elements->empty()) |
1358 | 267 | { |
1359 | 267 | libfreehand::FHPath fhPath; |
1360 | 267 | auto iter = elements->begin(); |
1361 | 267 | const libfreehand::FHPath *path = _findPath(*(iter++)); |
1362 | 267 | if (path) |
1363 | 206 | { |
1364 | 206 | fhPath = *path; |
1365 | 206 | if (!fhPath.getGraphicStyleId()) |
1366 | 0 | fhPath.setGraphicStyleId(compositePath->m_graphicStyleId); |
1367 | 206 | } |
1368 | | |
1369 | 2.48k | for (; iter != elements->end(); ++iter) |
1370 | 2.22k | { |
1371 | 2.22k | path = _findPath(*iter); |
1372 | 2.22k | if (path) |
1373 | 290 | { |
1374 | 290 | fhPath.appendPath(*path); |
1375 | 290 | if (!fhPath.getGraphicStyleId()) |
1376 | 36 | fhPath.setGraphicStyleId(compositePath->m_graphicStyleId); |
1377 | 290 | } |
1378 | 2.22k | } |
1379 | 267 | _outputPath(&fhPath, painter); |
1380 | 267 | } |
1381 | 322 | } |
1382 | | |
1383 | | void libfreehand::FHCollector::_outputTextObject(const libfreehand::FHTextObject *textObject, librevenge::RVNGDrawingInterface *painter) |
1384 | 223k | { |
1385 | 223k | if (!painter || !textObject) |
1386 | 203k | return; |
1387 | | |
1388 | 19.5k | double width=textObject->m_width; |
1389 | 19.5k | double height=textObject->m_height; |
1390 | 19.5k | unsigned num[]= {textObject->m_colNum,textObject->m_rowNum}; |
1391 | 19.5k | double decalX[]= {width+textObject->m_colSep,0}; |
1392 | 19.5k | double decalY[]= {0, height+textObject->m_rowSep}; |
1393 | 19.5k | if (textObject->m_rowBreakFirst) |
1394 | 68 | { |
1395 | 68 | std::swap(num[0],num[1]); |
1396 | 68 | std::swap(decalX[0],decalX[1]); |
1397 | 68 | std::swap(decalY[0],decalY[1]); |
1398 | 68 | } |
1399 | 19.5k | for (unsigned int &i : num) |
1400 | 39.1k | { |
1401 | 39.1k | if (i<=0 || i>10) |
1402 | 1.04k | { |
1403 | 1.04k | FH_DEBUG_MSG(("libfreehand::FHCollector::_outputTextObject: the number of row/col seems bad\n")); |
1404 | 1.04k | i=1; |
1405 | 1.04k | } |
1406 | 39.1k | } |
1407 | 19.5k | ++m_textBoxNumberId; |
1408 | 19.5k | for (unsigned dim0=0; dim0<num[0]; ++dim0) |
1409 | 19.5k | { |
1410 | 19.5k | for (unsigned dim1=0; dim1<num[1]; ++dim1) |
1411 | 19.5k | { |
1412 | 19.5k | unsigned id = dim0*num[1]+dim1; |
1413 | 19.5k | double rotation = 0, finalHeight = 0, finalWidth = 0, xmid=0, ymid=0; |
1414 | 19.5k | bool useShapeBox=false; |
1415 | 19.5k | if ((width<=0 || height<=0) && textObject->m_pathId) |
1416 | 266 | { |
1417 | | /* the position are not set for TFOnPath, so we must look for the shape box |
1418 | | |
1419 | | Note: the width and height seem better, the x,y position are still quite random :-~ |
1420 | | */ |
1421 | 266 | FHBoundingBox bbox; |
1422 | 266 | _getBBofSomething(textObject->m_pathId, bbox); |
1423 | 266 | useShapeBox=true; |
1424 | 266 | xmid=0.5*(bbox.m_xmin+bbox.m_xmax); |
1425 | 266 | ymid=0.5*(bbox.m_ymin+bbox.m_ymax); |
1426 | 266 | width=finalWidth=(bbox.m_xmax-bbox.m_xmin); |
1427 | 266 | height=finalHeight=(bbox.m_ymax-bbox.m_ymin); |
1428 | 266 | } |
1429 | 19.5k | if (!useShapeBox) |
1430 | 19.3k | { |
1431 | | #ifdef HAVE_CHAINED_TEXTBOX |
1432 | | // useme when we can chain frames in Draw |
1433 | | double startX=textObject->m_startX+dim0*decalX[0]+dim1*decalX[1]; |
1434 | | double startY=textObject->m_startY+dim0*decalY[0]+dim1*decalY[1]; |
1435 | | #else |
1436 | | /* if the number of row/column is greater than 1, we have a |
1437 | | big problem. Let increase the text-box size to contain all |
1438 | | the chained text-boxes... |
1439 | | */ |
1440 | 19.3k | double startX=textObject->m_startX; |
1441 | 19.3k | double startY=textObject->m_startY; |
1442 | 19.3k | width += (num[0]-1)*decalX[0]+(num[1]-1)*decalX[1]; |
1443 | 19.3k | height += (num[0]-1)*decalY[0]+(num[1]-1)*decalY[1]; |
1444 | 19.3k | #endif |
1445 | 19.3k | double xa = startX; |
1446 | 19.3k | double ya = startY; |
1447 | 19.3k | double xb = startX + width; |
1448 | 19.3k | double yb = startY + height; |
1449 | 19.3k | double xc = xa; |
1450 | 19.3k | double yc = yb; |
1451 | 19.3k | unsigned xFormId = textObject->m_xFormId; |
1452 | 19.3k | if (xFormId) |
1453 | 19.2k | { |
1454 | 19.2k | const FHTransform *trafo = _findTransform(xFormId); |
1455 | 19.2k | if (trafo) |
1456 | 19.0k | { |
1457 | 19.0k | trafo->applyToPoint(xa, ya); |
1458 | 19.0k | trafo->applyToPoint(xb, yb); |
1459 | 19.0k | trafo->applyToPoint(xc, yc); |
1460 | 19.0k | } |
1461 | 19.2k | } |
1462 | 19.3k | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
1463 | 80.6k | while (!groupTransforms.empty()) |
1464 | 61.3k | { |
1465 | 61.3k | groupTransforms.top().applyToPoint(xa, ya); |
1466 | 61.3k | groupTransforms.top().applyToPoint(xb, yb); |
1467 | 61.3k | groupTransforms.top().applyToPoint(xc, yc); |
1468 | 61.3k | groupTransforms.pop(); |
1469 | 61.3k | } |
1470 | 19.3k | _normalizePoint(xa, ya); |
1471 | 19.3k | _normalizePoint(xb, yb); |
1472 | 19.3k | _normalizePoint(xc, yc); |
1473 | | |
1474 | 20.0k | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
1475 | 705 | { |
1476 | 705 | iter->applyToPoint(xa, ya); |
1477 | 705 | iter->applyToPoint(xb, yb); |
1478 | 705 | iter->applyToPoint(xc, yc); |
1479 | 705 | } |
1480 | | |
1481 | 19.3k | rotation = atan2(yb-yc, xb-xc); |
1482 | 19.3k | finalHeight = sqrt((xc-xa)*(xc-xa) + (yc-ya)*(yc-ya)); |
1483 | 19.3k | finalWidth = sqrt((xc-xb)*(xc-xb) + (yc-yb)*(yc-yb)); |
1484 | 19.3k | xmid = (xa + xb) / 2.0; |
1485 | 19.3k | ymid = (ya + yb) / 2.0; |
1486 | 19.3k | } |
1487 | | |
1488 | 19.5k | librevenge::RVNGPropertyList textObjectProps; |
1489 | 19.5k | textObjectProps.insert("svg:x", xmid - width / 2.0); |
1490 | 19.5k | textObjectProps.insert("svg:y", ymid + height / 2.0); |
1491 | 19.5k | textObjectProps.insert("svg:height", finalHeight); |
1492 | 19.5k | textObjectProps.insert("svg:width", finalWidth); |
1493 | 19.5k | if (!FH_ALMOST_ZERO(rotation)) |
1494 | 513 | { |
1495 | 513 | textObjectProps.insert("librevenge:rotate", rotation * 180.0 / M_PI); |
1496 | 513 | textObjectProps.insert("librevenge:rotate-cx",xmid); |
1497 | 513 | textObjectProps.insert("librevenge:rotate-cy",ymid); |
1498 | 513 | } |
1499 | | #ifdef HAVE_CHAINED_TEXTBOX |
1500 | | if (id) |
1501 | | { |
1502 | | librevenge::RVNGString name; |
1503 | | name.sprintf("Textbox%d-%d",m_textBoxNumberId,id); |
1504 | | textObjectProps.insert("librevenge:frame-name",name); |
1505 | | } |
1506 | | if (id+1!=num[0]*num[1]) |
1507 | | { |
1508 | | librevenge::RVNGString name; |
1509 | | name.sprintf("Textbox%d-%d",m_textBoxNumberId,id+1); |
1510 | | textObjectProps.insert("librevenge:next-frame-name",name); |
1511 | | } |
1512 | | #endif |
1513 | 19.5k | painter->startTextObject(textObjectProps); |
1514 | | |
1515 | 19.5k | if (id==0) |
1516 | 19.5k | { |
1517 | 19.5k | const std::vector<unsigned> *elements = _findTStringElements(textObject->m_tStringId); |
1518 | 19.5k | unsigned actPos=0; |
1519 | 19.5k | if (elements && !elements->empty()) |
1520 | 19.4k | { |
1521 | 19.4k | for (unsigned int element : *elements) |
1522 | 80.1k | _outputParagraph(_findParagraph(element), painter, actPos, textObject->m_beginPos, textObject->m_endPos); |
1523 | 19.4k | } |
1524 | 19.5k | } |
1525 | 19.5k | painter->endTextObject(); |
1526 | | |
1527 | 19.5k | #if !defined(HAVE_CHAINED_TEXTBOX) |
1528 | 19.5k | break; |
1529 | 19.5k | #endif |
1530 | 19.5k | } |
1531 | 19.5k | #if !defined(HAVE_CHAINED_TEXTBOX) |
1532 | 19.5k | break; |
1533 | 19.5k | #endif |
1534 | 19.5k | } |
1535 | 19.5k | } |
1536 | | |
1537 | | void libfreehand::FHCollector::_outputParagraph(const libfreehand::FHParagraph *paragraph, librevenge::RVNGDrawingInterface *painter, unsigned &actPos, unsigned minPos, unsigned maxPos) |
1538 | 80.1k | { |
1539 | 80.1k | if (!painter || !paragraph) |
1540 | 55.4k | return; |
1541 | 24.6k | bool paragraphOpened=false; |
1542 | 24.6k | std::map<unsigned, std::vector<unsigned short> >::const_iterator iter = m_textBloks.find(paragraph->m_textBlokId); |
1543 | 24.6k | if (iter != m_textBloks.end()) |
1544 | 24.2k | { |
1545 | | |
1546 | 52.3k | for (std::vector<std::pair<unsigned, unsigned> >::size_type i = 0; i < paragraph->m_charStyleIds.size(); ++i) |
1547 | 30.1k | { |
1548 | 30.1k | if (actPos>=maxPos) break; |
1549 | 28.1k | unsigned lastChar=i+1 < paragraph->m_charStyleIds.size() ? paragraph->m_charStyleIds[i+1].first : iter->second.size(); |
1550 | 28.1k | unsigned numChar=lastChar-paragraph->m_charStyleIds[i].first; |
1551 | 28.1k | unsigned nextPos=actPos+numChar; |
1552 | 28.1k | if (nextPos<minPos) |
1553 | 679 | { |
1554 | 679 | actPos=nextPos; |
1555 | 679 | continue; |
1556 | 679 | } |
1557 | 27.4k | if (!paragraphOpened) |
1558 | 22.0k | { |
1559 | 22.0k | librevenge::RVNGPropertyList propList; |
1560 | 22.0k | _appendParagraphProperties(propList, paragraph->m_paraStyleId); |
1561 | 22.0k | painter->openParagraph(propList); |
1562 | 22.0k | paragraphOpened=true; |
1563 | 22.0k | } |
1564 | 27.4k | unsigned fChar=paragraph->m_charStyleIds[i].first + (actPos<minPos ? minPos-actPos : 0); |
1565 | 27.4k | numChar=lastChar-fChar; |
1566 | 27.4k | if (actPos+numChar>maxPos) numChar=maxPos-actPos; |
1567 | 27.4k | _outputTextRun(&(iter->second), fChar, numChar, paragraph->m_charStyleIds[i].second, painter); |
1568 | 27.4k | actPos=nextPos; |
1569 | 27.4k | } |
1570 | 24.2k | } |
1571 | 24.6k | ++actPos; // EOL |
1572 | 24.6k | if (paragraphOpened) |
1573 | 22.0k | painter->closeParagraph(); |
1574 | 24.6k | } |
1575 | | |
1576 | | void libfreehand::FHCollector::_appendCharacterProperties(librevenge::RVNGPropertyList &propList, unsigned charPropsId) |
1577 | 27.0k | { |
1578 | 27.0k | std::map<unsigned, FHCharProperties>::const_iterator iter = m_charProperties.find(charPropsId); |
1579 | 27.0k | if (iter == m_charProperties.end()) |
1580 | 1.82k | return; |
1581 | 25.1k | const FHCharProperties &charProps = iter->second; |
1582 | 25.1k | if (charProps.m_fontNameId) |
1583 | 36 | { |
1584 | 36 | std::map<unsigned, librevenge::RVNGString>::const_iterator iterString = m_strings.find(charProps.m_fontNameId); |
1585 | 36 | if (iterString != m_strings.end()) |
1586 | 36 | propList.insert("style:font-name", iterString->second); |
1587 | 36 | } |
1588 | 25.1k | propList.insert("fo:font-size", charProps.m_fontSize, librevenge::RVNG_POINT); |
1589 | 25.1k | if (charProps.m_fontId) |
1590 | 25.0k | _appendFontProperties(propList, charProps.m_fontId); |
1591 | 25.1k | if (charProps.m_textColorId) |
1592 | 510 | { |
1593 | 510 | std::map<unsigned, FHBasicFill>::const_iterator iterBasicFill = m_basicFills.find(charProps.m_textColorId); |
1594 | 510 | if (iterBasicFill != m_basicFills.end() && iterBasicFill->second.m_colorId) |
1595 | 140 | { |
1596 | 140 | librevenge::RVNGString color = getColorString(iterBasicFill->second.m_colorId); |
1597 | 140 | if (!color.empty()) |
1598 | 140 | propList.insert("fo:color", color); |
1599 | 140 | } |
1600 | 510 | } |
1601 | 25.1k | FHTEffect const *eff=_findTEffect(charProps.m_tEffectId); |
1602 | 25.1k | if (eff && eff->m_nameId) |
1603 | 627 | { |
1604 | 627 | std::map<unsigned, librevenge::RVNGString>::const_iterator iterString = m_strings.find(eff->m_nameId); |
1605 | 627 | if (iterString != m_strings.end()) |
1606 | 598 | { |
1607 | 598 | librevenge::RVNGString const &type=iterString->second; |
1608 | 598 | if (type=="InlineEffect") // inside col1, outside col0 |
1609 | 185 | { |
1610 | 185 | propList.insert("fo:font-weight", "bold"); |
1611 | 185 | librevenge::RVNGString color = getColorString(eff->m_colorId[1]); |
1612 | 185 | if (!color.empty()) |
1613 | 176 | propList.insert("fo:color", color); |
1614 | 185 | } |
1615 | 413 | else if (type=="ShadowEffect") |
1616 | 188 | propList.insert("fo:text-shadow", "1pt 1pt"); |
1617 | 225 | else if (type=="ZoomEffect") |
1618 | 162 | { |
1619 | 162 | propList.insert("style:font-relief", "embossed"); |
1620 | 162 | propList.insert("fo:text-shadow", "1pt -1pt"); |
1621 | 162 | librevenge::RVNGString color = getColorString(eff->m_colorId[0]); |
1622 | 162 | if (!color.empty()) |
1623 | 158 | propList.insert("fo:color", color); |
1624 | 162 | } |
1625 | 63 | else |
1626 | 63 | { |
1627 | 63 | FH_DEBUG_MSG(("libfreehand::FHCollector::_appendCharacterProperties: find unknown effect %s\n",type.cstr())); |
1628 | 63 | } |
1629 | 598 | } |
1630 | 627 | } |
1631 | 100k | for (auto it=charProps.m_idToDoubleMap.begin(); it!=charProps.m_idToDoubleMap.end(); ++it) |
1632 | 74.9k | { |
1633 | 74.9k | switch (it->first) |
1634 | 74.9k | { |
1635 | 24.8k | case FH_BASELN_SHIFT: |
1636 | 24.8k | { |
1637 | 24.8k | if (it->second<=0 && it->second>=0) break; |
1638 | 2.61k | librevenge::RVNGString value; |
1639 | 2.61k | double fontSize=(charProps.m_fontSize>0) ? charProps.m_fontSize : 24.; |
1640 | 2.61k | value.sprintf("%g%%",100.*it->second/fontSize); |
1641 | 2.61k | propList.insert("style:text-position", value); |
1642 | 2.61k | break; |
1643 | 24.8k | } |
1644 | 25.1k | case FH_HOR_SCALE: |
1645 | 25.1k | if (it->second<=1 && it->second>=1) break; |
1646 | 429 | propList.insert("style:text-scale", it->second, librevenge::RVNG_PERCENT); |
1647 | 429 | break; |
1648 | 24.9k | case FH_RNG_KERN: |
1649 | 24.9k | if (it->second<=0 && it->second>=0) break; |
1650 | 309 | propList.insert("fo:letter-spacing", it->second*charProps.m_fontSize, librevenge::RVNG_POINT); |
1651 | 309 | break; |
1652 | 0 | default: |
1653 | 0 | break; |
1654 | 74.9k | } |
1655 | 74.9k | } |
1656 | 25.1k | } |
1657 | | |
1658 | | void libfreehand::FHCollector::_appendCharacterProperties(librevenge::RVNGPropertyList &propList, const FH3CharProperties &charProps) |
1659 | 201k | { |
1660 | 201k | if (charProps.m_fontNameId) |
1661 | 199k | { |
1662 | 199k | std::map<unsigned, librevenge::RVNGString>::const_iterator iterString = m_strings.find(charProps.m_fontNameId); |
1663 | 199k | if (iterString != m_strings.end()) |
1664 | 197k | propList.insert("style:font-name", iterString->second); |
1665 | 199k | } |
1666 | 201k | propList.insert("fo:font-size", charProps.m_fontSize, librevenge::RVNG_POINT); |
1667 | 201k | if (charProps.m_fontColorId) |
1668 | 198k | { |
1669 | 198k | librevenge::RVNGString color = getColorString(charProps.m_fontColorId); |
1670 | 198k | if (!color.empty()) |
1671 | 195k | propList.insert("fo:color", color); |
1672 | 198k | } |
1673 | 201k | if (charProps.m_fontStyle & 1) |
1674 | 2.14k | propList.insert("fo:font-weight", "bold"); |
1675 | 201k | if (charProps.m_fontStyle & 2) |
1676 | 2.57k | propList.insert("fo:font-style", "italic"); |
1677 | 201k | if (charProps.m_letterSpacing<0 || charProps.m_letterSpacing>0) |
1678 | 7.57k | propList.insert("fo:letter-spacing", charProps.m_letterSpacing, librevenge::RVNG_POINT); |
1679 | 201k | if (charProps.m_horizontalScale<1 || charProps.m_horizontalScale>1) |
1680 | 6.15k | propList.insert("style:text-scale", charProps.m_horizontalScale, librevenge::RVNG_PERCENT); |
1681 | 201k | if (charProps.m_baselineShift<0 || charProps.m_baselineShift>0) |
1682 | 6.23k | { |
1683 | 6.23k | librevenge::RVNGString value; |
1684 | 6.23k | double fontSize=(charProps.m_fontSize>0) ? charProps.m_fontSize : 24.; |
1685 | 6.23k | value.sprintf("%g%%",100.*charProps.m_baselineShift/fontSize); |
1686 | 6.23k | propList.insert("style:text-position", value); |
1687 | 6.23k | } |
1688 | 201k | FHTEffect const *eff=_findTEffect(charProps.m_textEffsId); |
1689 | 201k | if (eff && eff->m_shortNameId) |
1690 | 156k | { |
1691 | 156k | std::map<unsigned, librevenge::RVNGString>::const_iterator iterString = m_strings.find(eff->m_shortNameId); |
1692 | 156k | if (iterString != m_strings.end()) |
1693 | 154k | { |
1694 | 154k | librevenge::RVNGString const &type=iterString->second; |
1695 | 154k | if (type=="inlin") // inside col1, outside col0 |
1696 | 33.9k | propList.insert("fo:font-weight", "bold"); |
1697 | 120k | else if (type=="otw stol") |
1698 | 27.2k | propList.insert("style:text-outline", "true"); |
1699 | 92.9k | else if (type=="stob") |
1700 | 17.4k | propList.insert("fo:font-style", "italic"); |
1701 | 75.5k | else if (type=="stsh") |
1702 | 16.4k | propList.insert("fo:text-shadow", "1pt 1pt"); |
1703 | 59.1k | else if (type=="sthv") |
1704 | 16.8k | propList.insert("fo:font-weight", "bold"); |
1705 | 42.2k | else if (type=="extrude") |
1706 | 34.7k | { |
1707 | 34.7k | propList.insert("style:font-relief", "embossed"); |
1708 | 34.7k | propList.insert("fo:text-shadow", "1pt -1pt"); |
1709 | 34.7k | librevenge::RVNGString color = getColorString(eff->m_colorId[0]); |
1710 | 34.7k | if (!color.empty()) |
1711 | 34.6k | propList.insert("fo:color", color); |
1712 | 34.7k | } |
1713 | 7.48k | else |
1714 | 7.48k | { |
1715 | 7.48k | FH_DEBUG_MSG(("libfreehand::FHCollector::_appendCharacterProperties: find unknown effect %s\n",type.cstr())); |
1716 | 7.48k | } |
1717 | 154k | } |
1718 | 156k | } |
1719 | 201k | } |
1720 | | |
1721 | | void libfreehand::FHCollector::_appendTabProperties(librevenge::RVNGPropertyList &propList, const libfreehand::FHTab &tab) |
1722 | 47.6k | { |
1723 | 47.6k | switch (tab.m_type) |
1724 | 47.6k | { |
1725 | 2.87k | case 0: |
1726 | 5.67k | case 4: // unsure, look like a left tab |
1727 | 5.84k | default: |
1728 | 5.84k | break; |
1729 | 36.1k | case 1: |
1730 | 36.1k | propList.insert("style:type", "right"); |
1731 | 36.1k | break; |
1732 | 2.85k | case 2: |
1733 | 2.85k | propList.insert("style:type", "center"); |
1734 | 2.85k | break; |
1735 | 2.80k | case 3: |
1736 | 2.80k | propList.insert("style:type", "char"); |
1737 | 2.80k | propList.insert("style:char", "."); // checkme |
1738 | 2.80k | break; |
1739 | 47.6k | } |
1740 | 47.6k | propList.insert("style:position", tab.m_position, librevenge::RVNG_POINT); |
1741 | 47.6k | } |
1742 | | |
1743 | | void libfreehand::FHCollector::_appendParagraphProperties(librevenge::RVNGPropertyList & /* propList */, const FH3ParaProperties & /* paraProps */) |
1744 | 37.2k | { |
1745 | 37.2k | } |
1746 | | |
1747 | | void libfreehand::FHCollector::_appendParagraphProperties(librevenge::RVNGPropertyList &propList, unsigned paragraphPropsId) |
1748 | 22.0k | { |
1749 | 22.0k | std::map<unsigned, FHParagraphProperties>::const_iterator iter = m_paragraphProperties.find(paragraphPropsId); |
1750 | 22.0k | if (iter == m_paragraphProperties.end()) |
1751 | 137 | return; |
1752 | 21.8k | FHParagraphProperties const ¶=iter->second; |
1753 | 21.8k | for (const auto &it : para.m_idToZoneIdMap) |
1754 | 21.6k | { |
1755 | 21.6k | switch (it.first) |
1756 | 21.6k | { |
1757 | 21.6k | case FH_PARA_TAB_TABLE_ID: |
1758 | 21.6k | if (m_tabs.find(it.second)!=m_tabs.end()) |
1759 | 19.5k | { |
1760 | 19.5k | std::vector<FHTab> const &tabs=m_tabs.find(it.second)->second; |
1761 | 19.5k | if (tabs.empty()) |
1762 | 0 | break; |
1763 | 19.5k | librevenge::RVNGPropertyListVector tabVect; |
1764 | 19.5k | for (const auto &tab : tabs) |
1765 | 47.6k | { |
1766 | 47.6k | librevenge::RVNGPropertyList tabList; |
1767 | 47.6k | _appendTabProperties(tabList, tab); |
1768 | 47.6k | tabVect.append(tabList); |
1769 | 47.6k | } |
1770 | 19.5k | propList.insert("style:tab-stops", tabVect); |
1771 | 19.5k | } |
1772 | 21.6k | break; |
1773 | 21.6k | default: |
1774 | 0 | break; |
1775 | 21.6k | } |
1776 | 21.6k | } |
1777 | 130k | for (auto it=para.m_idToDoubleMap.begin(); it!=para.m_idToDoubleMap.end(); ++it) |
1778 | 108k | { |
1779 | 108k | switch (it->first) |
1780 | 108k | { |
1781 | 21.7k | case FH_PARA_LEFT_INDENT: |
1782 | 21.7k | propList.insert("fo:margin-left", it->second, librevenge::RVNG_POINT); |
1783 | 21.7k | break; |
1784 | 21.2k | case FH_PARA_RIGHT_INDENT: |
1785 | 21.2k | propList.insert("fo:margin-right", it->second, librevenge::RVNG_POINT); |
1786 | 21.2k | break; |
1787 | 21.7k | case FH_PARA_TEXT_INDENT: |
1788 | 21.7k | propList.insert("fo:text-indent", it->second, librevenge::RVNG_POINT); |
1789 | 21.7k | break; |
1790 | 21.7k | case FH_PARA_SPC_ABOVE: |
1791 | 21.7k | propList.insert("fo:margin-top", it->second, librevenge::RVNG_POINT); |
1792 | 21.7k | break; |
1793 | 21.6k | case FH_PARA_SPC_BELLOW: |
1794 | 21.6k | propList.insert("fo:margin-bottom", it->second, librevenge::RVNG_POINT); |
1795 | 21.6k | break; |
1796 | 89 | case FH_PARA_LEADING: |
1797 | 89 | if (it->second<=0 && it->second>=0) break; |
1798 | 62 | if (para.m_idToIntMap.find(FH_PARA_LEADING_TYPE)==para.m_idToIntMap.end()) |
1799 | 22 | { |
1800 | 22 | FH_DEBUG_MSG(("libfreehand::FHCollector::_appendParagraphProperties: can not find the leading type\n")); |
1801 | 22 | break; |
1802 | 22 | } |
1803 | 40 | switch (para.m_idToIntMap.find(FH_PARA_LEADING_TYPE)->second) |
1804 | 40 | { |
1805 | 16 | case 0: // delta in point |
1806 | 16 | propList.insert("fo:line-height",1.+it->second/(it->second>0 ? 12 : 24), librevenge::RVNG_PERCENT); |
1807 | 16 | break; |
1808 | 10 | case 1: |
1809 | 10 | propList.insert("fo:line-height",it->second, librevenge::RVNG_POINT); |
1810 | 10 | break; |
1811 | 4 | case 2: |
1812 | 4 | propList.insert("fo:line-height",it->second, librevenge::RVNG_PERCENT); |
1813 | 4 | break; |
1814 | 10 | default: |
1815 | 10 | break; |
1816 | 40 | } |
1817 | 40 | break; |
1818 | 40 | default: |
1819 | 0 | break; |
1820 | 108k | } |
1821 | 108k | } |
1822 | 21.8k | for (const auto &it : para.m_idToIntMap) |
1823 | 43.5k | { |
1824 | 43.5k | switch (it.first) |
1825 | 43.5k | { |
1826 | 21.6k | case FH_PARA_TEXT_ALIGN: |
1827 | 21.6k | switch (it.second) |
1828 | 21.6k | { |
1829 | 19.9k | case 0: |
1830 | 19.9k | propList.insert("fo:text-align", "left"); |
1831 | 19.9k | break; |
1832 | 75 | case 1: |
1833 | 75 | propList.insert("fo:text-align", "end"); |
1834 | 75 | break; |
1835 | 320 | case 2: |
1836 | 320 | propList.insert("fo:text-align", "center"); |
1837 | 320 | break; |
1838 | 1.15k | case 3: |
1839 | 1.15k | propList.insert("fo:text-align", "justify"); |
1840 | 1.15k | break; |
1841 | 139 | default: |
1842 | 139 | break; |
1843 | 21.6k | } |
1844 | 21.6k | break; |
1845 | 21.6k | case FH_PARA_KEEP_SAME_LINE: |
1846 | 83 | if (it.second==1) |
1847 | 8 | propList.insert("fo:keep-together", "always"); |
1848 | 83 | break; |
1849 | 77 | case FH_PARA_LEADING_TYPE: // done with FH_PARA_LEADING |
1850 | 21.7k | default: |
1851 | 21.7k | break; |
1852 | 43.5k | } |
1853 | 43.5k | } |
1854 | 21.8k | } |
1855 | | |
1856 | | void libfreehand::FHCollector::_outputDisplayText(const libfreehand::FHDisplayText *displayText, librevenge::RVNGDrawingInterface *painter) |
1857 | 223k | { |
1858 | 223k | if (!painter || !displayText) |
1859 | 186k | return; |
1860 | | |
1861 | 37.2k | double xa = displayText->m_startX; |
1862 | 37.2k | double ya = displayText->m_startY; |
1863 | 37.2k | double xb = displayText->m_startX + displayText->m_width; |
1864 | 37.2k | double yb = displayText->m_startY + displayText->m_height; |
1865 | 37.2k | double xc = xa; |
1866 | 37.2k | double yc = yb; |
1867 | 37.2k | unsigned xFormId = displayText->m_xFormId; |
1868 | 37.2k | if (xFormId) |
1869 | 34.8k | { |
1870 | 34.8k | const FHTransform *trafo = _findTransform(xFormId); |
1871 | 34.8k | if (trafo) |
1872 | 34.6k | { |
1873 | 34.6k | trafo->applyToPoint(xa, ya); |
1874 | 34.6k | trafo->applyToPoint(xb, yb); |
1875 | 34.6k | trafo->applyToPoint(xc, yc); |
1876 | 34.6k | } |
1877 | 34.8k | } |
1878 | 37.2k | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
1879 | 73.1k | while (!groupTransforms.empty()) |
1880 | 35.9k | { |
1881 | 35.9k | groupTransforms.top().applyToPoint(xa, ya); |
1882 | 35.9k | groupTransforms.top().applyToPoint(xb, yb); |
1883 | 35.9k | groupTransforms.top().applyToPoint(xc, yc); |
1884 | 35.9k | groupTransforms.pop(); |
1885 | 35.9k | } |
1886 | 37.2k | _normalizePoint(xa, ya); |
1887 | 37.2k | _normalizePoint(xb, yb); |
1888 | 37.2k | _normalizePoint(xc, yc); |
1889 | | |
1890 | 37.4k | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
1891 | 191 | { |
1892 | 191 | iter->applyToPoint(xa, ya); |
1893 | 191 | iter->applyToPoint(xb, yb); |
1894 | 191 | iter->applyToPoint(xc, yc); |
1895 | 191 | } |
1896 | | |
1897 | 37.2k | double rotation = atan2(yb-yc, xb-xc); |
1898 | 37.2k | double height = sqrt((xc-xa)*(xc-xa) + (yc-ya)*(yc-ya)); |
1899 | 37.2k | double width = sqrt((xc-xb)*(xc-xb) + (yc-yb)*(yc-yb)); |
1900 | 37.2k | double xmid = (xa + xb) / 2.0; |
1901 | 37.2k | double ymid = (ya + yb) / 2.0; |
1902 | | |
1903 | 37.2k | librevenge::RVNGPropertyList textObjectProps; |
1904 | 37.2k | textObjectProps.insert("svg:x", xmid - displayText->m_width / 2.0); |
1905 | 37.2k | textObjectProps.insert("svg:y", ymid + displayText->m_height / 2.0); |
1906 | 37.2k | textObjectProps.insert("svg:height", height); |
1907 | 37.2k | textObjectProps.insert("svg:width", width); |
1908 | 186k | for (int i=0; i<4; ++i) // osnola: let assume that there is no padding |
1909 | 149k | { |
1910 | 149k | char const *padding[] = {"fo:padding-left","fo:padding-right","fo:padding-top","fo:padding-bottom"}; |
1911 | 149k | textObjectProps.insert(padding[i],0,librevenge::RVNG_POINT); |
1912 | 149k | } |
1913 | 37.2k | if (!FH_ALMOST_ZERO(rotation)) |
1914 | 243 | { |
1915 | 243 | textObjectProps.insert("librevenge:rotate", rotation * 180.0 / M_PI); |
1916 | 243 | textObjectProps.insert("librevenge:rotate-cx",xmid); |
1917 | 243 | textObjectProps.insert("librevenge:rotate-cy",ymid); |
1918 | 243 | } |
1919 | 37.2k | if (displayText->m_justify==4) // top-down: checkme do nothing |
1920 | 9 | textObjectProps.insert("style:writing-mode", "tb-lr"); |
1921 | 37.2k | painter->startTextObject(textObjectProps); |
1922 | | |
1923 | 37.2k | auto iterPara = displayText->m_paraProps.begin(); |
1924 | 37.2k | auto iterChar = displayText->m_charProps.begin(); |
1925 | | |
1926 | 37.2k | FH3ParaProperties paraProps = *iterPara++; |
1927 | 37.2k | FH3CharProperties charProps = *iterChar++; |
1928 | 37.2k | librevenge::RVNGString text; |
1929 | 37.2k | std::vector<unsigned char>::size_type i = 0; |
1930 | | |
1931 | 37.2k | librevenge::RVNGPropertyList paraPropList; |
1932 | 37.2k | _appendParagraphProperties(paraPropList, paraProps); |
1933 | 37.2k | switch (displayText->m_justify) |
1934 | 37.2k | { |
1935 | 37.1k | case 0: // left |
1936 | 37.1k | break; |
1937 | 35 | case 1: |
1938 | 35 | paraPropList.insert("fo:text-align", "center"); |
1939 | 35 | break; |
1940 | 101 | case 2: |
1941 | 101 | paraPropList.insert("fo:text-align", "end"); |
1942 | 101 | break; |
1943 | 9 | case 3: |
1944 | 9 | paraPropList.insert("fo:text-align", "justify"); |
1945 | 9 | break; |
1946 | 9 | case 4: |
1947 | 35 | default: |
1948 | 35 | break; |
1949 | 37.2k | } |
1950 | 37.2k | if (charProps.m_leading>0) |
1951 | 1.30k | paraPropList.insert("fo:line-height",charProps.m_leading,librevenge::RVNG_POINT); |
1952 | 35.9k | else |
1953 | 35.9k | paraPropList.insert("fo:line-height",1.,librevenge::RVNG_PERCENT); |
1954 | 37.2k | painter->openParagraph(paraPropList); |
1955 | 37.2k | bool isParagraphOpened = true; |
1956 | | |
1957 | 37.2k | librevenge::RVNGPropertyList charPropList; |
1958 | 37.2k | _appendCharacterProperties(charPropList, charProps); |
1959 | 37.2k | painter->openSpan(charPropList); |
1960 | 37.2k | bool isSpanOpened = true; |
1961 | | |
1962 | 1.06M | while (i < displayText->m_characters.size()) |
1963 | 1.06M | { |
1964 | 1.06M | _appendMacRoman(text, displayText->m_characters[i++]); |
1965 | 1.06M | if (i > paraProps.m_offset) |
1966 | 143k | { |
1967 | 143k | if (!text.empty()) |
1968 | 143k | painter->insertText(text); |
1969 | 143k | text.clear(); |
1970 | 143k | if (isParagraphOpened) |
1971 | 143k | { |
1972 | 143k | if (isSpanOpened) |
1973 | 143k | { |
1974 | 143k | painter->closeSpan(); |
1975 | 143k | isSpanOpened = false; |
1976 | 143k | } |
1977 | 143k | painter->closeParagraph(); |
1978 | 143k | isParagraphOpened = false; |
1979 | 143k | } |
1980 | 143k | if (iterPara != displayText->m_paraProps.end()) |
1981 | 106k | { |
1982 | 106k | paraProps = *iterPara++; |
1983 | 106k | } |
1984 | 143k | } |
1985 | 1.06M | if (i > charProps.m_offset) |
1986 | 200k | { |
1987 | 200k | if (!text.empty()) |
1988 | 58.4k | painter->insertText(text); |
1989 | 200k | text.clear(); |
1990 | 200k | if (isSpanOpened) |
1991 | 58.4k | { |
1992 | 58.4k | painter->closeSpan(); |
1993 | 58.4k | isSpanOpened = false; |
1994 | 58.4k | } |
1995 | 200k | if (iterChar != displayText->m_charProps.end()) |
1996 | 163k | { |
1997 | 163k | charProps = *iterChar++; |
1998 | 163k | } |
1999 | 200k | } |
2000 | 1.06M | if (i >= displayText->m_characters.size()) |
2001 | 37.2k | break; |
2002 | 1.02M | if (!isParagraphOpened) |
2003 | 106k | { |
2004 | | #if 0 |
2005 | | paraPropList.clear(); |
2006 | | _appendParagraphProperties(paraPropList, paraProps); |
2007 | | #endif |
2008 | 106k | if (charProps.m_leading>0) |
2009 | 1.20k | paraPropList.insert("fo:line-height",charProps.m_leading,librevenge::RVNG_POINT); |
2010 | 105k | else |
2011 | 105k | paraPropList.insert("fo:line-height",1.,librevenge::RVNG_PERCENT); |
2012 | 106k | painter->openParagraph(paraPropList); |
2013 | 106k | isParagraphOpened = true; |
2014 | 106k | if (!isSpanOpened) |
2015 | 106k | { |
2016 | 106k | charPropList.clear(); |
2017 | 106k | _appendCharacterProperties(charPropList, charProps); |
2018 | 106k | painter->openSpan(charPropList); |
2019 | 106k | isSpanOpened = true; |
2020 | 106k | } |
2021 | 106k | } |
2022 | 1.02M | if (!isSpanOpened) |
2023 | 58.0k | { |
2024 | 58.0k | charPropList.clear(); |
2025 | 58.0k | _appendCharacterProperties(charPropList, charProps); |
2026 | 58.0k | painter->openSpan(charPropList); |
2027 | 58.0k | isSpanOpened = true; |
2028 | 58.0k | } |
2029 | 1.02M | } |
2030 | 37.2k | if (!text.empty()) |
2031 | 80 | painter->insertText(text); |
2032 | 37.2k | if (isSpanOpened) |
2033 | 80 | painter->closeSpan(); |
2034 | 37.2k | if (isParagraphOpened) |
2035 | 547 | painter->closeParagraph(); |
2036 | | |
2037 | 37.2k | painter->endTextObject(); |
2038 | 37.2k | } |
2039 | | |
2040 | | void libfreehand::FHCollector::_outputImageImport(const FHImageImport *image, librevenge::RVNGDrawingInterface *painter) |
2041 | 223k | { |
2042 | 223k | if (!painter || !image) |
2043 | 223k | return; |
2044 | | |
2045 | 65 | librevenge::RVNGPropertyList propList; |
2046 | 65 | _appendStrokeProperties(propList, image->m_graphicStyleId); |
2047 | 65 | _appendFillProperties(propList, image->m_graphicStyleId); |
2048 | 65 | double xa = image->m_startX; |
2049 | 65 | double ya = image->m_startY; |
2050 | 65 | double xb = image->m_startX + image->m_width; |
2051 | 65 | double yb = image->m_startY + image->m_height; |
2052 | 65 | double xc = xa; |
2053 | 65 | double yc = yb; |
2054 | 65 | unsigned xFormId = image->m_xFormId; |
2055 | 65 | if (xFormId) |
2056 | 54 | { |
2057 | 54 | const FHTransform *trafo = _findTransform(xFormId); |
2058 | 54 | if (trafo) |
2059 | 0 | { |
2060 | 0 | trafo->applyToPoint(xa, ya); |
2061 | 0 | trafo->applyToPoint(xb, yb); |
2062 | 0 | trafo->applyToPoint(xc, yc); |
2063 | 0 | } |
2064 | 54 | } |
2065 | 65 | std::stack<FHTransform> groupTransforms(m_currentTransforms); |
2066 | 65 | while (!groupTransforms.empty()) |
2067 | 0 | { |
2068 | 0 | groupTransforms.top().applyToPoint(xa, ya); |
2069 | 0 | groupTransforms.top().applyToPoint(xb, yb); |
2070 | 0 | groupTransforms.top().applyToPoint(xc, yc); |
2071 | 0 | groupTransforms.pop(); |
2072 | 0 | } |
2073 | 65 | _normalizePoint(xa, ya); |
2074 | 65 | _normalizePoint(xb, yb); |
2075 | 65 | _normalizePoint(xc, yc); |
2076 | | |
2077 | 136 | for (std::vector<FHTransform>::const_iterator iter = m_fakeTransforms.begin(); iter != m_fakeTransforms.end(); ++iter) |
2078 | 71 | { |
2079 | 71 | iter->applyToPoint(xa, ya); |
2080 | 71 | iter->applyToPoint(xb, yb); |
2081 | 71 | iter->applyToPoint(xc, yc); |
2082 | 71 | } |
2083 | | |
2084 | 65 | double rotation = atan2(yb-yc, xb-xc); |
2085 | 65 | double height = sqrt((xc-xa)*(xc-xa) + (yc-ya)*(yc-ya)); |
2086 | 65 | double width = sqrt((xc-xb)*(xc-xb) + (yc-yb)*(yc-yb)); |
2087 | 65 | double xmid = (xa + xb) / 2.0; |
2088 | 65 | double ymid = (ya + yb) / 2.0; |
2089 | | |
2090 | 65 | librevenge::RVNGPropertyList imageProps; |
2091 | 65 | imageProps.insert("svg:x", xmid - width / 2.0); |
2092 | 65 | imageProps.insert("svg:y", ymid - height / 2.0); |
2093 | 65 | imageProps.insert("svg:height", height); |
2094 | 65 | imageProps.insert("svg:width", width); |
2095 | 65 | if (!FH_ALMOST_ZERO(rotation)) |
2096 | 42 | imageProps.insert("librevenge:rotate", rotation * 180.0 / M_PI); |
2097 | | |
2098 | 65 | imageProps.insert("librevenge:mime-type", "whatever"); |
2099 | 65 | librevenge::RVNGBinaryData data = getImageData(image->m_dataListId); |
2100 | | |
2101 | 65 | if (data.empty()) |
2102 | 65 | return; |
2103 | | |
2104 | 0 | const unsigned char *buffer = data.getDataBuffer(); |
2105 | 0 | unsigned long size = data.size(); |
2106 | 0 | if (isTiff(buffer, size)) |
2107 | 0 | imageProps.insert("librevenge:mime-type", "image/tiff"); |
2108 | 0 | else if (isBmp(buffer, size)) |
2109 | 0 | imageProps.insert("librevenge:mime-type", "image/bmp"); |
2110 | 0 | else if (isJpeg(buffer, size)) |
2111 | 0 | imageProps.insert("librevenge:mime-type", "image/jpeg"); |
2112 | 0 | else if (isPng(buffer, size)) |
2113 | 0 | imageProps.insert("librevenge:mime-type", "image/png"); |
2114 | |
|
2115 | 0 | imageProps.insert("office:binary-data", data); |
2116 | 0 | painter->setStyle(propList); |
2117 | 0 | painter->drawGraphicObject(imageProps); |
2118 | 0 | } |
2119 | | |
2120 | | void libfreehand::FHCollector::_outputTextRun(const std::vector<unsigned short> *characters, unsigned offset, unsigned length, |
2121 | | unsigned charStyleId, librevenge::RVNGDrawingInterface *painter) |
2122 | 27.4k | { |
2123 | 27.4k | if (!painter || !characters || characters->empty()) |
2124 | 449 | return; |
2125 | 27.0k | librevenge::RVNGPropertyList propList; |
2126 | 27.0k | _appendCharacterProperties(propList, charStyleId); |
2127 | 27.0k | painter->openSpan(propList); |
2128 | 27.0k | std::vector<unsigned short> tmpChars; |
2129 | 27.0k | bool lastIsSpace=false; |
2130 | 678k | for (unsigned i = offset; i < length+offset && i < characters->size(); ++i) |
2131 | 651k | { |
2132 | 651k | unsigned c=(*characters)[i]; |
2133 | 651k | if (c=='\t' || (c==' ' && lastIsSpace)) |
2134 | 10.0k | { |
2135 | 10.0k | if (!tmpChars.empty()) |
2136 | 4.79k | { |
2137 | 4.79k | librevenge::RVNGString text; |
2138 | 4.79k | _appendUTF16(text, tmpChars); |
2139 | 4.79k | painter->insertText(text); |
2140 | 4.79k | tmpChars.clear(); |
2141 | 4.79k | } |
2142 | 10.0k | if (c=='\t') |
2143 | 10.0k | painter->insertTab(); |
2144 | 5 | else |
2145 | 5 | painter->insertSpace(); |
2146 | 10.0k | continue; |
2147 | 10.0k | } |
2148 | 641k | else |
2149 | 641k | { |
2150 | 641k | if (c<=0x1f) |
2151 | 232k | { |
2152 | 232k | switch (c) |
2153 | 232k | { |
2154 | 591 | case 0xb: // end of column |
2155 | 591 | break; |
2156 | 192 | case 0x1f: // optional hyphen |
2157 | 192 | break; |
2158 | 231k | default: |
2159 | 231k | FH_DEBUG_MSG(("libfreehand::FHCollector::_outputTextRun: find character %x\n", c)); |
2160 | 231k | break; |
2161 | 232k | } |
2162 | 232k | } |
2163 | 408k | else |
2164 | 408k | tmpChars.push_back(c); |
2165 | 641k | } |
2166 | 641k | lastIsSpace=c==' '; |
2167 | 641k | } |
2168 | 27.0k | if (!tmpChars.empty()) |
2169 | 24.7k | { |
2170 | 24.7k | librevenge::RVNGString text; |
2171 | 24.7k | _appendUTF16(text, tmpChars); |
2172 | 24.7k | painter->insertText(text); |
2173 | 24.7k | } |
2174 | 27.0k | painter->closeSpan(); |
2175 | 27.0k | } |
2176 | | |
2177 | | const std::vector<unsigned> *libfreehand::FHCollector::_findListElements(unsigned id) |
2178 | 24.1k | { |
2179 | 24.1k | std::map<unsigned, FHList>::const_iterator iter = m_lists.find(id); |
2180 | 24.1k | if (iter != m_lists.end()) |
2181 | 23.7k | return &(iter->second.m_elements); |
2182 | 385 | return nullptr; |
2183 | 24.1k | } |
2184 | | |
2185 | | |
2186 | | void libfreehand::FHCollector::_appendFontProperties(librevenge::RVNGPropertyList &propList, unsigned agdFontId) |
2187 | 25.0k | { |
2188 | 25.0k | std::map<unsigned, FHAGDFont>::const_iterator iter = m_fonts.find(agdFontId); |
2189 | 25.0k | if (iter == m_fonts.end()) |
2190 | 206 | return; |
2191 | 24.8k | const FHAGDFont &font = iter->second; |
2192 | 24.8k | if (font.m_fontNameId) |
2193 | 24.2k | { |
2194 | 24.2k | std::map<unsigned, librevenge::RVNGString>::const_iterator iterString = m_strings.find(font.m_fontNameId); |
2195 | 24.2k | if (iterString != m_strings.end()) |
2196 | 23.4k | propList.insert("style:font-name", iterString->second); |
2197 | 24.2k | } |
2198 | 24.8k | propList.insert("fo:font-size", font.m_fontSize, librevenge::RVNG_POINT); |
2199 | 24.8k | if (font.m_fontStyle & 1) |
2200 | 1.66k | propList.insert("fo:font-weight", "bold"); |
2201 | 24.8k | if (font.m_fontStyle & 2) |
2202 | 1.48k | propList.insert("fo:font-style", "italic"); |
2203 | 24.8k | } |
2204 | | |
2205 | | void libfreehand::FHCollector::_appendFillProperties(librevenge::RVNGPropertyList &propList, unsigned graphicStyleId) |
2206 | 265k | { |
2207 | 265k | if (!propList["draw:fill"]) |
2208 | 129k | propList.insert("draw:fill", "none"); |
2209 | 265k | if (graphicStyleId && find(m_visitedObjects.begin(), m_visitedObjects.end(), graphicStyleId) == m_visitedObjects.end()) |
2210 | 261k | { |
2211 | 261k | const ObjectRecursionGuard guard(m_visitedObjects, graphicStyleId); |
2212 | 261k | const FHPropList *propertyList = _findPropList(graphicStyleId); |
2213 | 261k | if (propertyList) |
2214 | 248k | { |
2215 | 248k | if (propertyList->m_parentId) |
2216 | 132k | _appendFillProperties(propList, propertyList->m_parentId); |
2217 | 248k | auto iter = propertyList->m_elements.find(m_fillId); |
2218 | 248k | if (iter != propertyList->m_elements.end()) |
2219 | 14.4k | { |
2220 | 14.4k | _appendBasicFill(propList, _findBasicFill(iter->second)); |
2221 | 14.4k | _appendLinearFill(propList, _findLinearFill(iter->second)); |
2222 | 14.4k | _appendLensFill(propList, _findLensFill(iter->second)); |
2223 | 14.4k | _appendRadialFill(propList, _findRadialFill(iter->second)); |
2224 | 14.4k | _appendTileFill(propList, _findTileFill(iter->second)); |
2225 | 14.4k | _appendPatternFill(propList, _findPatternFill(iter->second)); |
2226 | 14.4k | _appendCustomProcFill(propList, _findCustomProc(iter->second)); |
2227 | 14.4k | } |
2228 | 248k | } |
2229 | 12.5k | else |
2230 | 12.5k | { |
2231 | 12.5k | const FHGraphicStyle *graphicStyle = _findGraphicStyle(graphicStyleId); |
2232 | 12.5k | if (graphicStyle) |
2233 | 5.64k | { |
2234 | 5.64k | if (graphicStyle->m_parentId) |
2235 | 3.16k | _appendFillProperties(propList, graphicStyle->m_parentId); |
2236 | 5.64k | unsigned fillId = _findFillId(*graphicStyle);; |
2237 | 5.64k | if (fillId) |
2238 | 1.21k | { |
2239 | 1.21k | _appendBasicFill(propList, _findBasicFill(fillId)); |
2240 | 1.21k | _appendLinearFill(propList, _findLinearFill(fillId)); |
2241 | 1.21k | _appendLensFill(propList, _findLensFill(fillId)); |
2242 | 1.21k | _appendRadialFill(propList, _findRadialFill(fillId)); |
2243 | 1.21k | _appendTileFill(propList, _findTileFill(fillId)); |
2244 | 1.21k | _appendPatternFill(propList, _findPatternFill(fillId)); |
2245 | 1.21k | _appendCustomProcFill(propList, _findCustomProc(fillId)); |
2246 | 1.21k | } |
2247 | 4.42k | else |
2248 | 4.42k | { |
2249 | 4.42k | const FHFilterAttributeHolder *filterAttributeHolder = _findFilterAttributeHolder(*graphicStyle); |
2250 | 4.42k | if (filterAttributeHolder) |
2251 | 0 | { |
2252 | 0 | if (filterAttributeHolder->m_graphicStyleId) |
2253 | 0 | _appendFillProperties(propList, filterAttributeHolder->m_graphicStyleId); |
2254 | 0 | if (filterAttributeHolder->m_filterId) |
2255 | 0 | _applyFilter(propList, filterAttributeHolder->m_filterId); |
2256 | 0 | } |
2257 | 4.42k | } |
2258 | 5.64k | } |
2259 | 12.5k | } |
2260 | 261k | } |
2261 | 265k | } |
2262 | | |
2263 | | void libfreehand::FHCollector::_appendStrokeProperties(librevenge::RVNGPropertyList &propList, unsigned graphicStyleId) |
2264 | 265k | { |
2265 | 265k | if (!propList["draw:stroke"]) |
2266 | 129k | propList.insert("draw:stroke", "none"); |
2267 | 265k | if (graphicStyleId && find(m_visitedObjects.begin(), m_visitedObjects.end(), graphicStyleId) == m_visitedObjects.end()) |
2268 | 261k | { |
2269 | 261k | const ObjectRecursionGuard guard(m_visitedObjects, graphicStyleId); |
2270 | 261k | const FHPropList *propertyList = _findPropList(graphicStyleId); |
2271 | 261k | if (propertyList) |
2272 | 248k | { |
2273 | 248k | if (propertyList->m_parentId) |
2274 | 132k | _appendStrokeProperties(propList, propertyList->m_parentId); |
2275 | 248k | auto iter = propertyList->m_elements.find(m_strokeId); |
2276 | 248k | if (iter != propertyList->m_elements.end()) |
2277 | 127k | { |
2278 | 127k | _appendBasicLine(propList, _findBasicLine(iter->second)); |
2279 | 127k | _appendPatternLine(propList, _findPatternLine(iter->second)); |
2280 | 127k | _appendCustomProcLine(propList, _findCustomProc(iter->second)); |
2281 | 127k | } |
2282 | 248k | } |
2283 | 12.5k | else |
2284 | 12.5k | { |
2285 | 12.5k | const FHGraphicStyle *graphicStyle = _findGraphicStyle(graphicStyleId); |
2286 | 12.5k | if (graphicStyle) |
2287 | 5.64k | { |
2288 | 5.64k | if (graphicStyle->m_parentId) |
2289 | 3.16k | _appendStrokeProperties(propList, graphicStyle->m_parentId); |
2290 | 5.64k | unsigned strokeId = _findStrokeId(*graphicStyle); |
2291 | 5.64k | if (strokeId) |
2292 | 2.86k | { |
2293 | 2.86k | _appendBasicLine(propList, _findBasicLine(strokeId)); |
2294 | 2.86k | _appendPatternLine(propList, _findPatternLine(strokeId)); |
2295 | 2.86k | _appendCustomProcLine(propList, _findCustomProc(strokeId)); |
2296 | 2.86k | } |
2297 | 2.77k | else |
2298 | 2.77k | { |
2299 | 2.77k | const FHFilterAttributeHolder *filterAttributeHolder = _findFilterAttributeHolder(*graphicStyle); |
2300 | 2.77k | if (filterAttributeHolder) |
2301 | 0 | { |
2302 | 0 | if (filterAttributeHolder->m_graphicStyleId) |
2303 | 0 | _appendFillProperties(propList, filterAttributeHolder->m_graphicStyleId); |
2304 | 0 | if (filterAttributeHolder->m_filterId) |
2305 | 0 | _applyFilter(propList, filterAttributeHolder->m_filterId); |
2306 | 0 | } |
2307 | 2.77k | } |
2308 | 5.64k | } |
2309 | 12.5k | } |
2310 | 261k | } |
2311 | 265k | } |
2312 | | |
2313 | | void libfreehand::FHCollector::_appendBasicFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHBasicFill *basicFill) |
2314 | 15.6k | { |
2315 | 15.6k | if (!basicFill) |
2316 | 12.5k | return; |
2317 | 3.13k | propList.insert("draw:fill", "solid"); |
2318 | 3.13k | librevenge::RVNGString color = getColorString(basicFill->m_colorId); |
2319 | 3.13k | if (!color.empty()) |
2320 | 2.67k | propList.insert("draw:fill-color", color); |
2321 | 458 | else |
2322 | 458 | propList.insert("draw:fill-color", "#000000"); |
2323 | 3.13k | } |
2324 | | |
2325 | | void libfreehand::FHCollector::_appendCustomProcFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHCustomProc *fill) |
2326 | 15.6k | { |
2327 | 15.6k | if (!fill || fill->m_ids.empty()) |
2328 | 14.4k | return; |
2329 | 1.22k | propList.insert("draw:fill", "solid"); |
2330 | 1.22k | librevenge::RVNGString color = getColorString(fill->m_ids[0]); |
2331 | 1.22k | if (!color.empty()) |
2332 | 1.14k | propList.insert("draw:fill-color", color); |
2333 | 80 | else |
2334 | 80 | propList.insert("draw:fill-color", "#000000"); |
2335 | 1.22k | } |
2336 | | |
2337 | | unsigned libfreehand::FHCollector::_findContentId(unsigned graphicStyleId) |
2338 | 129k | { |
2339 | 129k | if (graphicStyleId) |
2340 | 128k | { |
2341 | 128k | const FHPropList *propertyList = _findPropList(graphicStyleId); |
2342 | 128k | if (propertyList) |
2343 | 123k | { |
2344 | 123k | auto iter = propertyList->m_elements.find(m_contentId); |
2345 | 123k | if (iter != propertyList->m_elements.end()) |
2346 | 10.6k | return iter->second; |
2347 | 123k | } |
2348 | 5.09k | else |
2349 | 5.09k | { |
2350 | 5.09k | const FHGraphicStyle *graphicStyle = _findGraphicStyle(graphicStyleId); |
2351 | 5.09k | if (graphicStyle) |
2352 | 2.87k | { |
2353 | 2.87k | auto iter = graphicStyle->m_elements.find(m_contentId); |
2354 | 2.87k | if (iter != graphicStyle->m_elements.end()) |
2355 | 0 | return iter->second; |
2356 | 2.87k | } |
2357 | 5.09k | } |
2358 | 128k | } |
2359 | 118k | return 0; |
2360 | 129k | } |
2361 | | |
2362 | | void libfreehand::FHCollector::_appendLinearFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHLinearFill *linearFill) |
2363 | 15.6k | { |
2364 | 15.6k | if (!linearFill) |
2365 | 14.8k | return; |
2366 | 797 | propList.insert("draw:fill", "gradient"); |
2367 | 797 | propList.insert("draw:style", "linear"); |
2368 | 797 | double angle = 90.0 - linearFill->m_angle; |
2369 | 2.93k | while (angle < 0.0) |
2370 | 2.14k | angle += 360.0; |
2371 | 6.80k | while (angle > 360.0) |
2372 | 6.01k | angle -= 360.0; |
2373 | 797 | propList.insert("draw:angle", angle, librevenge::RVNG_GENERIC); |
2374 | | |
2375 | 797 | const std::vector<FHColorStop> *multiColorList = _findMultiColorList(linearFill->m_multiColorListId); |
2376 | 797 | if (multiColorList && multiColorList->size() > 1) |
2377 | 72 | { |
2378 | 72 | librevenge::RVNGString color = getColorString((*multiColorList)[0].m_colorId); |
2379 | 72 | if (!color.empty()) |
2380 | 72 | propList.insert("draw:start-color", color); |
2381 | 72 | color = getColorString((*multiColorList)[1].m_colorId); |
2382 | 72 | if (!color.empty()) |
2383 | 72 | propList.insert("draw:end-color", color); |
2384 | 72 | } |
2385 | 725 | else |
2386 | 725 | { |
2387 | 725 | librevenge::RVNGString color = getColorString(linearFill->m_color1Id); |
2388 | 725 | if (!color.empty()) |
2389 | 575 | propList.insert("draw:start-color", color); |
2390 | 725 | color = getColorString(linearFill->m_color2Id); |
2391 | 725 | if (!color.empty()) |
2392 | 526 | propList.insert("draw:end-color", color); |
2393 | 725 | } |
2394 | 797 | } |
2395 | | |
2396 | | void libfreehand::FHCollector::_applyFilter(librevenge::RVNGPropertyList &propList, unsigned filterId) |
2397 | 0 | { |
2398 | 0 | if (!filterId) |
2399 | 0 | return; |
2400 | 0 | _appendOpacity(propList, _findOpacityFilter(filterId)); |
2401 | 0 | _appendShadow(propList, _findFWShadowFilter(filterId)); |
2402 | 0 | _appendGlow(propList, _findFWGlowFilter(filterId)); |
2403 | 0 | } |
2404 | | |
2405 | | void libfreehand::FHCollector::_appendOpacity(librevenge::RVNGPropertyList &propList, const double *opacity) |
2406 | 0 | { |
2407 | 0 | if (!opacity) |
2408 | 0 | return; |
2409 | 0 | if (propList["draw:fill"] && propList["draw:fill"]->getStr() != "none") |
2410 | 0 | propList.insert("draw:opacity", *opacity, librevenge::RVNG_PERCENT); |
2411 | 0 | if (propList["draw:stroke"] && propList["draw:stroke"]->getStr() != "none") |
2412 | 0 | propList.insert("svg:stroke-opacity", *opacity, librevenge::RVNG_PERCENT); |
2413 | 0 | } |
2414 | | |
2415 | | void libfreehand::FHCollector::_appendShadow(librevenge::RVNGPropertyList &propList, const libfreehand::FWShadowFilter *filter) |
2416 | 0 | { |
2417 | 0 | if (!filter) |
2418 | 0 | return; |
2419 | 0 | if (!filter->m_inner) |
2420 | 0 | { |
2421 | 0 | propList.insert("draw:shadow","visible"); // for ODG |
2422 | 0 | propList.insert("draw:shadow-offset-x",filter->m_distribution * cos(M_PI * filter->m_angle / 180.0)); |
2423 | 0 | propList.insert("draw:shadow-offset-y",filter->m_distribution * sin(M_PI * filter->m_angle / 180.0)); |
2424 | 0 | propList.insert("draw:shadow-color",getColorString(filter->m_colorId)); |
2425 | 0 | propList.insert("draw:shadow-opacity",filter->m_opacity, librevenge::RVNG_PERCENT); |
2426 | 0 | } |
2427 | 0 | } |
2428 | | |
2429 | | void libfreehand::FHCollector::_appendGlow(librevenge::RVNGPropertyList & /* propList */, const libfreehand::FWGlowFilter *filter) |
2430 | 0 | { |
2431 | 0 | if (!filter) |
2432 | 0 | return; |
2433 | 0 | } |
2434 | | |
2435 | | void libfreehand::FHCollector::_appendLensFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHLensFill *lensFill) |
2436 | 15.6k | { |
2437 | 15.6k | if (!lensFill) |
2438 | 15.6k | return; |
2439 | | |
2440 | 0 | if (lensFill->m_colorId) |
2441 | 0 | { |
2442 | 0 | propList.insert("draw:fill", "solid"); |
2443 | 0 | librevenge::RVNGString color = getColorString(lensFill->m_colorId); |
2444 | 0 | if (!color.empty()) |
2445 | 0 | propList.insert("draw:fill-color", color); |
2446 | 0 | else |
2447 | 0 | propList.insert("draw:fill", "none"); |
2448 | 0 | } |
2449 | 0 | else |
2450 | 0 | propList.insert("draw:fill", "none"); |
2451 | |
|
2452 | 0 | switch (lensFill->m_mode) |
2453 | 0 | { |
2454 | 0 | case FH_LENSFILL_MODE_TRANSPARENCY: |
2455 | 0 | propList.insert("draw:opacity", lensFill->m_value / 100.0, librevenge::RVNG_PERCENT); |
2456 | 0 | break; |
2457 | 0 | case FH_LENSFILL_MODE_MONOCHROME: |
2458 | 0 | propList.insert("draw:fill", "none"); |
2459 | 0 | propList.insert("draw:color-mode", "greyscale"); |
2460 | 0 | break; |
2461 | 0 | case FH_LENSFILL_MODE_MAGNIFY: |
2462 | 0 | propList.insert("draw:fill", "none"); |
2463 | 0 | break; |
2464 | 0 | case FH_LENSFILL_MODE_LIGHTEN: // emulate by semi-transparent white fill |
2465 | 0 | propList.insert("draw:fill", "solid"); |
2466 | 0 | propList.insert("draw:fill-color", "#FFFFFF"); |
2467 | 0 | propList.insert("draw:opacity", lensFill->m_value / 100.0, librevenge::RVNG_PERCENT); |
2468 | 0 | break; |
2469 | 0 | case FH_LENSFILL_MODE_DARKEN: // emulate by semi-transparent black fill |
2470 | 0 | propList.insert("draw:fill", "solid"); |
2471 | 0 | propList.insert("draw:fill-color", "#000000"); |
2472 | 0 | propList.insert("draw:opacity", lensFill->m_value / 100.0, librevenge::RVNG_PERCENT); |
2473 | 0 | break; |
2474 | 0 | case FH_LENSFILL_MODE_INVERT: |
2475 | 0 | propList.insert("draw:fill", "none"); |
2476 | 0 | break; |
2477 | 0 | default: |
2478 | 0 | break; |
2479 | 0 | } |
2480 | 0 | } |
2481 | | |
2482 | | void libfreehand::FHCollector::_appendRadialFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHRadialFill *radialFill) |
2483 | 15.6k | { |
2484 | 15.6k | if (!radialFill) |
2485 | 13.3k | return; |
2486 | | |
2487 | 2.24k | propList.insert("draw:fill", "gradient"); |
2488 | 2.24k | propList.insert("draw:style", "radial"); |
2489 | 2.24k | propList.insert("svg:cx", radialFill->m_cx, librevenge::RVNG_PERCENT); |
2490 | 2.24k | propList.insert("svg:cy", radialFill->m_cy, librevenge::RVNG_PERCENT); |
2491 | | |
2492 | 2.24k | const std::vector<FHColorStop> *multiColorList = _findMultiColorList(radialFill->m_multiColorListId); |
2493 | 2.24k | if (multiColorList && multiColorList->size() > 1) |
2494 | 64 | { |
2495 | 64 | librevenge::RVNGString color = getColorString((*multiColorList)[0].m_colorId); |
2496 | 64 | if (!color.empty()) |
2497 | 64 | propList.insert("draw:start-color", color); |
2498 | 64 | color = getColorString((*multiColorList)[1].m_colorId); |
2499 | 64 | if (!color.empty()) |
2500 | 64 | propList.insert("draw:end-color", color); |
2501 | 64 | } |
2502 | 2.18k | else |
2503 | 2.18k | { |
2504 | 2.18k | librevenge::RVNGString color = getColorString(radialFill->m_color1Id); |
2505 | 2.18k | if (!color.empty()) |
2506 | 1.27k | propList.insert("draw:start-color", color); |
2507 | 2.18k | color = getColorString(radialFill->m_color2Id); |
2508 | 2.18k | if (!color.empty()) |
2509 | 1.34k | propList.insert("draw:end-color", color); |
2510 | 2.18k | } |
2511 | 2.24k | } |
2512 | | |
2513 | | void libfreehand::FHCollector::_appendTileFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHTileFill *tileFill) |
2514 | 15.6k | { |
2515 | 15.6k | if (!tileFill || !(tileFill->m_groupId)) |
2516 | 13.6k | return; |
2517 | | |
2518 | 1.98k | const FHTransform *trafo = _findTransform(tileFill->m_xFormId); |
2519 | 1.98k | if (trafo) |
2520 | 1.59k | m_currentTransforms.push(*trafo); |
2521 | 383 | else |
2522 | 383 | m_currentTransforms.push(FHTransform()); |
2523 | | |
2524 | 1.98k | FHBoundingBox bBox; |
2525 | 1.98k | _getBBofSomething(tileFill->m_groupId, bBox); |
2526 | 1.98k | if (bBox.isValid() && !FH_ALMOST_ZERO(bBox.m_xmax - bBox.m_xmin) && !FH_ALMOST_ZERO(bBox.m_ymax - bBox.m_ymin)) |
2527 | 1.83k | { |
2528 | 1.83k | FHTransform fakeTrafo(tileFill->m_scaleX, 0.0, 0.0, tileFill->m_scaleY, - bBox.m_xmin, -bBox.m_ymin); |
2529 | 1.83k | m_fakeTransforms.push_back(fakeTrafo); |
2530 | | |
2531 | 1.83k | librevenge::RVNGStringVector svgOutput; |
2532 | 1.83k | librevenge::RVNGSVGDrawingGenerator generator(svgOutput, ""); |
2533 | 1.83k | librevenge::RVNGPropertyList pList; |
2534 | 1.83k | pList.insert("svg:width", tileFill->m_scaleX * (bBox.m_xmax - bBox.m_xmin)); |
2535 | 1.83k | pList.insert("svg:height", tileFill->m_scaleY * (bBox.m_ymax - bBox.m_ymin)); |
2536 | 1.83k | generator.startPage(pList); |
2537 | | |
2538 | 1.83k | _outputSomething(tileFill->m_groupId, &generator); |
2539 | 1.83k | generator.endPage(); |
2540 | 1.83k | if (!svgOutput.empty() && svgOutput[0].size() > 140) // basically empty svg if it is not fullfilled |
2541 | 1.83k | { |
2542 | 1.83k | const char *header = |
2543 | 1.83k | "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"; |
2544 | 1.83k | librevenge::RVNGBinaryData output((const unsigned char *)header, strlen(header)); |
2545 | 1.83k | output.append((unsigned char *)svgOutput[0].cstr(), strlen(svgOutput[0].cstr())); |
2546 | | #if DUMP_TILE_FILLS |
2547 | | { |
2548 | | librevenge::RVNGString filename; |
2549 | | filename.sprintf("freehandtilefill%.4x.svg", tileFill->m_groupId); |
2550 | | FILE *f = fopen(filename.cstr(), "wb"); |
2551 | | if (f) |
2552 | | { |
2553 | | const unsigned char *tmpBuffer = output.getDataBuffer(); |
2554 | | for (unsigned long k = 0; k < output.size(); k++) |
2555 | | fprintf(f, "%c",tmpBuffer[k]); |
2556 | | fclose(f); |
2557 | | } |
2558 | | } |
2559 | | #endif |
2560 | 1.83k | propList.insert("draw:fill", "bitmap"); |
2561 | 1.83k | propList.insert("draw:fill-image", output); |
2562 | 1.83k | propList.insert("draw:fill-image-width", tileFill->m_scaleX * (bBox.m_xmax - bBox.m_xmin)); |
2563 | 1.83k | propList.insert("draw:fill-image-height", tileFill->m_scaleY * (bBox.m_ymax - bBox.m_ymin)); |
2564 | 1.83k | propList.insert("librevenge:mime-type", "image/svg+xml"); |
2565 | 1.83k | propList.insert("style:repeat", "repeat"); |
2566 | 1.83k | } |
2567 | | |
2568 | 1.83k | if (!m_fakeTransforms.empty()) |
2569 | 1.83k | m_fakeTransforms.pop_back(); |
2570 | 1.83k | } |
2571 | 1.98k | if (!m_currentTransforms.empty()) |
2572 | 1.98k | m_currentTransforms.pop(); |
2573 | 1.98k | } |
2574 | | |
2575 | | void libfreehand::FHCollector::_appendPatternFill(librevenge::RVNGPropertyList &propList, const libfreehand::FHPatternFill *patternFill) |
2576 | 15.6k | { |
2577 | 15.6k | if (!patternFill) |
2578 | 14.5k | return; |
2579 | 1.11k | librevenge::RVNGBinaryData output; |
2580 | 1.11k | _generateBitmapFromPattern(output, patternFill->m_colorId, patternFill->m_pattern); |
2581 | 1.11k | propList.insert("draw:fill", "bitmap"); |
2582 | 1.11k | propList.insert("draw:fill-image", output); |
2583 | 1.11k | propList.insert("librevenge:mime-type", "image/bmp"); |
2584 | 1.11k | propList.insert("style:repeat", "repeat"); |
2585 | 1.11k | } |
2586 | | |
2587 | | void libfreehand::FHCollector::_appendLinePattern(librevenge::RVNGPropertyList &propList, const libfreehand::FHLinePattern *linePattern) |
2588 | 118k | { |
2589 | 118k | if (!linePattern || linePattern->m_dashes.size()<=1) |
2590 | 116k | return; |
2591 | 1.80k | int nDots1=0, nDots2=0; |
2592 | 1.80k | double size1=0, size2=0, totalGap=0.0; |
2593 | 4.71k | for (size_t c=0; c+1 < linePattern->m_dashes.size();) |
2594 | 3.10k | { |
2595 | 3.10k | double sz=linePattern->m_dashes[c++]; |
2596 | 3.10k | if (nDots2 && (sz<size2||sz>size2)) |
2597 | 191 | { |
2598 | 191 | static bool first=true; |
2599 | 191 | if (first) |
2600 | 1 | { |
2601 | 1 | FH_DEBUG_MSG(("libfreehand::FHCollector::_appendLinePattern: can not set some dash\n")); |
2602 | 1 | first = false; |
2603 | 1 | } |
2604 | 191 | break; |
2605 | 191 | } |
2606 | 2.90k | if (nDots2) |
2607 | 375 | nDots2++; |
2608 | 2.53k | else if (!nDots1 || (sz>=size1 && sz <= size1)) |
2609 | 1.98k | { |
2610 | 1.98k | nDots1++; |
2611 | 1.98k | size1=sz; |
2612 | 1.98k | } |
2613 | 547 | else |
2614 | 547 | { |
2615 | 547 | nDots2=1; |
2616 | 547 | size2=sz; |
2617 | 547 | } |
2618 | 2.90k | totalGap += linePattern->m_dashes[c++]; |
2619 | 2.90k | } |
2620 | 1.80k | propList.insert("draw:stroke", "dash"); |
2621 | 1.80k | propList.insert("draw:dots1", nDots1); |
2622 | 1.80k | propList.insert("draw:dots1-length", double(size1), librevenge::RVNG_POINT); |
2623 | 1.80k | if (nDots2) |
2624 | 547 | { |
2625 | 547 | propList.insert("draw:dots2", nDots2); |
2626 | 547 | propList.insert("draw:dots2-length", double(size2), librevenge::RVNG_POINT); |
2627 | 547 | } |
2628 | 1.80k | const double distance = ((nDots1 + nDots2) > 0) ? double(totalGap)/double(nDots1+nDots2) : double(totalGap); |
2629 | 1.80k | propList.insert("draw:distance", distance, librevenge::RVNG_POINT);; |
2630 | 1.80k | } |
2631 | | |
2632 | | void libfreehand::FHCollector::_appendArrowPath(librevenge::RVNGPropertyList &propList, const FHPath *arrow, bool startArrow) |
2633 | 237k | { |
2634 | 237k | if (!arrow) |
2635 | 224k | return; |
2636 | | |
2637 | 13.1k | FHPath path=*arrow; |
2638 | 13.1k | path.transform(FHTransform(0,-1,1,0,0,0)); |
2639 | 13.1k | std::string pString=path.getPathString(); |
2640 | 13.1k | if (pString.empty()) return; |
2641 | 13.1k | std::string wh(startArrow ? "start" : "end"); |
2642 | 13.1k | propList.insert((std::string("draw:marker-")+wh+"-path").c_str(), pString.c_str()); |
2643 | 13.1k | FHBoundingBox box; |
2644 | 13.1k | path.getBoundingBox(box.m_xmin, box.m_ymin, box.m_xmax, box.m_ymax); |
2645 | 13.1k | librevenge::RVNGString boxString; |
2646 | 13.1k | boxString.sprintf("%d %d %d %d", int(box.m_xmin*35), int(box.m_ymin*35), int(35*(box.m_xmax-box.m_xmin)), int(35*(box.m_ymax-box.m_ymin))); |
2647 | 13.1k | propList.insert((std::string("draw:marker-")+wh+"-viewbox").c_str(), boxString); |
2648 | 13.1k | propList.insert((std::string("draw:marker-")+wh+"-width").c_str(), 10, librevenge::RVNG_POINT); // change me |
2649 | 13.1k | } |
2650 | | |
2651 | | void libfreehand::FHCollector::_appendBasicLine(librevenge::RVNGPropertyList &propList, const libfreehand::FHBasicLine *basicLine) |
2652 | 130k | { |
2653 | 130k | if (!basicLine) |
2654 | 11.7k | return; |
2655 | | // osnola: we do not want to change draw:stroke, if stroke is defined recursively |
2656 | 118k | propList.insert("draw:stroke", "solid"); |
2657 | 118k | librevenge::RVNGString color = getColorString(basicLine->m_colorId); |
2658 | 118k | if (!color.empty()) |
2659 | 104k | propList.insert("svg:stroke-color", color); |
2660 | 13.8k | else if (!propList["svg:stroke-color"]) // set to default |
2661 | 12.3k | propList.insert("svg:stroke-color", "#000000"); |
2662 | 118k | propList.insert("svg:stroke-width", basicLine->m_width); |
2663 | 118k | _appendLinePattern(propList, _findLinePattern(basicLine->m_linePatternId)); |
2664 | 118k | _appendArrowPath(propList, _findArrowPath(basicLine->m_startArrowId), true); |
2665 | 118k | _appendArrowPath(propList, _findArrowPath(basicLine->m_endArrowId), false); |
2666 | 118k | } |
2667 | | |
2668 | | void libfreehand::FHCollector::_appendCustomProcLine(librevenge::RVNGPropertyList &propList, const libfreehand::FHCustomProc *customProc) |
2669 | 130k | { |
2670 | 130k | if (!customProc) |
2671 | 129k | return; |
2672 | 753 | propList.insert("draw:stroke", "solid"); |
2673 | 753 | librevenge::RVNGString color; |
2674 | 753 | if (!customProc->m_ids.empty()) |
2675 | 656 | color= getColorString(customProc->m_ids[0]); |
2676 | 753 | if (!color.empty()) |
2677 | 553 | propList.insert("svg:stroke-color", color); |
2678 | 753 | if (!customProc->m_widths.empty()) |
2679 | 674 | propList.insert("svg:stroke-width", customProc->m_widths[0], librevenge::RVNG_POINT); |
2680 | 753 | } |
2681 | | |
2682 | | void libfreehand::FHCollector::_appendPatternLine(librevenge::RVNGPropertyList &propList, const libfreehand::FHPatternLine *patternLine) |
2683 | 130k | { |
2684 | 130k | if (!patternLine) |
2685 | 129k | return; |
2686 | 1.22k | propList.insert("draw:stroke", "solid"); |
2687 | 1.22k | librevenge::RVNGString color = getColorString(patternLine->m_colorId, patternLine->m_percentPattern); |
2688 | 1.22k | if (!color.empty()) |
2689 | 1.06k | propList.insert("svg:stroke-color", color); |
2690 | 157 | else if (!propList["svg:stroke-color"]) // set to default |
2691 | 69 | propList.insert("svg:stroke-color", "#000000"); |
2692 | 1.22k | propList.insert("svg:stroke-width", patternLine->m_width); |
2693 | 1.22k | } |
2694 | | |
2695 | | const libfreehand::FHPath *libfreehand::FHCollector::_findPath(unsigned id) |
2696 | 228k | { |
2697 | 228k | if (!id) |
2698 | 302 | return nullptr; |
2699 | 227k | std::map<unsigned, FHPath>::const_iterator iter = m_paths.find(id); |
2700 | 227k | if (iter != m_paths.end()) |
2701 | 131k | return &(iter->second); |
2702 | 96.6k | return nullptr; |
2703 | 227k | } |
2704 | | |
2705 | | const libfreehand::FHNewBlend *libfreehand::FHCollector::_findNewBlend(unsigned id) |
2706 | 225k | { |
2707 | 225k | if (!id) |
2708 | 0 | return nullptr; |
2709 | 225k | std::map<unsigned, FHNewBlend>::const_iterator iter = m_newBlends.find(id); |
2710 | 225k | if (iter != m_newBlends.end()) |
2711 | 12 | return &(iter->second); |
2712 | 225k | return nullptr; |
2713 | 225k | } |
2714 | | |
2715 | | const libfreehand::FHGroup *libfreehand::FHCollector::_findGroup(unsigned id) |
2716 | 225k | { |
2717 | 225k | if (!id) |
2718 | 0 | return nullptr; |
2719 | 225k | std::map<unsigned, FHGroup>::const_iterator iter = m_groups.find(id); |
2720 | 225k | if (iter != m_groups.end()) |
2721 | 19.6k | return &(iter->second); |
2722 | 205k | return nullptr; |
2723 | 225k | } |
2724 | | |
2725 | | const libfreehand::FHGroup *libfreehand::FHCollector::_findClipGroup(unsigned id) |
2726 | 225k | { |
2727 | 225k | if (!id) |
2728 | 0 | return nullptr; |
2729 | 225k | std::map<unsigned, FHGroup>::const_iterator iter = m_clipGroups.find(id); |
2730 | 225k | if (iter != m_clipGroups.end()) |
2731 | 84 | return &(iter->second); |
2732 | 225k | return nullptr; |
2733 | 225k | } |
2734 | | |
2735 | | const libfreehand::FHCompositePath *libfreehand::FHCollector::_findCompositePath(unsigned id) |
2736 | 225k | { |
2737 | 225k | if (!id) |
2738 | 0 | return nullptr; |
2739 | 225k | std::map<unsigned, FHCompositePath>::const_iterator iter = m_compositePaths.find(id); |
2740 | 225k | if (iter != m_compositePaths.end()) |
2741 | 322 | return &(iter->second); |
2742 | 225k | return nullptr; |
2743 | 225k | } |
2744 | | |
2745 | | const libfreehand::FHPathText *libfreehand::FHCollector::_findPathText(unsigned id) |
2746 | 225k | { |
2747 | 225k | if (!id) |
2748 | 0 | return nullptr; |
2749 | 225k | std::map<unsigned, FHPathText>::const_iterator iter = m_pathTexts.find(id); |
2750 | 225k | if (iter != m_pathTexts.end()) |
2751 | 189 | return &(iter->second); |
2752 | 225k | return nullptr; |
2753 | 225k | } |
2754 | | |
2755 | | const libfreehand::FHTextObject *libfreehand::FHCollector::_findTextObject(unsigned id) |
2756 | 225k | { |
2757 | 225k | if (!id) |
2758 | 0 | return nullptr; |
2759 | 225k | std::map<unsigned, FHTextObject>::const_iterator iter = m_textObjects.find(id); |
2760 | 225k | if (iter != m_textObjects.end()) |
2761 | 20.3k | return &(iter->second); |
2762 | 205k | return nullptr; |
2763 | 225k | } |
2764 | | |
2765 | | const libfreehand::FHTransform *libfreehand::FHCollector::_findTransform(unsigned id) |
2766 | 76.0k | { |
2767 | 76.0k | if (!id) |
2768 | 42 | return nullptr; |
2769 | 76.0k | std::map<unsigned, FHTransform>::const_iterator iter = m_transforms.find(id); |
2770 | 76.0k | if (iter != m_transforms.end()) |
2771 | 73.3k | return &(iter->second); |
2772 | 2.68k | return nullptr; |
2773 | 76.0k | } |
2774 | | |
2775 | | const libfreehand::FHTEffect *libfreehand::FHCollector::_findTEffect(unsigned id) |
2776 | 227k | { |
2777 | 227k | if (!id) |
2778 | 66.0k | return nullptr; |
2779 | 161k | std::map<unsigned, FHTEffect>::const_iterator iter = m_tEffects.find(id); |
2780 | 161k | if (iter != m_tEffects.end()) |
2781 | 158k | return &(iter->second); |
2782 | 2.99k | return nullptr; |
2783 | 161k | } |
2784 | | |
2785 | | const libfreehand::FHParagraph *libfreehand::FHCollector::_findParagraph(unsigned id) |
2786 | 80.1k | { |
2787 | 80.1k | if (!id) |
2788 | 23.9k | return nullptr; |
2789 | 56.1k | std::map<unsigned, FHParagraph>::const_iterator iter = m_paragraphs.find(id); |
2790 | 56.1k | if (iter != m_paragraphs.end()) |
2791 | 24.6k | return &(iter->second); |
2792 | 31.4k | return nullptr; |
2793 | 56.1k | } |
2794 | | |
2795 | | const std::vector<libfreehand::FHTab> *libfreehand::FHCollector::_findTabTable(unsigned id) |
2796 | 0 | { |
2797 | 0 | if (!id) |
2798 | 0 | return nullptr; |
2799 | 0 | std::map<unsigned, std::vector<libfreehand::FHTab> >::const_iterator iter = m_tabs.find(id); |
2800 | 0 | if (iter != m_tabs.end()) |
2801 | 0 | return &(iter->second); |
2802 | 0 | return nullptr; |
2803 | 0 | } |
2804 | | |
2805 | | const std::vector<unsigned> *libfreehand::FHCollector::_findTStringElements(unsigned id) |
2806 | 19.5k | { |
2807 | 19.5k | if (!id) |
2808 | 32 | return nullptr; |
2809 | 19.5k | std::map<unsigned, std::vector<unsigned> >::const_iterator iter = m_tStrings.find(id); |
2810 | 19.5k | if (iter != m_tStrings.end()) |
2811 | 19.4k | return &(iter->second); |
2812 | 101 | return nullptr; |
2813 | 19.5k | } |
2814 | | |
2815 | | const libfreehand::FHPropList *libfreehand::FHCollector::_findPropList(unsigned id) |
2816 | 651k | { |
2817 | 651k | if (!id) |
2818 | 0 | return nullptr; |
2819 | 651k | std::map<unsigned, FHPropList>::const_iterator iter = m_propertyLists.find(id); |
2820 | 651k | if (iter != m_propertyLists.end()) |
2821 | 620k | return &(iter->second); |
2822 | 30.2k | return nullptr; |
2823 | 651k | } |
2824 | | |
2825 | | const libfreehand::FHGraphicStyle *libfreehand::FHCollector::_findGraphicStyle(unsigned id) |
2826 | 30.2k | { |
2827 | 30.2k | if (!id) |
2828 | 0 | return nullptr; |
2829 | 30.2k | std::map<unsigned, FHGraphicStyle>::const_iterator iter = m_graphicStyles.find(id); |
2830 | 30.2k | if (iter != m_graphicStyles.end()) |
2831 | 14.1k | return &(iter->second); |
2832 | 16.1k | return nullptr; |
2833 | 30.2k | } |
2834 | | |
2835 | | const libfreehand::FHBasicFill *libfreehand::FHCollector::_findBasicFill(unsigned id) |
2836 | 25.2k | { |
2837 | 25.2k | if (!id) |
2838 | 4.93k | return nullptr; |
2839 | 20.3k | std::map<unsigned, FHBasicFill>::const_iterator iter = m_basicFills.find(id); |
2840 | 20.3k | if (iter != m_basicFills.end()) |
2841 | 4.21k | return &(iter->second); |
2842 | 16.1k | return nullptr; |
2843 | 20.3k | } |
2844 | | |
2845 | | const libfreehand::FHLinearFill *libfreehand::FHCollector::_findLinearFill(unsigned id) |
2846 | 24.2k | { |
2847 | 24.2k | if (!id) |
2848 | 4.93k | return nullptr; |
2849 | 19.2k | std::map<unsigned, FHLinearFill>::const_iterator iter = m_linearFills.find(id); |
2850 | 19.2k | if (iter != m_linearFills.end()) |
2851 | 869 | return &(iter->second); |
2852 | 18.4k | return nullptr; |
2853 | 19.2k | } |
2854 | | |
2855 | | const libfreehand::FHLensFill *libfreehand::FHCollector::_findLensFill(unsigned id) |
2856 | 24.1k | { |
2857 | 24.1k | if (!id) |
2858 | 4.93k | return nullptr; |
2859 | 19.1k | std::map<unsigned, FHLensFill>::const_iterator iter = m_lensFills.find(id); |
2860 | 19.1k | if (iter != m_lensFills.end()) |
2861 | 0 | return &(iter->second); |
2862 | 19.1k | return nullptr; |
2863 | 19.1k | } |
2864 | | |
2865 | | const libfreehand::FHRadialFill *libfreehand::FHCollector::_findRadialFill(unsigned id) |
2866 | 24.1k | { |
2867 | 24.1k | if (!id) |
2868 | 4.93k | return nullptr; |
2869 | 19.1k | std::map<unsigned, FHRadialFill>::const_iterator iter = m_radialFills.find(id); |
2870 | 19.1k | if (iter != m_radialFills.end()) |
2871 | 2.31k | return &(iter->second); |
2872 | 16.8k | return nullptr; |
2873 | 19.1k | } |
2874 | | |
2875 | | const libfreehand::FHTileFill *libfreehand::FHCollector::_findTileFill(unsigned id) |
2876 | 24.0k | { |
2877 | 24.0k | if (!id) |
2878 | 4.93k | return nullptr; |
2879 | 19.1k | std::map<unsigned, FHTileFill>::const_iterator iter = m_tileFills.find(id); |
2880 | 19.1k | if (iter != m_tileFills.end()) |
2881 | 2.56k | return &(iter->second); |
2882 | 16.5k | return nullptr; |
2883 | 19.1k | } |
2884 | | |
2885 | | const libfreehand::FHPatternFill *libfreehand::FHCollector::_findPatternFill(unsigned id) |
2886 | 24.0k | { |
2887 | 24.0k | if (!id) |
2888 | 4.93k | return nullptr; |
2889 | 19.1k | std::map<unsigned, FHPatternFill>::const_iterator iter = m_patternFills.find(id); |
2890 | 19.1k | if (iter != m_patternFills.end()) |
2891 | 1.11k | return &(iter->second); |
2892 | 18.0k | return nullptr; |
2893 | 19.1k | } |
2894 | | |
2895 | | const libfreehand::FHLinePattern *libfreehand::FHCollector::_findLinePattern(unsigned id) |
2896 | 118k | { |
2897 | 118k | if (!id) |
2898 | 110k | return nullptr; |
2899 | 8.24k | std::map<unsigned, FHLinePattern>::const_iterator iter = m_linePatterns.find(id); |
2900 | 8.24k | if (iter != m_linePatterns.end()) |
2901 | 1.97k | return &(iter->second); |
2902 | 6.27k | return nullptr; |
2903 | 8.24k | } |
2904 | | |
2905 | | const libfreehand::FHPath *libfreehand::FHCollector::_findArrowPath(unsigned id) |
2906 | 237k | { |
2907 | 237k | if (!id) |
2908 | 215k | return nullptr; |
2909 | 22.3k | std::map<unsigned, FHPath>::const_iterator iter = m_arrowPaths.find(id); |
2910 | 22.3k | if (iter != m_arrowPaths.end()) |
2911 | 13.1k | return &(iter->second); |
2912 | 9.20k | return nullptr; |
2913 | 22.3k | } |
2914 | | |
2915 | | const libfreehand::FHBasicLine *libfreehand::FHCollector::_findBasicLine(unsigned id) |
2916 | 140k | { |
2917 | 140k | if (!id) |
2918 | 4.93k | return nullptr; |
2919 | 135k | std::map<unsigned, FHBasicLine>::const_iterator iter = m_basicLines.find(id); |
2920 | 135k | if (iter != m_basicLines.end()) |
2921 | 121k | return &(iter->second); |
2922 | 13.6k | return nullptr; |
2923 | 135k | } |
2924 | | |
2925 | | const libfreehand::FHCustomProc *libfreehand::FHCollector::_findCustomProc(unsigned id) |
2926 | 154k | { |
2927 | 154k | if (!id) |
2928 | 4.93k | return nullptr; |
2929 | 149k | std::map<unsigned, FHCustomProc>::const_iterator iter = m_customProcs.find(id); |
2930 | 149k | if (iter != m_customProcs.end()) |
2931 | 2.06k | return &(iter->second); |
2932 | 147k | return nullptr; |
2933 | 149k | } |
2934 | | |
2935 | | const libfreehand::FHPatternLine *libfreehand::FHCollector::_findPatternLine(unsigned id) |
2936 | 130k | { |
2937 | 130k | if (!id) |
2938 | 0 | return nullptr; |
2939 | 130k | std::map<unsigned, FHPatternLine>::const_iterator iter = m_patternLines.find(id); |
2940 | 130k | if (iter != m_patternLines.end()) |
2941 | 1.22k | return &(iter->second); |
2942 | 129k | return nullptr; |
2943 | 130k | } |
2944 | | |
2945 | | const libfreehand::FHRGBColor *libfreehand::FHCollector::_findRGBColor(unsigned id) |
2946 | 365k | { |
2947 | 365k | if (!id) |
2948 | 4.95k | return nullptr; |
2949 | 360k | std::map<unsigned, FHRGBColor>::const_iterator iter = m_rgbColors.find(id); |
2950 | 360k | if (iter != m_rgbColors.end()) |
2951 | 345k | return &(iter->second); |
2952 | 15.3k | return nullptr; |
2953 | 360k | } |
2954 | | |
2955 | | const libfreehand::FHTintColor *libfreehand::FHCollector::_findTintColor(unsigned id) |
2956 | 20.2k | { |
2957 | 20.2k | if (!id) |
2958 | 4.95k | return nullptr; |
2959 | 15.2k | std::map<unsigned, FHTintColor>::const_iterator iter = m_tints.find(id); |
2960 | 15.2k | if (iter != m_tints.end()) |
2961 | 124 | return &(iter->second); |
2962 | 15.1k | return nullptr; |
2963 | 15.2k | } |
2964 | | |
2965 | | const libfreehand::FHDisplayText *libfreehand::FHCollector::_findDisplayText(unsigned id) |
2966 | 225k | { |
2967 | 225k | if (!id) |
2968 | 29 | return nullptr; |
2969 | 225k | std::map<unsigned, FHDisplayText>::const_iterator iter = m_displayTexts.find(id); |
2970 | 225k | if (iter != m_displayTexts.end()) |
2971 | 37.2k | return &(iter->second); |
2972 | 188k | return nullptr; |
2973 | 225k | } |
2974 | | |
2975 | | const libfreehand::FHImageImport *libfreehand::FHCollector::_findImageImport(unsigned id) |
2976 | 225k | { |
2977 | 225k | if (!id) |
2978 | 0 | return nullptr; |
2979 | 225k | std::map<unsigned, FHImageImport>::const_iterator iter = m_images.find(id); |
2980 | 225k | if (iter != m_images.end()) |
2981 | 65 | return &(iter->second); |
2982 | 225k | return nullptr; |
2983 | 225k | } |
2984 | | |
2985 | | const librevenge::RVNGBinaryData *libfreehand::FHCollector::_findData(unsigned id) |
2986 | 0 | { |
2987 | 0 | if (!id) |
2988 | 0 | return nullptr; |
2989 | 0 | std::map<unsigned, librevenge::RVNGBinaryData>::const_iterator iter = m_data.find(id); |
2990 | 0 | if (iter != m_data.end()) |
2991 | 0 | return &(iter->second); |
2992 | 0 | return nullptr; |
2993 | 0 | } |
2994 | | |
2995 | | const libfreehand::FHSymbolClass *libfreehand::FHCollector::_findSymbolClass(unsigned id) |
2996 | 0 | { |
2997 | 0 | if (!id) |
2998 | 0 | return nullptr; |
2999 | 0 | std::map<unsigned, FHSymbolClass>::const_iterator iter = m_symbolClasses.find(id); |
3000 | 0 | if (iter != m_symbolClasses.end()) |
3001 | 0 | return &(iter->second); |
3002 | 0 | return nullptr; |
3003 | 0 | } |
3004 | | |
3005 | | const libfreehand::FHSymbolInstance *libfreehand::FHCollector::_findSymbolInstance(unsigned id) |
3006 | 225k | { |
3007 | 225k | if (!id) |
3008 | 0 | return nullptr; |
3009 | 225k | std::map<unsigned, FHSymbolInstance>::const_iterator iter = m_symbolInstances.find(id); |
3010 | 225k | if (iter != m_symbolInstances.end()) |
3011 | 0 | return &(iter->second); |
3012 | 225k | return nullptr; |
3013 | 225k | } |
3014 | | |
3015 | | const libfreehand::FHFilterAttributeHolder *libfreehand::FHCollector::_findFilterAttributeHolder(unsigned id) |
3016 | 13.4k | { |
3017 | 13.4k | if (!id) |
3018 | 404 | return nullptr; |
3019 | 13.0k | std::map<unsigned, FHFilterAttributeHolder>::const_iterator iter = m_filterAttributeHolders.find(id); |
3020 | 13.0k | if (iter != m_filterAttributeHolders.end()) |
3021 | 0 | return &(iter->second); |
3022 | 13.0k | return nullptr; |
3023 | 13.0k | } |
3024 | | |
3025 | | const std::vector<libfreehand::FHColorStop> *libfreehand::FHCollector::_findMultiColorList(unsigned id) |
3026 | 3.04k | { |
3027 | 3.04k | if (!id) |
3028 | 2.90k | return nullptr; |
3029 | 136 | std::map<unsigned, std::vector<libfreehand::FHColorStop> >::const_iterator iter = m_multiColorLists.find(id); |
3030 | 136 | if (iter != m_multiColorLists.end()) |
3031 | 136 | return &(iter->second); |
3032 | 0 | return nullptr; |
3033 | 136 | } |
3034 | | |
3035 | | const double *libfreehand::FHCollector::_findOpacityFilter(unsigned id) |
3036 | 0 | { |
3037 | 0 | if (!id) |
3038 | 0 | return nullptr; |
3039 | 0 | std::map<unsigned, double>::const_iterator iter = m_opacityFilters.find(id); |
3040 | 0 | if (iter != m_opacityFilters.end()) |
3041 | 0 | return &(iter->second); |
3042 | 0 | return nullptr; |
3043 | 0 | } |
3044 | | |
3045 | | const libfreehand::FWShadowFilter *libfreehand::FHCollector::_findFWShadowFilter(unsigned id) |
3046 | 0 | { |
3047 | 0 | if (!id) |
3048 | 0 | return nullptr; |
3049 | 0 | std::map<unsigned, FWShadowFilter>::const_iterator iter = m_shadowFilters.find(id); |
3050 | 0 | if (iter != m_shadowFilters.end()) |
3051 | 0 | return &(iter->second); |
3052 | 0 | return nullptr; |
3053 | 0 | } |
3054 | | |
3055 | | const libfreehand::FWGlowFilter *libfreehand::FHCollector::_findFWGlowFilter(unsigned id) |
3056 | 0 | { |
3057 | 0 | if (!id) |
3058 | 0 | return nullptr; |
3059 | 0 | std::map<unsigned, FWGlowFilter>::const_iterator iter = m_glowFilters.find(id); |
3060 | 0 | if (iter != m_glowFilters.end()) |
3061 | 0 | return &(iter->second); |
3062 | 0 | return nullptr; |
3063 | 0 | } |
3064 | | |
3065 | | unsigned libfreehand::FHCollector::_findStrokeId(const libfreehand::FHGraphicStyle &graphicStyle) |
3066 | 5.64k | { |
3067 | 5.64k | unsigned listId = graphicStyle.m_attrId; |
3068 | 5.64k | if (!listId) |
3069 | 111 | return 0; |
3070 | 5.53k | std::map<unsigned, FHList>::const_iterator iter = m_lists.find(listId); |
3071 | 5.53k | if (iter == m_lists.end()) |
3072 | 402 | return 0; |
3073 | 5.13k | unsigned strokeId = 0; |
3074 | 5.13k | for (unsigned int element : iter->second.m_elements) |
3075 | 9.65k | { |
3076 | 9.65k | unsigned valueId = _findValueFromAttribute(element); |
3077 | 9.65k | if (_findBasicLine(valueId)) |
3078 | 2.86k | strokeId = valueId; |
3079 | 9.65k | } |
3080 | 5.13k | return strokeId; |
3081 | 5.53k | } |
3082 | | |
3083 | | unsigned libfreehand::FHCollector::_findFillId(const libfreehand::FHGraphicStyle &graphicStyle) |
3084 | 5.64k | { |
3085 | 5.64k | unsigned listId = graphicStyle.m_attrId; |
3086 | 5.64k | if (!listId) |
3087 | 111 | return 0; |
3088 | 5.53k | std::map<unsigned, FHList>::const_iterator iter = m_lists.find(listId); |
3089 | 5.53k | if (iter == m_lists.end()) |
3090 | 402 | return 0; |
3091 | 5.13k | unsigned fillId = 0; |
3092 | 5.13k | for (unsigned int element : iter->second.m_elements) |
3093 | 9.65k | { |
3094 | 9.65k | unsigned valueId = _findValueFromAttribute(element); |
3095 | | // Add other fills if we support them |
3096 | 9.65k | if (_findBasicFill(valueId) || _findLinearFill(valueId) |
3097 | 8.49k | || _findLensFill(valueId) || _findRadialFill(valueId) |
3098 | 8.43k | || _findTileFill(valueId) || _findPatternFill(valueId) || _findCustomProc(valueId)) |
3099 | 1.21k | fillId = valueId; |
3100 | 9.65k | } |
3101 | 5.13k | return fillId; |
3102 | 5.53k | } |
3103 | | |
3104 | | const libfreehand::FHFilterAttributeHolder *libfreehand::FHCollector::_findFilterAttributeHolder(const libfreehand::FHGraphicStyle &graphicStyle) |
3105 | 7.20k | { |
3106 | 7.20k | unsigned listId = graphicStyle.m_attrId; |
3107 | 7.20k | if (!listId) |
3108 | 222 | return nullptr; |
3109 | 6.98k | std::map<unsigned, FHList>::const_iterator iter = m_lists.find(listId); |
3110 | 6.98k | if (iter == m_lists.end()) |
3111 | 804 | return nullptr; |
3112 | 6.18k | for (unsigned int element : iter->second.m_elements) |
3113 | 13.4k | { |
3114 | 13.4k | const FHFilterAttributeHolder *attributeHolder = _findFilterAttributeHolder(element); |
3115 | | |
3116 | 13.4k | if (attributeHolder) |
3117 | 0 | return attributeHolder; |
3118 | 13.4k | } |
3119 | 6.18k | return nullptr; |
3120 | 6.18k | } |
3121 | | |
3122 | | |
3123 | | unsigned libfreehand::FHCollector::_findValueFromAttribute(unsigned id) |
3124 | 21.5k | { |
3125 | 21.5k | if (!id) |
3126 | 408 | return 0; |
3127 | 21.1k | std::map<unsigned, FHAttributeHolder>::const_iterator iter = m_attributeHolders.find(id); |
3128 | 21.1k | if (iter == m_attributeHolders.end()) |
3129 | 10.0k | return 0; |
3130 | 11.0k | unsigned value = 0; |
3131 | 11.0k | if (iter->second.m_parentId) |
3132 | 2.21k | value = _findValueFromAttribute(iter->second.m_parentId); |
3133 | 11.0k | if (iter->second.m_attrId) |
3134 | 10.2k | value = iter->second.m_attrId; |
3135 | 11.0k | return value; |
3136 | 21.1k | } |
3137 | | |
3138 | | librevenge::RVNGBinaryData libfreehand::FHCollector::getImageData(unsigned id) |
3139 | 65 | { |
3140 | 65 | std::map<unsigned, FHDataList>::const_iterator iter = m_dataLists.find(id); |
3141 | 65 | librevenge::RVNGBinaryData data; |
3142 | 65 | if (iter == m_dataLists.end()) |
3143 | 65 | return data; |
3144 | 0 | for (unsigned int element : iter->second.m_elements) |
3145 | 0 | { |
3146 | 0 | const librevenge::RVNGBinaryData *pData = _findData(element); |
3147 | 0 | if (pData) |
3148 | 0 | data.append(*pData); |
3149 | 0 | } |
3150 | 0 | return data; |
3151 | 65 | } |
3152 | | |
3153 | | librevenge::RVNGString libfreehand::FHCollector::getColorString(unsigned id, double tintVal) |
3154 | 364k | { |
3155 | 364k | FHRGBColor col; |
3156 | 364k | const FHRGBColor *color = _findRGBColor(id); |
3157 | 364k | if (color) |
3158 | 345k | col=*color; |
3159 | 19.6k | else |
3160 | 19.6k | { |
3161 | 19.6k | const FHTintColor *tint = _findTintColor(id); |
3162 | 19.6k | if (!tint) |
3163 | 19.5k | return librevenge::RVNGString(); |
3164 | 124 | col=getRGBFromTint(*tint); |
3165 | 124 | } |
3166 | 345k | if (tintVal<=0 || tintVal>=1) |
3167 | 344k | return _getColorString(col); |
3168 | | |
3169 | 1.06k | FHRGBColor finalColor; |
3170 | 1.06k | finalColor.m_red = col.m_red * tintVal + (1 - tintVal) * 65536; |
3171 | 1.06k | finalColor.m_green = col.m_green * tintVal + (1 - tintVal) * 65536; |
3172 | 1.06k | finalColor.m_blue = col.m_blue * tintVal + (1 - tintVal) * 65536; |
3173 | 1.06k | return _getColorString(finalColor); |
3174 | 345k | } |
3175 | | |
3176 | | libfreehand::FHRGBColor libfreehand::FHCollector::getRGBFromTint(const FHTintColor &tint) |
3177 | 124 | { |
3178 | 124 | if (!tint.m_baseColorId) |
3179 | 19 | return FHRGBColor(); |
3180 | 105 | const FHRGBColor *rgbColor = _findRGBColor(tint.m_baseColorId); |
3181 | 105 | if (!rgbColor) |
3182 | 64 | return FHRGBColor(); |
3183 | 41 | unsigned red = rgbColor->m_red * tint.m_tint + ((65536 - tint.m_tint) << 16); |
3184 | 41 | unsigned green = rgbColor->m_green * tint.m_tint + ((65536 - tint.m_tint) << 16); |
3185 | 41 | unsigned blue = rgbColor->m_blue * tint.m_tint + ((65536 - tint.m_tint) << 16); |
3186 | 41 | FHRGBColor color; |
3187 | 41 | color.m_red = (red >> 16); |
3188 | 41 | color.m_green = (green >> 16); |
3189 | 41 | color.m_blue = (blue >> 16); |
3190 | 41 | return color; |
3191 | 105 | } |
3192 | | |
3193 | | void libfreehand::FHCollector::_generateBitmapFromPattern(librevenge::RVNGBinaryData &bitmap, unsigned colorId, const std::vector<unsigned char> &pattern) |
3194 | 1.11k | { |
3195 | 1.11k | unsigned height = 8; |
3196 | 1.11k | unsigned width = 8; |
3197 | 1.11k | auto tmpPixelSize = (unsigned)(height * width); |
3198 | | |
3199 | 1.11k | unsigned tmpDIBImageSize = tmpPixelSize * 4; |
3200 | | |
3201 | 1.11k | unsigned tmpDIBOffsetBits = 14 + 40; |
3202 | 1.11k | unsigned tmpDIBFileSize = tmpDIBOffsetBits + tmpDIBImageSize; |
3203 | | |
3204 | | // Create DIB file header |
3205 | 1.11k | writeU16(bitmap, 0x4D42); // Type |
3206 | 1.11k | writeU32(bitmap, (int)tmpDIBFileSize); // Size |
3207 | 1.11k | writeU16(bitmap, 0); // Reserved1 |
3208 | 1.11k | writeU16(bitmap, 0); // Reserved2 |
3209 | 1.11k | writeU32(bitmap, (int)tmpDIBOffsetBits); // OffsetBits |
3210 | | |
3211 | | // Create DIB Info header |
3212 | 1.11k | writeU32(bitmap, 40); // Size |
3213 | | |
3214 | 1.11k | writeU32(bitmap, (int)width); // Width |
3215 | 1.11k | writeU32(bitmap, (int)height); // Height |
3216 | | |
3217 | 1.11k | writeU16(bitmap, 1); // Planes |
3218 | 1.11k | writeU16(bitmap, 32); // BitCount |
3219 | 1.11k | writeU32(bitmap, 0); // Compression |
3220 | 1.11k | writeU32(bitmap, (int)tmpDIBImageSize); // SizeImage |
3221 | 1.11k | writeU32(bitmap, 0); // XPelsPerMeter |
3222 | 1.11k | writeU32(bitmap, 0); // YPelsPerMeter |
3223 | 1.11k | writeU32(bitmap, 0); // ColorsUsed |
3224 | 1.11k | writeU32(bitmap, 0); // ColorsImportant |
3225 | | |
3226 | 1.11k | unsigned foreground = 0x000000; // Initialize to black and override after |
3227 | 1.11k | unsigned background = 0xffffff; // Initialize to white, since that is Freehand behaviour even if overlapping other colors |
3228 | | |
3229 | 1.11k | const FHRGBColor *color = _findRGBColor(colorId); |
3230 | 1.11k | if (color) |
3231 | 599 | foreground = ((unsigned)(color->m_red & 0xff00) << 8)|((unsigned)color->m_green & 0xff00)|((unsigned)color->m_blue >> 8); |
3232 | 515 | else |
3233 | 515 | { |
3234 | 515 | const FHTintColor *tintColor = _findTintColor(colorId); |
3235 | 515 | if (tintColor) |
3236 | 0 | { |
3237 | 0 | FHRGBColor rgbColor = getRGBFromTint(*tintColor); |
3238 | 0 | foreground = ((unsigned)(rgbColor.m_red & 0xff00) << 8)|((unsigned)rgbColor.m_green & 0xff00)|((unsigned)rgbColor.m_blue >> 8); |
3239 | 0 | } |
3240 | 515 | } |
3241 | 10.0k | for (unsigned j = height; j > 0; --j) |
3242 | 8.91k | { |
3243 | 8.91k | unsigned char c(pattern[j-1]); |
3244 | 80.2k | for (unsigned i = 0; i < width; ++i) |
3245 | 71.2k | { |
3246 | 71.2k | if (c & 0x80) |
3247 | 18.1k | writeU32(bitmap, foreground); |
3248 | 53.1k | else |
3249 | 53.1k | writeU32(bitmap, background); |
3250 | 71.2k | c <<= 1; |
3251 | 71.2k | } |
3252 | 8.91k | } |
3253 | 1.11k | } |
3254 | | |
3255 | | |
3256 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |