00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "vkopainter.h"
00023 #include "vstroke.h"
00024 #include "vfill.h"
00025 #include "vcolor.h"
00026 #include "vpattern.h"
00027
00028 #include <qpaintdevice.h>
00029 #include <qpixmap.h>
00030 #include <qpointarray.h>
00031 #include <qimage.h>
00032
00033 #include "libart_lgpl/art_vpath.h"
00034 #include <libart_lgpl/art_bpath.h>
00035 #include <libart_lgpl/art_vpath_bpath.h>
00036 #include <libart_lgpl/art_svp_vpath.h>
00037 #include <libart_lgpl/art_svp_vpath_stroke.h>
00038 #include <libart_lgpl/art_svp.h>
00039 #include <libart_lgpl/art_svp_ops.h>
00040 #include <libart_lgpl/art_affine.h>
00041 #include <libart_lgpl/art_svp_intersect.h>
00042 #include <libart_lgpl/art_rect_svp.h>
00043 #include <libart_lgpl/art_pathcode.h>
00044 #include <libart_lgpl/art_vpath_dash.h>
00045 #include "art_rgba_affine.h"
00046 #include "art_render_misc.h"
00047 #include <libart_lgpl/art_render_svp.h>
00048
00049 #include "art_rgb_svp.h"
00050 #include "art_render_pattern.h"
00051
00052 #include <X11/Xlib.h>
00053
00054 #include <gdk-pixbuf-xlibrgb.h>
00055
00056 #include <kdebug.h>
00057 #include <kglobal.h>
00058 #include <kiconloader.h>
00059 #include <math.h>
00060
00061 #include <KoPoint.h>
00062 #include <KoRect.h>
00063 #include <karbon_factory.h>
00064 #include <karbon_resourceserver.h>
00065
00066
00067 #define INITIAL_ALLOC 300
00068 #define ALLOC_INCREMENT 100
00069
00070 VKoPainter::VKoPainter( QPaintDevice *target, unsigned int w, unsigned int h, bool bDrawNodes )
00071 : VPainter( target, w, h ), m_target( target ), m_bDrawNodes( bDrawNodes )
00072 {
00073
00074
00075 m_width = w;
00076 m_height= h;
00077 m_buffer = 0L;
00078 m_path = 0L;
00079 m_index = 0;
00080 resize( m_width, m_height );
00081 clear();
00082 m_clipPaths.setAutoDelete( false );
00083
00084 m_stroke = 0L;
00085 m_fill = 0L;
00086 m_fillRule = evenOdd;
00087
00088 xlib_rgb_init_with_depth( target->x11Display(), XScreenOfDisplay( target->x11Display(),
00089 target->x11Screen() ), target->x11Depth() );
00090
00091 gc = XCreateGC( target->x11Display(), target->handle(), 0, 0 );
00092
00093 m_zoomFactor = 1;
00094 }
00095
00096 VKoPainter::VKoPainter( unsigned char *buffer, unsigned int w, unsigned int h, bool bDrawNodes )
00097 : VPainter( 0L, w, h ), m_buffer( buffer ), m_bDrawNodes( bDrawNodes )
00098 {
00099
00100
00101 m_target = 0L;
00102 m_width = w;
00103 m_height= h;
00104 m_path = 0L;
00105 m_index = 0;
00106 clear();
00107 m_clipPaths.setAutoDelete( false );
00108
00109 m_stroke = 0L;
00110 m_fill = 0L;
00111
00112 gc = 0L;
00113
00114 m_zoomFactor = 1;
00115 }
00116
00117 VKoPainter::~VKoPainter()
00118 {
00119
00120
00121 if( m_target )
00122 art_free( m_buffer );
00123
00124 delete m_stroke;
00125 delete m_fill;
00126 if( m_path )
00127 art_free( m_path );
00128
00129 if( gc )
00130 XFreeGC( m_target->x11Display(), gc );
00131 }
00132
00133 void
00134 VKoPainter::resize( unsigned int w, unsigned int h )
00135 {
00136 if( !m_buffer || w != m_width || h != m_height )
00137 {
00138
00139 art_free( m_buffer );
00140 m_buffer = 0;
00141 m_width = w;
00142 m_height = h;
00143 if ( m_width != 0 && m_height != 0 )
00144 m_buffer = art_new( art_u8, m_width * m_height * 4 );
00145 clear();
00146 }
00147 }
00148
00149 void
00150 VKoPainter::begin()
00151 {
00152 }
00153
00154 void
00155 VKoPainter::end()
00156 {
00157
00158
00159 xlib_draw_rgb_32_image( m_target->handle(), gc, 0, 0, m_width, m_height,
00160 XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
00161
00162
00163
00164 }
00165
00166 void
00167 VKoPainter::blit( const KoRect &r )
00168 {
00169
00170
00171 int x = KMAX( 0, int( r.x() ) );
00172 int y = KMAX( 0, int( r.y() ) );
00173 int width = KMIN( m_width, (unsigned int)KMAX( 0, int( r.x() + r.width() ) ) );
00174 int height = KMIN( m_height, (unsigned int)KMAX( 0, int( r.y() + r.height() ) ) );
00175 xlib_draw_rgb_32_image( m_target->handle(), gc, x, y, width - x, height - y,
00176 XLIB_RGB_DITHER_NONE, m_buffer + (x * 4) + (y * m_width * 4), m_width * 4 );
00177 }
00178
00179 void
00180 VKoPainter::clear()
00181 {
00182 if( m_buffer )
00183 memset( m_buffer, qRgba( 255, 255, 255, 255 ), m_width * m_height * 4 );
00184 }
00185
00186 void
00187 VKoPainter::clear( const QColor &c )
00188 {
00189 if( m_buffer )
00190 memset( m_buffer, c.rgb(), m_width * m_height * 4 );
00191 }
00192
00193 void
00194 VKoPainter::clear( const KoRect &r, const QColor &c )
00195 {
00196 unsigned int color = c.rgb();
00197 int x = KMAX( 0, int( r.x() ) );
00198 int y = KMAX( 0, int( r.y() ) );
00199 int width = KMIN( m_width, (unsigned int)KMAX( 0, int( r.x() + r.width() ) ) );
00200 int height = KMIN( m_height, (unsigned int)KMAX( 0, int( r.y() + r.height() ) ) );
00201 if( m_buffer )
00202 {
00203 for( int i = y;i < height;i++)
00204 memset( m_buffer + int( x * 4) + int( i * ( m_width * 4 ) ),
00205 qRgba( qRed( color ), qGreen( color ), qBlue( color ), 100 ), int( width * 4 ) );
00206 }
00207 }
00208
00209 void
00210 VKoPainter::setWorldMatrix( const QWMatrix &mat )
00211 {
00212 m_matrix = mat;
00213 }
00214
00215 void
00216 VKoPainter::setZoomFactor( double zoomFactor )
00217 {
00218 m_zoomFactor = zoomFactor;
00219 }
00220
00221 void
00222 VKoPainter::ensureSpace( unsigned int newindex )
00223 {
00224 if( m_index == 0 )
00225 {
00226 if( !m_path )
00227 m_path = art_new( ArtBpath, INITIAL_ALLOC );
00228 m_alloccount = INITIAL_ALLOC;
00229 }
00230 else if( newindex > m_alloccount )
00231 {
00232 m_alloccount += ALLOC_INCREMENT;
00233 m_path = art_renew( m_path, ArtBpath, m_alloccount );
00234 }
00235 }
00236
00237 void
00238 VKoPainter::moveTo( const KoPoint &p )
00239 {
00240 ensureSpace( m_index + 1 );
00241
00242 m_path[ m_index ].code = ART_MOVETO;
00243
00244 m_path[ m_index ].x3 = p.x() * m_zoomFactor;
00245 m_path[ m_index ].y3 = p.y() * m_zoomFactor;
00246
00247 m_index++;
00248 }
00249
00250 void
00251 VKoPainter::lineTo( const KoPoint &p )
00252 {
00253 ensureSpace( m_index + 1 );
00254
00255 m_path[ m_index ].code = ART_LINETO;
00256 m_path[ m_index ].x3 = p.x() * m_zoomFactor;
00257 m_path[ m_index ].y3 = p.y() * m_zoomFactor;
00258
00259 m_index++;
00260 }
00261
00262 void
00263 VKoPainter::curveTo( const KoPoint &p1, const KoPoint &p2, const KoPoint &p3 )
00264 {
00265 ensureSpace( m_index + 1 );
00266
00267 m_path[ m_index ].code = ART_CURVETO;
00268 m_path[ m_index ].x1 = p1.x() * m_zoomFactor;
00269 m_path[ m_index ].y1 = p1.y() * m_zoomFactor;
00270 m_path[ m_index ].x2 = p2.x() * m_zoomFactor;
00271 m_path[ m_index ].y2 = p2.y() * m_zoomFactor;
00272 m_path[ m_index ].x3 = p3.x() * m_zoomFactor;
00273 m_path[ m_index ].y3 = p3.y() * m_zoomFactor;
00274
00275 m_index++;
00276 }
00277
00278 void
00279 VKoPainter::newPath()
00280 {
00281 m_index = 0;
00282 }
00283
00284 void
00285 VKoPainter::setFillRule( VFillRule fillRule )
00286 {
00287 m_fillRule = fillRule;
00288 }
00289
00290 void
00291 VKoPainter::fillPath()
00292 {
00293 if( m_index == 0 ) return;
00294
00295
00296 int find = -1;
00297 for( int i = m_index - 1; i >= 0; i-- )
00298 {
00299 if( m_path[i].code == ART_MOVETO_OPEN || m_path[i].code == ART_MOVETO )
00300 {
00301 find = i;
00302 break;
00303 }
00304 }
00305
00306
00307 if( find != -1 && ( m_path[ find ].x3 != m_path[ m_index - 1 ].x3 ||
00308 m_path[ find ].y3 != m_path[ m_index - 1 ].y3 ) )
00309 {
00310 ensureSpace( m_index + 1 );
00311
00312 m_path[ m_index ].code = ART_LINETO;
00313 m_path[ m_index ].x3 = m_path[ find ].x3;
00314 m_path[ m_index ].y3 = m_path[ find ].y3;
00315
00316 m_index++;
00317 m_path[ m_index ].code = ART_END;
00318 }
00319 else
00320 m_path[ m_index++ ].code = ART_END;
00321
00322 if( m_fill && m_fill->type() != VFill::none )
00323 {
00324 ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
00325 drawVPath( path );
00326 }
00327
00328 m_index--;
00329 }
00330
00331 void
00332 VKoPainter::strokePath()
00333 {
00334 if( m_index == 0 ) return;
00335
00336 if( m_stroke && m_stroke->lineWidth() == 0 )
00337 return;
00338 if( m_path[ m_index ].code != ART_END)
00339 m_path[ m_index ].code = ART_END;
00340
00341 ArtVpath *path = art_bez_path_to_vec( m_path , 0.25 );
00342
00343 drawVPath( path );
00344 }
00345
00346 void
00347 VKoPainter::setClipPath()
00348 {
00349 ArtVpath *path;
00350 path = art_bez_path_to_vec( m_path , 0.25 );
00351 m_clipPaths.append( art_svp_from_vpath( path ) );
00352 art_free( path );
00353 }
00354
00355 void
00356 VKoPainter::resetClipPath()
00357 {
00358 art_svp_free( m_clipPaths.current() );
00359 m_clipPaths.remove();
00360 }
00361
00362 void
00363 VKoPainter::setPen( const VStroke &stroke )
00364 {
00365 delete m_stroke;
00366 m_stroke = new VStroke;
00367 *m_stroke = stroke;
00368 }
00369
00370 void
00371 VKoPainter::setPen( const QColor &c )
00372 {
00373 delete m_stroke;
00374 m_stroke = new VStroke;
00375
00376 float r = static_cast<float>( c.red() ) / 255.0;
00377 float g = static_cast<float>( c.green() ) / 255.0;
00378 float b = static_cast<float>( c.blue() ) / 255.0;
00379
00380 VColor color;
00381 color.set( r, g, b );
00382 m_stroke->setColor( color );
00383 }
00384
00385 void
00386 VKoPainter::setPen( Qt::PenStyle style )
00387 {
00388 if( style == Qt::NoPen )
00389 {
00390 delete m_stroke;
00391 m_stroke = 0L;
00392 }
00393 }
00394
00395 void
00396 VKoPainter::setBrush( const QColor &c )
00397 {
00398 delete m_fill;
00399 m_fill = new VFill;
00400
00401 float r = static_cast<float>( c.red() ) / 255.0;
00402 float g = static_cast<float>( c.green() ) / 255.0;
00403 float b = static_cast<float>( c.blue() ) / 255.0;
00404
00405 VColor color;
00406 color.set( r, g, b );
00407 m_fill->setColor( color );
00408 }
00409
00410 void
00411 VKoPainter::setBrush( Qt::BrushStyle style )
00412 {
00413 if( style == Qt::NoBrush )
00414 {
00415 delete m_fill;
00416 m_fill = 0L;
00417 }
00418 }
00419
00420 void
00421 VKoPainter::setBrush( const VFill &fill )
00422 {
00423 delete m_fill;
00424 m_fill = new VFill;
00425 *m_fill = fill;
00426 }
00427
00428 void
00429 VKoPainter::save()
00430 {
00431 }
00432
00433 void
00434 VKoPainter::restore()
00435 {
00436 }
00437
00438 void
00439 VKoPainter::setRasterOp( Qt::RasterOp )
00440 {
00441 }
00442
00443 void
00444 VKoPainter::clampToViewport( int &x0, int &y0, int &x1, int &y1 )
00445 {
00446
00447 x0 = kMax( x0, 0 );
00448 x0 = kMin( x0, int( m_width ) );
00449 y0 = kMax( y0, 0 );
00450 y0 = kMin( y0, int ( m_height ) );
00451 x1 = kMax( x1, 0 );
00452 x1 = kMin( x1, int( m_width ) );
00453 y1 = kMax( y1, 0 );
00454 y1 = kMin( y1, int( m_height ) );
00455 }
00456
00457 void
00458 VKoPainter::clampToViewport( const ArtSVP &svp, int &x0, int &y0, int &x1, int &y1 )
00459 {
00460
00461 ArtDRect bbox;
00462 art_drect_svp( &bbox, &svp );
00463
00464
00465
00466
00467 x0 = int( bbox.x0 );
00468 x0 = kMax( x0, 0 );
00469 x0 = kMin( x0, int( m_width ) );
00470 y0 = int( bbox.y0 );
00471 y0 = kMax( y0, 0 );
00472 y0 = kMin( y0, int ( m_height ) );
00473 x1 = int( bbox.x1 ) + 1;
00474 x1 = kMax( x1, 0 );
00475 x1 = kMin( x1, int( m_width ) );
00476 y1 = int( bbox.y1 ) + 1;
00477 y1 = kMax( y1, 0 );
00478 y1 = kMin( y1, int( m_height ) );
00479 }
00480
00481 void
00482 VKoPainter::drawVPath( ArtVpath *vec )
00483 {
00484 ArtSVP *strokeSvp = 0L;
00485 ArtSVP *fillSvp = 0L;
00486
00487
00488 double affine[6];
00489 affine[0] = m_matrix.m11();
00490 affine[1] = 0;
00491 affine[2] = 0;
00492 affine[3] = m_matrix.m22();
00493 affine[4] = m_matrix.dx();
00494 affine[5] = m_matrix.dy();
00495 ArtVpath *temp = art_vpath_affine_transform( vec, affine );
00496 art_free( vec );
00497 vec = temp;
00498
00499 int af = 0;
00500 int as = 0;
00501 art_u32 fillColor = 0;
00502
00503
00504 QColor color;
00505 if( m_fill && m_fill->type() != VFill::none )
00506 {
00507 color = m_fill->color();
00508 af = qRound( 255 * m_fill->color().opacity() );
00509 fillColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
00510
00511 ArtSvpWriter *swr;
00512 ArtSVP *temp;
00513 temp = art_svp_from_vpath( vec );
00514
00515 if( m_fillRule == evenOdd )
00516 swr = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN );
00517 else
00518 swr = art_svp_writer_rewind_new( ART_WIND_RULE_NONZERO );
00519
00520 art_svp_intersector( temp, swr );
00521 fillSvp = art_svp_writer_rewind_reap( swr );
00522
00523 art_svp_free( temp );
00524 }
00525
00526 art_u32 strokeColor = 0;
00527
00528 if( m_stroke && m_stroke->type() != VStroke::none )
00529 {
00530 ArtPathStrokeCapType capStyle = ART_PATH_STROKE_CAP_BUTT;
00531 ArtPathStrokeJoinType joinStyle = ART_PATH_STROKE_JOIN_MITER;
00532
00533
00534 color = m_stroke->color();
00535 as = qRound( 255 * m_stroke->color().opacity() );
00536 strokeColor = ( 0 << 24 ) | ( color.blue() << 16 ) | ( color.green() << 8 ) | color.red();
00537
00538 double ratio = m_zoomFactor;
00539 if( m_stroke->dashPattern().array().count() > 0 )
00540 {
00541
00542 ArtVpathDash dash;
00543 dash.offset = m_stroke->dashPattern().offset() * ratio;
00544 dash.n_dash = m_stroke->dashPattern().array().count();
00545 double *dashes = new double[ dash.n_dash ];
00546 for( int i = 0; i < dash.n_dash; i++ )
00547 dashes[i] = m_stroke->dashPattern().array()[i] * ratio;
00548
00549 dash.dash = dashes;
00550
00551 ArtVpath *vec2 = art_vpath_dash( vec, &dash );
00552 art_free( vec );
00553
00554 vec = vec2;
00555 delete [] dashes;
00556 }
00557
00558 if( m_stroke->lineCap() == VStroke::capRound )
00559 capStyle = ART_PATH_STROKE_CAP_ROUND;
00560 else if( m_stroke->lineCap() == VStroke::capSquare )
00561 capStyle = ART_PATH_STROKE_CAP_SQUARE;
00562
00563
00564 if( m_stroke->lineJoin() == VStroke::joinRound )
00565 joinStyle = ART_PATH_STROKE_JOIN_ROUND;
00566 else if( m_stroke->lineJoin() == VStroke::joinBevel )
00567 joinStyle = ART_PATH_STROKE_JOIN_BEVEL;
00568
00569
00570 strokeSvp = art_svp_vpath_stroke( vec, joinStyle, capStyle, ratio * m_stroke->lineWidth(), m_stroke->miterLimit(), 0.25 );
00571 }
00572
00573 int x0, y0, x1, y1;
00574
00575
00576 if( strokeSvp )
00577 {
00578 if( m_stroke && m_stroke->type() == VStroke::grad )
00579 applyGradient( strokeSvp, false );
00580 else if( m_stroke && m_stroke->type() == VStroke::patt )
00581 applyPattern( strokeSvp, false );
00582 else
00583 {
00584 clampToViewport( *strokeSvp, x0, y0, x1, y1 );
00585 if( x0 != x1 && y0 != y1 )
00586 art_rgb_svp_alpha_( strokeSvp, x0, y0, x1, y1, strokeColor, as, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
00587 }
00588 art_svp_free( strokeSvp );
00589 }
00590
00591 if( fillSvp )
00592 {
00593 if( m_fill && m_fill->type() == VFill::grad )
00594 applyGradient( fillSvp, true );
00595 else if( m_fill && m_fill->type() == VFill::patt )
00596 applyPattern( fillSvp, true );
00597 else
00598 {
00599 clampToViewport( *fillSvp, x0, y0, x1, y1 );
00600 if( x0 != x1 && y0 != y1 )
00601 art_rgb_svp_alpha_( fillSvp, x0, y0, x1, y1, fillColor, af, m_buffer + x0 * 4 + y0 * m_width * 4, m_width * 4, 0 );
00602 }
00603 art_svp_free( fillSvp );
00604 }
00605
00606
00607
00608
00609
00610
00611 art_free( vec );
00612 }
00613
00614 void
00615 VKoPainter::applyPattern( ArtSVP *svp, bool fill )
00616 {
00617 if(!svp) {
00618 return;
00619 }
00620
00621 int x0, y0, x1, y1;
00622 clampToViewport( *svp, x0, y0, x1, y1 );
00623
00624 ArtRender *render = 0L;
00625
00626 VPattern pat = fill ? m_fill->pattern() : m_stroke->pattern();
00627 if( !pat.isValid() ) {
00628 pat.load( KGlobal::iconLoader()->iconPath( "karbon.png", -KIcon::SizeMedium ) ); }
00629 if( !pat.isValid() ) {
00630 pat = *(dynamic_cast<VPattern *>(KarbonFactory::rServer()->patterns().getFirst() )) ;}
00631
00632 ArtPattern *pattern = art_new( ArtPattern, 1 );
00633
00634 double dx = ( pat.vector().x() - pat.origin().x() ) * m_zoomFactor;
00635 double dy = ( pat.vector().y() - pat.origin().y() ) * m_zoomFactor;
00636
00637 pattern->twidth = pat.tileWidth();
00638 pattern->theight = pat.tileHeight();
00639 pattern->buffer = pat.pixels();
00640 pattern->opacity = fill ? short( m_fill->color().opacity() * 255.0 ) : short( m_stroke->color().opacity() * 255.0 );
00641 pattern->angle = atan2( -dy, dx );
00642
00643 if( x0 != x1 && y0 != y1 )
00644 {
00645 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 );
00646 art_render_svp( render, svp );
00647 art_render_pattern( render, pattern, ART_FILTER_HYPER );
00648 }
00649
00650 if( render )
00651 art_render_invoke( render );
00652 art_free( pattern );
00653 }
00654
00655 void
00656 VKoPainter::applyGradient( ArtSVP *svp, bool fill )
00657 {
00658 int x0, y0, x1, y1;
00659 clampToViewport( *svp, x0, y0, x1, y1 );
00660
00661 ArtRender *render = 0L;
00662
00663 VGradient gradient = fill ? m_fill->gradient() : m_stroke->gradient();
00664 float opa = fill ? m_fill->color().opacity() : m_stroke->color().opacity();
00665
00666 if( gradient.type() == VGradient::linear )
00667 {
00668 ArtGradientLinear *linear = art_new( ArtGradientLinear, 1 );
00669
00670
00671 if( gradient.repeatMethod() == VGradient::none )
00672 linear->spread = ART_GRADIENT_PAD;
00673 else if( gradient.repeatMethod() == VGradient::repeat )
00674 linear->spread = ART_GRADIENT_REPEAT;
00675 else if( gradient.repeatMethod() == VGradient::reflect )
00676 linear->spread = ART_GRADIENT_REFLECT;
00677
00678 double _x1 = gradient.origin().x();
00679 double _x2 = gradient.vector().x();
00680 double _y2 = gradient.origin().y();
00681 double _y1 = gradient.vector().y();
00682
00683 double dx = ( _x2 - _x1 ) * m_zoomFactor;
00684 _y1 = m_matrix.m22() * _y1 + m_matrix.dy() / m_zoomFactor;
00685 _y2 = m_matrix.m22() * _y2 + m_matrix.dy() / m_zoomFactor;
00686 double dy = ( _y1 - _y2 ) * m_zoomFactor;
00687 double scale = 1.0 / ( dx * dx + dy * dy );
00688
00689 linear->a = dx * scale;
00690 linear->b = dy * scale;
00691 linear->c = -( ( _x1 * m_zoomFactor + m_matrix.dx() ) * linear->a +
00692 ( _y2 * m_zoomFactor ) * linear->b );
00693
00694
00695 int offsets = -1;
00696 linear->stops = buildStopArray( gradient, offsets );
00697 linear->n_stops = offsets;
00698
00699 if( x0 != x1 && y0 != y1 && offsets >= 0 )
00700 {
00701 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 );
00702 int opacity = int( opa * 255.0 );
00703 art_render_svp( render, svp );
00704 art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
00705 art_karbon_render_gradient_linear( render, linear, ART_FILTER_NEAREST );
00706 art_render_invoke( render );
00707 }
00708 art_free( linear->stops );
00709 art_free( linear );
00710 }
00711 else if( gradient.type() == VGradient::radial )
00712 {
00713 ArtGradientRadial *radial = art_new( ArtGradientRadial, 1 );
00714
00715
00716 if( gradient.repeatMethod() == VGradient::none )
00717 radial->spread = ART_GRADIENT_PAD;
00718 else if( gradient.repeatMethod() == VGradient::repeat )
00719 radial->spread = ART_GRADIENT_REPEAT;
00720 else if( gradient.repeatMethod() == VGradient::reflect )
00721 radial->spread = ART_GRADIENT_REFLECT;
00722
00723 radial->affine[0] = m_matrix.m11();
00724 radial->affine[1] = m_matrix.m12();
00725 radial->affine[2] = m_matrix.m21();
00726 radial->affine[3] = m_matrix.m22();
00727 radial->affine[4] = m_matrix.dx();
00728 radial->affine[5] = m_matrix.dy();
00729
00730 double cx = gradient.origin().x() * m_zoomFactor;
00731 double cy = gradient.origin().y() * m_zoomFactor;
00732 double fx = gradient.focalPoint().x() * m_zoomFactor;
00733 double fy = gradient.focalPoint().y() * m_zoomFactor;
00734 double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) +
00735 pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
00736 r *= m_zoomFactor;
00737
00738 radial->fx = (fx - cx) / r;
00739 radial->fy = (fy - cy) / r;
00740
00741 double aff1[6], aff2[6];
00742 art_affine_scale( aff1, r, r);
00743 art_affine_translate( aff2, cx, cy );
00744 art_affine_multiply( aff1, aff1, aff2 );
00745 art_affine_multiply( aff1, aff1, radial->affine );
00746 art_affine_invert( radial->affine, aff1 );
00747
00748
00749 int offsets = -1;
00750 radial->stops = buildStopArray( gradient, offsets );
00751 radial->n_stops = offsets;
00752
00753 if( x0 != x1 && y0 != y1 && offsets >= 0 )
00754 {
00755 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 );
00756 int opacity = int( opa * 255.0 );
00757 art_render_svp( render, svp );
00758 art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
00759 art_karbon_render_gradient_radial( render, radial, ART_FILTER_NEAREST );
00760 art_render_invoke( render );
00761 }
00762 art_free( radial->stops );
00763 art_free( radial );
00764 }
00765 else if( gradient.type() == VGradient::conic )
00766 {
00767 ArtGradientConical *conical = art_new( ArtGradientConical, 1 );
00768
00769
00770 if( gradient.repeatMethod() == VGradient::none )
00771 conical->spread = ART_GRADIENT_PAD;
00772 else if( gradient.repeatMethod() == VGradient::repeat )
00773 conical->spread = ART_GRADIENT_REPEAT;
00774 else if( gradient.repeatMethod() == VGradient::reflect )
00775 conical->spread = ART_GRADIENT_REFLECT;
00776
00777 double cx = gradient.origin().x() * m_zoomFactor;
00778 cx = m_matrix.m11() * cx + m_matrix.dx();
00779 double cy = gradient.origin().y() * m_zoomFactor;
00780 cy = m_matrix.m22() * cy + m_matrix.dy();
00781 double r = sqrt( pow( gradient.vector().x() - gradient.origin().x(), 2 ) +
00782 pow( gradient.vector().y() - gradient.origin().y(), 2 ) );
00783 r *= m_zoomFactor;
00784
00785 conical->cx = cx;
00786 conical->cy = cy;
00787 conical->r = r;
00788
00789
00790 int offsets = -1;
00791 conical->stops = buildStopArray( gradient, offsets );
00792 conical->n_stops = offsets;
00793
00794 if( x0 != x1 && y0 != y1 && offsets >= 0 )
00795 {
00796 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 );
00797 int opacity = int( opa * 255.0 );
00798 art_render_svp( render, svp );
00799 art_render_mask_solid (render, (opacity << 8) + opacity + (opacity >> 7));
00800 art_karbon_render_gradient_conical( render, conical, ART_FILTER_NEAREST );
00801 art_render_invoke( render );
00802 }
00803 art_free( conical->stops );
00804 art_free( conical );
00805 }
00806 }
00807
00808 ArtGradientStop *
00809 VKoPainter::buildStopArray( VGradient &gradient, int &offsets )
00810 {
00811
00812 QPtrVector<VColorStop> colorStops = gradient.colorStops();
00813 offsets = colorStops.count();
00814
00815 ArtGradientStop *stopArray = art_new( ArtGradientStop, offsets * 2 - 1 );
00816
00817 for( int offset = 0 ; offset < offsets ; offset++ )
00818 {
00819 double ramp = colorStops[ offset ]->rampPoint;
00820
00821 stopArray[ offset * 2 ].offset = ramp;
00822
00823 QColor qStopColor = colorStops[ offset ]->color;
00824 int r = qRed( qStopColor.rgb() );
00825 int g = qGreen( qStopColor.rgb() );
00826 int b = qBlue( qStopColor.rgb() );
00827 art_u32 rgba = (r << 24) | (g << 16) | (b << 8) | qAlpha(qStopColor.rgb());
00828
00829 int a = int( colorStops[ offset]->color.opacity() * 255.0 );
00830 r = (rgba >> 24) * a + 0x80;
00831 r = (r + (r >> 8)) >> 8;
00832 g = ((rgba >> 16) & 0xff) * a + 0x80;
00833 g = (g + (g >> 8)) >> 8;
00834 b = ((rgba >> 8) & 0xff) * a + 0x80;
00835 b = (b + (b >> 8)) >> 8;
00836 stopArray[ offset * 2 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
00837 stopArray[ offset * 2 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
00838 stopArray[ offset * 2 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
00839 stopArray[ offset * 2 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
00840
00841 if( offset + 1 != offsets )
00842 {
00843 stopArray[ offset * 2 + 1 ].offset = ramp + ( colorStops[ offset + 1 ]->rampPoint - ramp ) * colorStops[ offset ]->midPoint;
00844
00845 QColor qStopColor2 = colorStops[ offset + 1 ]->color;
00846 rgba = int(r + ((qRed(qStopColor2.rgb()) - r)) * 0.5) << 24 |
00847 int(g + ((qGreen(qStopColor2.rgb()) - g)) * 0.5) << 16 |
00848 int(b + ((qBlue(qStopColor2.rgb()) - b)) * 0.5) << 8 |
00849 qAlpha(qStopColor2.rgb());
00850
00851 int a = int( colorStops[ offset]->color.opacity() * 255.0 );
00852 r = (rgba >> 24) * a + 0x80;
00853 r = (r + (r >> 8)) >> 8;
00854 g = ((rgba >> 16) & 0xff) * a + 0x80;
00855 g = (g + (g >> 8)) >> 8;
00856 b = ((rgba >> 8) & 0xff) * a + 0x80;
00857 b = (b + (b >> 8)) >> 8;
00858 stopArray[ offset * 2 + 1 ].color[ 0 ] = ART_PIX_MAX_FROM_8(r);
00859 stopArray[ offset * 2 + 1 ].color[ 1 ] = ART_PIX_MAX_FROM_8(g);
00860 stopArray[ offset * 2 + 1 ].color[ 2 ] = ART_PIX_MAX_FROM_8(b);
00861 stopArray[ offset * 2 + 1 ].color[ 3 ] = ART_PIX_MAX_FROM_8(a);
00862 }
00863 }
00864
00865 offsets = offsets * 2 - 1;
00866 return stopArray;
00867 }
00868
00869 void
00870 VKoPainter::drawNode( const KoPoint& p, int width )
00871 {
00872 if( !m_bDrawNodes ) return;
00873
00874 KoPoint _p( m_matrix.map( QPoint( int( p.x() * m_zoomFactor ), int( p.y() * m_zoomFactor ) ) ) );
00875 int x1 = int( _p.x() - width );
00876 int x2 = int( _p.x() + width );
00877 int y1 = int( _p.y() - width );
00878 int y2 = int( _p.y() + width );
00879
00880 clampToViewport( x1, y1, x2, y2 );
00881
00882 int baseindex = 4 * x1 + ( m_width * 4 * y1 );
00883
00884 QColor color = m_fill->color();
00885 for( int i = 0; i < y2 - y1; i++ )
00886 {
00887 for( int j = 0; j < x2 - x1; j++ )
00888 {
00889 m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) ] = color.red();
00890 m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 1 ] = color.green();
00891 m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 2 ] = color.blue();
00892 m_buffer[ baseindex + 4 * j + ( m_width * 4 * i ) + 3 ] = 0xFF;
00893 }
00894 }
00895 }
00896
00897 void
00898 VKoPainter::drawImage( const QImage &image, const QWMatrix &affine )
00899 {
00900
00901 double affineresult[6];
00902
00903 affineresult[0] = affine.m11() * m_matrix.m11() * m_zoomFactor + affine.m12() * m_matrix.m21();
00904 affineresult[1] = (affine.m11() * m_matrix.m12() + affine.m12() * m_matrix.m22() ) * m_zoomFactor;
00905 affineresult[2] = (affine.m21() * m_matrix.m11() + affine.m22() * m_matrix.m21() ) * m_zoomFactor;
00906 affineresult[3] = affine.m22() * m_matrix.m22() * m_zoomFactor + affine.m21() * m_matrix.m12();
00907 affineresult[4] = m_matrix.dx() + affine.dx() * m_zoomFactor;
00908 affineresult[5] = m_matrix.dy() - affine.dy() * m_zoomFactor;
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 art_rgba_affine( m_buffer, 0, 0, m_width, m_height, m_width * 4,
00921 image.bits(), image.width(), image.height(), image.width() * 4,
00922 affineresult, ART_FILTER_NEAREST, 0L );
00923 }
00924
00925 void
00926 VKoPainter::drawRect( const KoRect &r )
00927 {
00928 newPath();
00929 moveTo( r.topLeft() );
00930 lineTo( r.topRight() );
00931 lineTo( r.bottomRight() );
00932 lineTo( r.bottomLeft() );
00933 lineTo( r.topLeft() );
00934 fillPath();
00935 strokePath();
00936 }
00937
00938 void
00939 VKoPainter::drawRect( double x, double y, double w, double h )
00940 {
00941 drawRect( KoRect( x, y, w, h ) );
00942 }
00943