File indexing completed on 2024-04-28 05:46:49
0001 /***************************************************************************** 0002 * Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 #ifndef __QTC_CAIRO_UTILS_H__ 0024 #define __QTC_CAIRO_UTILS_H__ 0025 0026 #include <qtcurve-utils/utils.h> 0027 #include <qtcurve-utils/options.h> 0028 #include <cairo.h> 0029 0030 #ifdef QTC_UTILS_GTK 0031 #include <gdk/gdk.h> 0032 #endif 0033 0034 struct _GdkPoint; 0035 struct _GdkColor; 0036 // cairo_rectangle_int_t is toooo long... 0037 typedef cairo_rectangle_int_t QtcRect; 0038 /** 0039 * Construct a QtcRect 0040 */ 0041 #define qtcRect(x, y, w, h) ((QtcRect){(x), (y), (w), (h)}) 0042 0043 namespace QtCurve { 0044 namespace Rect { 0045 0046 /** 0047 * \param a a QtcRect 0048 * \param b a QtcRect 0049 * 0050 * Test if rectangle \param a and rectangle \param b are equal. 0051 */ 0052 QTC_ALWAYS_INLINE static inline bool 0053 equal(const QtcRect &a, const QtcRect &b) 0054 { 0055 return (a.x == b.x && a.y == b.y && a.width == b.width && 0056 a.height == b.height); 0057 } 0058 0059 /** 0060 * \param src1 a QtcRect 0061 * \param src2 a QtcRect 0062 * \param[out] dest return location for the union 0063 * of \param src1 and \param src2 0064 * 0065 * Calculates the union of two rectangles. 0066 * The union of rectangles \param src1 and \param src2 is the smallest 0067 * rectangle which includes both \param src1 and \param src2 within it. 0068 * It is allowed for \param dest to be the same as either 0069 * \param src1 or \param src2. 0070 * \sa gdk_rectangle_union 0071 */ 0072 void union_(const QtcRect *src1, const QtcRect *src2, QtcRect *dest); 0073 0074 /** 0075 * \param src1 a QtcRect 0076 * \param src2 a QtcRect 0077 * \param[out] dest return location for the intersection of \param src1 and 0078 * \param src2, or NULL 0079 * 0080 * Calculates the intersection of two rectangles. It is allowed for 0081 * \param dest to be the same as either \param src1 or \param src2. 0082 * If the rectangles do not intersect, \param dest's width and height is set 0083 * to 0 and its x and y values are undefined. If you are only interested in 0084 * whether the rectangles intersect, but not in the intersecting area itself, 0085 * pass %NULL for \param dest. 0086 * 0087 * \return true if the rectangles intersect. 0088 * \sa gdk_rectangle_intersect 0089 */ 0090 bool intersect(const QtcRect *src1, const QtcRect *src2, QtcRect *dest); 0091 0092 /** 0093 * \param rect a QtcRect 0094 * \param con a QtcRect 0095 * 0096 * Constrain \param to be the part within \param con. 0097 * \sa qtcRectIntersect 0098 */ 0099 QTC_ALWAYS_INLINE static inline void 0100 constrain(QtcRect *_rect, const QtcRect *con) 0101 { 0102 intersect(_rect, con, _rect); 0103 } 0104 0105 } 0106 0107 namespace Cairo { 0108 0109 class Saver { 0110 Saver(const Saver&) = delete; 0111 public: 0112 inline 0113 Saver(cairo_t *cr) 0114 : m_cr(cr), 0115 m_restored(true) 0116 { 0117 save(); 0118 } 0119 inline void 0120 restore() 0121 { 0122 // not thread safe but we don't care... 0123 if (!m_restored) { 0124 m_restored = true; 0125 cairo_restore(m_cr); 0126 } 0127 } 0128 inline void 0129 save() 0130 { 0131 // not thread safe but we don't care... 0132 if (m_restored) { 0133 m_restored = false; 0134 cairo_save(m_cr); 0135 } 0136 } 0137 inline void 0138 resave() 0139 { 0140 // not thread safe but we don't care... 0141 if (!m_restored) { 0142 restore(); 0143 save(); 0144 } 0145 } 0146 inline 0147 ~Saver() 0148 { 0149 restore(); 0150 } 0151 private: 0152 cairo_t *const m_cr; 0153 bool m_restored; 0154 }; 0155 0156 /** 0157 * \param cr a cairo_t 0158 * \param pts an array of GdkPoint 0159 * \param count the number of points in \param pts 0160 * 0161 * Add points in \param pts to the current path of \param cr. 0162 * The path is shifted by (0.5, 0.5) so that it is in the middle of the pixel. 0163 */ 0164 void pathPoints(cairo_t *cr, const _GdkPoint *pts, int count); 0165 0166 /** 0167 * \param cr a cairo_t 0168 * \param region a cairo_region_t 0169 * 0170 * Clip \param cr on \param region. The current path of \param cr will 0171 * be cleared. 0172 */ 0173 void clipRegion(cairo_t *cr, const cairo_region_t *region); 0174 0175 /** 0176 * \param cr a cairo_t 0177 * \param rect a QtcRect 0178 * 0179 * Clip \param cr on \param rect. The current path of \param cr will 0180 * be cleared. 0181 */ 0182 void clipRect(cairo_t *cr, const QtcRect *_rect); 0183 0184 /** 0185 * \param cr a cairo_t 0186 * \param col the color to be set 0187 * \param a (optional) the opacity of the color in the range [0.0 .. 1.0] 0188 * (default: 1). 0189 * 0190 * Set the source of \param cr to \param col with opacity \param a 0191 * \sa cairo_set_source_rgba 0192 */ 0193 void setColor(cairo_t *cr, const _GdkColor *col, double a=1); 0194 0195 /** 0196 * \param pt a cairo_pattern_t 0197 * \param offset an offset in the range [0.0 .. 1.0] 0198 * \param col the color to be added. 0199 * \param a (optional) the opacity of the color in the range [0.0 .. 1.0] 0200 * (default: 1). 0201 * 0202 * Adds a color stop with color \param col and opacity \param a to 0203 * a gradient pattern at \param offset. 0204 * \sa cairo_pattern_add_color_stop_rgba 0205 */ 0206 void patternAddColorStop(cairo_pattern_t *pt, double offset, 0207 const _GdkColor *col, double a=1); 0208 0209 void pathTopLeft(cairo_t *cr, double xd, double yd, double width, 0210 double height, double radius, ECornerBits round); 0211 void pathBottomRight(cairo_t *cr, double xd, double yd, double width, 0212 double height, double radius, ECornerBits round); 0213 void pathWhole(cairo_t *cr, double xd, double yd, double width, 0214 double height, double radius, ECornerBits round); 0215 0216 QTC_ALWAYS_INLINE static inline void 0217 clipWhole(cairo_t *cr, double x, double y, int w, int h, 0218 double radius, ECornerBits round) 0219 { 0220 cairo_new_path(cr); 0221 pathWhole(cr, x, y, w, h, radius, round); 0222 cairo_clip(cr); 0223 } 0224 0225 #ifdef QTC_UTILS_GTK 0226 QTC_ALWAYS_INLINE static inline cairo_t* 0227 gdkCreateClip(GdkWindow *window, const QtcRect *area, double width=1) 0228 { 0229 cairo_t *cr = gdk_cairo_create(window); 0230 clipRect(cr, area); 0231 cairo_set_line_width(cr, width); 0232 return cr; 0233 } 0234 0235 QTC_ALWAYS_INLINE static inline cairo_t* 0236 gdkCreateClip(GdkWindow *window, const GdkRectangle *area, double width=1) 0237 { 0238 return gdkCreateClip(window, (const QtcRect*)area, width); 0239 } 0240 #endif 0241 0242 } 0243 } 0244 0245 #endif