1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2 
3 /* libmwaw
4 * Version: MPL 2.0 / LGPLv2+
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 2.0 (the "License"); you may not use this file except in compliance with
8 * the License or as specified alternatively below. You may obtain a copy of
9 * the License at http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Major Contributor(s):
17 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20 * Copyright (C) 2006, 2007 Andrew Ziem
21 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22 *
23 *
24 * All Rights Reserved.
25 *
26 * For minor contributions see the git repository.
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30 * in which case the provisions of the LGPLv2+ are applicable
31 * instead of those above.
32 */
33 
34 #ifndef LIBMWAW_INTERNAL_H
35 #define LIBMWAW_INTERNAL_H
36 #ifdef DEBUG
37 #include <stdio.h>
38 #endif
39 
40 #include <math.h>
41 
42 #include <algorithm>
43 #include <cmath>
44 #include <limits>
45 #include <map>
46 #include <memory>
47 #include <ostream>
48 #include <string>
49 #include <vector>
50 
51 #ifndef M_PI
52 #define M_PI 3.14159265358979323846
53 #endif
54 
55 #include <librevenge-stream/librevenge-stream.h>
56 #include <librevenge/librevenge.h>
57 
58 #if defined(_MSC_VER) || defined(__DJGPP__)
59 
60 typedef signed char int8_t;
61 typedef unsigned char uint8_t;
62 typedef signed short int16_t;
63 typedef unsigned short uint16_t;
64 typedef signed int int32_t;
65 typedef unsigned int uint32_t;
66 typedef unsigned __int64 uint64_t;
67 typedef __int64 int64_t;
68 
69 #else /* !_MSC_VER && !__DJGPP__*/
70 
71 #  ifdef HAVE_CONFIG_H
72 
73 #    include <config.h>
74 #    ifdef HAVE_STDINT_H
75 #      include <stdint.h>
76 #    endif
77 #    ifdef HAVE_INTTYPES_H
78 #      include <inttypes.h>
79 #    endif
80 
81 #  else
82 
83 // assume that the headers are there inside LibreOffice build when no HAVE_CONFIG_H is defined
84 #    include <stdint.h>
85 #    include <inttypes.h>
86 
87 #  endif
88 
89 #endif /* _MSC_VER || __DJGPP__ */
90 
91 // define gmtime_r and localtime_r on Windows, so that can use
92 // thread-safe functions on other environments
93 #ifdef _WIN32
94 #  define gmtime_r(tp,tmp) (gmtime(tp)?(*(tmp)=*gmtime(tp),(tmp)):0)
95 #  define localtime_r(tp,tmp) (localtime(tp)?(*(tmp)=*localtime(tp),(tmp)):0)
96 #endif
97 
98 /* ---------- memory  --------------- */
99 /** an noop deleter used to transform a libwpd pointer in a false std::shared_ptr */
100 template <class T>
101 struct MWAW_shared_ptr_noop_deleter {
operator ()MWAW_shared_ptr_noop_deleter102   void operator()(T *) {}
103 };
104 
105 #if defined(HAVE_FUNC_ATTRIBUTE_FORMAT)
106 #  define LIBMWAW_ATTRIBUTE_PRINTF(fmt, arg) __attribute__((format(printf, fmt, arg)))
107 #else
108 #  define LIBMWAW_ATTRIBUTE_PRINTF(fmt, arg)
109 #endif
110 
111 #define MWAW_N_ELEMENTS(m) sizeof(m)/sizeof(m[0])
112 
113 #if defined(HAVE_CLANG_ATTRIBUTE_FALLTHROUGH)
114 #  define MWAW_FALLTHROUGH [[clang::fallthrough]]
115 #elif defined(HAVE_GCC_ATTRIBUTE_FALLTHROUGH)
116 #  define MWAW_FALLTHROUGH __attribute__((fallthrough))
117 #else
118 #  define MWAW_FALLTHROUGH ((void) 0)
119 #endif
120 
121 /* ---------- debug  --------------- */
122 #ifdef DEBUG
123 namespace libmwaw
124 {
125 void printDebugMsg(const char *format, ...) LIBMWAW_ATTRIBUTE_PRINTF(1,2);
126 }
127 #define MWAW_DEBUG_MSG(M) libmwaw::printDebugMsg M
128 #else
129 #define MWAW_DEBUG_MSG(M)
130 #endif
131 
132 namespace libmwaw
133 {
134 // Various exceptions:
135 class VersionException
136 {
137 };
138 
139 class FileException
140 {
141 };
142 
143 class ParseException
144 {
145 };
146 
147 class GenericException
148 {
149 };
150 
151 class WrongPasswordException
152 {
153 };
154 }
155 
156 /* ---------- input ----------------- */
157 namespace libmwaw
158 {
159 uint8_t readU8(librevenge::RVNGInputStream *input);
160 //! adds an unicode character to a string
161 void appendUnicode(uint32_t val, librevenge::RVNGString &buffer);
162 
163 //! checks whether addition of \c x and \c y would overflow
164 template<typename T>
checkAddOverflow(T x,T y)165 bool checkAddOverflow(T x, T y)
166 {
167   return (x < 0 && y < std::numeric_limits<T>::lowest() - x)
168          || (x > 0 && y > std::numeric_limits<T>::max() - x);
169 }
170 }
171 
172 /* ---------- small enum/class ------------- */
173 namespace libmwaw
174 {
175 //! basic position enum
176 enum Position { Left = 0, Right = 1, Top = 2, Bottom = 3, HMiddle = 4, VMiddle = 5 };
177 //! basic position enum bits
178 enum { LeftBit = 0x01,  RightBit = 0x02, TopBit=0x4, BottomBit = 0x08, HMiddleBit = 0x10, VMiddleBit = 0x20 };
179 
180 enum NumberingType { NONE, BULLET, ARABIC, LOWERCASE, UPPERCASE, LOWERCASE_ROMAN, UPPERCASE_ROMAN };
181 std::string numberingTypeToString(NumberingType type);
182 std::string numberingValueToString(NumberingType type, int value);
183 
184 //! the different writing mode
185 enum WritingMode { WritingLeftTop, WritingLeftBottom, WritingRightTop, WritingRightBottom, WritingInherited };
186 //! a function to convert a writing mode in string lt-rb, ...
187 std::string writingModeToString(WritingMode mode);
188 enum SubDocumentType { DOC_NONE, DOC_CHART, DOC_CHART_ZONE, DOC_COMMENT_ANNOTATION, DOC_GRAPHIC_GROUP, DOC_HEADER_FOOTER, DOC_NOTE, DOC_SHEET, DOC_TABLE, DOC_TEXT_BOX };
189 }
190 
191 //! the class to store a color
192 struct MWAWColor {
193   //! constructor
MWAWColorMWAWColor194   explicit MWAWColor(uint32_t argb=0)
195     : m_value(argb)
196   {
197   }
198   //! constructor from color
MWAWColorMWAWColor199   MWAWColor(unsigned char r, unsigned char g,  unsigned char b, unsigned char a=255)
200     : m_value(uint32_t((a<<24)+(r<<16)+(g<<8)+b))
201   {
202   }
203   //! copy constructor
204   MWAWColor(MWAWColor const &) = default;
205   //! move assignement
206   MWAWColor(MWAWColor &&) = default;
207   //! operator=
208   MWAWColor &operator=(MWAWColor const &) = default;
209   //! move operator=
210   MWAWColor &operator=(MWAWColor &&) = default;
211   //! operator=
operator =MWAWColor212   MWAWColor &operator=(uint32_t argb)
213   {
214     m_value = argb;
215     return *this;
216   }
217   //! return a color from a cmyk color ( basic)
colorFromCMYKMWAWColor218   static MWAWColor colorFromCMYK(unsigned char c, unsigned char m,  unsigned char y, unsigned char k)
219   {
220     double w=1.-static_cast<double>(k)/255.;
221     return MWAWColor
222            (static_cast<unsigned char>(255 * (1-static_cast<double>(c)/255) * w),
223             static_cast<unsigned char>(255 * (1-static_cast<double>(m)/255) * w),
224             static_cast<unsigned char>(255 * (1-static_cast<double>(y)/255) * w)
225            );
226   }
227   //! return a color from a hsl color (basic)
colorFromHSLMWAWColor228   static MWAWColor colorFromHSL(unsigned char H, unsigned char S,  unsigned char L)
229   {
230     double c=(1-((L>=128) ? (2*static_cast<double>(L)-255) : (255-2*static_cast<double>(L)))/255)*
231              static_cast<double>(S)/255;
232     double tmp=std::fmod((static_cast<double>(H)*6/255),2)-1;
233     double x=c*(1-(tmp>0 ? tmp : -tmp));
234     auto C=static_cast<unsigned char>(255*c);
235     auto M=static_cast<unsigned char>(static_cast<double>(L)-255*c/2);
236     auto X=static_cast<unsigned char>(255*x);
237     if (H<=42) return MWAWColor(static_cast<unsigned char>(M+C),static_cast<unsigned char>(M+X),static_cast<unsigned char>(M));
238     if (H<=85) return MWAWColor(static_cast<unsigned char>(M+X),static_cast<unsigned char>(M+C),static_cast<unsigned char>(M));
239     if (H<=127) return MWAWColor(static_cast<unsigned char>(M),static_cast<unsigned char>(M+C),static_cast<unsigned char>(M+X));
240     if (H<=170) return MWAWColor(static_cast<unsigned char>(M),static_cast<unsigned char>(M+X),static_cast<unsigned char>(M+C));
241     if (H<=212) return MWAWColor(static_cast<unsigned char>(M+X),static_cast<unsigned char>(M),static_cast<unsigned char>(M+C));
242     return MWAWColor(static_cast<unsigned char>(M+C),static_cast<unsigned char>(M),static_cast<unsigned char>(M+X));
243   }
244   //! return the back color
blackMWAWColor245   static MWAWColor black()
246   {
247     return MWAWColor(0,0,0);
248   }
249   //! return the white color
whiteMWAWColor250   static MWAWColor white()
251   {
252     return MWAWColor(255,255,255);
253   }
254 
255   //! return alpha*colA+beta*colB
256   static MWAWColor barycenter(float alpha, MWAWColor const &colA,
257                               float beta, MWAWColor const &colB);
258   //! return the rgba value
valueMWAWColor259   uint32_t value() const
260   {
261     return m_value;
262   }
263   //! returns the alpha value
getAlphaMWAWColor264   unsigned char getAlpha() const
265   {
266     return static_cast<unsigned char>((m_value>>24)&0xFF);
267   }
268   //! returns the green value
getBlueMWAWColor269   unsigned char getBlue() const
270   {
271     return static_cast<unsigned char>(m_value&0xFF);
272   }
273   //! returns the red value
getRedMWAWColor274   unsigned char getRed() const
275   {
276     return static_cast<unsigned char>((m_value>>16)&0xFF);
277   }
278   //! returns the green value
getGreenMWAWColor279   unsigned char getGreen() const
280   {
281     return static_cast<unsigned char>((m_value>>8)&0xFF);
282   }
283   //! return true if the color is black
isBlackMWAWColor284   bool isBlack() const
285   {
286     return (m_value&0xFFFFFF)==0;
287   }
288   //! return true if the color is white
isWhiteMWAWColor289   bool isWhite() const
290   {
291     return (m_value&0xFFFFFF)==0xFFFFFF;
292   }
293   //! operator==
operator ==MWAWColor294   bool operator==(MWAWColor const &c) const
295   {
296     return (c.m_value&0xFFFFFF)==(m_value&0xFFFFFF);
297   }
298   //! operator!=
operator !=MWAWColor299   bool operator!=(MWAWColor const &c) const
300   {
301     return !operator==(c);
302   }
303   //! operator<
operator <MWAWColor304   bool operator<(MWAWColor const &c) const
305   {
306     return (c.m_value&0xFFFFFF)<(m_value&0xFFFFFF);
307   }
308   //! operator<=
operator <=MWAWColor309   bool operator<=(MWAWColor const &c) const
310   {
311     return (c.m_value&0xFFFFFF)<=(m_value&0xFFFFFF);
312   }
313   //! operator>
operator >MWAWColor314   bool operator>(MWAWColor const &c) const
315   {
316     return !operator<=(c);
317   }
318   //! operator>=
operator >=MWAWColor319   bool operator>=(MWAWColor const &c) const
320   {
321     return !operator<(c);
322   }
323   //! operator<< in the form \#rrggbb
324   friend std::ostream &operator<< (std::ostream &o, MWAWColor const &c);
325   //! print the color in the form \#rrggbb
326   std::string str() const;
327 protected:
328   //! the argb color
329   uint32_t m_value;
330 };
331 
332 //! a border
333 struct MWAWBorder {
334   /** the line style */
335   enum Style { None, Simple, Dot, LargeDot, Dash };
336   /** the line repetition */
337   enum Type { Single, Double, Triple };
338 
339   //! constructor
MWAWBorderMWAWBorder340   MWAWBorder()
341     : m_style(Simple)
342     , m_type(Single)
343     , m_width(1)
344     , m_widthsList()
345     , m_color(MWAWColor::black())
346     , m_extra("") { }
347   MWAWBorder(MWAWBorder const &) = default;
348   MWAWBorder(MWAWBorder &&) = default;
349   MWAWBorder &operator=(MWAWBorder const &) = default;
350   MWAWBorder &operator=(MWAWBorder &&) = default;
351   /** add the border property to proplist (if needed )
352 
353   \note if set which must be equal to "left", "top", ... */
354   bool addTo(librevenge::RVNGPropertyList &propList, std::string which="") const;
355   //! returns true if the border is empty
isEmptyMWAWBorder356   bool isEmpty() const
357   {
358     return m_style==None || m_width <= 0;
359   }
360   //! operator==
operator ==MWAWBorder361   bool operator==(MWAWBorder const &orig) const
362   {
363     return !operator!=(orig);
364   }
365   //! operator!=
operator !=MWAWBorder366   bool operator!=(MWAWBorder const &orig) const
367   {
368     return m_style != orig.m_style || m_type != orig.m_type ||
369            m_width < orig.m_width || m_width > orig.m_width || m_color != orig.m_color ||
370            m_widthsList != orig.m_widthsList;
371   }
372   //! compare two borders
373   int compare(MWAWBorder const &orig) const;
374 
375   //! operator<<
376   friend std::ostream &operator<< (std::ostream &o, MWAWBorder const &border);
377   //! operator<<: prints data in form "none|dot|..."
378   friend std::ostream &operator<< (std::ostream &o, MWAWBorder::Style const &style);
379   //! the border style
380   Style m_style;
381 
382   // multiple borders
383 
384   //! the border repetition
385   Type m_type;
386   //! the border total width in point
387   double m_width;
388   /** the different length used for each line/sep (if defined)
389 
390   \note when defined, the size of this list must be equal to 2*Type-1*/
391   std::vector<double> m_widthsList;
392   //! the border color
393   MWAWColor m_color;
394   //! extra data ( if needed)
395   std::string m_extra;
396 };
397 
398 //! a field
399 struct MWAWField {
400   /** Defines some basic type for field */
401   enum Type { None, PageCount, PageNumber, Date, Time, Title, Database, BookmarkStart, BookmarkEnd };
402 
403   /** basic constructor */
MWAWFieldMWAWField404   explicit MWAWField(Type type)
405     : m_type(type)
406     , m_numberingType(libmwaw::ARABIC)
407     , m_DTFormat("")
408     , m_data("")
409   {
410   }
411   MWAWField(MWAWField &&) = default;
412   MWAWField(MWAWField const &) = default;
413   MWAWField &operator=(MWAWField const &) = default;
414   MWAWField &operator=(MWAWField &&) = default;
415   /** add the link property to proplist (if possible) */
416   bool addTo(librevenge::RVNGPropertyList &propList) const;
417   //! returns a string corresponding to the field (if possible) */
418   librevenge::RVNGString getString() const;
419   //! the type
420   Type m_type;
421   //! the number type ( for number field )
422   libmwaw::NumberingType m_numberingType;
423   //! the date/time format using strftime format if defined
424   std::string m_DTFormat;
425   //! the database/link field ( if defined ) or the bookmark name
426   std::string m_data;
427 };
428 
429 //! a link
430 struct MWAWLink {
431   /** basic constructor */
MWAWLinkMWAWLink432   MWAWLink()
433     : m_HRef("")
434   {
435   }
436 
437   /** add the link property to proplist (if needed ) */
438   bool addTo(librevenge::RVNGPropertyList &propList) const;
439 
440   //! the href field
441   std::string m_HRef;
442 };
443 
444 //! a note
445 struct MWAWNote {
446   //! enum to define note type
447   enum Type { FootNote, EndNote };
448   //! constructor
MWAWNoteMWAWNote449   explicit MWAWNote(Type type)
450     : m_type(type)
451     , m_label("")
452     , m_number(-1)
453   {
454   }
455   //! the note type
456   Type m_type;
457   //! the note label
458   librevenge::RVNGString m_label;
459   //! the note number if defined
460   int m_number;
461 };
462 
463 /** small class use to define a embedded object
464 
465     \note mainly used to store picture
466  */
467 struct MWAWEmbeddedObject {
468   //! empty constructor
MWAWEmbeddedObjectMWAWEmbeddedObject469   MWAWEmbeddedObject()
470     : m_dataList()
471     , m_typeList()
472   {
473   }
474   //! constructor
MWAWEmbeddedObjectMWAWEmbeddedObject475   MWAWEmbeddedObject(librevenge::RVNGBinaryData const &binaryData,
476                      std::string const &type="image/pict") : m_dataList(), m_typeList()
477   {
478     add(binaryData, type);
479   }
480   MWAWEmbeddedObject(MWAWEmbeddedObject const &)=default;
481   MWAWEmbeddedObject &operator=(MWAWEmbeddedObject const &)=default;
482   MWAWEmbeddedObject &operator=(MWAWEmbeddedObject &&)=default;
483   //! destructor
484   ~MWAWEmbeddedObject();
485   //! return true if the picture contains no data
isEmptyMWAWEmbeddedObject486   bool isEmpty() const
487   {
488     for (auto const &data : m_dataList) {
489       if (!data.empty())
490         return false;
491     }
492     return true;
493   }
494   //! add a picture
addMWAWEmbeddedObject495   void add(librevenge::RVNGBinaryData const &binaryData, std::string const &type="image/pict")
496   {
497     size_t pos=m_dataList.size();
498     if (pos<m_typeList.size()) pos=m_typeList.size();
499     m_dataList.resize(pos+1);
500     m_dataList[pos]=binaryData;
501     m_typeList.resize(pos+1);
502     m_typeList[pos]=type;
503   }
504   /** add the link property to proplist */
505   bool addTo(librevenge::RVNGPropertyList &propList) const;
506   /** operator<<*/
507   friend std::ostream &operator<<(std::ostream &o, MWAWEmbeddedObject const &pict);
508   /** a comparison function */
509   int cmp(MWAWEmbeddedObject const &pict) const;
510 
511   //! the picture content: one data by representation
512   std::vector<librevenge::RVNGBinaryData> m_dataList;
513   //! the picture type: one type by representation
514   std::vector<std::string> m_typeList;
515 };
516 
517 // forward declarations of basic classes and smart pointers
518 struct MWAWStream;
519 class MWAWEntry;
520 class MWAWFont;
521 class MWAWGraphicEncoder;
522 class MWAWGraphicShape;
523 class MWAWGraphicStyle;
524 class MWAWHeader;
525 class MWAWList;
526 class MWAWPageSpan;
527 class MWAWParagraph;
528 class MWAWParser;
529 class MWAWPosition;
530 class MWAWSection;
531 
532 class MWAWFontConverter;
533 class MWAWFontManager;
534 class MWAWGraphicListener;
535 class MWAWInputStream;
536 class MWAWListener;
537 class MWAWListManager;
538 class MWAWParserState;
539 class MWAWPresentationListener;
540 class MWAWRSRCParser;
541 class MWAWSpreadsheetListener;
542 class MWAWSubDocument;
543 class MWAWTextListener;
544 //! a smart pointer of MWAWFontConverter
545 typedef std::shared_ptr<MWAWFontConverter> MWAWFontConverterPtr;
546 //! a smart pointer of MWAWFontManager
547 typedef std::shared_ptr<MWAWFontManager> MWAWFontManagerPtr;
548 //! a smart pointer of MWAWGraphicListener
549 typedef std::shared_ptr<MWAWGraphicListener> MWAWGraphicListenerPtr;
550 //! a smart pointer of MWAWInputStream
551 typedef std::shared_ptr<MWAWInputStream> MWAWInputStreamPtr;
552 //! a smart pointer of MWAWListener
553 typedef std::shared_ptr<MWAWListener> MWAWListenerPtr;
554 //! a smart pointer of MWAWListManager
555 typedef std::shared_ptr<MWAWListManager> MWAWListManagerPtr;
556 //! a smart pointer of MWAWParserState
557 typedef std::shared_ptr<MWAWParserState> MWAWParserStatePtr;
558 //! a smart pointer of MWAWPresentationListener
559 typedef std::shared_ptr<MWAWPresentationListener> MWAWPresentationListenerPtr;
560 //! a smart pointer of MWAWRSRCParser
561 typedef std::shared_ptr<MWAWRSRCParser> MWAWRSRCParserPtr;
562 //! a smart pointer of MWAWSpreadsheetListener
563 typedef std::shared_ptr<MWAWSpreadsheetListener> MWAWSpreadsheetListenerPtr;
564 //! a smart pointer of MWAWSubDocument
565 typedef std::shared_ptr<MWAWSubDocument> MWAWSubDocumentPtr;
566 //! a smart pointer of MWAWTextListener
567 typedef std::shared_ptr<MWAWTextListener> MWAWTextListenerPtr;
568 
569 /** a generic variable template: value + flag to know if the variable is set
570 
571 \note the variable is considered set as soon a new value is set or
572 when its content is acceded by a function which returns a not-const
573 reference... You can use the function setSet to unset it.
574 
575 \note must be replaced by std::optional when we will be comptable with std::c++-17
576 */
577 template <class T> struct MWAWVariable {
578   //! constructor
MWAWVariableMWAWVariable579   MWAWVariable()
580     : m_data()
581     , m_set(false) {}
582   //! constructor with a default value
MWAWVariableMWAWVariable583   explicit MWAWVariable(T const &def)
584     : m_data(def)
585     , m_set(false) {}
586   //! copy constructor
MWAWVariableMWAWVariable587   MWAWVariable(MWAWVariable const &orig)
588     : m_data(orig.m_data)
589     , m_set(orig.m_set) {}
590   //! copy operator
591   MWAWVariable &operator=(MWAWVariable const &) = default;
592   //! set a value
operator =MWAWVariable593   MWAWVariable &operator=(T const &val)
594   {
595     m_data = val;
596     m_set = true;
597     return std::forward<MWAWVariable &>(*this);
598   }
599   //! update the current value if orig is set
insertMWAWVariable600   void insert(MWAWVariable const &orig)
601   {
602     if (orig.m_set) {
603       m_data = orig.m_data;
604       m_set = orig.m_set;
605     }
606   }
607   //! operator*
operator ->MWAWVariable608   T const *operator->() const
609   {
610     return &m_data;
611   }
612   /** operator* */
operator ->MWAWVariable613   T *operator->()
614   {
615     m_set = true;
616     return &m_data;
617   }
618   //! operator*
operator *MWAWVariable619   T const &operator*() const
620   {
621     return m_data;
622   }
623   //! operator*
operator *MWAWVariable624   T &operator*()
625   {
626     m_set = true;
627     return m_data;
628   }
629   //! return the current value
getMWAWVariable630   T const &get() const
631   {
632     return m_data;
633   }
634   //! return true if the variable is set
isSetMWAWVariable635   bool isSet() const
636   {
637     return m_set;
638   }
639   //! define if the variable is set
setSetMWAWVariable640   void setSet(bool newVal)
641   {
642     m_set=newVal;
643   }
644 protected:
645   //! the value
646   T m_data;
647   //! a flag to know if the variable is set or not
648   bool m_set;
649 };
650 
651 /* ---------- vec2/box2f ------------- */
652 /*! \class MWAWVec2
653  *   \brief small class which defines a vector with 2 elements
654  */
655 template <class T> class MWAWVec2
656 {
657 public:
658   //! constructor
MWAWVec2(T xx=0,T yy=0)659   explicit MWAWVec2(T xx=0,T yy=0)
660     : m_x(xx)
661     , m_y(yy) { }
662   //! generic copy constructor
MWAWVec2(MWAWVec2<U> const & p)663   template <class U> explicit MWAWVec2(MWAWVec2<U> const &p)
664     : m_x(T(p.x()))
665     , m_y(T(p.y())) {}
666 
667   //! first element
x() const668   T x() const
669   {
670     return m_x;
671   }
672   //! second element
y() const673   T y() const
674   {
675     return m_y;
676   }
677   //! operator[]
operator [](int c) const678   T operator[](int c) const
679   {
680     if (c<0 || c>1) throw libmwaw::GenericException();
681     return (c==0) ? m_x : m_y;
682   }
683   //! operator[]
operator [](int c)684   T &operator[](int c)
685   {
686     if (c<0 || c>1) throw libmwaw::GenericException();
687     return (c==0) ? m_x : m_y;
688   }
689 
690   //! resets the two elements
set(T xx,T yy)691   void set(T xx, T yy)
692   {
693     m_x = xx;
694     m_y = yy;
695   }
696   //! resets the first element
setX(T xx)697   void setX(T xx)
698   {
699     m_x = xx;
700   }
701   //! resets the second element
setY(T yy)702   void setY(T yy)
703   {
704     m_y = yy;
705   }
706 
707   //! increases the actuals values by \a dx and \a dy
add(T dx,T dy)708   void add(T dx, T dy)
709   {
710     if (libmwaw::checkAddOverflow(m_x, dx) || libmwaw::checkAddOverflow(m_y, dy))
711       throw libmwaw::GenericException();
712     m_x += dx;
713     m_y += dy;
714   }
715 
716   //! operator+=
operator +=(MWAWVec2<T> const & p)717   MWAWVec2<T> &operator+=(MWAWVec2<T> const &p)
718   {
719     add(p.m_x, p.m_y);
720     return *this;
721   }
722   //! operator-=
operator -=(MWAWVec2<T> const & p)723   MWAWVec2<T> &operator-=(MWAWVec2<T> const &p)
724   {
725     // check if negation of either of the coords will cause overflow
726     const T diff = std::numeric_limits<T>::min() + std::numeric_limits<T>::max();
727     if (libmwaw::checkAddOverflow(p.m_x, diff) || libmwaw::checkAddOverflow(p.m_y, diff))
728       throw libmwaw::GenericException();
729     add(-p.m_x, -p.m_y);
730     return *this;
731   }
732   //! generic operator*=
733   template <class U>
operator *=(U scale)734   MWAWVec2<T> &operator*=(U scale)
735   {
736     m_x = T(m_x*scale);
737     m_y = T(m_y*scale);
738     return *this;
739   }
740 
741   //! operator+
operator +(MWAWVec2<T> const & p1,MWAWVec2<T> const & p2)742   friend MWAWVec2<T> operator+(MWAWVec2<T> const &p1, MWAWVec2<T> const &p2)
743   {
744     MWAWVec2<T> p(p1);
745     return p+=p2;
746   }
747   //! operator-
operator -(MWAWVec2<T> const & p1,MWAWVec2<T> const & p2)748   friend MWAWVec2<T> operator-(MWAWVec2<T> const &p1, MWAWVec2<T> const &p2)
749   {
750     MWAWVec2<T> p(p1);
751     return p-=p2;
752   }
753   //! generic operator*
754   template <class U>
operator *(U scale,MWAWVec2<T> const & p1)755   friend MWAWVec2<T> operator*(U scale, MWAWVec2<T> const &p1)
756   {
757     MWAWVec2<T> p(p1);
758     return p *= scale;
759   }
760 
761   //! comparison==
operator ==(MWAWVec2<T> const & p) const762   bool operator==(MWAWVec2<T> const &p) const
763   {
764     return cmpY(p) == 0;
765   }
766   //! comparison!=
operator !=(MWAWVec2<T> const & p) const767   bool operator!=(MWAWVec2<T> const &p) const
768   {
769     return cmpY(p) != 0;
770   }
771   //! comparison<: sort by y
operator <(MWAWVec2<T> const & p) const772   bool operator<(MWAWVec2<T> const &p) const
773   {
774     return cmpY(p) < 0;
775   }
776   //! a comparison function: which first compares x then y
cmp(MWAWVec2<T> const & p) const777   int cmp(MWAWVec2<T> const &p) const
778   {
779     if (m_x < p.m_x) return -1;
780     if (m_x > p.m_x) return 1;
781     if (m_y < p.m_y) return -1;
782     if (m_y > p.m_y) return 1;
783     return 0;
784   }
785   //! a comparison function: which first compares y then x
cmpY(MWAWVec2<T> const & p) const786   int cmpY(MWAWVec2<T> const &p) const
787   {
788     if (m_y < p.m_y) return -1;
789     if (m_y > p.m_y) return 1;
790     if (m_x < p.m_x) return -1;
791     if (m_x > p.m_x) return 1;
792     return 0;
793   }
794 
795   //! operator<<: prints data in form "XxY"
operator <<(std::ostream & o,MWAWVec2<T> const & f)796   friend std::ostream &operator<< (std::ostream &o, MWAWVec2<T> const &f)
797   {
798     o << f.m_x << "x" << f.m_y;
799     return o;
800   }
801 
802   /*! \struct PosSizeLtX
803    * \brief internal struct used to create sorted map, sorted by X
804    */
805   struct PosSizeLtX {
806     //! comparaison function
operator ()MWAWVec2::PosSizeLtX807     bool operator()(MWAWVec2<T> const &s1, MWAWVec2<T> const &s2) const
808     {
809       return s1.cmp(s2) < 0;
810     }
811   };
812   /*! \typedef MapX
813    *  \brief map of MWAWVec2
814    */
815   typedef std::map<MWAWVec2<T>, T,struct PosSizeLtX> MapX;
816 
817   /*! \struct PosSizeLtY
818    * \brief internal struct used to create sorted map, sorted by Y
819    */
820   struct PosSizeLtY {
821     //! comparaison function
operator ()MWAWVec2::PosSizeLtY822     bool operator()(MWAWVec2<T> const &s1, MWAWVec2<T> const &s2) const
823     {
824       return s1.cmpY(s2) < 0;
825     }
826   };
827   /*! \typedef MapY
828    *  \brief map of MWAWVec2
829    */
830   typedef std::map<MWAWVec2<T>, T,struct PosSizeLtY> MapY;
831 protected:
832   T m_x/*! \brief first element */, m_y/*! \brief second element */;
833 };
834 
835 /*! \brief MWAWVec2 of bool */
836 typedef MWAWVec2<bool> MWAWVec2b;
837 /*! \brief MWAWVec2 of int */
838 typedef MWAWVec2<int> MWAWVec2i;
839 /*! \brief MWAWVec2 of long */
840 typedef MWAWVec2<long> MWAWVec2l;
841 /*! \brief MWAWVec2 of float */
842 typedef MWAWVec2<float> MWAWVec2f;
843 
844 /*! \class MWAWVec3
845  *   \brief small class which defines a vector with 3 elements
846  */
847 template <class T> class MWAWVec3
848 {
849 public:
850   //! constructor
MWAWVec3(T xx=0,T yy=0,T zz=0)851   explicit MWAWVec3(T xx=0,T yy=0,T zz=0)
852   {
853     m_val[0] = xx;
854     m_val[1] = yy;
855     m_val[2] = zz;
856   }
857   //! generic copy constructor
MWAWVec3(MWAWVec3<U> const & p)858   template <class U> explicit MWAWVec3(MWAWVec3<U> const &p)
859   {
860     for (int c = 0; c < 3; c++) m_val[c] = T(p[c]);
861   }
862 
863   //! first element
x() const864   T x() const
865   {
866     return m_val[0];
867   }
868   //! second element
y() const869   T y() const
870   {
871     return m_val[1];
872   }
873   //! third element
z() const874   T z() const
875   {
876     return m_val[2];
877   }
878   //! operator[]
operator [](int c) const879   T operator[](int c) const
880   {
881     if (c<0 || c>2) throw libmwaw::GenericException();
882     return m_val[c];
883   }
884   //! operator[]
operator [](int c)885   T &operator[](int c)
886   {
887     if (c<0 || c>2) throw libmwaw::GenericException();
888     return m_val[c];
889   }
890 
891   //! resets the three elements
set(T xx,T yy,T zz)892   void set(T xx, T yy, T zz)
893   {
894     m_val[0] = xx;
895     m_val[1] = yy;
896     m_val[2] = zz;
897   }
898   //! resets the first element
setX(T xx)899   void setX(T xx)
900   {
901     m_val[0] = xx;
902   }
903   //! resets the second element
setY(T yy)904   void setY(T yy)
905   {
906     m_val[1] = yy;
907   }
908   //! resets the third element
setZ(T zz)909   void setZ(T zz)
910   {
911     m_val[2] = zz;
912   }
913 
914   //! increases the actuals values by \a dx, \a dy, \a dz
add(T dx,T dy,T dz)915   void add(T dx, T dy, T dz)
916   {
917     m_val[0] += dx;
918     m_val[1] += dy;
919     m_val[2] += dz;
920   }
921 
922   //! operator+=
operator +=(MWAWVec3<T> const & p)923   MWAWVec3<T> &operator+=(MWAWVec3<T> const &p)
924   {
925     for (int c = 0; c < 3; c++) m_val[c] = T(m_val[c]+p.m_val[c]);
926     return *this;
927   }
928   //! operator-=
operator -=(MWAWVec3<T> const & p)929   MWAWVec3<T> &operator-=(MWAWVec3<T> const &p)
930   {
931     for (int c = 0; c < 3; c++) m_val[c] = T(m_val[c]-p.m_val[c]);
932     return *this;
933   }
934   //! generic operator*=
935   template <class U>
operator *=(U scale)936   MWAWVec3<T> &operator*=(U scale)
937   {
938     for (auto &c : m_val) c = T(c*scale);
939     return *this;
940   }
941 
942   //! operator+
operator +(MWAWVec3<T> const & p1,MWAWVec3<T> const & p2)943   friend MWAWVec3<T> operator+(MWAWVec3<T> const &p1, MWAWVec3<T> const &p2)
944   {
945     MWAWVec3<T> p(p1);
946     return p+=p2;
947   }
948   //! operator-
operator -(MWAWVec3<T> const & p1,MWAWVec3<T> const & p2)949   friend MWAWVec3<T> operator-(MWAWVec3<T> const &p1, MWAWVec3<T> const &p2)
950   {
951     MWAWVec3<T> p(p1);
952     return p-=p2;
953   }
954   //! generic operator*
955   template <class U>
operator *(U scale,MWAWVec3<T> const & p1)956   friend MWAWVec3<T> operator*(U scale, MWAWVec3<T> const &p1)
957   {
958     MWAWVec3<T> p(p1);
959     return p *= scale;
960   }
961 
962   //! comparison==
operator ==(MWAWVec3<T> const & p) const963   bool operator==(MWAWVec3<T> const &p) const
964   {
965     return cmp(p) == 0;
966   }
967   //! comparison!=
operator !=(MWAWVec3<T> const & p) const968   bool operator!=(MWAWVec3<T> const &p) const
969   {
970     return cmp(p) != 0;
971   }
972   //! comparison<: which first compares x values, then y values then z values.
operator <(MWAWVec3<T> const & p) const973   bool operator<(MWAWVec3<T> const &p) const
974   {
975     return cmp(p) < 0;
976   }
977   //! a comparison function: which first compares x values, then y values then z values.
cmp(MWAWVec3<T> const & p) const978   int cmp(MWAWVec3<T> const &p) const
979   {
980     for (int c = 0; c < 3; c++) {
981       if (m_val[c]<p.m_val[c]) return -1;
982       if (m_val[c]>p.m_val[c]) return 1;
983     }
984     return 0;
985   }
986 
987   //! operator<<: prints data in form "XxYxZ"
operator <<(std::ostream & o,MWAWVec3<T> const & f)988   friend std::ostream &operator<< (std::ostream &o, MWAWVec3<T> const &f)
989   {
990     o << f.m_val[0] << "x" << f.m_val[1] << "x" << f.m_val[2];
991     return o;
992   }
993 
994   /*! \struct PosSizeLt
995    * \brief internal struct used to create sorted map, sorted by X, Y, Z
996    */
997   struct PosSizeLt {
998     //! comparaison function
operator ()MWAWVec3::PosSizeLt999     bool operator()(MWAWVec3<T> const &s1, MWAWVec3<T> const &s2) const
1000     {
1001       return s1.cmp(s2) < 0;
1002     }
1003   };
1004   /*! \typedef Map
1005    *  \brief map of MWAWVec3
1006    */
1007   typedef std::map<MWAWVec3<T>, T,struct PosSizeLt> Map;
1008 
1009 protected:
1010   //! the values
1011   T m_val[3];
1012 };
1013 
1014 /*! \brief MWAWVec3 of unsigned char */
1015 typedef MWAWVec3<unsigned char> MWAWVec3uc;
1016 /*! \brief MWAWVec3 of int */
1017 typedef MWAWVec3<int> MWAWVec3i;
1018 /*! \brief MWAWVec3 of float */
1019 typedef MWAWVec3<float> MWAWVec3f;
1020 
1021 /*! \class MWAWBox2
1022  *   \brief small class which defines a 2D Box
1023  */
1024 template <class T> class MWAWBox2
1025 {
1026 public:
1027   //! constructor
MWAWBox2(MWAWVec2<T> minPt=MWAWVec2<T> (),MWAWVec2<T> maxPt=MWAWVec2<T> ())1028   explicit MWAWBox2(MWAWVec2<T> minPt=MWAWVec2<T>(), MWAWVec2<T> maxPt=MWAWVec2<T>())
1029     : m_data(minPt, maxPt)
1030   {
1031   }
1032   //! generic constructor
MWAWBox2(MWAWBox2<U> const & p)1033   template <class U> explicit MWAWBox2(MWAWBox2<U> const &p)
1034     : m_data(MWAWVec2<T>(p.min()), MWAWVec2<T>(p.max()))
1035   {
1036   }
1037 
1038   //! the minimum 2D point (in x and in y)
min() const1039   MWAWVec2<T> const &min() const
1040   {
1041     return m_data.first;
1042   }
1043   //! the maximum 2D point (in x and in y)
max() const1044   MWAWVec2<T> const &max() const
1045   {
1046     return m_data.second;
1047   }
1048   //! the minimum 2D point (in x and in y)
min()1049   MWAWVec2<T> &min()
1050   {
1051     return m_data.first;
1052   }
1053   //! the maximum 2D point (in x and in y)
max()1054   MWAWVec2<T> &max()
1055   {
1056     return m_data.second;
1057   }
1058   /*! \brief the two extremum points which defined the box
1059    * \param c 0 means the minimum and 1 the maximum
1060    */
operator [](int c) const1061   MWAWVec2<T> const &operator[](int c) const
1062   {
1063     if (c<0 || c>1) throw libmwaw::GenericException();
1064     return c==0 ? m_data.first : m_data.second;
1065   }
1066   //! the box size
size() const1067   MWAWVec2<T> size() const
1068   {
1069     return m_data.second-m_data.first;
1070   }
1071   //! the box center
center() const1072   MWAWVec2<T> center() const
1073   {
1074     return MWAWVec2<T>((m_data.first.x()+m_data.second.x())/2,
1075                        (m_data.first.y()+m_data.second.y())/2);
1076   }
1077 
1078   //! resets the data to minimum \a x and maximum \a y
set(MWAWVec2<T> const & x,MWAWVec2<T> const & y)1079   void set(MWAWVec2<T> const &x, MWAWVec2<T> const &y)
1080   {
1081     m_data.first = x;
1082     m_data.second = y;
1083   }
1084   //! resets the minimum point
setMin(MWAWVec2<T> const & x)1085   void setMin(MWAWVec2<T> const &x)
1086   {
1087     m_data.first = x;
1088   }
1089   //! resets the maximum point
setMax(MWAWVec2<T> const & y)1090   void setMax(MWAWVec2<T> const &y)
1091   {
1092     m_data.second = y;
1093   }
1094 
1095   //!  resize the box keeping the minimum
resizeFromMin(MWAWVec2<T> const & sz)1096   void resizeFromMin(MWAWVec2<T> const &sz)
1097   {
1098     m_data.second = m_data.first+sz;
1099   }
1100   //!  resize the box keeping the maximum
resizeFromMax(MWAWVec2<T> const & sz)1101   void resizeFromMax(MWAWVec2<T> const &sz)
1102   {
1103     m_data.first = m_data.second-sz;
1104   }
1105   //!  resize the box keeping the center
resizeFromCenter(MWAWVec2<T> const & sz)1106   void resizeFromCenter(MWAWVec2<T> const &sz)
1107   {
1108     MWAWVec2<T> centerPt = center();
1109     MWAWVec2<T> decal(sz.x()/2,sz.y()/2);
1110     m_data.first = centerPt - decal;
1111     m_data.second = centerPt + (sz - decal);
1112   }
1113 
1114   //! scales all points of the box by \a factor
scale(U factor)1115   template <class U> void scale(U factor)
1116   {
1117     m_data.first *= factor;
1118     m_data.second *= factor;
1119   }
1120 
1121   //! extends the bdbox by (\a val, \a val) keeping the center
extend(T val)1122   void extend(T val)
1123   {
1124     m_data.first -= MWAWVec2<T>(val/2,val/2);
1125     m_data.second += MWAWVec2<T>(val-(val/2),val-(val/2));
1126   }
1127 
1128   //! returns the union between this and box
getUnion(MWAWBox2<T> const & box) const1129   MWAWBox2<T> getUnion(MWAWBox2<T> const &box) const
1130   {
1131     MWAWBox2<T> res;
1132     res.m_data.first=MWAWVec2<T>(m_data.first[0]<box.m_data.first[0]?m_data.first[0] : box.m_data.first[0],
1133                                  m_data.first[1]<box.m_data.first[1]?m_data.first[1] : box.m_data.first[1]);
1134     res.m_data.second=MWAWVec2<T>(m_data.second[0]>box.m_data.second[0]?m_data.second[0] : box.m_data.second[0],
1135                                   m_data.second[1]>box.m_data.second[1]?m_data.second[1] : box.m_data.second[1]);
1136     return res;
1137   }
1138   //! returns the intersection between this and box
getIntersection(MWAWBox2<T> const & box) const1139   MWAWBox2<T> getIntersection(MWAWBox2<T> const &box) const
1140   {
1141     MWAWBox2<T> res;
1142     res.m_data.first=MWAWVec2<T>(m_data.first[0]>box.m_data.first[0]?m_data.first[0] : box.m_data.first[0],
1143                                  m_data.first[1]>box.m_data.first[1]?m_data.first[1] : box.m_data.first[1]);
1144     res.m_data.second=MWAWVec2<T>(m_data.second[0]<box.m_data.second[0]?m_data.second[0] : box.m_data.second[0],
1145                                   m_data.second[1]<box.m_data.second[1]?m_data.second[1] : box.m_data.second[1]);
1146     return res;
1147   }
1148   //! operator==
operator ==(MWAWBox2<T> const & mat) const1149   bool operator==(MWAWBox2<T> const &mat) const
1150   {
1151     return m_data==mat.m_data;
1152   }
1153   //! operator!=
operator !=(MWAWBox2<T> const & mat) const1154   bool operator!=(MWAWBox2<T> const &mat) const
1155   {
1156     return m_data!=mat.m_data;
1157   }
1158   //! operator<
operator <(MWAWBox2<T> const & mat) const1159   bool operator<(MWAWBox2<T> const &mat) const
1160   {
1161     return m_data<mat.m_data;
1162   }
1163   //! operator<=
operator <=(MWAWBox2<T> const & mat) const1164   bool operator<=(MWAWBox2<T> const &mat) const
1165   {
1166     return m_data<=mat.m_data;
1167   }
1168   //! operator>
operator >(MWAWBox2<T> const & mat) const1169   bool operator>(MWAWBox2<T> const &mat) const
1170   {
1171     return m_data>mat.m_data;
1172   }
1173   //! operator>=
operator >=(MWAWBox2<T> const & mat) const1174   bool operator>=(MWAWBox2<T> const &mat) const
1175   {
1176     return m_data>=mat.m_data;
1177   }
1178   //! print data in form X0xY0<->X1xY1
operator <<(std::ostream & o,MWAWBox2<T> const & f)1179   friend std::ostream &operator<< (std::ostream &o, MWAWBox2<T> const &f)
1180   {
1181     o << "(" << f.min() << "<->" << f.max() << ")";
1182     return o;
1183   }
1184 
1185 protected:
1186   //! the data
1187   std::pair<MWAWVec2<T>, MWAWVec2<T> > m_data;
1188 };
1189 
1190 /*! \brief MWAWBox2 of int */
1191 typedef MWAWBox2<int> MWAWBox2i;
1192 /*! \brief MWAWBox2 of float */
1193 typedef MWAWBox2<float> MWAWBox2f;
1194 /*! \brief MWAWBox2 of long */
1195 typedef MWAWBox2<long> MWAWBox2l;
1196 
1197 /** a transformation which stored the first row of a 3x3 perspective matrix */
1198 class MWAWTransformation
1199 {
1200 public:
1201   //! constructor
MWAWTransformation(MWAWVec3f const & xRow=MWAWVec3f (1,0,0),MWAWVec3f const & yRow=MWAWVec3f (0,1,0))1202   explicit MWAWTransformation(MWAWVec3f const &xRow=MWAWVec3f(1,0,0), MWAWVec3f const &yRow=MWAWVec3f(0,1,0))
1203     : m_data(xRow, yRow)
1204     , m_isIdentity(false)
1205   {
1206     checkIdentity();
1207   }
1208   //! returns true if the matrix is an identity matrix
isIdentity() const1209   bool isIdentity() const
1210   {
1211     return m_isIdentity;
1212   }
1213   //! check if a matrix is the identity matrix
checkIdentity() const1214   void checkIdentity() const
1215   {
1216     m_isIdentity= m_data.first==MWAWVec3f(1,0,0) && m_data.second==MWAWVec3f(0,1,0);
1217   }
1218   /*! \brief the two extremum points which defined the box
1219    * \param c 0 means the minimum and 1 the maximum
1220    */
operator [](int c) const1221   MWAWVec3f const &operator[](int c) const
1222   {
1223     if (c<0 || c>1) throw libmwaw::GenericException();
1224     return c==0 ? m_data.first : m_data.second;
1225   }
1226   //! operator* for vec2f
operator *(MWAWVec2f const & pt) const1227   MWAWVec2f operator*(MWAWVec2f const &pt) const
1228   {
1229     if (m_isIdentity) return pt;
1230     return multiplyDirection(pt)+MWAWVec2f(m_data.first[2],m_data.second[2]);
1231   }
1232   //! operator* for direction
multiplyDirection(MWAWVec2f const & dir) const1233   MWAWVec2f multiplyDirection(MWAWVec2f const &dir) const
1234   {
1235     if (m_isIdentity) return dir;
1236     MWAWVec2f res;
1237     for (int coord=0; coord<2; ++coord) {
1238       MWAWVec3f const &row=coord==0 ? m_data.first : m_data.second;
1239       float value=0;
1240       for (int i=0; i<2; ++i)
1241         value+=row[i]*dir[i];
1242       res[coord]=value;
1243     }
1244     return res;
1245   }
1246   //! operator* for box2f
operator *(MWAWBox2f const & box) const1247   MWAWBox2f operator*(MWAWBox2f const &box) const
1248   {
1249     if (m_isIdentity) return box;
1250     return MWAWBox2f(operator*(box.min()), operator*(box.max()));
1251   }
1252   //! operator* for transform
operator *(MWAWTransformation const & mat) const1253   MWAWTransformation operator*(MWAWTransformation const &mat) const
1254   {
1255     if (mat.m_isIdentity) return *this;
1256     MWAWTransformation res;
1257     for (int row=0; row<2; ++row) {
1258       MWAWVec3f &resRow=row==0 ? res.m_data.first : res.m_data.second;
1259       for (int col=0; col<3; ++col) {
1260         float value=0;
1261         for (int i=0; i<3; ++i)
1262           value+=(*this)[row][i]*(i==2 ? (col==2 ? 1.f : 0.f) : mat[i][col]);
1263         resRow[col]=value;
1264       }
1265     }
1266     res.checkIdentity();
1267     return res;
1268   }
1269   //! operator*=
operator *=(MWAWTransformation const & mat)1270   MWAWTransformation &operator*=(MWAWTransformation const &mat)
1271   {
1272     if (!mat.m_isIdentity)
1273       *this=(*this)*mat;
1274     return *this;
1275   }
1276   //! operator==
operator ==(MWAWTransformation const & mat) const1277   bool operator==(MWAWTransformation const &mat) const
1278   {
1279     return m_data==mat.m_data;
1280   }
1281   //! operator!=
operator !=(MWAWTransformation const & mat) const1282   bool operator!=(MWAWTransformation const &mat) const
1283   {
1284     return m_data!=mat.m_data;
1285   }
1286   //! operator<
operator <(MWAWTransformation const & mat) const1287   bool operator<(MWAWTransformation const &mat) const
1288   {
1289     return m_data<mat.m_data;
1290   }
1291   //! operator<=
operator <=(MWAWTransformation const & mat) const1292   bool operator<=(MWAWTransformation const &mat) const
1293   {
1294     return m_data<=mat.m_data;
1295   }
1296   //! operator>
operator >(MWAWTransformation const & mat) const1297   bool operator>(MWAWTransformation const &mat) const
1298   {
1299     return m_data>mat.m_data;
1300   }
1301   //! operator>=
operator >=(MWAWTransformation const & mat) const1302   bool operator>=(MWAWTransformation const &mat) const
1303   {
1304     return m_data>=mat.m_data;
1305   }
1306   /** try to decompose the matrix in a rotation + scaling/translation matrix.
1307 
1308       Note: the center of rotation is given before applying the transformation(this) */
1309   bool decompose(float &rotation, MWAWVec2f &shearing, MWAWTransformation &transform, MWAWVec2f const &center) const;
1310 
1311   /** returns a translation transformation */
translation(MWAWVec2f const & trans)1312   static MWAWTransformation translation(MWAWVec2f const &trans)
1313   {
1314     return MWAWTransformation(MWAWVec3f(1, 0, trans[0]), MWAWVec3f(0, 1, trans[1]));
1315   }
1316   /** returns a scaling transformation */
scale(MWAWVec2f const & trans)1317   static MWAWTransformation scale(MWAWVec2f const &trans)
1318   {
1319     return MWAWTransformation(MWAWVec3f(trans[0], 0, 0), MWAWVec3f(0, trans[1], 0));
1320   }
1321   /** returns a rotation transformation around center.
1322 
1323    \note angle must be given in degree */
1324   static MWAWTransformation rotation(float angle, MWAWVec2f const &center=MWAWVec2f(0,0));
1325   /** returns a shear transformation letting center invariant, ie. a matrix
1326       ( 1 s[0] -s[0]*center[1], s[1] 1 -s[1]*center[0], 0 0 1)
1327    */
shear(MWAWVec2f s,MWAWVec2f const & center=MWAWVec2f (0,0))1328   static MWAWTransformation shear(MWAWVec2f s, MWAWVec2f const &center=MWAWVec2f(0,0))
1329   {
1330     return MWAWTransformation(MWAWVec3f(1, s[0], -s[0]*center[1]), MWAWVec3f(s[1], 1, -s[1]*center[0]));
1331   }
1332 protected:
1333   //! the data
1334   std::pair<MWAWVec3f, MWAWVec3f > m_data;
1335   //! flag to know if this matrix is an identity matrix
1336   mutable bool m_isIdentity;
1337 };
1338 
1339 // some format function
1340 namespace libmwaw
1341 {
1342 //! convert a DTFormat in a propertyList
1343 bool convertDTFormat(std::string const &dtFormat, librevenge::RVNGPropertyListVector &propVect);
1344 }
1345 
1346 // some geometrical function
1347 namespace libmwaw
1348 {
1349 //! rotate a point around center, angle is given in degree
1350 MWAWVec2f rotatePointAroundCenter(MWAWVec2f const &point, MWAWVec2f const &center, float angle);
1351 //! rotate a bdox and returns the final bdbox, angle is given in degree
1352 MWAWBox2f rotateBoxFromCenter(MWAWBox2f const &box, float angle);
1353 }
1354 #endif /* LIBMWAW_INTERNAL_H */
1355 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
1356