Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libmspub
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2012 Brennan Vincent <brennanv@email.arizona.edu>
17 : * Copyright (C) 2011 Fridrich Strba <fridrich.strba@bluewin.ch>
18 : * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
19 : *
20 : *
21 : * All Rights Reserved.
22 : *
23 : * For minor contributions see the git repository.
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
27 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
28 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
29 : * instead of those above.
30 : */
31 :
32 : #include <string.h> // for memcpy
33 : #include <math.h>
34 : #include <zlib.h>
35 : #include "libmspub_utils.h"
36 :
37 : #ifndef M_PI
38 : #define M_PI 3.14159265358979323846
39 : #endif
40 :
41 : #define ZLIB_CHUNK 16384
42 :
43 0 : const char *libmspub::mimeByImgType(ImgType type)
44 : {
45 0 : switch (type)
46 : {
47 : case PNG:
48 0 : return "image/png";
49 : case JPEG:
50 0 : return "image/jpeg";
51 : case DIB:
52 0 : return "image/bmp";
53 : case PICT:
54 0 : return "image/pict";
55 : case WMF:
56 0 : return "image/wmf";
57 : case EMF:
58 0 : return "image/emf";
59 : case TIFF:
60 0 : return "image/tiff";
61 : default:
62 : MSPUB_DEBUG_MSG(("Unknown image type %d passed to mimeByImgType!\n", type));
63 0 : return 0;
64 : }
65 : }
66 :
67 0 : void libmspub::rotateCounter(double &x, double &y, double centerX, double centerY, short rotation)
68 : {
69 0 : double vecX = x - centerX;
70 0 : double vecY = centerY - y;
71 0 : double sinTheta = sin(rotation * M_PI / 180.);
72 0 : double cosTheta = cos(rotation * M_PI / 180.);
73 0 : double newVecX = cosTheta * vecX - sinTheta * vecY;
74 0 : double newVecY = sinTheta * vecX + cosTheta * vecY;
75 0 : x = centerX + newVecX;
76 0 : y = centerY - newVecY;
77 0 : }
78 :
79 0 : double libmspub::doubleModulo(double x, double y)
80 : {
81 0 : if (y <= 0) // y <= 0 doesn't make sense
82 : {
83 0 : return x;
84 : }
85 0 : while (x < 0)
86 : {
87 0 : x += y;
88 : }
89 0 : while (x >= y)
90 : {
91 0 : x -= y;
92 : }
93 0 : return x;
94 : }
95 :
96 0 : double libmspub::toFixedPoint(int fp)
97 : {
98 0 : unsigned short fractionalPart = ((unsigned short) fp) & 0xFFFF;
99 0 : short integralPart = fp >> 16;
100 0 : return integralPart + fractionalPart / 65536.;
101 : }
102 :
103 0 : double libmspub::readFixedPoint(WPXInputStream *input)
104 : {
105 0 : return toFixedPoint(readS32(input));
106 : }
107 :
108 0 : void libmspub::flipIfNecessary(double &x, double &y, double centerX, double centerY, bool flipVertical, bool flipHorizontal)
109 : {
110 0 : double vecX = x - centerX;
111 0 : double vecY = centerY - y;
112 0 : if (flipVertical)
113 : {
114 0 : y = centerY + vecY;
115 : }
116 0 : if (flipHorizontal)
117 : {
118 0 : x = centerX - vecX;
119 : }
120 0 : }
121 :
122 0 : unsigned libmspub::correctModulo(int x, unsigned n) // returns the canonical representation of x in Z/nZ
123 : //difference with C++ % operator is that this never returns negative values.
124 : {
125 0 : if (x < 0)
126 : {
127 0 : int result = x % (int)n;
128 : //sign of result is implementation defined
129 0 : if (result < 0)
130 : {
131 0 : return n + result;
132 : }
133 0 : return result;
134 : }
135 0 : return x % n;
136 : }
137 :
138 0 : WPXBinaryData libmspub::inflateData(WPXBinaryData deflated)
139 : {
140 0 : WPXBinaryData inflated;
141 : unsigned char out[ZLIB_CHUNK];
142 0 : const unsigned char *data = deflated.getDataBuffer();
143 : z_stream strm;
144 : int ret;
145 0 : strm.zalloc = Z_NULL;
146 0 : strm.zfree = Z_NULL;
147 0 : strm.opaque = Z_NULL;
148 0 : strm.avail_in = 0;
149 0 : strm.next_in = Z_NULL;
150 0 : if (inflateInit2(&strm,-MAX_WBITS) != Z_OK)
151 : {
152 0 : return WPXBinaryData();
153 : }
154 : int have;
155 0 : unsigned left = deflated.size();
156 0 : do
157 : {
158 0 : strm.avail_in = ZLIB_CHUNK > left ? left : ZLIB_CHUNK;
159 0 : strm.next_in = (unsigned char *)data;
160 0 : do
161 : {
162 0 : strm.avail_out = ZLIB_CHUNK;
163 0 : strm.next_out = out;
164 0 : ret = inflate(&strm, Z_NO_FLUSH);
165 0 : if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
166 : {
167 0 : inflateEnd(&strm);
168 0 : return WPXBinaryData();
169 : }
170 0 : have = ZLIB_CHUNK - strm.avail_out;
171 0 : inflated.append(out, have);
172 : }
173 : while (strm.avail_out == 0);
174 0 : data += ZLIB_CHUNK > left ? left : ZLIB_CHUNK;
175 0 : left -= ZLIB_CHUNK > left ? left : ZLIB_CHUNK;
176 : }
177 : while (ret != Z_STREAM_END);
178 0 : inflateEnd(&strm);
179 0 : return inflated;
180 : }
181 :
182 : namespace
183 : {
184 :
185 0 : static uint32_t _win1252ToUCS4(unsigned char win1252Character)
186 : {
187 0 : switch (win1252Character)
188 : {
189 : case 0x80:
190 0 : return 0x20AC;
191 : case 0x82:
192 0 : return 0x201A;
193 : case 0x83:
194 0 : return 0x0192;
195 : case 0x84:
196 0 : return 0x201E;
197 : case 0x85:
198 0 : return 0x2026;
199 : case 0x86:
200 0 : return 0x2020;
201 : case 0x87:
202 0 : return 0x2021;
203 : case 0x88:
204 0 : return 0x02C6;
205 : case 0x89:
206 0 : return 0x2030;
207 : case 0x8A:
208 0 : return 0x0160;
209 : case 0x8B:
210 0 : return 0x2039;
211 : case 0x8C:
212 0 : return 0x0152;
213 : case 0x8E:
214 0 : return 0x017D;
215 : case 0x91:
216 0 : return 0x2018;
217 : case 0x92:
218 0 : return 0x2019;
219 : case 0x93:
220 0 : return 0x201C;
221 : case 0x94:
222 0 : return 0x201D;
223 : case 0x95:
224 0 : return 0x2022;
225 : case 0x96:
226 0 : return 0x2013;
227 : case 0x97:
228 0 : return 0x2014;
229 : case 0x98:
230 0 : return 0x02DC;
231 : case 0x99:
232 0 : return 0x2122;
233 : case 0x9A:
234 0 : return 0x0161;
235 : case 0x9B:
236 0 : return 0x203A;
237 : case 0x9C:
238 0 : return 0x0153;
239 : case 0x9E:
240 0 : return 0x017E;
241 : case 0x9F:
242 0 : return 0x0178;
243 : default:
244 0 : return win1252Character;
245 : }
246 : }
247 :
248 0 : static void _appendUCS4(WPXString &text, unsigned ucs4Character)
249 : {
250 : unsigned char first;
251 : int len;
252 0 : if (ucs4Character < 0x80)
253 : {
254 0 : first = 0;
255 0 : len = 1;
256 : }
257 0 : else if (ucs4Character < 0x800)
258 : {
259 0 : first = 0xc0;
260 0 : len = 2;
261 : }
262 0 : else if (ucs4Character < 0x10000)
263 : {
264 0 : first = 0xe0;
265 0 : len = 3;
266 : }
267 0 : else if (ucs4Character < 0x200000)
268 : {
269 0 : first = 0xf0;
270 0 : len = 4;
271 : }
272 0 : else if (ucs4Character < 0x4000000)
273 : {
274 0 : first = 0xf8;
275 0 : len = 5;
276 : }
277 : else
278 : {
279 0 : first = 0xfc;
280 0 : len = 6;
281 : }
282 :
283 0 : unsigned char outbuf[6] = { 0, 0, 0, 0, 0, 0 };
284 : int i;
285 0 : for (i = len - 1; i > 0; --i)
286 : {
287 0 : outbuf[i] = (ucs4Character & 0x3f) | 0x80;
288 0 : ucs4Character >>= 6;
289 : }
290 0 : outbuf[0] = (ucs4Character & 0xff) | first;
291 :
292 0 : for (i = 0; i < len; i++)
293 0 : text.append(outbuf[i]);
294 0 : }
295 :
296 : } // anonymous namespace
297 :
298 : #define MSPUB_NUM_ELEMENTS(array) sizeof(array)/sizeof(array[0])
299 :
300 0 : uint8_t libmspub::readU8(WPXInputStream *input)
301 : {
302 0 : if (!input || input->atEOS())
303 : {
304 : MSPUB_DEBUG_MSG(("Something bad happened here!Tell: %ld\n", input->tell()));
305 0 : throw EndOfStreamException();
306 : }
307 : unsigned long numBytesRead;
308 0 : uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead);
309 :
310 0 : if (p && numBytesRead == sizeof(uint8_t))
311 0 : return *(uint8_t const *)(p);
312 0 : throw EndOfStreamException();
313 : }
314 :
315 0 : uint16_t libmspub::readU16(const unsigned char *input, unsigned offset)
316 : {
317 0 : uint16_t p0 = (uint16_t)(*(input + offset));
318 0 : uint16_t p1 = (uint16_t)(*(input + offset + 1));
319 0 : return (uint16_t)(p0|(p1<<8));
320 : }
321 :
322 0 : uint32_t libmspub::readU32(const unsigned char *input, unsigned offset)
323 : {
324 0 : uint32_t p0 = (uint32_t)(*(input + offset));
325 0 : uint32_t p1 = (uint32_t)(*(input + offset + 1));
326 0 : uint32_t p2 = (uint32_t)(*(input + offset + 2));
327 0 : uint32_t p3 = (uint32_t)(*(input + offset + 3));
328 0 : return (uint32_t)(p0|(p1<<8)|(p2<<16)|(p3<<24));
329 : }
330 :
331 0 : uint16_t libmspub::readU16(WPXInputStream *input)
332 : {
333 0 : uint16_t p0 = (uint16_t)readU8(input);
334 0 : uint16_t p1 = (uint16_t)readU8(input);
335 0 : return (uint16_t)(p0|(p1<<8));
336 : }
337 :
338 0 : uint32_t libmspub::readU32(WPXInputStream *input)
339 : {
340 0 : uint32_t p0 = (uint32_t)readU8(input);
341 0 : uint32_t p1 = (uint32_t)readU8(input);
342 0 : uint32_t p2 = (uint32_t)readU8(input);
343 0 : uint32_t p3 = (uint32_t)readU8(input);
344 0 : return (uint32_t)(p0|(p1<<8)|(p2<<16)|(p3<<24));
345 : }
346 :
347 0 : int8_t libmspub::readS8(WPXInputStream *input)
348 : {
349 0 : return (int8_t)readU8(input);
350 : }
351 :
352 0 : int16_t libmspub::readS16(WPXInputStream *input)
353 : {
354 0 : return (int16_t)readU16(input);
355 : }
356 :
357 0 : int32_t libmspub::readS32(WPXInputStream *input)
358 : {
359 0 : return (int32_t)readU32(input);
360 : }
361 :
362 0 : uint64_t libmspub::readU64(WPXInputStream *input)
363 : {
364 0 : uint64_t p0 = (uint64_t)readU8(input);
365 0 : uint64_t p1 = (uint64_t)readU8(input);
366 0 : uint64_t p2 = (uint64_t)readU8(input);
367 0 : uint64_t p3 = (uint64_t)readU8(input);
368 0 : uint64_t p4 = (uint64_t)readU8(input);
369 0 : uint64_t p5 = (uint64_t)readU8(input);
370 0 : uint64_t p6 = (uint64_t)readU8(input);
371 0 : uint64_t p7 = (uint64_t)readU8(input);
372 0 : return (uint64_t)(p0|(p1<<8)|(p2<<16)|(p3<<24)|(p4<<32)|(p5<<40)|(p6<<48)|(p7<<56));
373 : }
374 :
375 0 : void libmspub::readNBytes(WPXInputStream *input, unsigned long length, std::vector<unsigned char> &out)
376 : {
377 0 : unsigned long numBytesRead = 0;
378 0 : const unsigned char *tmpBuffer = input->read(length, numBytesRead);
379 0 : if (numBytesRead != length)
380 : {
381 0 : out.clear();
382 : return;
383 : }
384 0 : out = std::vector<unsigned char>(numBytesRead);
385 0 : memcpy(&out[0], tmpBuffer, numBytesRead);
386 : return;
387 : }
388 :
389 : #define SURROGATE_VALUE(h,l) (((h) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000)
390 :
391 0 : void libmspub::appendCharacters(WPXString &text, const std::vector<unsigned char> characters,
392 : Encoding encoding)
393 : {
394 0 : switch (encoding)
395 : {
396 : case UTF_16:
397 0 : for (std::vector<unsigned char>::const_iterator iter = characters.begin();
398 0 : iter != characters.end();)
399 : {
400 0 : uint16_t high_surrogate = 0;
401 0 : bool fail = false;
402 0 : uint32_t ucs4Character = 0;
403 0 : while (true)
404 : {
405 0 : if (iter == characters.end())
406 : {
407 0 : fail = true;
408 0 : break;
409 : }
410 0 : uint16_t character = *iter++;
411 0 : character |= (uint16_t)(*iter++) << 8;
412 0 : if (character >= 0xdc00 && character < 0xe000) /* low surrogate */
413 : {
414 0 : if (high_surrogate)
415 : {
416 0 : ucs4Character = SURROGATE_VALUE(high_surrogate, character);
417 0 : high_surrogate = 0;
418 0 : break;
419 : }
420 : else
421 : {
422 0 : fail = true;
423 0 : break;
424 : }
425 : }
426 : else
427 : {
428 0 : if (high_surrogate)
429 : {
430 0 : fail = true;
431 0 : break;
432 : }
433 0 : if (character >= 0xd800 && character < 0xdc00) /* high surrogate */
434 0 : high_surrogate = character;
435 : else
436 : {
437 0 : ucs4Character = character;
438 0 : break;
439 : }
440 : }
441 : }
442 0 : if (fail)
443 0 : throw libmspub::GenericException();
444 :
445 0 : _appendUCS4(text, ucs4Character);
446 : }
447 0 : break;
448 : case WIN_1252:
449 0 : for (std::vector<unsigned char>::const_iterator iter = characters.begin();
450 0 : iter != characters.end(); ++iter)
451 : {
452 0 : uint32_t ucs4 = _win1252ToUCS4(*iter);
453 0 : _appendUCS4(text, ucs4);
454 : }
455 0 : break;
456 : }
457 0 : }
458 :
459 0 : bool libmspub::stillReading(WPXInputStream *input, unsigned long until)
460 : {
461 0 : if (input->atEOS())
462 0 : return false;
463 0 : if (input->tell() < 0)
464 0 : return false;
465 0 : if ((unsigned long)input->tell() >= until)
466 0 : return false;
467 0 : return true;
468 : }
469 :
470 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|