/src/libstaroffice/src/lib/libstaroffice_internal.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libstaroffice |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <cmath> |
35 | | #include <cstdarg> |
36 | | #include <cstdio> |
37 | | #include <iomanip> |
38 | | #include <string> |
39 | | #include <sstream> |
40 | | #include <time.h> |
41 | | |
42 | | #include <ctype.h> |
43 | | #include <locale.h> |
44 | | |
45 | | #include <librevenge-stream/librevenge-stream.h> |
46 | | |
47 | | #include "libstaroffice_internal.hxx" |
48 | | |
49 | | /** namespace used to regroup all libwpd functions, enumerations which we have redefined for internal usage */ |
50 | | namespace libstoff |
51 | | { |
52 | | uint8_t readU8(librevenge::RVNGInputStream *input) |
53 | 0 | { |
54 | 0 | unsigned long numBytesRead; |
55 | 0 | uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead); |
56 | |
|
57 | 0 | if (!p || numBytesRead != sizeof(uint8_t)) |
58 | 0 | throw libstoff::FileException(); |
59 | | |
60 | 0 | return *p; |
61 | 0 | } |
62 | | |
63 | | librevenge::RVNGString getString(std::vector<uint32_t> const &unicode) |
64 | 3.47M | { |
65 | 3.47M | librevenge::RVNGString res(""); |
66 | 648M | for (unsigned int i : unicode) { |
67 | 648M | if (i<0x20 && i!=0x9 && i!=0xa && i!=0xd) { |
68 | 392M | static int numErrors=0; |
69 | 392M | if (++numErrors<10) { |
70 | 36 | STOFF_DEBUG_MSG(("libstoff::getString: find odd char %x\n", static_cast<unsigned int>(i))); |
71 | 36 | } |
72 | 392M | } |
73 | 256M | else if (i<0x80) |
74 | 157M | res.append(char(i)); |
75 | 99.5M | else |
76 | 99.5M | appendUnicode(i, res); |
77 | 648M | } |
78 | 3.47M | return res; |
79 | 3.47M | } |
80 | | |
81 | | void appendUnicode(uint32_t val, librevenge::RVNGString &buffer) |
82 | 102M | { |
83 | 102M | uint8_t first; |
84 | 102M | int len; |
85 | 102M | if (val < 0x80) { |
86 | 2.59M | first = 0; |
87 | 2.59M | len = 1; |
88 | 2.59M | } |
89 | 100M | else if (val < 0x800) { |
90 | 53.5M | first = 0xc0; |
91 | 53.5M | len = 2; |
92 | 53.5M | } |
93 | 46.5M | else if (val < 0x10000) { |
94 | 46.4M | first = 0xe0; |
95 | 46.4M | len = 3; |
96 | 46.4M | } |
97 | 95.5k | else if (val < 0x200000) { |
98 | 5.60k | first = 0xf0; |
99 | 5.60k | len = 4; |
100 | 5.60k | } |
101 | 89.9k | else if (val < 0x4000000) { |
102 | 16.1k | first = 0xf8; |
103 | 16.1k | len = 5; |
104 | 16.1k | } |
105 | 73.7k | else { |
106 | 73.7k | first = 0xfc; |
107 | 73.7k | len = 6; |
108 | 73.7k | } |
109 | | |
110 | 102M | char outbuf[7]; |
111 | 102M | int i; |
112 | 249M | for (i = len - 1; i > 0; --i) { |
113 | 147M | outbuf[i] = char((val & 0x3f) | 0x80); |
114 | 147M | val >>= 6; |
115 | 147M | } |
116 | 102M | outbuf[0] = char(val | first); |
117 | 102M | outbuf[len] = 0; |
118 | 102M | buffer.append(outbuf); |
119 | 102M | } |
120 | | } |
121 | | |
122 | | namespace libstoff |
123 | | { |
124 | | std::string numberingTypeToString(NumberingType type) |
125 | 0 | { |
126 | 0 | switch (type) { |
127 | 0 | case ARABIC: |
128 | 0 | return "1"; |
129 | 0 | case LOWERCASE: |
130 | 0 | return "a"; |
131 | 0 | case UPPERCASE: |
132 | 0 | return "A"; |
133 | 0 | case LOWERCASE_ROMAN: |
134 | 0 | return "i"; |
135 | 0 | case UPPERCASE_ROMAN: |
136 | 0 | return "I"; |
137 | 0 | case NONE: |
138 | 0 | case BULLET: |
139 | 0 | default: |
140 | 0 | break; |
141 | 0 | } |
142 | 0 | STOFF_DEBUG_MSG(("libstoff::numberingTypeToString: must not be called with type %d\n", int(type))); |
143 | 0 | return "1"; |
144 | 0 | } |
145 | | |
146 | | std::string numberingValueToString(NumberingType type, int value) |
147 | 0 | { |
148 | 0 | std::stringstream ss; |
149 | 0 | std::string s(""); |
150 | 0 | switch (type) { |
151 | 0 | case ARABIC: |
152 | 0 | ss << value; |
153 | 0 | return ss.str(); |
154 | 0 | case LOWERCASE: |
155 | 0 | case UPPERCASE: |
156 | 0 | if (value <= 0) { |
157 | 0 | STOFF_DEBUG_MSG(("libstoff::numberingValueToString: value can not be negative or null for type %d\n", int(type))); |
158 | 0 | return (type == LOWERCASE) ? "a" : "A"; |
159 | 0 | } |
160 | 0 | while (value > 0) { |
161 | 0 | s = char((type == LOWERCASE ? 'a' : 'A')+((value-1)%26))+s; |
162 | 0 | value = (value-1)/26; |
163 | 0 | } |
164 | 0 | return s; |
165 | 0 | case LOWERCASE_ROMAN: |
166 | 0 | case UPPERCASE_ROMAN: { |
167 | 0 | static char const* const romanS[] = {"M", "CM", "D", "CD", "C", "XC", "L", |
168 | 0 | "XL", "X", "IX", "V", "IV", "I" |
169 | 0 | }; |
170 | 0 | static char const* const romans[] = {"m", "cm", "d", "cd", "c", "xc", "l", |
171 | 0 | "xl", "x", "ix", "v", "iv", "i" |
172 | 0 | }; |
173 | 0 | static int const romanV[] = {1000, 900, 500, 400, 100, 90, 50, |
174 | 0 | 40, 10, 9, 5, 4, 1 |
175 | 0 | }; |
176 | 0 | if (value <= 0 || value >= 4000) { |
177 | 0 | STOFF_DEBUG_MSG(("libstoff::numberingValueToString: out of range value for type %d\n", int(type))); |
178 | 0 | return (type == LOWERCASE_ROMAN) ? "i" : "I"; |
179 | 0 | } |
180 | 0 | for (int p = 0; p < 13; p++) { |
181 | 0 | while (value >= romanV[p]) { |
182 | 0 | ss << ((type == LOWERCASE_ROMAN) ? romans[p] : romanS[p]); |
183 | 0 | value -= romanV[p]; |
184 | 0 | } |
185 | 0 | } |
186 | 0 | return ss.str(); |
187 | 0 | } |
188 | 0 | case NONE: |
189 | 0 | return ""; |
190 | 0 | case BULLET: |
191 | 0 | default: |
192 | 0 | STOFF_DEBUG_MSG(("libstoff::numberingValueToString: must not be called with type %d\n", int(type))); |
193 | 0 | break; |
194 | 0 | } |
195 | 0 | return ""; |
196 | 0 | } |
197 | | } |
198 | | |
199 | | // color function |
200 | | STOFFColor STOFFColor::barycenter(float alpha, STOFFColor const &colA, |
201 | | float beta, STOFFColor const &colB) |
202 | 722 | { |
203 | 722 | uint32_t res = 0; |
204 | 3.61k | for (int i=0, depl=0; i<4; i++, depl+=8) { |
205 | 2.88k | float val=alpha*float((colA.m_value>>depl)&0xFF)+beta*float((colB.m_value>>depl)&0xFF); |
206 | 2.88k | if (val < 0) val=0; |
207 | 2.88k | if (val > 256) val=256; |
208 | 2.88k | auto comp= static_cast<unsigned char>(val); |
209 | 2.88k | res+=uint32_t(comp<<depl); |
210 | 2.88k | } |
211 | 722 | return STOFFColor(res); |
212 | 722 | } |
213 | | |
214 | | std::ostream &operator<< (std::ostream &o, STOFFColor const &c) |
215 | 563k | { |
216 | 563k | const std::streamsize width = o.width(); |
217 | 563k | const char fill = o.fill(); |
218 | 563k | o << "#" << std::hex << std::setfill('0') << std::setw(6) |
219 | 563k | << (c.m_value&0xFFFFFF) |
220 | | // std::ios::width() takes/returns std::streamsize (long), but |
221 | | // std::setw() takes int. Go figure... |
222 | 563k | << std::dec << std::setfill(fill) << std::setw(static_cast<int>(width)); |
223 | 563k | return o; |
224 | 563k | } |
225 | | |
226 | | std::string STOFFColor::str() const |
227 | 292k | { |
228 | 292k | std::stringstream stream; |
229 | 292k | stream << *this; |
230 | 292k | return stream.str(); |
231 | 292k | } |
232 | | |
233 | | // field function |
234 | | void STOFFField::addTo(librevenge::RVNGPropertyList &pList) const |
235 | 1.92k | { |
236 | 1.92k | librevenge::RVNGPropertyList::Iter i(m_propertyList); |
237 | 4.74k | for (i.rewind(); i.next();) { |
238 | 2.82k | if (i.child()) { |
239 | 0 | pList.insert(i.key(), *i.child()); |
240 | 0 | continue; |
241 | 0 | } |
242 | 2.82k | pList.insert(i.key(), i()->clone()); |
243 | 2.82k | } |
244 | 1.92k | } |
245 | | |
246 | | // link function |
247 | | bool STOFFLink::addTo(librevenge::RVNGPropertyList &propList) const |
248 | 92 | { |
249 | 92 | propList.insert("xlink:type","simple"); |
250 | 92 | if (!m_HRef.empty()) |
251 | 92 | propList.insert("xlink:href",m_HRef.c_str()); |
252 | 92 | return true; |
253 | 92 | } |
254 | | |
255 | | // border function |
256 | | bool STOFFBorderLine::addTo(librevenge::RVNGPropertyList &propList, std::string const which) const |
257 | 994k | { |
258 | 994k | std::stringstream stream, field; |
259 | 994k | field << "fo:border"; |
260 | 994k | if (which.length()) |
261 | 994k | field << "-" << which; |
262 | 994k | if (isEmpty()) { |
263 | 723k | propList.insert(field.str().c_str(), "none"); |
264 | 723k | return true; |
265 | 723k | } |
266 | 271k | stream << float(m_inWidth+m_distance+m_outWidth)/20.f << "pt "; |
267 | 271k | stream << ((m_inWidth && m_outWidth) ? "double" : "solid") << " " << m_color; |
268 | 271k | propList.insert(field.str().c_str(), stream.str().c_str()); |
269 | | |
270 | 271k | if (m_inWidth && m_outWidth) { |
271 | 34.3k | field.str(""); |
272 | 34.3k | field << "style:border-line-width"; |
273 | 34.3k | if (which.length()) |
274 | 34.3k | field << "-" << which; |
275 | 34.3k | stream.str(""); |
276 | 34.3k | stream << float(m_inWidth)/20.f << "pt " << float(m_distance)/20.f << "pt " << float(m_outWidth)/20.f << "pt"; |
277 | 34.3k | propList.insert(field.str().c_str(), stream.str().c_str()); |
278 | 34.3k | } |
279 | 271k | return true; |
280 | 994k | } |
281 | | |
282 | | std::ostream &operator<< (std::ostream &o, STOFFBorderLine const &border) |
283 | 0 | { |
284 | 0 | if (border.m_outWidth) o << "width[out]=" << border.m_outWidth << ":"; |
285 | 0 | if (border.m_inWidth) o << "width[in]=" << border.m_inWidth << ":"; |
286 | 0 | if (border.m_distance) o << "distance=" << border.m_distance << ":"; |
287 | 0 | if (!border.m_color.isBlack()) o << "col=" << border.m_color << ":"; |
288 | 0 | o << ","; |
289 | 0 | return o; |
290 | 0 | } |
291 | | |
292 | | // picture function |
293 | | STOFFEmbeddedObject::~STOFFEmbeddedObject() |
294 | 494k | { |
295 | 494k | } |
296 | | |
297 | | bool STOFFEmbeddedObject::addAsFillImageTo(librevenge::RVNGPropertyList &propList) const |
298 | 852 | { |
299 | 852 | for (size_t i=0; i<m_dataList.size(); ++i) { |
300 | 852 | if (m_dataList[i].empty()) continue; |
301 | 852 | std::string type=m_typeList.size() ? m_typeList[i] : "image/pict"; |
302 | 852 | propList.insert("librevenge:mime-type", type.c_str()); |
303 | 852 | propList.insert("draw:fill-image", m_dataList[i].getBase64Data()); |
304 | 852 | return true; |
305 | 852 | } |
306 | 0 | return false; |
307 | 852 | } |
308 | | |
309 | | bool STOFFEmbeddedObject::addTo(librevenge::RVNGPropertyList &propList) const |
310 | 37.8k | { |
311 | 37.8k | bool firstSet=false; |
312 | 37.8k | librevenge::RVNGPropertyListVector auxiliarVector; |
313 | 75.7k | for (size_t i=0; i<m_dataList.size(); ++i) { |
314 | 37.8k | if (m_dataList[i].empty()) continue; |
315 | 37.8k | std::string type=m_typeList.size() ? m_typeList[i] : "image/pict"; |
316 | 37.8k | if (!firstSet) { |
317 | 37.8k | propList.insert("librevenge:mime-type", type.c_str()); |
318 | 37.8k | propList.insert("office:binary-data", m_dataList[i]); |
319 | 37.8k | firstSet=true; |
320 | 37.8k | continue; |
321 | 37.8k | } |
322 | 0 | librevenge::RVNGPropertyList auxiList; |
323 | 0 | auxiList.insert("librevenge:mime-type", type.c_str()); |
324 | 0 | auxiList.insert("office:binary-data", m_dataList[i]); |
325 | 0 | auxiliarVector.append(auxiList); |
326 | 0 | } |
327 | 37.8k | if (!m_filenameLink.empty()) { |
328 | 6 | if (!firstSet) { |
329 | 6 | propList.insert("librevenge:xlink", m_filenameLink); |
330 | 6 | firstSet=true; |
331 | 6 | } |
332 | 0 | else { |
333 | 0 | librevenge::RVNGPropertyList auxiList; |
334 | 0 | auxiList.insert("librevenge:xlink", m_filenameLink); |
335 | 0 | auxiliarVector.append(auxiList); |
336 | 0 | } |
337 | 6 | } |
338 | 37.8k | if (!auxiliarVector.empty()) |
339 | 0 | propList.insert("librevenge:replacement-objects", auxiliarVector); |
340 | 37.8k | if (!firstSet) { |
341 | 0 | STOFF_DEBUG_MSG(("STOFFEmbeddedObject::addTo: called without picture\n")); |
342 | 0 | return false; |
343 | 0 | } |
344 | 37.8k | return true; |
345 | 37.8k | } |
346 | | |
347 | | int STOFFEmbeddedObject::cmp(STOFFEmbeddedObject const &pict) const |
348 | 0 | { |
349 | 0 | if (m_typeList.size()!=pict.m_typeList.size()) |
350 | 0 | return m_typeList.size()<pict.m_typeList.size() ? -1 : 1; |
351 | 0 | for (size_t i=0; i<m_typeList.size(); ++i) { |
352 | 0 | if (m_typeList[i]<pict.m_typeList[i]) return -1; |
353 | 0 | if (m_typeList[i]>pict.m_typeList[i]) return 1; |
354 | 0 | } |
355 | 0 | if (m_dataList.size()!=pict.m_dataList.size()) |
356 | 0 | return m_dataList.size()<pict.m_dataList.size() ? -1 : 1; |
357 | 0 | for (size_t i=0; i<m_dataList.size(); ++i) { |
358 | 0 | if (m_dataList[i].size() < pict.m_dataList[i].size()) return 1; |
359 | 0 | if (m_dataList[i].size() > pict.m_dataList[i].size()) return -1; |
360 | | |
361 | 0 | auto const *ptr=m_dataList[i].getDataBuffer(); |
362 | 0 | auto const *aPtr=pict.m_dataList[i].getDataBuffer(); |
363 | 0 | if (!ptr || !aPtr) continue; // must only appear if the two buffers are empty |
364 | 0 | for (unsigned long h=0; h < m_dataList[i].size(); ++h, ++ptr, ++aPtr) { |
365 | 0 | if (*ptr < *aPtr) return 1; |
366 | 0 | if (*ptr > *aPtr) return -1; |
367 | 0 | } |
368 | 0 | } |
369 | 0 | return 0; |
370 | 0 | } |
371 | | |
372 | | std::ostream &operator<<(std::ostream &o, STOFFEmbeddedObject const &pict) |
373 | 0 | { |
374 | 0 | if (pict.isEmpty()) return o; |
375 | 0 | o << "["; |
376 | 0 | for (auto const &t : pict.m_typeList) { |
377 | 0 | if (t.empty()) |
378 | 0 | o << "_,"; |
379 | 0 | else |
380 | 0 | o << t << ","; |
381 | 0 | } |
382 | 0 | o << "],"; |
383 | 0 | return o; |
384 | 0 | } |
385 | | |
386 | | namespace libstoff |
387 | | { |
388 | | // some date conversion |
389 | | bool convertToDateTime(uint32_t date, uint32_t time, std::string &dateTime) |
390 | 51.8k | { |
391 | 51.8k | std::stringstream s; |
392 | 51.8k | s << std::setfill('0') << std::setw(8) << date; |
393 | 51.8k | dateTime=s.str(); |
394 | 51.8k | if (dateTime.length()!=8) { |
395 | 3.11k | STOFF_DEBUG_MSG(("libstoff:convertToDateTime: can not convert the date")); |
396 | 3.11k | return false; |
397 | 3.11k | } |
398 | 48.7k | s.str(""); |
399 | 48.7k | s << std::setfill('0') << std::setw(8) << time; |
400 | 48.7k | if (s.str().length()!=8) { |
401 | 5.71k | STOFF_DEBUG_MSG(("libstoff:convertToDateTime: can not convert the time")); |
402 | 5.71k | return false; |
403 | 5.71k | } |
404 | 43.0k | dateTime+=s.str(); |
405 | 43.0k | dateTime.insert(14,1,'.'); |
406 | 43.0k | dateTime.insert(12,1,':'); |
407 | 43.0k | dateTime.insert(10,1,':'); |
408 | 43.0k | dateTime.insert(8,1,'T'); |
409 | 43.0k | dateTime.insert(6,1,'-'); |
410 | 43.0k | dateTime.insert(4,1,'-'); |
411 | 43.0k | return true; |
412 | 48.7k | } |
413 | | |
414 | | void splitString(librevenge::RVNGString const &string, librevenge::RVNGString const &delim, |
415 | | librevenge::RVNGString &string1, librevenge::RVNGString &string2) |
416 | 710 | { |
417 | 710 | std::string fString(string.cstr()); |
418 | 710 | std::string fDelim(delim.cstr()); |
419 | 710 | size_t pos=fString.find(fDelim); |
420 | 710 | if (pos!=std::string::npos) { |
421 | 17 | if (pos+fDelim.length()<fString.length()) |
422 | 17 | string2=librevenge::RVNGString(fString.substr(pos+fDelim.length()).c_str()); |
423 | 17 | if (pos>0) |
424 | 17 | string1=librevenge::RVNGString(fString.substr(0,pos).c_str()); |
425 | 17 | } |
426 | 693 | else |
427 | 693 | string1=string; |
428 | 710 | } |
429 | | |
430 | | librevenge::RVNGString simplifyString(librevenge::RVNGString const &s) |
431 | 109k | { |
432 | 109k | librevenge::RVNGString res(""); |
433 | 109k | char const *ptr=s.cstr(); |
434 | 109k | if (!ptr) return res; |
435 | 109k | int numBad=0; |
436 | 1.34M | while (*ptr) { |
437 | 1.23M | char c=*(ptr++); |
438 | 1.23M | if (unsigned(c)<0x80) { |
439 | 1.01M | if (numBad) { |
440 | 32.1k | numBad=0; |
441 | 32.1k | res.append('@'); |
442 | 32.1k | } |
443 | 1.01M | res.append(c); |
444 | 1.01M | continue; |
445 | 1.01M | } |
446 | 219k | if (numBad++>=4) { |
447 | 27.2k | res.append('@'); |
448 | 27.2k | numBad=0; |
449 | 27.2k | } |
450 | 219k | } |
451 | 109k | if (numBad) res.append('@'); |
452 | 109k | return res; |
453 | 109k | } |
454 | | |
455 | | std::string getCellName(STOFFVec2i const &cellPos, STOFFVec2b const &relative) |
456 | 0 | { |
457 | 0 | if (cellPos[0]<0 || cellPos[0]>=26*26*26 || cellPos[1]<0) { |
458 | 0 | STOFF_DEBUG_MSG(("libwps::getCellName: invalid cell position\n")); |
459 | 0 | return ""; |
460 | 0 | } |
461 | 0 | std::stringstream o; |
462 | 0 | if (!relative[0]) o << "$"; |
463 | 0 | if (cellPos[0]>=26*26) o << (char)(cellPos[0]/26/26-1 + 'A'); |
464 | 0 | if (cellPos[0]>=26) o << (char)((cellPos[0]%(26*26))/26-1 + 'A'); |
465 | 0 | o << (char)(cellPos[0]%26+'A'); |
466 | 0 | if (!relative[1]) o << "$"; |
467 | 0 | o << cellPos[1]+1; |
468 | 0 | return o.str(); |
469 | 0 | } |
470 | | // a little geometry |
471 | | STOFFVec2f rotatePointAroundCenter(STOFFVec2f const &point, STOFFVec2f const ¢er, float angle) |
472 | 0 | { |
473 | 0 | float angl=float(M_PI/180.)*angle; |
474 | 0 | STOFFVec2f pt = point-center; |
475 | 0 | return center + STOFFVec2f(std::cos(angl)*pt[0]-std::sin(angl)*pt[1], |
476 | 0 | std::sin(angl)*pt[0]+std::cos(angl)*pt[1]); |
477 | 0 | } |
478 | | |
479 | | STOFFBox2f rotateBoxFromCenter(STOFFBox2f const &box, float angle) |
480 | 0 | { |
481 | 0 | STOFFVec2f center=box.center(); |
482 | 0 | STOFFVec2f minPt, maxPt; |
483 | 0 | for (int p=0; p<4; ++p) { |
484 | 0 | STOFFVec2f pt=rotatePointAroundCenter(STOFFVec2f(box[p<2?0:1][0],box[(p%2)?0:1][1]), center, angle); |
485 | 0 | if (p==0) { |
486 | 0 | minPt=maxPt=pt; |
487 | 0 | continue; |
488 | 0 | } |
489 | 0 | for (int c=0; c<2; ++c) { |
490 | 0 | if (pt[c]<minPt[c]) |
491 | 0 | minPt[c]=pt[c]; |
492 | 0 | else if (pt[c]>maxPt[c]) |
493 | 0 | maxPt[c]=pt[c]; |
494 | 0 | } |
495 | 0 | } |
496 | 0 | return STOFFBox2f(minPt,maxPt); |
497 | 0 | } |
498 | | |
499 | | float getScaleFactor(librevenge::RVNGUnit orig, librevenge::RVNGUnit dest) |
500 | 0 | { |
501 | 0 | float actSc = 1.0, newSc = 1.0; |
502 | 0 | switch (orig) { |
503 | 0 | case librevenge::RVNG_TWIP: |
504 | 0 | break; |
505 | 0 | case librevenge::RVNG_POINT: |
506 | 0 | actSc=20; |
507 | 0 | break; |
508 | 0 | case librevenge::RVNG_INCH: |
509 | 0 | actSc = 1440; |
510 | 0 | break; |
511 | 0 | case librevenge::RVNG_PERCENT: |
512 | 0 | case librevenge::RVNG_GENERIC: |
513 | 0 | case librevenge::RVNG_UNIT_ERROR: |
514 | 0 | default: |
515 | 0 | STOFF_DEBUG_MSG(("libstoff::getScaleFactor %d unit must not appear\n", int(orig))); |
516 | 0 | } |
517 | 0 | switch (dest) { |
518 | 0 | case librevenge::RVNG_TWIP: |
519 | 0 | break; |
520 | 0 | case librevenge::RVNG_POINT: |
521 | 0 | newSc=20; |
522 | 0 | break; |
523 | 0 | case librevenge::RVNG_INCH: |
524 | 0 | newSc = 1440; |
525 | 0 | break; |
526 | 0 | case librevenge::RVNG_PERCENT: |
527 | 0 | case librevenge::RVNG_GENERIC: |
528 | 0 | case librevenge::RVNG_UNIT_ERROR: |
529 | 0 | default: |
530 | 0 | STOFF_DEBUG_MSG(("libstoff::getScaleFactor %d unit must not appear\n", int(dest))); |
531 | 0 | } |
532 | 0 | return actSc/newSc; |
533 | 0 | } |
534 | | |
535 | | // debug message |
536 | | #ifdef DEBUG |
537 | | void printDebugMsg(const char *format, ...) |
538 | | { |
539 | | va_list args; |
540 | | va_start(args, format); |
541 | | std::vfprintf(stderr, format, args); |
542 | | va_end(args); |
543 | | } |
544 | | #endif |
545 | | } |
546 | | |
547 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |