From 7d1ad9f6f50c3ba3829b14c0eb9a52836b8d7d5d Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 16 Sep 2012 15:32:39 -0500 Subject: Add more primitives to Cairo drawing backend --- tdegtk/tqtcairopainter.cpp | 287 ++++++++++++++++++++++++++++++++++++++------- tdegtk/tqtcairopainter.h | 11 +- 2 files changed, 255 insertions(+), 43 deletions(-) (limited to 'tdegtk') diff --git a/tdegtk/tqtcairopainter.cpp b/tdegtk/tqtcairopainter.cpp index ae440b7..8f917e1 100644 --- a/tdegtk/tqtcairopainter.cpp +++ b/tdegtk/tqtcairopainter.cpp @@ -99,16 +99,16 @@ void TQt3CairoPaintDevice::dualStrokePen() { cairo_stroke(m_painter); } -void TQt3CairoPaintDevice::dualStrokeBrush() { +void TQt3CairoPaintDevice::dualStrokeBrush(cairo_fill_rule_t fillMethod) { if (m_bgColorMode == TQt::OpaqueMode) { // Draw background cairo_save(m_painter); - updateBrush(TRUE); + updateBrush(TRUE, fillMethod); cairo_fill(m_painter); cairo_restore(m_painter); } // Draw foreground - updateBrush(FALSE); + updateBrush(FALSE, fillMethod); cairo_fill(m_painter); } @@ -222,7 +222,7 @@ void TQt3CairoPaintDevice::updatePen(bool backgroundStroke) { cairo_set_source_rgba(m_painter, tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color)); } -void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke) { +void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t fillMethod) { if (!m_painter) { return; } @@ -338,6 +338,203 @@ void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke) { cairo_pattern_destroy(pattern); } } + cairo_set_fill_rule(m_painter, fillMethod); +} + +static inline void fix_neg_rect( int *x, int *y, int *w, int *h ) { + if ( *w < 0 ) { + *w = -*w + 2; + *x -= *w - 1; + } + if ( *h < 0 ) { + *h = -*h + 2; + *y -= *h - 1; + } +} + +void TQt3CairoPaintDevice::drawPolygon(const TQPointArray* pointarray, bool winding, bool fill, bool close) { + int i; + + if (m_painter) { + cairo_save(m_painter); + if (pointarray) { + int x; + int y; + bool first; + if ((m_brush.style() != TQBrush::NoBrush) && fill) { + first = true; + for (i=0;icount();i++) { + pointarray->point(i, &x, &y ); + if (first) { + cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + first = false; + } + else { + cairo_line_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + } + } + if (close) { + cairo_close_path(m_painter); + } + dualStrokeBrush((winding)?CAIRO_FILL_RULE_EVEN_ODD:CAIRO_FILL_RULE_WINDING); + } + if (m_pen.style() != TQPen::NoPen) { + first = true; + for (i=0;icount();i++) { + pointarray->point(i, &x, &y ); + if (first) { + cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + first = false; + } + else { + cairo_line_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + } + } + if (close) { + cairo_close_path(m_painter); + } + dualStrokePen(); + } + } + cairo_restore(m_painter); + } +} + +void TQt3CairoPaintDevice::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd) { + if (!m_painter) { + return; + } + + if ( xRnd <= 0 || yRnd <= 0 ) { + // Draw normal rectangle + TQPDevCmdParam param[2]; + int command = PdcDrawRect; + TQRect rectangle(x, y, w, h); + param[0].rect = &rectangle; + cmd(command, NULL, param); + return; + } + + if ( xRnd >= 100 ) { // fix ranges + xRnd = 99; + } + if ( yRnd >= 100 ) { + yRnd = 99; + } + + if ( w <= 0 || h <= 0 ) { + fix_neg_rect( &x, &y, &w, &h ); + } + w--; + h--; + int rxx = w*xRnd/200; + int ryy = h*yRnd/200; + // were there overflows? + if ( rxx < 0 ) { + rxx = w/200*xRnd; + } + if ( ryy < 0 ) { + ryy = h/200*yRnd; + } + int rxx2 = 2*rxx; + int ryy2 = 2*ryy; + TQPointArray a[4]; + a[0].makeArc( x, y, rxx2, ryy2, 1*16*90, 16*90 ); + a[1].makeArc( x, y+h-ryy2, rxx2, ryy2, 2*16*90, 16*90 ); + a[2].makeArc( x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*16*90, 16*90 ); + a[3].makeArc( x+w-rxx2, y, rxx2, ryy2, 0*16*90, 16*90 ); + // ### is there a better way to join TQPointArrays? + TQPointArray aa; + aa.resize( a[0].size() + a[1].size() + a[2].size() + a[3].size() ); + uint j = 0; + for ( int k=0; k<4; k++ ) { + for ( uint i=0; i (360*16) ) { + a = a % (360*16); + } + else if ( a < 0 ) { + a = a % (360*16); + if ( a < 0 ) { + a += (360*16); + } + } + + TQPointArray pa; + pa.makeArc(x, y, w, h, a, alen); // arc polyline + int n = pa.size(); + int cx, cy; + cx = x+w/2; + cy = y+h/2; + pa.resize(n+2); + pa.setPoint(n, cx, cy); // add legs + pa.setPoint(n+1, pa.at(0)); + + // Draw polygon + drawPolygon(&pa, false, true, true); + + return; +} + +void TQt3CairoPaintDevice::drawChord(int x, int y, int w, int h, int a, int alen) { + if (!m_painter) { + return; + } + + TQPointArray pa; + pa.makeArc(x, y, w-1, h-1, a, alen); // arc polygon + int n = pa.size(); + pa.resize(n+1); + pa.setPoint(n, pa.at(0)); // connect endpoints + + // Draw polygon + drawPolygon(&pa, false, true, true); + + return; } /*! @@ -478,7 +675,7 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) if (m_brush.style() != TQBrush::NoBrush) { int line_width = m_pen.width(); cairo_rectangle(m_painter, x+line_width+CAIRO_PIXEL_OFFSET, y+line_width+CAIRO_PIXEL_OFFSET, width-(line_width*2), height-(line_width*2)); - dualStrokeBrush(); + dualStrokeBrush(CAIRO_FILL_RULE_EVEN_ODD); } cairo_restore(m_painter); } @@ -488,22 +685,52 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) #endif } break; -#if 0 case PdcDrawRoundRect: - m_qt4painter->drawRoundedRect( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter), p[1].ival, p[2].ival ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + drawRoundRect(x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height, p[1].ival, p[2].ival); + } + cairo_restore(m_painter); + } break; case PdcDrawEllipse: - m_qt4painter->drawEllipse( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter) ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + drawEllipse(x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height); + } + cairo_restore(m_painter); + } break; case PdcDrawArc: - m_qt4painter->drawArc( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter), p[1].ival, p[2].ival ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + drawArc(x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height, p[1].ival, p[2].ival); + } + cairo_restore(m_painter); + } break; case PdcDrawPie: - m_qt4painter->drawPie( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter), p[1].ival, p[2].ival ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + drawPie(x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height, p[1].ival, p[2].ival); + } + cairo_restore(m_painter); + } break; case PdcDrawChord: - m_qt4painter->drawChord( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter), p[1].ival, p[2].ival ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + drawChord(x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height, p[1].ival, p[2].ival); + } + cairo_restore(m_painter); + } break; +#if 0 case PdcDrawLineSegments: index = 0; count = -1; @@ -512,36 +739,16 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) break; #endif case PdcDrawPolyline: - if (m_painter) { - cairo_save(m_painter); - if (p) { - const TQPointArray* pointarray = p[0].ptarr; - if (pointarray) { - int x; - int y; - bool first=true; - for (i=0;icount();i++) { - pointarray->point(i, &x, &y ); - if (first) { - cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); - first = false; - } - else { - cairo_line_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); - } - } - if (m_pen.style() != TQPen::NoPen) { - dualStrokePen(); - } - } - } - cairo_restore(m_painter); + if (p) { + drawPolygon(p[0].ptarr, false, false, true); } break; -#if 0 case PdcDrawPolygon: - m_qt4painter->drawPolygon( qt4polygon, (p[1].ival == 0)?Qt::OddEvenFill:Qt::WindingFill ); + if (p) { + drawPolygon(p[0].ptarr, p[1].ival, true, true); + } break; +#if 0 case PdcDrawCubicBezier: index = 0; path.moveTo(qt4polygon.at(index)); @@ -592,14 +799,12 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) m_painter = NULL; } break; -#if 0 case PdcSave: - m_qt4painter->save(); + cairo_save(m_painter); break; case PdcRestore: - m_qt4painter->restore(); + cairo_restore(m_painter); break; -#endif case PdcSetBkColor: if (p) { const TQColor* color = p[0].color; diff --git a/tdegtk/tqtcairopainter.h b/tdegtk/tqtcairopainter.h index fa051c2..7e43468 100644 --- a/tdegtk/tqtcairopainter.h +++ b/tdegtk/tqtcairopainter.h @@ -44,8 +44,15 @@ class Q_EXPORT TQt3CairoPaintDevice : public TQPaintDevice // picture class void updatePen(bool backgroundStroke=FALSE); void dualStrokePen(); - void updateBrush(bool backgroundStroke=FALSE); - void dualStrokeBrush(); + void updateBrush(bool backgroundStroke=FALSE, cairo_fill_rule_t fillMethod=CAIRO_FILL_RULE_WINDING); + void dualStrokeBrush(cairo_fill_rule_t fillMethod=CAIRO_FILL_RULE_WINDING); + + void drawPolygon(const TQPointArray* pointarray, bool winding, bool fill, bool close); + void drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd); + void drawEllipse(int x, int y, int w, int h); + void drawArc(int x, int y, int w, int h, int a, int alen); + void drawPie(int x, int y, int w, int h, int a, int alen); + void drawChord(int x, int y, int w, int h, int a, int alen); private: cairo_surface_t *m_surface; -- cgit v1.2.1