diff options
author | Timothy Pearson <[email protected]> | 2012-09-16 15:32:39 -0500 |
---|---|---|
committer | Timothy Pearson <[email protected]> | 2012-09-16 15:32:39 -0500 |
commit | 7d1ad9f6f50c3ba3829b14c0eb9a52836b8d7d5d (patch) | |
tree | 784d3ea1add0f296cfeeaf1e04b692a9b1f689cb | |
parent | 2e57d2cf81ee9f642a59bd20712f80fa9b13ee08 (diff) | |
download | gtk3-tqt-engine-7d1ad9f6f50c3ba3829b14c0eb9a52836b8d7d5d.tar.gz gtk3-tqt-engine-7d1ad9f6f50c3ba3829b14c0eb9a52836b8d7d5d.zip |
Add more primitives to Cairo drawing backend
-rw-r--r-- | tdegtk/tqtcairopainter.cpp | 287 | ||||
-rw-r--r-- | tdegtk/tqtcairopainter.h | 11 | ||||
-rw-r--r-- | tests/test-painter.cpp | 61 |
3 files changed, 315 insertions, 44 deletions
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;i<pointarray->count();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;i<pointarray->count();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<a[k].size(); i++ ) { + aa.setPoint( j, a[k].point(i) ); + j++; + } + } + + // Draw polygon + drawPolygon(&aa, false, true, true); + + return; +} + +void TQt3CairoPaintDevice::drawEllipse(int x, int y, int w, int h) { + if (!m_painter) { + return; + } + + TQPointArray a; + a.makeArc(x, y, w, h, 0, 360*16); + + // Draw polygon + drawPolygon(&a, false, true, true); + + return; +} + +void TQt3CairoPaintDevice::drawArc(int x, int y, int w, int h, int a, int alen) { + if (!m_painter) { + return; + } + + TQPointArray pa; + pa.makeArc(x, y, w, h, a, alen); // arc polyline + + // Draw polygon + drawPolygon(&pa, false, false, false); + + return; +} + +void TQt3CairoPaintDevice::drawPie(int x, int y, int w, int h, int a, int alen) { + if (!m_painter) { + return; + } + + // Make sure "a" is 0..360*16, as otherwise a*4 may overflow 16 bits. + if ( a > (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;i<pointarray->count();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; diff --git a/tests/test-painter.cpp b/tests/test-painter.cpp index 8a2b02e..f932c83 100644 --- a/tests/test-painter.cpp +++ b/tests/test-painter.cpp @@ -65,7 +65,7 @@ main (int argc, char *argv[]) // Polyline tests { TQPointArray a; - int x1 = 200; + int x1 = 250; int y1 = 10; a.setPoints( 11, x1+0, y1+85, x1+75, y1+75, x1+100, y1+10, x1+125, y1+75, x1+200, y1+85, x1+150, y1+125, x1+160, y1+190, x1+100, y1+150, x1+40, y1+190, x1+50, y1+125, x1+0, y1+85 ); @@ -73,6 +73,65 @@ main (int argc, char *argv[]) p.drawPolyline(a); } + // Polyfill tests + { + TQPointArray a; + int x1 = 250; + int y1 = 200; + + a.setPoints( 11, x1+0, y1+85, x1+75, y1+75, x1+100, y1+10, x1+125, y1+75, x1+200, y1+85, x1+150, y1+125, x1+160, y1+190, x1+100, y1+150, x1+40, y1+190, x1+50, y1+125, x1+0, y1+85 ); + p.setPen(TQt::blue); + p.setBrush(TQt::green); + p.drawPolygon(a); + } + + // Rounded rectangle tests + { + p.setBrush(TQt::green); + p.setPen(TQPen(TQt::red, 1)); + p.drawRoundRect(10, 150, 50, 50); + p.setBrush(TQBrush()); + p.setPen(TQPen(TQt::blue, 1)); + p.drawRoundRect(80, 150, 50, 50); + } + + // Ellipse tests + { + p.setBrush(TQt::green); + p.setPen(TQPen(TQt::red, 1)); + p.drawEllipse(10, 220, 50, 50); + p.setBrush(TQBrush()); + p.setPen(TQPen(TQt::blue, 1)); + p.drawEllipse(80, 220, 50, 50); + } + + // Arc tests + { + p.setBrush(TQBrush()); + p.setPen(TQPen(TQt::yellow, 1)); + p.drawArc(10,10, 70,100, 100*16, 160*16); // draws a "(" arc + } + + // Pie tests + { + p.setBrush(TQBrush()); + p.setPen(TQPen(TQt::red, 1)); + p.drawPie(250, 400, 200, 100, 45*16, 90*16); + p.setBrush(TQt::green); + p.setPen(TQPen(TQt::blue, 1)); + p.drawPie(250, 450, 200, 100, 45*16, 90*16); + } + + // Chord tests + { + p.setBrush(TQBrush()); + p.setPen(TQPen(TQt::red, 1)); + p.drawChord(100, 400, 200, 100, 45*16, 90*16); + p.setBrush(TQt::green); + p.setPen(TQPen(TQt::blue, 1)); + p.drawChord(100, 450, 200, 100, 45*16, 90*16); + } + p.end(); /* Write output and clean up */ |