karbon

vkopainter.cc

00001 /* This file is part of the KDE project.
00002    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 // kopainter/libart wrapper
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     //kdDebug(38000) << "w : " << w << endl;
00074     //kdDebug(38000) << "h : " << h << endl;
00075     m_width = w;//( w > 0 ) ? w : target->width();
00076     m_height= h;//( h > 0 ) ? h : target->height();
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     //kdDebug(38000) << "w : " << w << endl;
00100     //kdDebug(38000) << "h : " << h << endl;
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     // If we are in target mode, we created a buffer, else if we used the other ctor
00120     // we didn't.
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         // TODO : realloc?
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     //xlib_draw_rgb_image( m_target->handle(), gc, 0, 0, m_width, m_height,
00158     //                   XLIB_RGB_DITHER_NONE, m_buffer, m_width * 4 );
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     /*xlib_draw_rgb_image( pix.handle(), gc, 0, 0, m_width, m_height,
00162                          XLIB_RGB_DITHER_NONE, m_buffer, m_width * 3 );
00163     bitBlt( m_target, 0, 0, &pix, 0, 0, m_width, m_height );*/
00164 }
00165 
00166 void
00167 VKoPainter::blit( const KoRect &r )
00168 {
00169     //kdDebug(38000) << "m_width : " << m_width << endl;
00170     //kdDebug(38000) << "m_height : " << m_height << endl;
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     // find begin of last subpath
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     // for now, always close
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     // clamp to viewport
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     // get SVP bbox
00461     ArtDRect bbox;
00462     art_drect_svp( &bbox, &svp );
00463     // Remove comments if we really decide for SVP bbox usage
00464     //m_bbox = KoRect( bbox.x0, bbox.y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0 );
00465 
00466     // clamp to viewport
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     // set up world matrix
00488     double affine[6];
00489     affine[0] = m_matrix.m11();
00490     affine[1] = 0;//m_matrix.m12();
00491     affine[2] = 0;//m_matrix.m21();
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     // filling
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     // stroke
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         // TODO : non rgb support ?
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;//sqrt(pow(affine[0], 2) + pow(affine[3], 2)) / sqrt(2);
00539         if( m_stroke->dashPattern().array().count() > 0 )
00540         {
00541             // there are dashes to be rendered
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             // get the dashed VPath and use that for the stroke render operation
00551             ArtVpath *vec2 = art_vpath_dash( vec, &dash );
00552             art_free( vec );
00553 
00554             vec = vec2;
00555             delete [] dashes;
00556         }
00557         // caps translation karbon -> art
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         // join translation karbon -> art
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         // zoom stroke width;
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     // render the svp to the buffer
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     //delete m_stroke;
00607     //m_stroke = 0L;
00608     //delete m_fill;
00609     //m_fill = 0L;
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         // TODO : make variable
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         // get stop array
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         // TODO : make variable
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         // get stop array
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         // TODO : make variable
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         // get stop array
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     // TODO : make this generic
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         //double mid  = colorStops[ offset ]->midPoint;
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         /* convert from separated to premultiplied alpha */
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             /* convert from separated to premultiplied alpha */
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     // set up world matrix
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     //art_affine_scale( affineresult, m_zoomFactor, m_zoomFactor);
00911     /*kdDebug(38000) << "affineresult[0] : " << affineresult[0] << endl;
00912     kdDebug(38000) << "affineresult[1] : " << affineresult[1] << endl;
00913     kdDebug(38000) << "affineresult[2] : " << affineresult[2] << endl;
00914     kdDebug(38000) << "affineresult[3] : " << affineresult[3] << endl;
00915     kdDebug(38000) << "affineresult[4] : " << affineresult[4] << endl;
00916     kdDebug(38000) << "affineresult[5] : " << affineresult[5] << endl;
00917     kdDebug(38000) << "m_matrix.dx() : " << m_matrix.dx() << endl;
00918     kdDebug(38000) << "affine.dx() : " << affine.dx() << endl;
00919     kdDebug(38000) << "image.height() : " << image.height() << endl;*/
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 
KDE Home | KDE Accessibility Home | Description of Access Keys