1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * This file is part of the libetonyek 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 #ifndef LIBETONYEK_UTILS_H_INCLUDED
11 #define LIBETONYEK_UTILS_H_INCLUDED
12 
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16 
17 #include <cmath>
18 #include <memory>
19 #include <string>
20 
21 #include <boost/cstdint.hpp>
22 
23 #include <librevenge/librevenge.h>
24 #include <librevenge-stream/librevenge-stream.h>
25 
26 #define ETONYEK_EPSILON 1e-9
27 #define ETONYEK_ALMOST_ZERO(x) (std::fabs(x) < ETONYEK_EPSILON)
28 
29 #define ETONYEK_NUM_ELEMENTS(array) (sizeof(array) / sizeof((array)[0]))
30 
31 #if defined(HAVE_FUNC_ATTRIBUTE_FORMAT)
32 #  define ETONYEK_ATTRIBUTE_PRINTF(fmt, arg) __attribute__((__format__(__printf__, fmt, arg)))
33 #else
34 #  define ETONYEK_ATTRIBUTE_PRINTF(fmt, arg)
35 #endif
36 
37 #if defined(HAVE_CLANG_ATTRIBUTE_FALLTHROUGH)
38 #  define ETONYEK_FALLTHROUGH [[clang::fallthrough]]
39 #elif defined(HAVE_GCC_ATTRIBUTE_FALLTHROUGH)
40 #  define ETONYEK_FALLTHROUGH __attribute__((fallthrough))
41 #else
42 #  define ETONYEK_FALLTHROUGH ((void) 0)
43 #endif
44 
45 // do nothing with debug messages in a release compile
46 #ifdef DEBUG
47 namespace libetonyek
48 {
49 void debugPrint(const char *format, ...) ETONYEK_ATTRIBUTE_PRINTF(1, 2);
50 }
51 #define ETONYEK_DEBUG_MSG(M) libetonyek::debugPrint M
52 #define ETONYEK_DEBUG(M) M
53 #else
54 #define ETONYEK_DEBUG_MSG(M)
55 #define ETONYEK_DEBUG(M)
56 #endif
57 
58 namespace libetonyek
59 {
60 
61 struct IWORKColor;
62 struct IWORKGradient;
63 struct IWORKStroke;
64 
65 /* Constants */
66 const double etonyek_half_pi(1.57079632679489661923132169163975144209858469968755291048747229615390820314310449931401741267105853399107404326e+00);
67 const double etonyek_third_pi(1.04719755119659774615421446109316762806572313312503527365831486410260546876206966620934494178070568932738269550e+00);
68 const double etonyek_pi(3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+00);
69 const double etonyek_two_pi(6.28318530717958647692528676655900576839433879875021164194988918461563281257241799725606965068423413596429617303e+00);
70 
71 const double etonyek_root_three(1.73205080756887729352744634150587236694280525381038062805580697945193301690880003708114618675724857567562614142e+00);
72 const double etonyek_root_two(1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623e+00);
73 
74 // Apple Numbers timestamp starts from 01 Jan 2001 00:00:00
75 const unsigned ETONYEK_EPOCH_BEGIN(978307200);
76 
77 struct EtonyekDummyDeleter
78 {
operatorEtonyekDummyDeleter79   void operator()(void *) {}
80 };
81 
82 typedef std::shared_ptr<librevenge::RVNGInputStream> RVNGInputStreamPtr_t;
83 
84 uint8_t readU8(const RVNGInputStreamPtr_t &input, bool = false);
85 uint16_t readU16(const RVNGInputStreamPtr_t &input, bool bigEndian=false);
86 uint32_t readU32(const RVNGInputStreamPtr_t &input, bool bigEndian=false);
87 uint64_t readU64(const RVNGInputStreamPtr_t &input, bool bigEndian=false);
88 
89 uint64_t readUVar(const RVNGInputStreamPtr_t &input);
90 int64_t readSVar(const RVNGInputStreamPtr_t &input);
91 
92 double readDouble(const RVNGInputStreamPtr_t &input);
93 float readFloat(const RVNGInputStreamPtr_t &input);
94 
95 unsigned long getLength(const RVNGInputStreamPtr_t &input);
96 unsigned long getRemainingLength(const RVNGInputStreamPtr_t &input);
97 
98 /** Test two floating point numbers for equality.
99   *
100   * @arg[in] x first number
101   * @arg[in] y second number
102   * @arg[in] eps precision
103   */
104 bool approxEqual(double x, double y, double eps = ETONYEK_EPSILON);
105 
106 template<class T>
107 bool approxEqual(const T &left, const T &right, const double eps = ETONYEK_EPSILON)
108 {
109   assert(left.length() == right.length());
110 
111   for (int i = 0; i != left.length(); ++i)
112   {
113     if (!approxEqual(left[i], right[i], eps))
114       return false;
115   }
116   return true;
117 }
118 
119 /** Convert a length from points to inches.
120   *
121   * @arg[in] d length in points
122   * @returns length in inches
123   */
124 double pt2in(double d);
125 
126 /** Convert an angle from degrees to radians.
127   *
128   * @arg[in] value angle in degrees
129   * @returns the same angle in radians
130   */
131 double deg2rad(double value);
132 
133 /** Convert an angle from radians to degrees.
134   *
135   * @arg[in] value angle in radians
136   * @returns the same angle in degrees
137   */
138 double rad2deg(double value);
139 
140 librevenge::RVNGString makeColor(const IWORKColor &color);
141 /** Compute the average color of a gradient and return it as a string.
142    */
143 librevenge::RVNGString makeColor(const IWORKGradient &gradient);
144 
145 void writeBorder(const IWORKStroke &stroke, const char *name, librevenge::RVNGPropertyList &props);
146 
147 std::string detectMimetype(const RVNGInputStreamPtr_t &stream);
148 
149 class EndOfStreamException
150 {
151 };
152 
153 class GenericException
154 {
155 };
156 
157 } // namespace libetonyek
158 
159 #endif // LIBETONYEK_UTILS_H_INCLUDED
160 
161 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
162