Rev 9217 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4430 | cbradney | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
68 | Franz | 7 | /* This file is part of the KDE project. |
8 | Copyright (C) 2001, 2002, 2003 The Karbon Developers |
||
9 | |||
10 | This library is free software; you can redistribute it and/or |
||
11 | modify it under the terms of the GNU Library General Public |
||
12 | License as published by the Free Software Foundation; either |
||
13 | version 2 of the License, or (at your option) any later version. |
||
14 | |||
15 | This library is distributed in the hope that it will be useful, |
||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
18 | Library General Public License for more details. |
||
19 | |||
20 | You should have received a copy of the GNU Library General Public License |
||
21 | along with this library; see the file COPYING.LIB. If not, write to |
||
22 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
||
23 | Boston, MA 02111-1307, USA. |
||
24 | */ |
||
25 | /* Adapted for Scribus 22.08.2003 by Franz Schmid */ |
||
26 | // kopainter/libart wrapper |
||
27 | |||
28 | #include <qpaintdevice.h> |
||
29 | #include <qpixmap.h> |
||
30 | #include <qpointarray.h> |
||
31 | #include <qimage.h> |
||
32 | |||
6733 | avox | 33 | #include "scpainter.h" |
34 | |||
3113 | fschmid | 35 | #ifdef HAVE_CAIRO |
5810 | avox | 36 | #include <cairo.h> |
6128 | fschmid | 37 | #include "colorutil.h" |
5688 | jghali | 38 | #if defined(_WIN32) |
39 | #include <cairo-win32.h> |
||
5810 | avox | 40 | #elif defined(Q_WS_X11) |
5688 | jghali | 41 | #include <cairo-xlib.h> |
5810 | avox | 42 | #elif defined(Q_WS_MAC) |
6733 | avox | 43 | // #include <cairo-quartz.h> |
5688 | jghali | 44 | #endif |
7199 | fschmid | 45 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6) |
5471 | fschmid | 46 | #include <cairo-svg.h> |
7199 | fschmid | 47 | // #endif |
3113 | fschmid | 48 | #else |
5699 | avox | 49 | // not HAVE_CAIRO |
68 | Franz | 50 | #include <libart_lgpl/art_vpath.h> |
51 | #include <libart_lgpl/art_bpath.h> |
||
52 | #include <libart_lgpl/art_vpath_bpath.h> |
||
53 | #include <libart_lgpl/art_svp_vpath.h> |
||
54 | #include <libart_lgpl/art_svp_vpath_stroke.h> |
||
55 | #include <libart_lgpl/art_svp.h> |
||
56 | #include <libart_lgpl/art_svp_ops.h> |
||
57 | #include <libart_lgpl/art_affine.h> |
||
58 | #include <libart_lgpl/art_svp_intersect.h> |
||
59 | #include <libart_lgpl/art_rect_svp.h> |
||
60 | #include <libart_lgpl/art_pathcode.h> |
||
61 | #include <libart_lgpl/art_vpath_dash.h> |
||
62 | #include <libart_lgpl/art_render_svp.h> |
||
63 | #include <libart_lgpl/art_vpath_svp.h> |
||
3369 | craig | 64 | #include "libart/art_render_misc.h" |
65 | #include "libart/art_rgb_svp.h" |
||
66 | #include "libart/art_render_pattern.h" |
||
67 | #include "libart/art_kmisc.h" |
||
3113 | fschmid | 68 | #define INITIAL_ALLOC 300 |
69 | #define ALLOC_INCREMENT 100 |
||
70 | #endif |
||
68 | Franz | 71 | |
1669 | craig | 72 | #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF) |
68 | Franz | 73 | #include <X11/Xlib.h> |
5064 | cbradney | 74 | #include "pixbuf/gdk-pixbuf-xlibrgb.h" |
1669 | craig | 75 | #endif |
68 | Franz | 76 | |
2686 | craig | 77 | #if defined(_WIN32) && defined(SC_USE_GDI) |
78 | #include <windows.h> |
||
79 | #endif |
||
80 | |||
5810 | avox | 81 | #if defined(Q_WS_MAC) && defined(SC_USE_QUARTZ) |
82 | // #include ??? |
||
83 | #endif |
||
84 | |||
68 | Franz | 85 | #include <math.h> |
86 | |||
6733 | avox | 87 | |
5699 | avox | 88 | /// screen painter |
1624 | fschmid | 89 | ScPainter::ScPainter( QPaintDevice *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y ) |
68 | Franz | 90 | { |
91 | m_target = target; |
||
92 | m_width = w; |
||
93 | m_height= h; |
||
1624 | fschmid | 94 | m_x = x; |
95 | m_y = y; |
||
68 | Franz | 96 | m_buffer = 0L; |
5699 | avox | 97 | #ifdef HAVE_CAIRO |
98 | #else |
||
68 | Franz | 99 | m_path = 0L; |
6463 | fschmid | 100 | m_clipPath = 0L; |
3113 | fschmid | 101 | #endif |
68 | Franz | 102 | m_index = 0; |
103 | m_stroke = QColor(0,0,0); |
||
104 | m_fill = QColor(0,0,0); |
||
105 | fill_trans = 1.0; |
||
106 | stroke_trans = 1.0; |
||
107 | m_fillRule = true; |
||
108 | fillMode = 1; |
||
109 | LineWidth = 1.0; |
||
110 | m_offset = 0; |
||
111 | m_array.clear(); |
||
112 | mf_underline = false; |
||
113 | mf_strikeout = false; |
||
114 | mf_shadow = false; |
||
115 | mf_outlined = false; |
||
205 | Franz | 116 | PLineEnd = Qt::SquareCap; |
117 | PLineJoin = Qt::RoundJoin; |
||
68 | Franz | 118 | fill_gradient = VGradient(VGradient::linear); |
119 | stroke_gradient = VGradient(VGradient::linear); |
||
1669 | craig | 120 | m_zoomFactor = 1; |
1815 | fschmid | 121 | imageMode = false; |
3113 | fschmid | 122 | m_matrix = QWMatrix(); |
123 | #ifdef HAVE_CAIRO |
||
5373 | fschmid | 124 | layeredMode = false; |
5471 | fschmid | 125 | svgMode = false; |
5810 | avox | 126 | cairo_surface_t *img; |
127 | #ifdef Q_WS_X11 |
||
3113 | fschmid | 128 | pixm = QPixmap(w, h); |
129 | Display *dpy = pixm.x11AppDisplay(); |
||
130 | Drawable drw = pixm.handle(); |
||
131 | img = cairo_xlib_surface_create(dpy, drw, (Visual*)pixm.x11Visual(), w, h); |
||
5810 | avox | 132 | #elif defined(_WIN32) |
5688 | jghali | 133 | pixm = QPixmap(w, h, 32); |
134 | img = cairo_win32_surface_create(pixm.handle()); |
||
5810 | avox | 135 | #elif defined(SC_USE_QUARTZ) |
136 | // ??? |
||
137 | #else |
||
138 | m_img.create(w, h, 32); |
||
9217 | avox | 139 | img = cairo_image_surface_create_for_data(m_img.bits(), CAIRO_FORMAT_ARGB32, w, h, w*4); |
5688 | jghali | 140 | #endif |
3113 | fschmid | 141 | m_cr = cairo_create(img); |
142 | clear(); |
||
143 | cairo_save( m_cr ); |
||
144 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD); |
||
3173 | fschmid | 145 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
3120 | fschmid | 146 | /* Setting to 0.5 here gives a good tradeoff between speed and precision |
147 | the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */ |
||
148 | cairo_set_tolerance( m_cr, 0.5 ); |
||
5699 | avox | 149 | #else |
150 | // not HAVE_CAIRO |
||
151 | #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF) |
||
3113 | fschmid | 152 | resize( m_width, m_height ); |
153 | clear(); |
||
1624 | fschmid | 154 | xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(), target->x11Screen() ), target->x11Depth() ); |
68 | Franz | 155 | gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 ); |
2686 | craig | 156 | #elif defined(_WIN32) && defined(SC_USE_GDI) |
3113 | fschmid | 157 | resize( m_width, m_height ); |
158 | clear(); |
||
2686 | craig | 159 | dc = CreateCompatibleDC( target->handle() ); |
3175 | avox | 160 | #else |
161 | resize( m_width, m_height ); |
||
162 | clear(); |
||
1669 | craig | 163 | #endif |
5699 | avox | 164 | #endif |
68 | Franz | 165 | } |
166 | |||
5699 | avox | 167 | /// std image painter |
7537 | fschmid | 168 | ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, unsigned int x, unsigned int y ) |
1815 | fschmid | 169 | { |
170 | m_target = 0L; |
||
171 | m_width = w; |
||
172 | m_height= h; |
||
173 | m_x = x; |
||
174 | m_y = y; |
||
175 | m_buffer = 0L; |
||
3113 | fschmid | 176 | m_index = 0; |
1815 | fschmid | 177 | m_stroke = QColor(0,0,0); |
178 | m_fill = QColor(0,0,0); |
||
179 | fill_trans = 1.0; |
||
180 | stroke_trans = 1.0; |
||
181 | m_fillRule = true; |
||
182 | fillMode = 1; |
||
183 | LineWidth = 1.0; |
||
184 | m_offset = 0; |
||
185 | m_array.clear(); |
||
186 | mf_underline = false; |
||
187 | mf_strikeout = false; |
||
188 | mf_shadow = false; |
||
189 | mf_outlined = false; |
||
190 | PLineEnd = Qt::SquareCap; |
||
191 | PLineJoin = Qt::RoundJoin; |
||
192 | fill_gradient = VGradient(VGradient::linear); |
||
193 | stroke_gradient = VGradient(VGradient::linear); |
||
194 | m_zoomFactor = 1; |
||
195 | imageMode = true; |
||
196 | m_image = target; |
||
5260 | fschmid | 197 | m_matrix = QWMatrix(); |
3376 | fschmid | 198 | #ifdef HAVE_CAIRO |
5373 | fschmid | 199 | layeredMode = false; |
5471 | fschmid | 200 | svgMode = false; |
3376 | fschmid | 201 | cairo_surface_t *img = cairo_image_surface_create_for_data(target->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4); |
202 | m_cr = cairo_create(img); |
||
203 | clear(); |
||
204 | cairo_save( m_cr ); |
||
205 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD); |
||
206 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
||
207 | /* Setting to 0.5 here gives a good tradeoff between speed and precision |
||
208 | the former setting of 0.2 is just too precise, and setting it to 0.9 or greater will give bad rendering */ |
||
209 | cairo_set_tolerance( m_cr, 0.5 ); |
||
210 | #else |
||
211 | resize( m_width, m_height ); |
||
212 | clear(); |
||
213 | m_path = 0L; |
||
6463 | fschmid | 214 | m_clipPath = 0L; |
3376 | fschmid | 215 | #endif |
1815 | fschmid | 216 | } |
217 | |||
5373 | fschmid | 218 | #ifdef HAVE_CAIRO |
5699 | avox | 219 | /// image painter |
7537 | fschmid | 220 | ScPainter::ScPainter( QImage *target, unsigned int w, unsigned int h, double transparency, int blendmode ) |
5373 | fschmid | 221 | { |
222 | m_target = 0L; |
||
223 | m_width = w; |
||
224 | m_height= h; |
||
225 | m_buffer = 0L; |
||
226 | m_index = 0; |
||
227 | m_stroke = QColor(0,0,0); |
||
228 | m_fill = QColor(0,0,0); |
||
229 | fill_trans = 1.0; |
||
230 | stroke_trans = 1.0; |
||
231 | m_fillRule = true; |
||
232 | fillMode = 1; |
||
233 | LineWidth = 1.0; |
||
234 | m_offset = 0; |
||
235 | m_layerTransparency = transparency; |
||
236 | m_blendMode = blendmode; |
||
237 | m_array.clear(); |
||
238 | mf_underline = false; |
||
239 | mf_strikeout = false; |
||
240 | mf_shadow = false; |
||
241 | mf_outlined = false; |
||
242 | PLineEnd = Qt::SquareCap; |
||
243 | PLineJoin = Qt::RoundJoin; |
||
244 | fill_gradient = VGradient(VGradient::linear); |
||
245 | stroke_gradient = VGradient(VGradient::linear); |
||
246 | m_zoomFactor = 1; |
||
247 | layeredMode = true; |
||
248 | imageMode = true; |
||
5471 | fschmid | 249 | svgMode = false; |
5373 | fschmid | 250 | m_image = target; |
251 | m_matrix = QWMatrix(); |
||
7199 | fschmid | 252 | /* |
5471 | fschmid | 253 | #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6) |
5469 | fschmid | 254 | tmp_image = QImage(w, h, 32, QImage::BigEndian); |
5373 | fschmid | 255 | tmp_image.fill( qRgba(255, 255, 255, 0) ); |
256 | cairo_surface_t *img = cairo_image_surface_create_for_data(tmp_image.bits(), CAIRO_FORMAT_ARGB32, w, h, w*4); |
||
257 | m_cr = cairo_create(img); |
||
258 | clear(); |
||
5471 | fschmid | 259 | #else |
7199 | fschmid | 260 | */ |
7537 | fschmid | 261 | // m_image->fill( qRgba(255, 255, 255, 0) ); |
5471 | fschmid | 262 | cairo_surface_t *img = cairo_image_surface_create_for_data(m_image->bits(), CAIRO_FORMAT_ARGB32, w, h, w*4); |
263 | m_cr = cairo_create(img); |
||
7199 | fschmid | 264 | // #endif |
5373 | fschmid | 265 | cairo_save( m_cr ); |
266 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD); |
||
267 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
||
268 | cairo_set_tolerance( m_cr, 0.5 ); |
||
269 | } |
||
5471 | fschmid | 270 | |
7199 | fschmid | 271 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6) |
5699 | avox | 272 | /// SVG file painter |
273 | ScPainter::ScPainter( QString target, unsigned int w, unsigned int h, |
||
274 | double transparency, int blendmode ) |
||
5471 | fschmid | 275 | { |
276 | m_target = 0L; |
||
277 | m_width = w; |
||
278 | m_height= h; |
||
279 | m_buffer = 0L; |
||
280 | m_index = 0; |
||
281 | m_stroke = QColor(0,0,0); |
||
282 | m_fill = QColor(0,0,0); |
||
283 | fill_trans = 1.0; |
||
284 | stroke_trans = 1.0; |
||
285 | m_fillRule = true; |
||
286 | fillMode = 1; |
||
287 | LineWidth = 1.0; |
||
288 | m_offset = 0; |
||
289 | m_layerTransparency = transparency; |
||
290 | m_blendMode = blendmode; |
||
291 | m_array.clear(); |
||
292 | mf_underline = false; |
||
293 | mf_strikeout = false; |
||
294 | mf_shadow = false; |
||
295 | mf_outlined = false; |
||
296 | PLineEnd = Qt::SquareCap; |
||
297 | PLineJoin = Qt::RoundJoin; |
||
298 | fill_gradient = VGradient(VGradient::linear); |
||
299 | stroke_gradient = VGradient(VGradient::linear); |
||
300 | m_zoomFactor = 1; |
||
301 | layeredMode = true; |
||
302 | imageMode = false; |
||
303 | svgMode = true; |
||
304 | m_matrix = QWMatrix(); |
||
305 | cairo_surface_t *img = cairo_svg_surface_create(target, w, h); |
||
306 | m_cr = cairo_create(img); |
||
307 | cairo_save( m_cr ); |
||
308 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD); |
||
309 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
||
310 | cairo_set_tolerance( m_cr, 0.5 ); |
||
311 | } |
||
7199 | fschmid | 312 | // #endif |
5699 | avox | 313 | // HAVE_CAIRO |
5471 | fschmid | 314 | #endif |
315 | |||
68 | Franz | 316 | ScPainter::~ScPainter() |
317 | { |
||
5699 | avox | 318 | #ifdef HAVE_CAIRO |
319 | #else |
||
68 | Franz | 320 | // If we are in target mode, we created a buffer, else if we used the other ctor |
321 | // we didnt. |
||
1815 | fschmid | 322 | if (( m_target ) || ( imageMode)) |
68 | Franz | 323 | art_free( m_buffer ); |
324 | if( m_path ) |
||
325 | art_free( m_path ); |
||
3113 | fschmid | 326 | #endif |
5699 | avox | 327 | |
328 | |||
3113 | fschmid | 329 | #ifdef HAVE_CAIRO |
4447 | fschmid | 330 | cairo_surface_destroy(cairo_get_target(m_cr)); |
3113 | fschmid | 331 | cairo_destroy( m_cr ); |
5699 | avox | 332 | #else |
333 | // not HAVE_CAIRO |
||
334 | #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF) |
||
5471 | fschmid | 335 | if ((imageMode) || (svgMode)) |
3376 | fschmid | 336 | return; |
68 | Franz | 337 | if( gc ) |
338 | XFreeGC( m_target->x11Display(), gc ); |
||
2686 | craig | 339 | #elif defined(_WIN32) && defined(SC_USE_GDI) |
5699 | avox | 340 | if (imageMode || svgMode) |
3376 | fschmid | 341 | return; |
2686 | craig | 342 | if( dc ) |
343 | DeleteDC( dc ); |
||
1669 | craig | 344 | #endif |
5699 | avox | 345 | #endif |
68 | Franz | 346 | } |
347 | |||
5373 | fschmid | 348 | #ifdef HAVE_CAIRO |
7049 | fschmid | 349 | void ScPainter::beginLayer(double transparency, int blendmode, FPointArray *clipArray) |
5373 | fschmid | 350 | { |
7199 | fschmid | 351 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6) |
5604 | fschmid | 352 | layerProp la; |
7199 | fschmid | 353 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8) |
5604 | fschmid | 354 | la.data = cairo_get_group_target(m_cr); |
7199 | fschmid | 355 | // #endif |
5604 | fschmid | 356 | la.blendmode = m_blendMode; |
357 | la.tranparency = m_layerTransparency; |
||
5373 | fschmid | 358 | m_layerTransparency = transparency; |
359 | m_blendMode = blendmode; |
||
7049 | fschmid | 360 | la.pushed = false; |
361 | la.groupClip.resize(0); |
||
362 | if (clipArray != NULL) |
||
5604 | fschmid | 363 | { |
7049 | fschmid | 364 | la.groupClip = *clipArray; |
5604 | fschmid | 365 | } |
7757 | fschmid | 366 | // if ((transparency != 1.0) || (blendmode != 0) || (clipArray != NULL)) |
367 | // { |
||
7049 | fschmid | 368 | cairo_push_group(m_cr); |
369 | la.pushed = true; |
||
7757 | fschmid | 370 | // } |
7049 | fschmid | 371 | Layers.push(la); |
7199 | fschmid | 372 | /* |
5471 | fschmid | 373 | #else |
5373 | fschmid | 374 | tmp_image.fill( qRgba(255, 255, 255, 0) ); |
5471 | fschmid | 375 | #endif |
7199 | fschmid | 376 | */ |
5373 | fschmid | 377 | } |
378 | |||
7049 | fschmid | 379 | void ScPainter::endLayer() |
5373 | fschmid | 380 | { |
7049 | fschmid | 381 | layerProp la; |
9096 | fschmid | 382 | if (Layers.count() == 0) |
383 | return; |
||
7049 | fschmid | 384 | la = Layers.top(); |
7199 | fschmid | 385 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 6) |
7049 | fschmid | 386 | if (la.pushed) |
387 | { |
||
7199 | fschmid | 388 | // #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 1, 8) |
9316 | fschmid | 389 | if ((m_blendMode != 0) && (Layers.count() != 0)) |
5601 | fschmid | 390 | { |
7077 | fschmid | 391 | cairo_surface_t *tmp = cairo_get_group_target(m_cr); |
392 | cairo_surface_t *tmpB = Layers.top().data; |
||
393 | if ((tmp != NULL) && (tmpB != NULL)) |
||
5601 | fschmid | 394 | { |
7077 | fschmid | 395 | if ((cairo_surface_get_type(tmp) == CAIRO_SURFACE_TYPE_IMAGE) && (cairo_surface_get_type(tmpB) == CAIRO_SURFACE_TYPE_IMAGE)) |
5601 | fschmid | 396 | { |
7077 | fschmid | 397 | cairo_surface_flush(tmp); |
398 | int stride = cairo_image_surface_get_stride(tmp); |
||
399 | unsigned char *s = cairo_image_surface_get_data(tmp); |
||
400 | unsigned char *d = cairo_image_surface_get_data(tmpB); |
||
401 | int h = cairo_image_surface_get_height(tmp); |
||
402 | int w = cairo_image_surface_get_width(tmp); |
||
403 | uint oldDst = 1; |
||
404 | uint oldSrc = 2; |
||
405 | uint newResult = 0; |
||
406 | bool first = true; |
||
7175 | fschmid | 407 | QRgb *src; |
408 | QRgb *dst; |
||
409 | uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b, new_r, new_g, new_b; |
||
7077 | fschmid | 410 | for( int yi=0; yi < h; ++yi ) |
5601 | fschmid | 411 | { |
7175 | fschmid | 412 | dst = (QRgb*)d; |
413 | src = (QRgb*)s; |
||
7077 | fschmid | 414 | for( int xi=0; xi < w; ++xi ) |
5601 | fschmid | 415 | { |
7175 | fschmid | 416 | src_r = qRed(*src); |
417 | src_g = qGreen(*src); |
||
418 | src_b = qBlue(*src); |
||
419 | src_a = qAlpha(*src); |
||
420 | dst_r = qRed(*dst); |
||
421 | dst_g = qGreen(*dst); |
||
422 | dst_b = qBlue(*dst); |
||
423 | dst_a = qAlpha(*dst); |
||
7077 | fschmid | 424 | if ((src_a > 0) && (dst_a > 0)) |
5601 | fschmid | 425 | { |
7077 | fschmid | 426 | if (((*dst) != oldDst) || ((*src) != oldSrc) || (first)) |
6505 | fschmid | 427 | { |
7077 | fschmid | 428 | if (m_blendMode == 1) |
429 | { |
||
430 | src_r = dst_r < src_r ? dst_r : src_r; |
||
431 | src_g = dst_g < src_g ? dst_g : src_g; |
||
432 | src_b = dst_b < src_b ? dst_b : src_b; |
||
433 | } |
||
434 | else if (m_blendMode == 2) |
||
435 | { |
||
436 | src_r = dst_r < src_r ? src_r : dst_r; |
||
437 | src_g = dst_g < src_g ? src_g : dst_g; |
||
438 | src_b = dst_b < src_b ? src_b : dst_b; |
||
439 | } |
||
440 | else if (m_blendMode == 3) |
||
441 | { |
||
442 | src_r = INT_MULT(src_r, dst_r); |
||
443 | src_g = INT_MULT(src_g, dst_g); |
||
444 | src_b = INT_MULT(src_b, dst_b); |
||
445 | } |
||
446 | else if (m_blendMode == 4) |
||
447 | { |
||
448 | src_r = 255 - ((255-src_r) * (255-dst_r) / 128); |
||
449 | src_g = 255 - ((255-src_g) * (255-dst_g) / 128); |
||
450 | src_b = 255 - ((255-src_b) * (255-dst_b) / 128); |
||
451 | } |
||
452 | else if (m_blendMode == 5) |
||
453 | { |
||
454 | src_r = dst_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128); |
||
455 | src_g = dst_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128); |
||
456 | src_b = dst_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128); |
||
457 | } |
||
458 | else if (m_blendMode == 6) |
||
459 | { |
||
460 | src_r = src_r < 128 ? src_r * dst_r / 128 : 255 - ((255-src_r) * (255-dst_r) / 128); |
||
461 | src_g = src_g < 128 ? src_g * dst_g / 128 : 255 - ((255-src_g) * (255-dst_g) / 128); |
||
462 | src_b = src_b < 128 ? src_b * dst_b / 128 : 255 - ((255-src_b) * (255-dst_b) / 128); |
||
463 | } |
||
464 | else if (m_blendMode == 7) |
||
465 | { |
||
466 | float s_r = (255 - src_r) / 255.0; |
||
467 | float s_g = (255 - src_g) / 255.0; |
||
468 | float s_b = (255 - src_b) / 255.0; |
||
469 | float d_r = (255 - dst_r) / 255.0; |
||
470 | float d_g = (255 - dst_g) / 255.0; |
||
471 | float d_b = (255 - dst_b) / 255.0; |
||
472 | float dzr = d_r > 0.25 ? sqrt(d_r) : ((16 * d_r - 12) * d_r + 4) * d_r; |
||
473 | float dzg = d_g > 0.25 ? sqrt(d_g) : ((16 * d_g - 12) * d_g + 4) * d_g; |
||
474 | float dzb = d_b > 0.25 ? sqrt(d_b) : ((16 * d_b - 12) * d_b + 4) * d_b; |
||
475 | s_r = s_r <= 0.5 ? d_r - (1 - 2 * s_r) * d_r * (1 - d_r) : d_r + (2 * s_r - 1) * (dzr - d_r); |
||
476 | s_g = s_g <= 0.5 ? d_g - (1 - 2 * s_g) * d_g * (1 - d_g) : d_g + (2 * s_g - 1) * (dzg - d_g); |
||
477 | s_b = s_b <= 0.5 ? d_b - (1 - 2 * s_b) * d_b * (1 - d_b) : d_b + (2 * s_b - 1) * (dzb - d_b); |
||
478 | src_r = 255 - qRound(s_r * 255); |
||
479 | src_g = 255 - qRound(s_g * 255); |
||
480 | src_b = 255 - qRound(s_b * 255); |
||
481 | } |
||
482 | else if (m_blendMode == 8) |
||
483 | { |
||
484 | src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r; |
||
485 | src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g; |
||
486 | src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b; |
||
487 | } |
||
488 | else if (m_blendMode == 9) |
||
489 | { |
||
490 | src_r = dst_r + src_r - src_r * dst_r / 128; |
||
491 | src_g = dst_g + src_g - src_g * dst_g / 128; |
||
492 | src_b = dst_b + src_b - src_b * dst_b / 128; |
||
493 | } |
||
494 | else if (m_blendMode == 10) |
||
495 | { |
||
496 | src_r = src_r == 255 ? QMIN(255, dst_r * 256) : QMIN(255, ((dst_r * 256) / (255-src_r))); |
||
497 | src_g = src_g == 255 ? QMIN(255, dst_g * 256) : QMIN(255, ((dst_g * 256) / (255-src_g))); |
||
498 | src_b = src_b == 255 ? QMIN(255, dst_b * 256) : QMIN(255, ((dst_b * 256) / (255-src_b))); |
||
499 | } |
||
500 | else if (m_blendMode == 11) |
||
501 | { |
||
502 | src_r = QMAX(1, src_r); |
||
503 | src_g = QMAX(1, src_g); |
||
504 | src_b = QMAX(1, src_b); |
||
505 | src_r = static_cast<int>(255 - (((255-dst_r) * 256) / src_r)) < 0 ? 0 : 255 - (((255-dst_r) * 256) / src_r); |
||
506 | src_g = static_cast<int>(255 - (((255-dst_g) * 256) / src_g)) < 0 ? 0 : 255 - (((255-dst_g) * 256) / src_g); |
||
507 | src_b = static_cast<int>(255 - (((255-dst_b) * 256) / src_b)) < 0 ? 0 : 255 - (((255-dst_b) * 256) / src_b); |
||
508 | } |
||
509 | // else if (m_blendMode == 12) |
||
510 | // { |
||
511 | /* This code is a blendmode that simulates the effect of overprinting |
||
512 | Works by converting source and destination colour to CMYK and adding them together |
||
513 | Finally the result is converted back to RGB */ |
||
514 | /* int K1 = QMIN(QMIN(255 - src_r, 255 - src_g), 255 - src_b); |
||
515 | int K2 = QMIN(QMIN(255 - dst_r, 255 - dst_g), 255 - dst_b); |
||
516 | int C = QMIN(QMIN(255 - src_r - K1, 255) + QMIN(255 - dst_r - K2, 255), 255); |
||
517 | int M = QMIN(QMIN(255 - src_g - K1, 255) + QMIN(255 - dst_g - K2, 255), 255) ; |
||
518 | int Y = QMIN(QMIN(255 - src_b - K1, 255) + QMIN(255 - dst_b - K2, 255), 255) ; |
||
519 | int K = QMIN(K1 + K2, 255); |
||
520 | src_r = 255 - QMIN(255, C + K); |
||
521 | src_g = 255 - QMIN(255, M + K); |
||
522 | src_b = 255 - QMIN(255, Y+ K); |
||
523 | } */ |
||
524 | else if (m_blendMode == 12) |
||
525 | { |
||
7175 | fschmid | 526 | new_r = dst_r; |
527 | new_g = dst_g; |
||
528 | new_b = dst_b; |
||
8027 | fschmid | 529 | RGBTOHLS(src_r, src_g, src_b); |
530 | RGBTOHLS(new_r, new_g, new_b); |
||
531 | new_r = src_r; |
||
532 | HLSTORGB(new_r, new_g, new_b); |
||
533 | /* RGBTOHSV(src_r, src_g, src_b); |
||
7077 | fschmid | 534 | RGBTOHSV(new_r, new_g, new_b); |
535 | new_r = src_r; |
||
8027 | fschmid | 536 | HSVTORGB(new_r, new_g, new_b); */ |
7077 | fschmid | 537 | src_r = new_r; |
538 | src_g = new_g; |
||
539 | src_b = new_b; |
||
540 | } |
||
541 | else if (m_blendMode == 13) |
||
542 | { |
||
7175 | fschmid | 543 | new_r = dst_r; |
544 | new_g = dst_g; |
||
545 | new_b = dst_b; |
||
8027 | fschmid | 546 | RGBTOHLS(src_r, src_g, src_b); |
547 | RGBTOHLS(new_r, new_g, new_b); |
||
548 | new_b = src_b; |
||
549 | HLSTORGB(new_r, new_g, new_b); |
||
550 | /* RGBTOHSV(src_r, src_g, src_b); |
||
7077 | fschmid | 551 | RGBTOHSV(new_r, new_g, new_b); |
552 | new_g = src_g; |
||
8027 | fschmid | 553 | HSVTORGB(new_r, new_g, new_b); */ |
7077 | fschmid | 554 | src_r = new_r; |
555 | src_g = new_g; |
||
556 | src_b = new_b; |
||
557 | } |
||
558 | else if (m_blendMode == 14) |
||
559 | { |
||
8019 | fschmid | 560 | new_r = src_r; |
561 | new_g = src_g; |
||
562 | new_b = src_b; |
||
563 | setLum(new_r, new_g, new_b, Lum(dst_r, dst_g, dst_b)); |
||
564 | /* RGBTOHLS(src_r, src_g, src_b); |
||
7077 | fschmid | 565 | RGBTOHLS(new_r, new_g, new_b); |
566 | new_r = src_r; |
||
567 | new_b = src_b; |
||
8019 | fschmid | 568 | HLSTORGB(new_r, new_g, new_b); */ |
7077 | fschmid | 569 | src_r = new_r; |
570 | src_g = new_g; |
||
571 | src_b = new_b; |
||
572 | } |
||
573 | else if (m_blendMode == 15) |
||
574 | { |
||
7175 | fschmid | 575 | new_r = dst_r; |
576 | new_g = dst_g; |
||
577 | new_b = dst_b; |
||
8018 | fschmid | 578 | setLum(new_r, new_g, new_b, Lum(src_r, src_g, src_b)); |
579 | /* RGBTOHSV(src_r, src_g, src_b); |
||
7077 | fschmid | 580 | RGBTOHSV(new_r, new_g, new_b); |
581 | new_b = src_b; |
||
8018 | fschmid | 582 | HSVTORGB(new_r, new_g, new_b); */ |
7077 | fschmid | 583 | src_r = new_r; |
584 | src_g = new_g; |
||
585 | src_b = new_b; |
||
586 | } |
||
587 | newResult = qRgba(src_r, src_g, src_b, src_a); |
||
588 | oldDst = (*dst); |
||
589 | oldSrc = (*src); |
||
590 | first = false; |
||
6505 | fschmid | 591 | } |
7077 | fschmid | 592 | (*src) = newResult; |
5601 | fschmid | 593 | } |
7077 | fschmid | 594 | src++; |
595 | dst++; |
||
5601 | fschmid | 596 | } |
7077 | fschmid | 597 | s += stride; |
598 | d += stride; |
||
5601 | fschmid | 599 | } |
7077 | fschmid | 600 | cairo_surface_mark_dirty(tmp); |
5601 | fschmid | 601 | } |
602 | } |
||
603 | } |
||
7199 | fschmid | 604 | // #endif |
5601 | fschmid | 605 | } |
5604 | fschmid | 606 | la = Layers.pop(); |
7049 | fschmid | 607 | if (la.pushed) |
6451 | fschmid | 608 | { |
7049 | fschmid | 609 | cairo_pop_group_to_source (m_cr); |
610 | if (la.groupClip.size() != 0) |
||
611 | { |
||
612 | setupPolygon(&la.groupClip); |
||
613 | setClipPath(); |
||
614 | } |
||
615 | if (m_blendMode == 0) |
||
616 | { |
||
617 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
||
618 | cairo_paint_with_alpha (m_cr, m_layerTransparency); |
||
619 | } |
||
620 | else |
||
621 | { |
||
622 | cairo_set_operator(m_cr, CAIRO_OPERATOR_DEST_OUT); |
||
623 | cairo_paint_with_alpha (m_cr, m_layerTransparency); |
||
624 | cairo_set_operator(m_cr, CAIRO_OPERATOR_ADD); |
||
625 | cairo_paint_with_alpha (m_cr, m_layerTransparency); |
||
626 | } |
||
5637 | fschmid | 627 | cairo_set_operator(m_cr, CAIRO_OPERATOR_OVER); |
628 | } |
||
5604 | fschmid | 629 | m_layerTransparency = la.tranparency; |
630 | m_blendMode = la.blendmode; |
||
7199 | fschmid | 631 | /* |
5471 | fschmid | 632 | #else |
5373 | fschmid | 633 | cairo_surface_flush(cairo_get_target(m_cr)); |
634 | int words = m_image->numBytes() / 4; |
||
635 | QRgb *s = (QRgb*)(tmp_image.bits()); |
||
636 | QRgb *d = (QRgb*)(m_image->bits()); |
||
7175 | fschmid | 637 | QRgb src, dst; |
638 | uchar src_a, src_r, src_g, src_b, dst_a, dst_r, dst_g, dst_b; |
||
639 | int layOpa; |
||
5373 | fschmid | 640 | for(int x = 0; x < words; ++x ) |
641 | { |
||
7175 | fschmid | 642 | src = (*s); |
643 | dst = (*d); |
||
644 | src_a = qAlpha(src); |
||
5469 | fschmid | 645 | if (src_a > 0) |
5373 | fschmid | 646 | { |
7175 | fschmid | 647 | src_r = qRed(src); |
648 | src_g = qGreen(src); |
||
649 | src_b = qBlue(src); |
||
650 | dst_a = qAlpha(dst); |
||
651 | dst_r = qRed(dst); |
||
652 | dst_g = qGreen(dst); |
||
653 | dst_b = qBlue(dst); |
||
654 | layOpa = qRound(255 * m_layerTransparency); |
||
5433 | fschmid | 655 | src_a = INT_MULT(src_a, layOpa); |
5469 | fschmid | 656 | if ((dst_a > 0) && (src_a > 0)) |
5433 | fschmid | 657 | (*d) = qRgba((dst_r * (255 - layOpa) + src_r * layOpa) / 255, (dst_g * (255 - layOpa) + src_g * layOpa) / 255, (dst_b * (255 - layOpa) + src_b * layOpa) / 255, dst_a + INT_MULT(255 - dst_a, src_a)); |
5469 | fschmid | 658 | else if (src_a > 0) |
5433 | fschmid | 659 | (*d) = qRgba(src_r, src_g, src_b, src_a); |
5373 | fschmid | 660 | } |
661 | s++; |
||
662 | d++; |
||
663 | } |
||
5471 | fschmid | 664 | #endif |
7199 | fschmid | 665 | */ |
5373 | fschmid | 666 | } |
5699 | avox | 667 | //HAVE_CAIRO |
5373 | fschmid | 668 | #endif |
669 | |||
68 | Franz | 670 | void ScPainter::begin() |
671 | { |
||
672 | } |
||
673 | |||
674 | void ScPainter::end() |
||
675 | { |
||
5373 | fschmid | 676 | #ifdef HAVE_CAIRO |
5471 | fschmid | 677 | if (svgMode) |
678 | cairo_show_page (m_cr); |
||
5373 | fschmid | 679 | if (layeredMode) |
680 | { |
||
7199 | fschmid | 681 | /* |
5471 | fschmid | 682 | #if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 6) |
5373 | fschmid | 683 | endLayer(); |
5471 | fschmid | 684 | #endif |
7199 | fschmid | 685 | */ |
5433 | fschmid | 686 | cairo_surface_flush(cairo_get_target(m_cr)); |
5373 | fschmid | 687 | cairo_restore( m_cr ); |
688 | return; |
||
689 | } |
||
690 | #endif |
||
1815 | fschmid | 691 | if (imageMode) |
692 | { |
||
3376 | fschmid | 693 | #ifdef HAVE_CAIRO |
694 | cairo_surface_flush(cairo_get_target(m_cr)); |
||
695 | cairo_restore( m_cr ); |
||
696 | #else |
||
1815 | fschmid | 697 | QRgb * bits = (QRgb *) m_image->bits(); |
698 | int words = m_image->numBytes() / 4; |
||
699 | art_u8 * p = m_buffer;; |
||
700 | for (int i=0; i < words; ++i) |
||
701 | { |
||
702 | art_u8 r = *p++; |
||
703 | art_u8 g = *p++; |
||
704 | art_u8 b = *p++; |
||
705 | art_u8 a = *p++; |
||
706 | *bits++ = qRgba(r,g,b,a); |
||
707 | } |
||
3113 | fschmid | 708 | #endif |
1815 | fschmid | 709 | } |
710 | else |
||
711 | { |
||
3113 | fschmid | 712 | #ifdef HAVE_CAIRO |
713 | cairo_surface_flush(cairo_get_target(m_cr)); |
||
5810 | avox | 714 | #ifdef Q_WS_X11 |
3113 | fschmid | 715 | bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height ); |
5810 | avox | 716 | #elif defined(_WIN32) |
717 | bitBlt( m_target, m_x, m_y, &pixm, 0, 0, m_width, m_height ); |
||
718 | #elif defined(SC_USE_QUARTZ) |
||
719 | // ??? |
||
720 | #else |
||
721 | bitBlt( m_target, m_x, m_y, &m_img, 0, 0, m_width, m_height ); |
||
722 | #endif |
||
3113 | fschmid | 723 | cairo_restore( m_cr ); |
5699 | avox | 724 | #else |
725 | // not HAVE_CAIRO |
||
726 | #if defined(Q_WS_X11) && defined(SC_USE_PIXBUF) |
||
1815 | fschmid | 727 | // Use the original gdk-pixbuf based bitblit on X11 |
728 | xlib_draw_rgb_32_image( m_target->handle(), gc, m_x, m_y, m_width, m_height, XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 ); |
||
5699 | avox | 729 | #elif defined(_WIN32) && defined(SC_USE_GDI) |
2686 | craig | 730 | // Use Win32 implementation |
731 | BITMAPINFO bmpInfo; |
||
732 | BITMAPINFOHEADER *bmpHeader; |
||
733 | long* bmpData; |
||
734 | |||
735 | bmpHeader = &(bmpInfo.bmiHeader); |
||
736 | bmpHeader->biSize = sizeof(BITMAPINFOHEADER); |
||
737 | bmpHeader->biWidth = m_width; |
||
738 | bmpHeader->biHeight = -m_height; |
||
739 | bmpHeader->biPlanes = 1; |
||
740 | bmpHeader->biBitCount = 32; |
||
741 | bmpHeader->biCompression = BI_RGB; |
||
742 | bmpHeader->biSizeImage = 0; // Valid only if biCompression = BI_RGB |
||
743 | bmpHeader->biXPelsPerMeter = 0; |
||
744 | bmpHeader->biYPelsPerMeter = 0; |
||
745 | bmpHeader->biClrUsed = 0; |
||
746 | bmpHeader->biClrImportant = 0; |
||
747 | |||
748 | // Create a device independent Bitmap |
||
749 | HBITMAP hBmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, (void** ) (&bmpData), NULL, NULL); |
||
750 | art_u8 * p = m_buffer; |
||
751 | art_u8 r, g, b, a; |
||
752 | int words = m_width * m_height; // Valid only if biBitCount = 32 |
||
753 | |||
754 | for (int i = 0; i < words; ++i) { |
||
755 | r = *p++; |
||
756 | g = *p++; |
||
757 | b = *p++; |
||
758 | a = *p++; |
||
759 | *bmpData++ = ( (a << 24) + (r << 16) + (g << 8) + b); |
||
760 | } |
||
761 | |||
762 | HGDIOBJ obj = SelectObject( dc, hBmp); |
||
763 | BitBlt( m_target->handle() , m_x, m_y, m_width, m_height, dc, 0, 0, SRCCOPY); |
||
764 | SelectObject( dc, obj); |
||
765 | DeleteObject( hBmp ); |
||
5699 | avox | 766 | #else |
1815 | fschmid | 767 | // Portable copying onto the canvas with no X11 dependency by Andreas Vox |
768 | QImage qimg(m_width, m_height, 32, QImage::BigEndian); |
||
769 | QRgb * bits = (QRgb *) qimg.bits(); |
||
770 | int words = qimg.numBytes() / 4; |
||
771 | art_u8 * p = m_buffer;; |
||
772 | for (int i=0; i < words; ++i) { |
||
773 | art_u8 r = *p++; |
||
774 | art_u8 g = *p++; |
||
775 | art_u8 b = *p++; |
||
776 | art_u8 a = *p++; |
||
777 | *bits++ = qRgba(r,g,b,a); |
||
778 | } |
||
779 | bitBlt(m_target, m_x, m_y, &qimg); |
||
5699 | avox | 780 | #endif |
1815 | fschmid | 781 | #endif |
1669 | craig | 782 | } |
68 | Franz | 783 | } |
784 | |||
1624 | fschmid | 785 | void ScPainter::clear() |
68 | Franz | 786 | { |
3113 | fschmid | 787 | #ifdef HAVE_CAIRO |
3376 | fschmid | 788 | if (imageMode) |
789 | m_image->fill( qRgba(255, 255, 255, 255) ); |
||
5810 | avox | 790 | else { |
791 | if (! m_img.isNull()) |
||
792 | m_img.fill( qRgba(255, 255, 255, 255) ); |
||
793 | else |
||
794 | pixm.fill( Qt::white ); |
||
795 | } |
||
3113 | fschmid | 796 | #else |
68 | Franz | 797 | if( m_buffer ) |
214 | Franz | 798 | memset( m_buffer, 255, m_width * m_height * 4 ); |
3113 | fschmid | 799 | #endif |
68 | Franz | 800 | } |
801 | |||
1624 | fschmid | 802 | void ScPainter::clear( const QColor &c ) |
68 | Franz | 803 | { |
3113 | fschmid | 804 | #ifdef HAVE_CAIRO |
3376 | fschmid | 805 | QRgb cs = c.rgb(); |
806 | if (imageMode) |
||
807 | m_image->fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) ); |
||
5810 | avox | 808 | else { |
809 | if (!m_img.isNull()) |
||
810 | m_img.fill( qRgba(qRed(cs), qGreen(cs), qBlue(cs), qAlpha(cs)) ); |
||
811 | else |
||
812 | pixm.fill( c ); |
||
813 | } |
||
3113 | fschmid | 814 | #else |
68 | Franz | 815 | if( m_buffer ) |
214 | Franz | 816 | { |
817 | unsigned int *src = (unsigned int*)m_buffer; |
||
818 | unsigned int co = qRgba(c.blue(), c.green(), c.red(), 255); |
||
819 | for(unsigned int cc = 0; cc < (m_width * m_height); ++cc) |
||
820 | { |
||
821 | *src++ = co; |
||
822 | } |
||
823 | } |
||
3113 | fschmid | 824 | #endif |
68 | Franz | 825 | } |
826 | |||
3113 | fschmid | 827 | const QWMatrix ScPainter::worldMatrix() |
828 | { |
||
829 | #ifdef HAVE_CAIRO |
||
830 | cairo_matrix_t matrix; |
||
831 | cairo_get_matrix(m_cr, &matrix); |
||
832 | QWMatrix mat; |
||
833 | mat.setMatrix ( matrix.xx, matrix.yx, matrix.xy, matrix.yy, matrix.x0, matrix.y0 ); |
||
834 | return mat; |
||
835 | #else |
||
836 | return m_matrix; |
||
837 | #endif |
||
838 | } |
||
839 | |||
68 | Franz | 840 | void ScPainter::setWorldMatrix( const QWMatrix &mat ) |
841 | { |
||
3113 | fschmid | 842 | #ifdef HAVE_CAIRO |
843 | cairo_matrix_t matrix; |
||
844 | cairo_matrix_init(&matrix, mat.m11(), mat.m12(), mat.m21(), mat.m22(), mat.dx(), mat.dy()); |
||
845 | cairo_set_matrix(m_cr, &matrix); |
||
846 | #else |
||
68 | Franz | 847 | m_matrix = mat; |
3113 | fschmid | 848 | #endif |
68 | Franz | 849 | } |
850 | |||
6809 | fschmid | 851 | #ifdef HAVE_CAIRO |
852 | void ScPainter::setAntialiasing(bool enable) |
||
853 | { |
||
854 | if (enable) |
||
855 | cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_DEFAULT); |
||
856 | else |
||
857 | cairo_set_antialias(m_cr, CAIRO_ANTIALIAS_NONE); |
||
858 | } |
||
859 | #endif |
||
860 | |||
68 | Franz | 861 | void ScPainter::setZoomFactor( double zoomFactor ) |
862 | { |
||
863 | m_zoomFactor = zoomFactor; |
||
7141 | fschmid | 864 | #ifdef HAVE_CAIRO |
865 | cairo_scale (m_cr, m_zoomFactor, m_zoomFactor); |
||
866 | #endif |
||
68 | Franz | 867 | } |
868 | |||
869 | void ScPainter::translate( double x, double y ) |
||
870 | { |
||
3113 | fschmid | 871 | #ifdef HAVE_CAIRO |
872 | cairo_translate (m_cr, x, y); |
||
873 | #else |
||
68 | Franz | 874 | m_matrix.translate(x, y); |
3113 | fschmid | 875 | #endif |
68 | Franz | 876 | } |
877 | |||
878 | void ScPainter::rotate( double r ) |
||
879 | { |
||
3113 | fschmid | 880 | #ifdef HAVE_CAIRO |
881 | cairo_rotate (m_cr, r * 3.1415927 / 180.0); |
||
882 | #else |
||
68 | Franz | 883 | m_matrix.rotate(r); |
3113 | fschmid | 884 | #endif |
68 | Franz | 885 | } |
886 | |||
887 | void ScPainter::scale( double x, double y ) |
||
888 | { |
||
3113 | fschmid | 889 | #ifdef HAVE_CAIRO |
890 | cairo_scale (m_cr, x, y); |
||
891 | #else |
||
68 | Franz | 892 | m_matrix.scale(x, y); |
3113 | fschmid | 893 | #endif |
68 | Franz | 894 | } |
895 | |||
896 | void ScPainter::moveTo( const double &x, const double &y ) |
||
897 | { |
||
3113 | fschmid | 898 | #ifdef HAVE_CAIRO |
7141 | fschmid | 899 | cairo_move_to( m_cr, x, y); |
3113 | fschmid | 900 | #else |
68 | Franz | 901 | ensureSpace( m_index + 1 ); |
902 | m_path[ m_index ].code = ART_MOVETO; |
||
903 | m_path[ m_index ].x3 = x * m_zoomFactor; |
||
904 | m_path[ m_index ].y3 = y * m_zoomFactor; |
||
905 | m_index++; |
||
3113 | fschmid | 906 | #endif |
68 | Franz | 907 | } |
908 | |||
4646 | subik | 909 | void |
68 | Franz | 910 | ScPainter::lineTo( const double &x, const double &y ) |
911 | { |
||
3113 | fschmid | 912 | #ifdef HAVE_CAIRO |
7141 | fschmid | 913 | cairo_line_to( m_cr, x, y); |
3113 | fschmid | 914 | #else |
68 | Franz | 915 | ensureSpace( m_index + 1 ); |
916 | m_path[ m_index ].code = ART_LINETO; |
||
917 | m_path[ m_index ].x3 = x * m_zoomFactor; |
||
918 | m_path[ m_index ].y3 = y * m_zoomFactor; |
||
919 | m_index++; |
||
3113 | fschmid | 920 | #endif |
68 | Franz | 921 | } |
922 | |||
923 | void ScPainter::curveTo( FPoint p1, FPoint p2, FPoint p3 ) |
||
924 | { |
||
3113 | fschmid | 925 | #ifdef HAVE_CAIRO |
7141 | fschmid | 926 | cairo_curve_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y()); |
3113 | fschmid | 927 | #else |
68 | Franz | 928 | ensureSpace( m_index + 1 ); |
929 | m_path[ m_index ].code = ART_CURVETO; |
||
86 | Franz | 930 | m_path[ m_index ].x1 = p1.x() * m_zoomFactor; |
931 | m_path[ m_index ].y1 = p1.y() * m_zoomFactor; |
||
932 | m_path[ m_index ].x2 = p2.x() * m_zoomFactor; |
||
933 | m_path[ m_index ].y2 = p2.y() * m_zoomFactor; |
||
934 | m_path[ m_index ].x3 = p3.x() * m_zoomFactor; |
||
935 | m_path[ m_index ].y3 = p3.y() * m_zoomFactor; |
||
68 | Franz | 936 | m_index++; |
3113 | fschmid | 937 | #endif |
68 | Franz | 938 | } |
939 | |||
940 | void ScPainter::newPath() |
||
941 | { |
||
3113 | fschmid | 942 | #ifdef HAVE_CAIRO |
943 | cairo_new_path( m_cr ); |
||
944 | #else |
||
68 | Franz | 945 | m_index = 0; |
3113 | fschmid | 946 | #endif |
68 | Franz | 947 | } |
948 | |||
5233 | fschmid | 949 | void ScPainter::closePath() |
950 | { |
||
951 | #ifdef HAVE_CAIRO |
||
952 | cairo_close_path( m_cr ); |
||
953 | #else |
||
954 | ensureSpace( m_index + 1 ); |
||
955 | m_path[ m_index ].code = ART_END; |
||
956 | m_index++; |
||
957 | #endif |
||
958 | } |
||
959 | |||
68 | Franz | 960 | void ScPainter::setFillRule( bool fillRule ) |
961 | { |
||
962 | m_fillRule = fillRule; |
||
963 | } |
||
964 | |||
965 | void ScPainter::setFillMode( int fill ) |
||
966 | { |
||
967 | fillMode = fill; |
||
968 | } |
||
969 | |||
970 | void ScPainter::setGradient(VGradient::VGradientType mode, FPoint orig, FPoint vec, FPoint foc) |
||
971 | { |
||
972 | fill_gradient.setType(mode); |
||
973 | fill_gradient.setOrigin(orig); |
||
974 | fill_gradient.setVector(vec); |
||
975 | fill_gradient.setFocalPoint(foc); |
||
976 | } |
||
977 | |||
1998 | fschmid | 978 | void ScPainter::fillTextPath() |
979 | { |
||
3113 | fschmid | 980 | #ifdef HAVE_CAIRO |
981 | drawVPath( 0 ); |
||
982 | #else |
||
1998 | fschmid | 983 | ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 ); |
984 | drawVPath( path, 0, true ); |
||
3113 | fschmid | 985 | #endif |
1998 | fschmid | 986 | } |
987 | |||
988 | void ScPainter::strokeTextPath() |
||
989 | { |
||
990 | if( LineWidth == 0 ) |
||
991 | return; |
||
3113 | fschmid | 992 | #ifdef HAVE_CAIRO |
993 | drawVPath( 1 ); |
||
994 | #else |
||
1998 | fschmid | 995 | ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 ); |
996 | drawVPath( path, 1, true ); |
||
3113 | fschmid | 997 | #endif |
1998 | fschmid | 998 | } |
999 | |||
68 | Franz | 1000 | void ScPainter::fillPath() |
1001 | { |
||
3113 | fschmid | 1002 | #ifdef HAVE_CAIRO |
1003 | if( fillMode != 0) |
||
1004 | drawVPath( 0 ); |
||
1005 | #else |
||
4646 | subik | 1006 | if( m_index == 0 ) |
1998 | fschmid | 1007 | return; |
68 | Franz | 1008 | if( fillMode != 0) |
384 | Franz | 1009 | { |
68 | Franz | 1010 | ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 ); |
1011 | drawVPath( path, 0 ); |
||
384 | Franz | 1012 | } |
3113 | fschmid | 1013 | #endif |
68 | Franz | 1014 | } |
1015 | |||
1016 | void ScPainter::strokePath() |
||
1017 | { |
||
3113 | fschmid | 1018 | if( LineWidth == 0 ) |
1019 | return; |
||
1020 | #ifdef HAVE_CAIRO |
||
1021 | drawVPath( 1 ); |
||
1022 | #else |
||
68 | Franz | 1023 | if( m_index == 0 ) |
1024 | return; |
||
1025 | if( m_path[ m_index ].code != ART_END) |
||
1026 | m_path[ m_index ].code = ART_END; |
||
1027 | ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 ); |
||
1028 | drawVPath( path, 1 ); |
||
3113 | fschmid | 1029 | #endif |
68 | Franz | 1030 | } |
1031 | |||
1032 | QColor ScPainter::pen() |
||
1033 | { |
||
1034 | return m_stroke; |
||
1035 | } |
||
1036 | |||
1037 | QColor ScPainter::brush() |
||
1038 | { |
||
1039 | return m_fill; |
||
1040 | } |
||
1041 | |||
1042 | void ScPainter::setPen( const QColor &c ) |
||
1043 | { |
||
1044 | m_stroke = c; |
||
1045 | } |
||
1046 | |||
80 | Franz | 1047 | void ScPainter::setPen( const QColor &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo ) |
68 | Franz | 1048 | { |
1049 | m_stroke = c; |
||
1050 | LineWidth = w; |
||
1051 | PLineEnd = ca; |
||
1052 | PLineJoin = jo; |
||
80 | Franz | 1053 | double Dt = QMAX(2*w, 1); |
1054 | double Da = QMAX(6*w, 1); |
||
1055 | QValueList<double> tmp; |
||
68 | Franz | 1056 | m_array.clear(); |
1057 | m_offset = 0; |
||
1058 | switch (st) |
||
1059 | { |
||
1060 | case Qt::SolidLine: |
||
1061 | break; |
||
1062 | case Qt::DashLine: |
||
1063 | m_array.append(Da); |
||
1064 | m_array.append(Dt); |
||
1065 | break; |
||
1066 | case Qt::DotLine: |
||
1067 | m_array.append(Dt); |
||
1068 | break; |
||
1069 | case Qt::DashDotLine: |
||
1070 | m_array.append(Da); |
||
1071 | m_array.append(Dt); |
||
1072 | m_array.append(Dt); |
||
1073 | m_array.append(Dt); |
||
1074 | break; |
||
1075 | case Qt::DashDotDotLine: |
||
1076 | m_array.append(Da); |
||
1077 | m_array.append(Dt); |
||
1078 | m_array.append(Dt); |
||
1079 | m_array.append(Dt); |
||
1080 | m_array.append(Dt); |
||
1081 | m_array.append(Dt); |
||
1082 | break; |
||
1083 | default: |
||
1084 | break; |
||
1085 | } |
||
1086 | } |
||
1087 | |||
80 | Franz | 1088 | void ScPainter::setLineWidth( double w ) |
68 | Franz | 1089 | { |
1090 | LineWidth = w; |
||
1091 | } |
||
1092 | |||
80 | Franz | 1093 | void ScPainter::setPenOpacity( double op ) |
68 | Franz | 1094 | { |
1095 | stroke_trans = op; |
||
1096 | } |
||
1097 | |||
1098 | |||
80 | Franz | 1099 | void ScPainter::setDash(const QValueList<double>& array, double ofs) |
68 | Franz | 1100 | { |
1101 | m_array = array; |
||
1102 | m_offset = ofs; |
||
1103 | } |
||
1104 | |||
1105 | void ScPainter::setBrush( const QColor &c ) |
||
1106 | { |
||
1107 | m_fill = c; |
||
1108 | } |
||
1109 | |||
80 | Franz | 1110 | void ScPainter::setBrushOpacity( double op ) |
68 | Franz | 1111 | { |
1112 | fill_trans = op; |
||
1113 | } |
||
1114 | |||
80 | Franz | 1115 | void ScPainter::setOpacity( double op ) |
68 | Franz | 1116 | { |
1117 | fill_trans = op; |
||
1118 | stroke_trans = op; |
||
1119 | } |
||
1120 | |||
1121 | void ScPainter::setFont( const QFont &f) |
||
1122 | { |
||
1123 | m_font = f; |
||
1124 | } |
||
1125 | |||
1126 | QFont ScPainter::font() |
||
1127 | { |
||
1128 | return m_font; |
||
1129 | } |
||
1130 | |||
1131 | void ScPainter::save() |
||
1132 | { |
||
3113 | fschmid | 1133 | #ifdef HAVE_CAIRO |
1134 | cairo_save( m_cr ); |
||
1135 | #else |
||
68 | Franz | 1136 | MStack.push(m_matrix); |
3113 | fschmid | 1137 | #endif |
68 | Franz | 1138 | } |
1139 | |||
1140 | void ScPainter::restore() |
||
1141 | { |
||
3113 | fschmid | 1142 | #ifdef HAVE_CAIRO |
1143 | cairo_restore( m_cr ); |
||
1144 | #else |
||
68 | Franz | 1145 | m_matrix = MStack.pop(); |
3113 | fschmid | 1146 | #endif |
68 | Franz | 1147 | } |
1148 | |||
3240 | fschmid | 1149 | void ScPainter::setRasterOp( int ) |
68 | Franz | 1150 | { |
1151 | } |
||
1152 | |||
6414 | fschmid | 1153 | void ScPainter::setPattern(ScPattern *pattern, double scaleX, double scaleY, double offsetX, double offsetY, double rotation) |
6368 | fschmid | 1154 | { |
6369 | fschmid | 1155 | m_pattern = pattern; |
6414 | fschmid | 1156 | patternScaleX = scaleX / 100.0; |
1157 | patternScaleY = scaleY / 100.0; |
||
1158 | patternOffsetX = offsetX; |
||
1159 | patternOffsetY = offsetY; |
||
1160 | patternRotation = rotation; |
||
6368 | fschmid | 1161 | } |
1162 | |||
1163 | #ifdef HAVE_CAIRO |
||
3113 | fschmid | 1164 | void ScPainter::drawVPath( int mode ) |
68 | Franz | 1165 | { |
3113 | fschmid | 1166 | cairo_save( m_cr ); |
1167 | if (mode == 0) |
||
1168 | { |
||
1169 | if( m_fillRule ) |
||
1170 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_EVEN_ODD); |
||
1171 | else |
||
1172 | cairo_set_fill_rule (m_cr, CAIRO_FILL_RULE_WINDING); |
||
6368 | fschmid | 1173 | if (fillMode == 1) |
3113 | fschmid | 1174 | { |
6368 | fschmid | 1175 | double r = qRed( m_fill.rgb() ) / 255.0; |
1176 | double g = qGreen( m_fill.rgb() ) / 255.0; |
||
1177 | double b = qBlue( m_fill.rgb() ) / 255.0; |
||
1178 | cairo_set_source_rgba( m_cr, r, g, b, fill_trans ); |
||
1179 | cairo_fill_preserve( m_cr ); |
||
1180 | } |
||
1181 | else if (fillMode == 2) |
||
1182 | { |
||
3113 | fschmid | 1183 | cairo_pattern_t *pat; |
7141 | fschmid | 1184 | double x1 = fill_gradient.origin().x(); |
1185 | double y1 = fill_gradient.origin().y(); |
||
1186 | double x2 = fill_gradient.vector().x(); |
||
1187 | double y2 = fill_gradient.vector().y(); |
||
3113 | fschmid | 1188 | if (fill_gradient.type() == VGradient::linear) |
1189 | pat = cairo_pattern_create_linear (x1, y1, x2, y2); |
||
1190 | else |
||
1191 | pat = cairo_pattern_create_radial (x1, y1, 0.1, x1, y1, sqrt(pow(x2 - x1, 2) + pow(y2 - y1,2))); |
||
1192 | QPtrVector<VColorStop> colorStops = fill_gradient.colorStops(); |
||
7175 | fschmid | 1193 | QColor qStopColor; |
3113 | fschmid | 1194 | for( uint offset = 0 ; offset < colorStops.count() ; offset++ ) |
1195 | { |
||
7175 | fschmid | 1196 | qStopColor = colorStops[ offset ]->color; |
6795 | jghali | 1197 | int h, s, v, sneu, vneu; |
3113 | fschmid | 1198 | int shad = colorStops[offset]->shade; |
6795 | jghali | 1199 | qStopColor.hsv(&h, &s, &v); |
1200 | sneu = s * shad / 100; |
||
1201 | vneu = 255 - ((255 - v) * shad / 100); |
||
1202 | qStopColor.setHsv(h, sneu, vneu); |
||
3113 | fschmid | 1203 | double r = qRed( qStopColor.rgb() ) / 255.0; |
1204 | double g = qGreen( qStopColor.rgb() ) / 255.0; |
||
1205 | double b = qBlue( qStopColor.rgb() ) / 255.0; |
||
1206 | double a = colorStops[offset]->opacity; |
||
6368 | fschmid | 1207 | cairo_pattern_add_color_stop_rgba (pat, colorStops[ offset ]->rampPoint, r, g, b, a); |
3113 | fschmid | 1208 | } |
1209 | cairo_set_source (m_cr, pat); |
||
1210 | cairo_clip_preserve (m_cr); |
||
6368 | fschmid | 1211 | cairo_paint_with_alpha (m_cr, fill_trans); |
3113 | fschmid | 1212 | cairo_pattern_destroy (pat); |
1213 | } |
||
6368 | fschmid | 1214 | else if (fillMode == 3) |
3113 | fschmid | 1215 | { |
6620 | fschmid | 1216 | cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)m_pattern->getPattern()->bits(), CAIRO_FORMAT_RGB24, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width()*4); |
6369 | fschmid | 1217 | cairo_pattern_t *m_pat = cairo_pattern_create_for_surface(image2); |
1218 | cairo_pattern_set_extend(m_pat, CAIRO_EXTEND_REPEAT); |
||
6608 | fschmid | 1219 | QImage mask; |
1220 | cairo_surface_t *image3; |
||
1221 | if (fill_trans != 1.0) |
||
1222 | { |
||
1223 | mask.create(m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), 8); |
||
7175 | fschmid | 1224 | QRgb * s; |
1225 | unsigned char *d; |
||
6608 | fschmid | 1226 | for( int yi = 0; yi < m_pattern->getPattern()->height(); ++yi ) |
1227 | { |
||
7175 | fschmid | 1228 | s = (QRgb*)(m_pattern->getPattern()->scanLine( yi )); |
1229 | d = (unsigned char *)(mask.scanLine( yi )); |
||
6608 | fschmid | 1230 | for( int xi=0; xi < m_pattern->getPattern()->width(); ++xi ) |
1231 | { |
||
1232 | *d++ = static_cast<unsigned char>(qAlpha(*s++) * fill_trans); |
||
1233 | } |
||
1234 | } |
||
1235 | int adj; |
||
1236 | if (m_pattern->getPattern()->width() % 4 == 0) |
||
1237 | adj = 0; |
||
1238 | else |
||
1239 | adj = 4 - (m_pattern->getPattern()->width() % 4); |
||
1240 | image3 = cairo_image_surface_create_for_data ((uchar*)mask.bits(), CAIRO_FORMAT_A8, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width() + adj); |
||
1241 | } |
||
1242 | else |
||
1243 | image3 = cairo_image_surface_create_for_data ((uchar*)m_pattern->getPattern()->bits(), CAIRO_FORMAT_ARGB32, m_pattern->getPattern()->width(), m_pattern->getPattern()->height(), m_pattern->getPattern()->width()*4); |
||
6368 | fschmid | 1244 | cairo_matrix_t matrix; |
6414 | fschmid | 1245 | QWMatrix qmatrix; |
7141 | fschmid | 1246 | // qmatrix.scale(m_zoomFactor, m_zoomFactor); |
6414 | fschmid | 1247 | qmatrix.translate(patternOffsetX, patternOffsetY); |
1248 | qmatrix.rotate(patternRotation); |
||
1249 | qmatrix.scale(patternScaleX, patternScaleY); |
||
1250 | cairo_matrix_init(&matrix, qmatrix.m11(), qmatrix.m12(), qmatrix.m21(), qmatrix.m22(), qmatrix.dx(), qmatrix.dy()); |
||
1251 | cairo_matrix_invert(&matrix); |
||
6368 | fschmid | 1252 | cairo_pattern_set_matrix (m_pat, &matrix); |
1253 | cairo_set_source (m_cr, m_pat); |
||
1254 | cairo_clip_preserve (m_cr); |
||
6608 | fschmid | 1255 | cairo_pattern_t *m_pat2 = cairo_pattern_create_for_surface(image3); |
1256 | cairo_pattern_set_extend(m_pat2, CAIRO_EXTEND_REPEAT); |
||
1257 | cairo_pattern_set_matrix (m_pat2, &matrix); |
||
1258 | cairo_mask (m_cr, m_pat2); |
||
6368 | fschmid | 1259 | cairo_pattern_destroy (m_pat); |
6608 | fschmid | 1260 | cairo_pattern_destroy (m_pat2); |
1261 | cairo_surface_destroy (image2); |
||
1262 | cairo_surface_destroy (image3); |
||
3113 | fschmid | 1263 | } |
1264 | } |
||
1265 | else |
||
1266 | { |
||
7980 | fschmid | 1267 | double *dashes = NULL; |
7141 | fschmid | 1268 | cairo_set_line_width( m_cr, LineWidth ); |
3113 | fschmid | 1269 | if( m_array.count() > 0 ) |
1270 | { |
||
1271 | dashes = new double[ m_array.count() ]; |
||
1272 | for( uint i = 0; i < m_array.count();++ i ) |
||
1273 | { |
||
7141 | fschmid | 1274 | dashes[i] = static_cast<double>(m_array[i]); |
3113 | fschmid | 1275 | } |
7141 | fschmid | 1276 | cairo_set_dash( m_cr, dashes, m_array.count(), static_cast<double>(m_offset)); |
3113 | fschmid | 1277 | } |
1278 | else |
||
1279 | cairo_set_dash( m_cr, NULL, 0, 0 ); |
||
1280 | double r = qRed( m_stroke.rgb() ) / 255.0; |
||
1281 | double g = qGreen( m_stroke.rgb() ) / 255.0; |
||
1282 | double b = qBlue( m_stroke.rgb() ) / 255.0; |
||
6368 | fschmid | 1283 | cairo_set_source_rgba( m_cr, r, g, b, stroke_trans ); |
3113 | fschmid | 1284 | if( PLineEnd == Qt::RoundCap ) |
1285 | cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_ROUND); |
||
1286 | else if( PLineEnd == Qt::SquareCap ) |
||
1287 | cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_SQUARE); |
||
1288 | else if( PLineEnd == Qt::FlatCap ) |
||
1289 | cairo_set_line_cap (m_cr, CAIRO_LINE_CAP_BUTT); |
||
1290 | if( PLineJoin == Qt::RoundJoin ) |
||
1291 | cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_ROUND ); |
||
1292 | else if( PLineJoin == Qt::BevelJoin ) |
||
1293 | cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_BEVEL ); |
||
1294 | else if( PLineJoin == Qt::MiterJoin ) |
||
1295 | cairo_set_line_join( m_cr, CAIRO_LINE_JOIN_MITER ); |
||
1296 | cairo_stroke_preserve( m_cr ); |
||
1297 | if( m_array.count() > 0 ) |
||
1298 | delete [] dashes; |
||
1299 | } |
||
1300 | cairo_restore( m_cr ); |
||
1301 | #else |
||
5699 | avox | 1302 | // not HAVE_CAIRO |
4646 | subik | 1303 | void ScPainter::drawVPath( struct _ArtVpath *vec, int mode, bool preCal ) |
68 | Franz | 1304 | { |
1305 | ArtSVP *strokeSvp = 0L; |
||
1306 | ArtSVP *fillSvp = 0L; |
||
1998 | fschmid | 1307 | if (!preCal) |
1308 | { |
||
1309 | double affine[6]; |
||
1310 | affine[0] = m_matrix.m11(); |
||
1311 | affine[1] = m_matrix.m12(); |
||
1312 | affine[2] = m_matrix.m21(); |
||
1313 | affine[3] = m_matrix.m22(); |
||
1314 | affine[4] = m_matrix.dx(); |
||
1315 | affine[5] = m_matrix.dy(); |
||
1316 | ArtVpath *temp1 = art_vpath_affine_transform( vec, affine ); |
||
1317 | art_free( vec ); |
||
1318 | vec = temp1; |
||
1319 | } |
||
68 | Franz | 1320 | int af = 0; |
1321 | int as = 0; |
||
1322 | art_u32 fillColor = 0; |
||
1323 | QColor color; |
||
1324 | if (mode == 0) |
||
1325 | { |
||
1326 | color = m_fill; |
||
1327 | af = qRound( 255 * fill_trans ); |
||
86 | Franz | 1328 | #ifdef WORDS_BIGENDIAN |
1329 | fillColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 ); |
||
1330 | #else |
||
1331 | fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red(); |
||
1332 | #endif |
||
68 | Franz | 1333 | ArtSvpWriter *swr; |
1334 | ArtSVP *temp; |
||
6461 | fschmid | 1335 | ArtSVP *temp2; |
68 | Franz | 1336 | temp = art_svp_from_vpath( vec ); |
1337 | if( m_fillRule ) |
||
1338 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN ); |
||
1339 | else |
||
1340 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO ); |
||
1341 | art_svp_intersector( temp, swr ); |
||
1342 | fillSvp = art_svp_writer_rewind_reap( swr ); |
||
1343 | art_svp_free( temp ); |
||
1344 | } |
||
1345 | art_u32 strokeColor = 0; |
||
1346 | if (mode == 1) |
||
1347 | { |
||
1348 | ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT; |
||
1349 | ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER; |
||
1350 | color = m_stroke; |
||
1351 | as = qRound( 255 * stroke_trans ); |
||
86 | Franz | 1352 | #ifdef WORDS_BIGENDIAN |
5699 | avox | 1353 | strokeColor = ( color.red() << 24 ) | ( color.green() << 16 ) | ( color.blue() << 8 ); |
86 | Franz | 1354 | #else |
68 | Franz | 1355 | strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red(); |
86 | Franz | 1356 | #endif |
3113 | fschmid | 1357 | double ratio = m_zoomFactor; |
68 | Franz | 1358 | if( m_array.count() > 0 ) |
1359 | { |
||
1360 | ArtVpathDash dash; |
||
1361 | dash.offset = static_cast<double>(m_offset) * ratio; |
||
1362 | dash.n_dash = m_array.count(); |
||
1363 | double *dashes = new double[ dash.n_dash ]; |
||
1364 | for( int i = 0; i < dash.n_dash; i++ ) |
||
1365 | { |
||
1366 | dashes[i] = static_cast<double>(m_array[i]) * ratio; |
||
1367 | } |
||
1368 | dash.dash = dashes; |
||
1369 | ArtVpath *vec2 = art_vpath_dash( vec, &dash ); |
||
1370 | art_free( vec ); |
||
1371 | vec = vec2; |
||
1372 | delete [] dashes; |
||
1373 | } |
||
1374 | if( PLineEnd == Qt::RoundCap ) |
||
1375 | capStyle = ART_PATH_STROKE_CAP_ROUND; |
||
1376 | else if( PLineEnd == Qt::SquareCap ) |
||
1377 | capStyle = ART_PATH_STROKE_CAP_SQUARE; |
||
1378 | if( PLineJoin == Qt::RoundJoin ) |
||
1379 | joinStyle = ART_PATH_STROKE_JOIN_ROUND; |
||
1380 | else if( PLineJoin == Qt::BevelJoin ) |
||
1381 | joinStyle = ART_PATH_STROKE_JOIN_BEVEL; |
||
5096 | mrdocs | 1382 | //strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 ); |
1383 | ArtVpath* strokeVpath = art_svp_vpath_stroke_raw( vec, joinStyle, capStyle, ratio * LineWidth, 10, 0.25 ); |
||
1384 | strokeSvp = art_svp_from_vpath( strokeVpath ); |
||
1385 | art_free(strokeVpath); |
||
68 | Franz | 1386 | } |
1387 | int x0, y0, x1, y1; |
||
237 | Franz | 1388 | if(( fillSvp ) && (mode == 0)) |
68 | Franz | 1389 | { |
1390 | if (fillMode == 2) |
||
1391 | applyGradient( fillSvp, true ); |
||
6368 | fschmid | 1392 | else if (fillMode == 3) |
1393 | applyPattern(fillSvp); |
||
68 | Franz | 1394 | else |
6368 | fschmid | 1395 | { |
68 | Franz | 1396 | clampToViewport( *fillSvp, x0, y0, x1, y1 ); |
1397 | if( x0 != x1 && y0 != y1 ) |
||
1398 | art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 ); |
||
6368 | fschmid | 1399 | } |
68 | Franz | 1400 | art_svp_free( fillSvp ); |
1401 | } |
||
237 | Franz | 1402 | if(( strokeSvp ) && (mode == 1)) |
68 | Franz | 1403 | { |
1404 | clampToViewport( *strokeSvp, x0, y0, x1, y1 ); |
||
1405 | if( x0 != x1 && y0 != y1 ) |
||
1406 | art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 ); |
||
1407 | art_svp_free( strokeSvp ); |
||
1408 | } |
||
1409 | art_free( vec ); |
||
3113 | fschmid | 1410 | #endif |
68 | Franz | 1411 | } |
1412 | |||
267 | Franz | 1413 | void ScPainter::setClipPath() |
1414 | { |
||
3113 | fschmid | 1415 | #ifdef HAVE_CAIRO |
1416 | cairo_clip (m_cr); |
||
1417 | #else |
||
267 | Franz | 1418 | ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 ); |
1419 | double affine[6]; |
||
1420 | affine[0] = m_matrix.m11(); |
||
632 | fschmid | 1421 | affine[1] = m_matrix.m12(); |
1422 | affine[2] = m_matrix.m21(); |
||
267 | Franz | 1423 | affine[3] = m_matrix.m22(); |
1424 | affine[4] = m_matrix.dx(); |
||
1425 | affine[5] = m_matrix.dy(); |
||
1426 | ArtVpath *temp1 = art_vpath_affine_transform( vec, affine ); |
||
1427 | art_free( vec ); |
||
1428 | ArtSvpWriter *swr; |
||
268 | Franz | 1429 | ArtSVP *temp = art_svp_from_vpath( temp1 ); |
267 | Franz | 1430 | if( m_fillRule ) |
1431 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN ); |
||
1432 | else |
||
1433 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO ); |
||
1434 | art_svp_intersector( temp, swr ); |
||
1435 | m_clipPath = art_svp_writer_rewind_reap( swr ); |
||
1436 | art_svp_free( temp ); |
||
268 | Franz | 1437 | art_free( temp1 ); |
3113 | fschmid | 1438 | #endif |
267 | Franz | 1439 | } |
1440 | |||
5699 | avox | 1441 | #ifdef HAVE_CAIRO |
1442 | #else |
||
4748 | fschmid | 1443 | void ScPainter::setClipPath2(FPointArray *points, bool closed) |
1444 | { |
||
1445 | setClipPath(); |
||
1446 | setupPolygon(points, closed); |
||
1447 | ArtVpath *vec = art_bez_path_to_vec( m_path , 0.25 ); |
||
1448 | double affine[6]; |
||
1449 | affine[0] = m_matrix.m11(); |
||
1450 | affine[1] = m_matrix.m12(); |
||
1451 | affine[2] = m_matrix.m21(); |
||
1452 | affine[3] = m_matrix.m22(); |
||
1453 | affine[4] = m_matrix.dx(); |
||
1454 | affine[5] = m_matrix.dy(); |
||
1455 | ArtVpath *temp1 = art_vpath_affine_transform( vec, affine ); |
||
1456 | art_free( vec ); |
||
1457 | ArtSvpWriter *swr; |
||
1458 | ArtSVP *temp = art_svp_from_vpath( temp1 ); |
||
1459 | if( m_fillRule ) |
||
1460 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN ); |
||
1461 | else |
||
1462 | swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO ); |
||
1463 | art_svp_intersector( temp, swr ); |
||
1464 | temp = art_svp_writer_rewind_reap( swr ); |
||
1465 | ArtSVP *temp2 = art_svp_intersect( temp, m_clipPath ); |
||
1466 | m_clipPath = temp2; |
||
1467 | art_svp_free( temp ); |
||
1468 | art_free( temp1 ); |
||
1469 | } |
||
5699 | avox | 1470 | // not HAVE_CAIRO |
4748 | fschmid | 1471 | #endif |
1472 | |||
270 | Franz | 1473 | void ScPainter::drawImage( QImage *image ) |
68 | Franz | 1474 | { |
3113 | fschmid | 1475 | #ifdef HAVE_CAIRO |
6856 | fschmid | 1476 | #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 6) |
1477 | /* Code with Layers, crashes on cairo_push_group */ |
||
7141 | fschmid | 1478 | // cairo_scale(m_cr, m_zoomFactor, m_zoomFactor); |
6312 | fschmid | 1479 | cairo_push_group(m_cr); |
3113 | fschmid | 1480 | cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr)); |
6312 | fschmid | 1481 | cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4); |
1482 | cairo_surface_t *image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4); |
||
1483 | cairo_set_source_surface (m_cr, image2, 0, 0); |
||
1484 | cairo_mask_surface (m_cr, image3, 0, 0); |
||
1485 | cairo_surface_destroy (image2); |
||
1486 | cairo_surface_destroy (image3); |
||
1487 | cairo_pop_group_to_source (m_cr); |
||
1488 | cairo_paint_with_alpha (m_cr, fill_trans); |
||
6856 | fschmid | 1489 | #else |
6312 | fschmid | 1490 | /* Working code, sadly we need to create an additional mask image with the same size as the image to be painted */ |
6314 | fschmid | 1491 | cairo_surface_t *image3; |
1492 | QImage mask; |
||
6312 | fschmid | 1493 | cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr)); |
1494 | cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_RGB24, image->width(), image->height(), image->width()*4); |
||
6314 | fschmid | 1495 | if (fill_trans != 1.0) |
6312 | fschmid | 1496 | { |
6315 | fschmid | 1497 | mask.create(image->width(), image->height(), 8); |
6314 | fschmid | 1498 | for( int yi = 0; yi < image->height(); ++yi ) |
6312 | fschmid | 1499 | { |
6314 | fschmid | 1500 | QRgb * s = (QRgb*)(image->scanLine( yi )); |
6315 | fschmid | 1501 | unsigned char *d = (unsigned char *)(mask.scanLine( yi )); |
6314 | fschmid | 1502 | for( int xi=0; xi < image->width(); ++xi ) |
1503 | { |
||
6315 | fschmid | 1504 | *d++ = static_cast<unsigned char>(qAlpha(*s++) * fill_trans); |
6314 | fschmid | 1505 | } |
6312 | fschmid | 1506 | } |
6315 | fschmid | 1507 | int adj; |
1508 | if (image->width() % 4 == 0) |
||
1509 | adj = 0; |
||
1510 | else |
||
1511 | adj = 4 - (image->width() % 4); |
||
1512 | image3 = cairo_image_surface_create_for_data ((uchar*)mask.bits(), CAIRO_FORMAT_A8, image->width(), image->height(), image->width() + adj); |
||
6312 | fschmid | 1513 | } |
6314 | fschmid | 1514 | else |
1515 | image3 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4); |
||
7141 | fschmid | 1516 | // cairo_scale(m_cr, m_zoomFactor, m_zoomFactor); |
3113 | fschmid | 1517 | cairo_set_source_surface (m_cr, image2, 0, 0); |
6312 | fschmid | 1518 | cairo_mask_surface (m_cr, image3, 0, 0); |
1519 | cairo_surface_destroy (image2); |
||
1520 | cairo_surface_destroy (image3); |
||
6856 | fschmid | 1521 | #endif |
6312 | fschmid | 1522 | /* Original Code |
1523 | cairo_set_fill_rule(m_cr, cairo_get_fill_rule(m_cr)); |
||
1524 | cairo_surface_t *image2 = cairo_image_surface_create_for_data ((uchar*)image->bits(), CAIRO_FORMAT_ARGB32, image->width(), image->height(), image->width()*4); |
||
1525 | cairo_scale(m_cr, m_zoomFactor, m_zoomFactor); |
||
1526 | cairo_set_source_surface (m_cr, image2, 0, 0); |
||
3113 | fschmid | 1527 | cairo_paint_with_alpha(m_cr, fill_trans); |
1528 | cairo_surface_destroy (image2); |
||
6312 | fschmid | 1529 | */ |
3113 | fschmid | 1530 | #else |
68 | Franz | 1531 | double affineresult[6]; |
1532 | affineresult[0] = m_matrix.m11() * m_zoomFactor; |
||
1533 | affineresult[1] = m_matrix.m12() * m_zoomFactor; |
||
1534 | affineresult[2] = m_matrix.m21() * m_zoomFactor; |
||
1535 | affineresult[3] = m_matrix.m22() * m_zoomFactor; |
||
632 | fschmid | 1536 | affineresult[4] = m_matrix.dx(); |
1537 | affineresult[5] = m_matrix.dy(); |
||
267 | Franz | 1538 | ksvg_art_rgb_affine_clip( m_clipPath, m_buffer, 0, 0, m_width, m_height, m_width * 4, 4, |
270 | Franz | 1539 | image->bits(), image->width(), image->height(), image->width() * 4, |
267 | Franz | 1540 | affineresult, qRound( 255 * fill_trans ), 0L ); |
1541 | art_svp_free( m_clipPath ); |
||
6461 | fschmid | 1542 | m_clipPath = 0; |
3113 | fschmid | 1543 | #endif |
68 | Franz | 1544 | } |
1545 | |||
264 | Franz | 1546 | void ScPainter::setupPolygon(FPointArray *points, bool closed) |
68 | Franz | 1547 | { |
1548 | bool nPath = true; |
||
1549 | FPoint np, np1, np2, np3; |
||
3113 | fschmid | 1550 | #ifdef HAVE_CAIRO |
68 | Franz | 1551 | if (points->size() > 3) |
3113 | fschmid | 1552 | { |
1553 | newPath(); |
||
1554 | for (uint poi=0; poi<points->size()-3; poi += 4) |
||
68 | Franz | 1555 | { |
3113 | fschmid | 1556 | if (points->point(poi).x() > 900000) |
1557 | { |
||
1558 | nPath = true; |
||
1559 | continue; |
||
1560 | } |
||
1561 | if (nPath) |
||
1562 | { |
||
1563 | np = points->point(poi); |
||
7141 | fschmid | 1564 | cairo_move_to( m_cr, np.x(), np.y()); |
3113 | fschmid | 1565 | nPath = false; |
1566 | } |
||
1567 | np = points->point(poi); |
||
1568 | np1 = points->point(poi+1); |
||
1569 | np2 = points->point(poi+3); |
||
1570 | np3 = points->point(poi+2); |
||
1571 | if ((np == np1) && (np2 == np3)) |
||
7141 | fschmid | 1572 | cairo_line_to( m_cr, np3.x(), np3.y()); |
3113 | fschmid | 1573 | else |
7141 | fschmid | 1574 | cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y()); |
3113 | fschmid | 1575 | } |
1576 | if (closed) |
||
1577 | cairo_close_path( m_cr ); |
||
1578 | } |
||
1579 | #else |
||
5699 | avox | 1580 | // not HAVE_CAIRO |
3113 | fschmid | 1581 | if (points->size() > 3) |
1582 | { |
||
68 | Franz | 1583 | newPath(); |
1584 | for (uint poi=0; poi<points->size()-3; poi += 4) |
||
1585 | { |
||
1586 | if (points->point(poi).x() > 900000) |
||
1587 | { |
||
1588 | nPath = true; |
||
173 | Franz | 1589 | ensureSpace( m_index + 1 ); |
1590 | m_path[ m_index ].code = ART_END; |
||
68 | Franz | 1591 | continue; |
1592 | } |
||
1593 | if (nPath) |
||
1594 | { |
||
1595 | np = points->point(poi); |
||
1596 | ensureSpace( m_index + 1 ); |
||
264 | Franz | 1597 | if (closed) |
1598 | m_path[ m_index ].code = ART_MOVETO; |
||
1599 | else |
||
1600 | m_path[ m_index ].code = ART_MOVETO_OPEN; |
||
86 | Franz | 1601 | m_path[ m_index ].x3 = np.x() * m_zoomFactor; |
1602 | m_path[ m_index ].y3 = np.y() * m_zoomFactor; |
||
68 | Franz | 1603 | m_index++; |
1604 | nPath = false; |
||
1605 | } |
||
1606 | np = points->point(poi); |
||
1607 | np1 = points->point(poi+1); |
||
1608 | np2 = points->point(poi+3); |
||
1609 | np3 = points->point(poi+2); |
||
1610 | ensureSpace( m_index + 1 ); |
||
1611 | if ((np == np1) && (np2 == np3)) |
||
1612 | { |
||
1613 | m_path[ m_index ].code = ART_LINETO; |
||
86 | Franz | 1614 | m_path[ m_index ].x3 = np3.x() * m_zoomFactor; |
1615 | m_path[ m_index ].y3 = np3.y() * m_zoomFactor; |
||
68 | Franz | 1616 | } |
1617 | else |
||
1618 | { |
||
1619 | m_path[ m_index ].code = ART_CURVETO; |
||
86 | Franz | 1620 | m_path[ m_index ].x1 = np1.x() * m_zoomFactor; |
1621 | m_path[ m_index ].y1 = np1.y() * m_zoomFactor; |
||
1622 | m_path[ m_index ].x2 = np2.x() * m_zoomFactor; |
||
1623 | m_path[ m_index ].y2 = np2.y() * m_zoomFactor; |
||
1624 | m_path[ m_index ].x3 = np3.x() * m_zoomFactor; |
||
1625 | m_path[ m_index ].y3 = np3.y() * m_zoomFactor; |
||
68 | Franz | 1626 | } |
1627 | m_index++; |
||
1628 | } |
||
173 | Franz | 1629 | ensureSpace( m_index + 1 ); |
1630 | m_path[ m_index ].code = ART_END; |
||
1631 | m_index++; |
||
68 | Franz | 1632 | } |
3113 | fschmid | 1633 | #endif |
68 | Franz | 1634 | } |
1635 | |||
638 | fschmid | 1636 | void ScPainter::setupTextPolygon(FPointArray *points) |
1637 | { |
||
1638 | bool nPath = true; |
||
1639 | FPoint np, np1, np2, np3; |
||
3113 | fschmid | 1640 | #ifdef HAVE_CAIRO |
1641 | if (points->size() > 3) |
||
1642 | { |
||
1643 | newPath(); |
||
1644 | for (uint poi=0; poi<points->size()-3; poi += 4) |
||
1645 | { |
||
1646 | if (points->point(poi).x() > 900000) |
||
1647 | { |
||
1648 | nPath = true; |
||
1649 | continue; |
||
1650 | } |
||
1651 | if (nPath) |
||
1652 | { |
||
1653 | np = points->point(poi); |
||
1654 | cairo_move_to( m_cr, np.x(), np.y()); |
||
1655 | nPath = false; |
||
1656 | } |
||
1657 | np = points->point(poi); |
||
1658 | np1 = points->point(poi+1); |
||
1659 | np2 = points->point(poi+3); |
||
1660 | np3 = points->point(poi+2); |
||
1661 | if ((np == np1) && (np2 == np3)) |
||
1662 | cairo_line_to( m_cr, np3.x(), np3.y()); |
||
1663 | else |
||
1664 | cairo_curve_to(m_cr, np1.x(), np1.y(), np2.x(), np2.y(), np3.x(), np3.y()); |
||
1665 | } |
||
1666 | cairo_close_path( m_cr ); |
||
1667 | } |
||
1668 | #else |
||
638 | fschmid | 1669 | newPath(); |
1670 | for (uint poi=0; poi<points->size()-3; poi += 4) |
||
1671 | { |
||
1672 | if (points->point(poi).x() > 900000) |
||
1673 | { |
||
1674 | nPath = true; |
||
1675 | ensureSpace( m_index + 1 ); |
||
1676 | m_path[ m_index ].code = ART_END; |
||
1677 | continue; |
||
1678 | } |
||
1679 | if (nPath) |
||
1680 | { |
||
1681 | np = points->point(poi); |
||
1682 | ensureSpace( m_index + 1 ); |
||
1683 | m_path[ m_index ].code = ART_MOVETO; |
||
1684 | m_path[ m_index ].x3 = np.x(); |
||
1685 | m_path[ m_index ].y3 = np.y(); |
||
1686 | m_index++; |
||
1687 | nPath = false; |
||
1688 | } |
||
1689 | np = points->point(poi); |
||
1690 | np1 = points->point(poi+1); |
||
1691 | np2 = points->point(poi+3); |
||
1692 | np3 = points->point(poi+2); |
||
1693 | ensureSpace( m_index + 1 ); |
||
1694 | if ((np == np1) && (np2 == np3)) |
||
1695 | { |
||
1696 | m_path[ m_index ].code = ART_LINETO; |
||
1697 | m_path[ m_index ].x3 = np3.x(); |
||
1698 | m_path[ m_index ].y3 = np3.y(); |
||
1699 | } |
||
1700 | else |
||
1701 | { |
||
1702 | m_path[ m_index ].code = ART_CURVETO; |
||
1703 | m_path[ m_index ].x1 = np1.x(); |
||
1704 | m_path[ m_index ].y1 = np1.y(); |
||
1705 | m_path[ m_index ].x2 = np2.x(); |
||
1706 | m_path[ m_index ].y2 = np2.y(); |
||
1707 | m_path[ m_index ].x3 = np3.x(); |
||
1708 | m_path[ m_index ].y3 = np3.y(); |
||
1709 | } |
||
1710 | m_index++; |
||
1711 | } |
||
1712 | ensureSpace( m_index + 1 ); |
||
1713 | m_path[ m_index ].code = ART_END; |
||
1714 | m_index++; |
||
3113 | fschmid | 1715 | #endif |
638 | fschmid | 1716 | } |
1717 | |||
68 | Franz | 1718 | void ScPainter::drawPolygon() |
1719 | { |
||
1720 | fillPath(); |
||
1721 | } |
||
1722 | |||
1723 | void ScPainter::drawPolyLine() |
||
1724 | { |
||
1725 | strokePath(); |
||
1726 | } |
||
1727 | |||
1728 | void ScPainter::drawLine(FPoint start, FPoint end) |
||
1729 | { |
||
1730 | newPath(); |
||
1731 | moveTo(start.x(), start.y()); |
||
1732 | lineTo(end.x(), end.y()); |
||
1733 | strokePath(); |
||
1734 | } |
||
1735 | |||
1736 | void ScPainter::drawRect(double x, double y, double w, double h) |
||
1737 | { |
||
1738 | newPath(); |
||
1739 | moveTo( x, y ); |
||
1740 | lineTo( x+w, y ); |
||
1741 | lineTo( x+w, y+h ); |
||
1742 | lineTo( x, y+h ); |
||
1743 | lineTo( x, y ); |
||
3113 | fschmid | 1744 | #ifdef HAVE_CAIRO |
1745 | cairo_close_path( m_cr ); |
||
1746 | #else |
||
173 | Franz | 1747 | ensureSpace( m_index + 1 ); |
1748 | m_path[ m_index ].code = ART_END; |
||
1749 | m_index++; |
||
3113 | fschmid | 1750 | #endif |
68 | Franz | 1751 | fillPath(); |
1752 | strokePath(); |
||
1753 | } |
||
3113 | fschmid | 1754 | |
5699 | avox | 1755 | #ifdef HAVE_CAIRO |
1756 | #else |
||
3113 | fschmid | 1757 | void ScPainter::ensureSpace( unsigned int newindex ) |
1758 | { |
||
1759 | if( m_index == 0 ) |
||
1760 | { |
||
1761 | if( !m_path ) |
||
1762 | m_path = art_new( ArtBpath, INITIAL_ALLOC ); |
||
1763 | m_alloccount = INITIAL_ALLOC; |
||
1764 | } |
||
1765 | else if( newindex > m_alloccount ) |
||
1766 | { |
||
1767 | m_alloccount += ALLOC_INCREMENT; |
||
1768 | m_path = art_renew( m_path, ArtBpath, m_alloccount ); |
||
1769 | } |
||
1770 | } |
||
1771 | |||
1772 | void ScPainter::resize( unsigned int w, unsigned int h ) |
||
1773 | { |
||
1774 | if( !m_buffer || w != m_width || h != m_height ) |
||
1775 | { |
||
1776 | // TODO : realloc? |
||
1777 | art_free( m_buffer ); |
||
1778 | m_buffer = 0; |
||
1779 | m_width = w; |
||
1780 | m_height = h; |
||
1781 | if ( m_width != 0 && m_height != 0 ) |
||
1782 | m_buffer = art_new( art_u8, m_width * m_height * 4 ); |
||
1783 | clear(); |
||
1784 | } |
||
1785 | } |
||
1786 | |||
1787 | void ScPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 ) |
||
1788 | { |
||
1789 | x0 = QMAX( x0, 0 ); |
||
1790 | x0 = QMIN( x0, static_cast<int>( m_width ) ); |
||
1791 | y0 = QMAX( y0, 0 ); |
||
1792 | y0 = QMIN( y0, static_cast<int>( m_height ) ); |
||
1793 | x1 = QMAX( x1, 0 ); |
||
1794 | x1 = QMIN( x1, static_cast<int>( m_width ) ); |
||
1795 | y1 = QMAX( y1, 0 ); |
||
1796 | y1 = QMIN( y1, static_cast<int>( m_height ) ); |
||
1797 | } |
||
1798 | |||
4646 | subik | 1799 | void ScPainter::clampToViewport( const _ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 ) |
3113 | fschmid | 1800 | { |
1801 | ArtDRect bbox; |
||
1802 | art_drect_svp( &bbox, &svp ); |
||
1803 | x0 = static_cast<int>( bbox.x0 ); |
||
1804 | x0 = QMAX( x0, 0 ); |
||
1805 | x0 = QMIN( x0, static_cast<int>( m_width ) ); |
||
1806 | y0 = static_cast<int>( bbox.y0 ); |
||
1807 | y0 = QMAX( y0, 0 ); |
||
1808 | y0 = QMIN( y0, static_cast<int>( m_height ) ); |
||
1809 | x1 = static_cast<int>( bbox.x1 ) + 1; |
||
1810 | x1 = QMAX( x1, 0 ); |
||
1811 | x1 = QMIN( x1, static_cast<int>( m_width ) ); |
||
1812 | y1 = static_cast<int>( bbox.y1 ) + 1; |
||
1813 | y1 = QMAX( y1, 0 ); |
||
1814 | y1 = QMIN( y1, static_cast<int>( m_height ) ); |
||
1815 | } |
||
1816 | |||
4646 | subik | 1817 | void ScPainter::applyGradient( _ArtSVP *svp, bool fill ) |
3113 | fschmid | 1818 | { |
1819 | int x0, y0, x1, y1; |
||
1820 | clampToViewport( *svp, x0, y0, x1, y1 ); |
||
1821 | ArtRender *render = 0L; |
||
1822 | VGradient gradient; |
||
1823 | if (fill) |
||
1824 | gradient = fill_gradient; |
||
1825 | else |
||
1826 | gradient = stroke_gradient; |
||
1827 | double opa = fill ? fill_trans : stroke_trans; |
||
1828 | if (gradient.type() == VGradient::linear) |
||
1829 | { |
||
1830 | ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 ); |
||
1831 | linear->spread = ART_GRADIENT_PAD; |
||
1832 | double _x1 = static_cast<double>(gradient.origin().x()); |
||
1833 | double _x2 = static_cast<double>(gradient.vector().x()); |
||
1834 | double _y2 = static_cast<double>(gradient.origin().y()); |
||
1835 | double _y1 = static_cast<double>(gradient.vector().y()); |
||
1836 | double dx = ( _x2 - _x1 ) * m_zoomFactor; |
||
1837 | _y1 = _y1 + m_matrix.dy() / m_zoomFactor; |
||
1838 | _y2 = _y2 + m_matrix.dy() / m_zoomFactor; |
||
1839 | if (dx == 0.0) |
||
1840 | dx = 1; |
||
1841 | double dy = ( _y1 - _y2 ) * m_zoomFactor; |
||
1842 | if (dy == 0.0) |
||
1843 | dy = 1; |
||
1844 | double scale = 1.0 / ( dx * dx + dy * dy ); |
||
1845 | linear->a = dx * scale; |
||
1846 | linear->b = dy * scale; |
||
1847 | linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a + ( _y2 * m_zoomFactor ) * linear->b ); |
||
1848 | int offsets = -1; |
||
1849 | linear->stops = buildStopArray( gradient, offsets ); |
||
1850 | linear->n_stops = offsets; |
||
1851 | if( x0 != x1 && y0 != y1 ) |
||
1852 | { |
||
1853 | render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * static_cast<int>(x0) + m_width * 4 * static_cast<int>(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 ); |
||
1854 | int opacity = static_cast<int>( opa * 255.0 ); |
||
1855 | art_render_svp( render, svp ); |
||
1856 | art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7)); |
||
1857 | art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST ); |
||
1858 | art_render_invoke( render ); |
||
1859 | } |
||
1860 | art_free( linear->stops ); |
||
1861 | art_free( linear ); |
||
1862 | } |
||
1863 | else if( gradient.type() == VGradient::radial ) |
||
1864 | { |
||
1865 | ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 ); |
||
1866 | radial->spread = ART_GRADIENT_PAD; |
||
1867 | radial->affine[0] = m_matrix.m11(); |
||
1868 | radial->affine[1] = m_matrix.m12(); |
||
1869 | radial->affine[2] = m_matrix.m21(); |
||
1870 | radial->affine[3] = m_matrix.m22(); |
||
1871 | radial->affine[4] = m_matrix.dx(); |
||
1872 | radial->affine[5] = m_matrix.dy(); |
||
1873 | double cx = gradient.origin().x() * m_zoomFactor; |
||
1874 | double cy = gradient.origin().y() * m_zoomFactor; |
||
1875 | double fx = gradient.focalPoint().x() * m_zoomFactor; |
||
1876 | double fy = gradient.focalPoint().y() * m_zoomFactor; |
||
1877 | double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) + pow( gradient.vector().y() - gradient.origin().y(), 2 ) ); |
||
1878 | r *= m_zoomFactor; |
||
1879 | radial->fx = (fx - cx) / r; |
||
1880 | radial->fy = (fy - cy) / r; |
||
1881 | double aff1[6], aff2[6]; |
||
1882 | art_affine_scale( aff1, r, r); |
||
1883 | art_affine_translate( aff2, cx, cy ); |
||
1884 | art_affine_multiply( aff1, aff1, aff2 ); |
||
1885 | art_affine_multiply( aff1, aff1, radial->affine ); |
||
1886 | art_affine_invert( radial->affine, aff1 ); |
||
1887 | int offsets = -1; |
||
1888 | radial->stops = buildStopArray( gradient, offsets ); |
||
1889 | radial->n_stops = offsets; |
||
1890 | if( x0 != x1 && y0 != y1 ) |
||
1891 | { |
||
1892 | render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * x0 + m_width * 4 * y0, m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 ); |
||
1893 | int opacity = static_cast<int>( opa * 255.0 ); |
||
1894 | art_render_svp( render, svp ); |
||
1895 | art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7)); |
||
1896 | art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST ); |
||
1897 | art_render_invoke( render ); |
||
1898 | } |
||
1899 | art_free( radial->stops ); |
||
1900 | art_free( radial ); |
||
1901 | } |
||
1902 | } |
||
1903 | |||
1904 | ArtGradientStop * ScPainter::buildStopArray( VGradient &gradient, int &offsets ) |
||
1905 | { |
||
1906 | QPtrVector<VColorStop> colorStops = gradient.colorStops(); |
||
1907 | offsets = colorStops.count(); |
||
1908 | ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 ); |
||
1909 | for( int offset = 0 ; offset < offsets ; offset++ ) |
||
1910 | { |
||
1911 | double ramp = colorStops[ offset ]->rampPoint; |
||
1912 | stopArray[ offset * 2 ].offset = ramp; |
||
1913 | QColor qStopColor = colorStops[ offset ]->color; |
||
6795 | jghali | 1914 | int h, s, v, sneu, vneu; |
3113 | fschmid | 1915 | int shad = colorStops[offset]->shade; |
6795 | jghali | 1916 | qStopColor.hsv(&h, &s, &v); |
1917 | sneu = s * shad / 100; |
||
1918 | vneu = 255 - ((255 - v) * shad / 100); |
||
1919 | qStopColor.setHsv(h, sneu, vneu); |
||
3113 | fschmid | 1920 | int r = qRed( qStopColor.rgb() ); |
1921 | int g = qGreen( qStopColor.rgb() ); |
||
1922 | int b = qBlue( qStopColor.rgb() ); |
||
1923 | art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb()); |
||
1924 | int a = static_cast<int>( colorStops[offset]->opacity * 255.0 ); |
||
1925 | r = (rgba >> 24) * a + 0x80; |
||
1926 | r = (r + (r >> 8)) >> 8; |
||
1927 | g = ((rgba >> 16) & 0xff) * a + 0x80; |
||
1928 | g = (g + (g >> 8)) >> 8; |
||
1929 | b = ((rgba >> 8) & 0xff) * a + 0x80; |
||
1930 | b = (b + (b >> 8)) >> 8; |
||
1931 | stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r); |
||
1932 | stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g); |
||
1933 | stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b); |
||
1934 | stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a); |
||
1935 | if( offset + 1 != offsets ) |
||
1936 | { |
||
1937 | stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint; |
||
1938 | QColor qStopColor2 = colorStops[ offset + 1 ]->color; |
||
1939 | rgba = static_cast<int>(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 | |
||
1940 | static_cast<int>(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 | |
||
1941 | static_cast<int>(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 | |
||
1942 | qAlpha(qStopColor2.rgb()); |
||
1943 | int a = static_cast<int>( colorStops[offset]->opacity * 255.0 ); |
||
1944 | r = (rgba >> 24) * a + 0x80; |
||
1945 | r = (r + (r >> 8)) >> 8; |
||
1946 | g = ((rgba >> 16) & 0xff) * a + 0x80; |
||
1947 | g = (g + (g >> 8)) >> 8; |
||
1948 | b = ((rgba >> 8) & 0xff) * a + 0x80; |
||
1949 | b = (b + (b >> 8)) >> 8; |
||
1950 | stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r); |
||
1951 | stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g); |
||
1952 | stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b); |
||
1953 | stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a); |
||
1954 | } |
||
1955 | } |
||
1956 | offsets = offsets * 2 - 1; |
||
1957 | return stopArray; |
||
1958 | } |
||
6368 | fschmid | 1959 | |
1960 | void ScPainter::applyPattern( ArtSVP *svp) |
||
1961 | { |
||
1962 | if(!svp) |
||
1963 | return; |
||
1964 | int x0, y0, x1, y1; |
||
1965 | clampToViewport( *svp, x0, y0, x1, y1 ); |
||
1966 | ArtRender *render = 0L; |
||
1967 | ArtPattern *pattern = art_new( ArtPattern, 1 ); |
||
1968 | double dx = 0.0; |
||
1969 | double dy =0.0; |
||
6516 | fschmid | 1970 | QImage pat = m_pattern->getPattern()->scale(m_pattern->getPattern()->width() * m_zoomFactor * patternScaleX, m_pattern->getPattern()->height() * m_zoomFactor * patternScaleY); |
6368 | fschmid | 1971 | pattern->twidth = pat.width(); |
1972 | pattern->theight = pat.height(); |
||
1973 | pattern->buffer = pat.bits(); |
||
1974 | pattern->opacity = qRound( 255 * fill_trans ); |
||
6516 | fschmid | 1975 | pattern->angle = patternRotation * 3.1415927 / 180.0; |
6368 | fschmid | 1976 | if( x0 != x1 && y0 != y1 ) |
1977 | { |
||
1978 | render = art_render_new( x0, y0, x1, y1, m_buffer + 4 * int(x0) + m_width * 4 * int(y0), m_width * 4, 3, 8, ART_ALPHA_PREMUL, 0 ); |
||
1979 | art_render_svp( render, svp ); |
||
1980 | art_render_pattern( render, pattern, ART_FILTER_HYPER ); |
||
1981 | } |
||
1982 | if( render ) |
||
1983 | art_render_invoke( render ); |
||
1984 | art_free( pattern ); |
||
1985 | } |
||
5699 | avox | 1986 | //not HAVE_CAIRO |
3113 | fschmid | 1987 | #endif |