summaryrefslogtreecommitdiffstats
path: root/tdegtk/tqtcairopainter.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-09-15 23:02:11 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-09-15 23:02:11 -0500
commitc2a1262df888a6c2913c608614f00dbb41233321 (patch)
treed3a4a39f5702fa403f0134a98322e2bb3b9316b7 /tdegtk/tqtcairopainter.cpp
parent827cba3a39a4afe688bfa848fc7dd7c5899b506f (diff)
downloadgtk3-tqt-engine-c2a1262df888a6c2913c608614f00dbb41233321.tar.gz
gtk3-tqt-engine-c2a1262df888a6c2913c608614f00dbb41233321.zip
Rectangle drawing via Cairo now functions
Diffstat (limited to 'tdegtk/tqtcairopainter.cpp')
-rw-r--r--tdegtk/tqtcairopainter.cpp434
1 files changed, 410 insertions, 24 deletions
diff --git a/tdegtk/tqtcairopainter.cpp b/tdegtk/tqtcairopainter.cpp
index 8b38bc7..6bf5b9f 100644
--- a/tdegtk/tqtcairopainter.cpp
+++ b/tdegtk/tqtcairopainter.cpp
@@ -29,6 +29,317 @@
#include "tqpaintdevicemetrics.h"
#undef Qt
+#define CAIRO_PIXEL_OFFSET (0.5)
+
+#define SET_BIT(x, y) (x |= 1 << y)
+#define TEST_BIT(x, y) ((x & (1 << y)) >> y)
+
+cairo_surface_t* TQImageToCairoSurface(TQImage origimg) {
+ cairo_surface_t* ret;
+
+ TQImage img;
+ if (origimg.depth() < 24) {
+ img = origimg.convertDepth(32);
+ }
+ else {
+ img = origimg;
+ }
+
+ cairo_format_t cairo_format;
+ int depth = img.depth();
+ if (depth == 32) {
+ cairo_format = CAIRO_FORMAT_ARGB32;
+ }
+ else if (depth == 24) {
+ cairo_format = CAIRO_FORMAT_RGB24;
+ }
+ else {
+ cairo_format = CAIRO_FORMAT_RGB24;
+ }
+
+ int stride = cairo_format_stride_for_width(cairo_format, img.width());
+ ret = cairo_image_surface_create_for_data(img.bits(), cairo_format, img.width(), img.height(), stride);
+
+ return ret;
+}
+
+TQImage CairoSurfaceToTQImage(cairo_surface_t* surface) {
+ cairo_surface_flush(surface);
+
+ cairo_format_t cairo_format = cairo_image_surface_get_format(surface);
+ int height = cairo_image_surface_get_height(surface);
+ int width = cairo_image_surface_get_width(surface);
+ int depth;
+ if (cairo_format == CAIRO_FORMAT_ARGB32) {
+ depth = 32;
+ }
+ else if (cairo_format == CAIRO_FORMAT_RGB24) {
+ depth = 24;
+ }
+ else {
+ // FIXME
+ // Force Cairo to convert the surface to a format that TQImage can read!
+ printf("[WARNING] Tried to convert a Cairo surface of format %d to a TQImage (NULL image returned!)\n\r", cairo_format); fflush(stdout);
+ return TQImage();
+ }
+
+ return TQImage(cairo_image_surface_get_data(surface), width, height, depth, (TQRgb*)NULL, 0, TQImage::BigEndian);
+}
+
+void TQt3CairoPaintDevice::dualStrokePen() {
+ if (m_bgColorMode == TQt::OpaqueMode) {
+ // Draw background
+ cairo_save(m_painter);
+ updatePen(TRUE);
+ cairo_stroke(m_painter);
+ cairo_restore(m_painter);
+ }
+ // Draw foreground
+ updatePen(FALSE);
+ cairo_stroke(m_painter);
+}
+
+void TQt3CairoPaintDevice::dualStrokeBrush() {
+ if (m_bgColorMode == TQt::OpaqueMode) {
+ // Draw background
+ cairo_save(m_painter);
+ updateBrush(TRUE);
+ cairo_fill(m_painter);
+ cairo_restore(m_painter);
+ }
+ // Draw foreground
+ updateBrush(FALSE);
+ cairo_fill(m_painter);
+}
+
+void TQt3CairoPaintDevice::updatePen(bool backgroundStroke) {
+ if (!m_painter) {
+ return;
+ }
+
+ int ps = m_pen.style();
+
+ double dashes[10]; // custom pen dashes
+ int dash_len = 0; // length of dash list
+ int dash_offset = 0;
+ cairo_line_cap_t cp = CAIRO_LINE_CAP_BUTT;
+ cairo_line_join_t jn = CAIRO_LINE_JOIN_MITER;
+
+ /*
+ We are emulating Windows here. Windows treats m_pen.width() == 1
+ (or 0) as a very special case. The fudge variable unifies this
+ case with the general case.
+ */
+ int dot = m_pen.width(); // width of a dot
+ int fudge = 1;
+ //bool allow_zero_lw = TRUE;
+ bool allow_zero_lw = FALSE;
+ if ( dot <= 1 ) {
+ dot = 3;
+ fudge = 2;
+ }
+
+ switch( ps ) {
+ case TQPainter::NoPen:
+ case TQPainter::SolidLine:
+ break;
+ case TQPainter::DashLine:
+ dashes[0] = fudge * 3 * dot;
+ dashes[1] = fudge * dot;
+ dash_len = 2;
+ allow_zero_lw = FALSE;
+ break;
+ case TQPainter::DotLine:
+ dashes[0] = dot;
+ dashes[1] = dot;
+ dash_len = 2;
+ allow_zero_lw = FALSE;
+ break;
+ case TQPainter::DashDotLine:
+ dashes[0] = 3 * dot;
+ dashes[1] = fudge * dot;
+ dashes[2] = dot;
+ dashes[3] = fudge * dot;
+ dash_len = 4;
+ allow_zero_lw = FALSE;
+ break;
+ case TQPainter::DashDotDotLine:
+ dashes[0] = 3 * dot;
+ dashes[1] = dot;
+ dashes[2] = dot;
+ dashes[3] = dot;
+ dashes[4] = dot;
+ dashes[5] = dot;
+ dash_len = 6;
+ allow_zero_lw = FALSE;
+ break;
+ case TQPainter::FineDotLine:
+ dot = 1;
+ dashes[0] = dot;
+ dashes[1] = dot;
+ dash_len = 2;
+ allow_zero_lw = FALSE;
+ }
+ Q_ASSERT( dash_len <= (int) sizeof(dashes) );
+
+ switch ( m_pen.capStyle() ) {
+ case TQPainter::SquareCap:
+ cp = CAIRO_LINE_CAP_SQUARE;
+ break;
+ case TQPainter::RoundCap:
+ cp = CAIRO_LINE_CAP_ROUND;
+ break;
+ case TQPainter::FlatCap:
+ default:
+ cp = CAIRO_LINE_CAP_BUTT;
+ break;
+ }
+
+ switch ( m_pen.joinStyle() ) {
+ case TQPainter::BevelJoin:
+ jn = CAIRO_LINE_JOIN_BEVEL;
+ break;
+ case TQPainter::RoundJoin:
+ jn = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case TQPainter::MiterJoin:
+ default:
+ jn = CAIRO_LINE_JOIN_MITER;
+ break;
+ }
+
+ if (backgroundStroke) {
+ dash_len = 0;
+
+ }
+
+ cairo_set_dash(m_painter, dashes, dash_len, dash_offset);
+ cairo_set_line_cap(m_painter, cp);
+ cairo_set_line_join(m_painter, jn);
+ cairo_set_line_width(m_painter, ((!allow_zero_lw) && (m_pen.width() == 0)) ? 1 : m_pen.width());
+
+ TQRgb color = (backgroundStroke)?m_bgColor.rgb():m_pen.color().rgb();
+ cairo_set_source_rgba(m_painter, tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color));
+}
+
+void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke) {
+ if (!m_painter) {
+ return;
+ }
+
+ if (backgroundStroke) {
+ TQRgb color = m_bgColor.rgb();
+ cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color));
+ cairo_set_source(m_painter, pattern);
+ cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT);
+ cairo_pattern_destroy(pattern);
+ }
+ else {
+ static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
+ static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
+ static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
+ static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
+ static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
+ static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
+ static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
+ static const uchar hor_pat[] = { // horizontal pattern
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const uchar ver_pat[] = { // vertical pattern
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20 };
+ static const uchar cross_pat[] = { // cross pattern
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0xff, 0xff, 0xff,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0xff, 0xff, 0xff,
+ 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20,
+ 0x08, 0x82, 0x20, 0xff, 0xff, 0xff, 0x08, 0x82, 0x20, 0x08, 0x82, 0x20 };
+ static const uchar bdiag_pat[] = { // backward diagonal pattern
+ 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01,
+ 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
+ 0x02, 0x02, 0x01, 0x01, 0x80, 0x80, 0x40, 0x40 };
+ static const uchar fdiag_pat[] = { // forward diagonal pattern
+ 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40,
+ 0x80, 0x80, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10,
+ 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x01, 0x01 };
+ static const uchar dcross_pat[] = { // diagonal cross pattern
+ 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x41, 0x41,
+ 0x80, 0x80, 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x14, 0x14,
+ 0x22, 0x22, 0x41, 0x41, 0x80, 0x80, 0x41, 0x41 };
+ static const uchar * const pat_tbl[] = {
+ dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
+ dense6_pat, dense7_pat,
+ hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
+
+ int bs = m_brush.style();
+
+ const uchar *pat = 0; // pattern
+ int d = 0; // defalt pattern size: d*d
+ if ( bs >= TQBrush::Dense1Pattern && bs <= TQBrush::DiagCrossPattern ) {
+ pat = pat_tbl[ bs-TQBrush::Dense1Pattern ];
+ if ( bs <= TQBrush::Dense7Pattern ) {
+ d = 8;
+ }
+ else if ( bs <= TQBrush::CrossPattern ) {
+ d = 24;
+ }
+ else {
+ d = 16;
+ }
+ }
+
+ if ( (bs == TQBrush::CustomPattern) || pat ) {
+ TQImage brushImage;
+ if ( pat ) {
+ TQRgb color = m_brush.color().rgb();
+ brushImage = TQImage(d, d, 32);
+ int x;
+ int y;
+ int byte = 0;
+ int bit = 7;
+ for (x=0; x<d; x++) {
+ for (y=0; y<d; y++) {
+ brushImage.setPixel(x, y, (TEST_BIT(pat[byte], bit))?color:0x00000000);
+ bit--;
+ if (bit < 0) {
+ bit = 7;
+ byte++;
+ }
+ }
+ }
+ }
+ else {
+ TQPixmap *pm;
+ pm = m_brush.pixmap();
+ brushImage = pm->convertToImage();
+ }
+
+ cairo_surface_t* brushSurface = TQImageToCairoSurface(brushImage);
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(brushSurface);
+ cairo_set_source(m_painter, pattern);
+ cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT);
+ cairo_pattern_destroy(pattern);
+ cairo_surface_destroy(brushSurface);
+ }
+ else {
+ TQRgb color = m_brush.color().rgb();
+ cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color));
+ cairo_set_source(m_painter, pattern);
+ cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT);
+ cairo_pattern_destroy(pattern);
+ }
+ }
+}
+
/*!
\class TQt3CairoPaintDevice tdeqt4painter.h
\brief The TQt3CairoPaintDevice class is a paint device that translates
@@ -44,10 +355,9 @@
*/
TQt3CairoPaintDevice::TQt3CairoPaintDevice( cairo_surface_t *cairosurface )
- : TQPaintDevice( TQInternal::Picture | TQInternal::ExternalDevice )
+ : TQPaintDevice( TQInternal::Picture | TQInternal::ExternalDevice ), m_painter(NULL)
{
m_surface = cairosurface;
- m_painter = cairo_create(m_surface);
}
/*!
@@ -55,7 +365,10 @@ TQt3CairoPaintDevice::TQt3CairoPaintDevice( cairo_surface_t *cairosurface )
*/
TQt3CairoPaintDevice::~TQt3CairoPaintDevice()
{
- cairo_destroy(m_painter);
+ if (m_painter) {
+ cairo_destroy(m_painter);
+ m_painter = NULL;
+ }
}
/*!
@@ -68,13 +381,42 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
Q_UNUSED(pt);
unsigned int i;
- int x;
- int y;
+
+ double x;
+ double y;
+ double width;
+ double height;
int index;
int count;
int lineCount;
+ // Convert data types
+ if (p) {
+// if ((c == PdcDrawPoint) || (c == PdcMoveTo) || (c == PdcLineTo) || (c == PdcSetBrushOrigin)) {
+// qt4point1 = QPoint(p[0].point->x(), p[0].point->y());
+// }
+// if (c == PdcDrawLine) {
+// qt4point1 = QPoint(p[0].point->x(), p[0].point->y());
+// qt4point2 = QPoint(p[1].point->x(), p[1].point->y());
+// }
+// if ((c == PdcDrawPolyline) || (c == PdcDrawPolygon) || (c == PdcDrawLineSegments) || (c == PdcDrawCubicBezier)) {
+// TQPointArray qt3parray = *p[0].ptarr;
+// qt4polygon.resize(qt3parray.count());
+// for (i=0;i<qt3parray.count();i++) {
+// qt3parray.point(i, &x, &y );
+// qt4polygon.setPoint(i, x, y);
+// }
+// }
+ if ((c == PdcDrawRect) || (c == PdcDrawRoundRect) || (c == PdcDrawEllipse) || (c == PdcDrawArc) || (c == PdcDrawPie) || (c == PdcDrawChord)) {
+ x = p[0].rect->x();
+ y = p[0].rect->y();
+ width = p[0].rect->width();
+ height = p[0].rect->height();
+ }
+ }
+
+ // Perform drawing operation
switch ( c ) { // exec cmd
case PdcNOP:
break;
@@ -93,9 +435,26 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
case PdcDrawLine:
m_qt4painter->drawLine( qt4point1, qt4point2 );
break;
+#endif
case PdcDrawRect:
- m_qt4painter->drawRect( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter) );
+ if (m_painter) {
+ if (m_pen.style() != TQPen::NoPen) {
+ cairo_rectangle(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET, width, height);
+ dualStrokePen();
+ }
+ 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();
+ }
+ }
+ else {
+#if defined(QT_CHECK_RANGE)
+ tqWarning( "TQt3CairoPaintDevice::cmd: TQPainter::begin must be called before PdcDrawRect" );
+#endif
+ }
break;
+#if 0
case PdcDrawRoundRect:
m_qt4painter->drawRoundedRect( qt4PainterAdjustedRectangle(qt4rect, m_qt4painter), p[1].ival, p[2].ival );
break;
@@ -157,35 +516,44 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
}
break;
#endif
+#endif
case PdcBegin:
- if (m_qt4painter->isActive()) {
- // KEEP THIS DEACTIVATED
-// QPaintDevice* pd = m_qt4painter->device();
-// m_qt4painter->end();
-// m_qt4painter->begin(pd);
+ if (!m_painter) {
+ m_bgColor = TQColor(0,0,0);
+ m_bgColorMode = TQt::TransparentMode;
+ m_painter = cairo_create(m_surface);
+ m_pen = TQPen();
+ m_brush = TQBrush();
}
-#if defined(QT_CHECK_RANGE)
- else {
- tqWarning( "TQt3CairoPaintDevice::cmd: Painter has no paint device available" );
- }
-#endif
break;
case PdcEnd:
- // KEEP THIS DEACTIVATED
-// m_qt4painter->end();
+ if (m_painter) {
+ cairo_destroy(m_painter);
+ m_painter = NULL;
+ }
break;
+#if 0
case PdcSave:
m_qt4painter->save();
break;
case PdcRestore:
m_qt4painter->restore();
break;
+#endif
case PdcSetBkColor:
- m_qt4painter->setBackground( QBrush(QColor(p[0].color->red(), p[0].color->green(), p[0].color->blue())) );
+ if (p) {
+ const TQColor* color = p[0].color;
+ if (color) {
+ m_bgColor = *color;
+ }
+ }
break;
case PdcSetBkMode:
- m_qt4painter->setBackgroundMode( qt4bkmode );
+ if (p) {
+ m_bgColorMode = (TQt::BGMode)p[0].ival;
+ }
break;
+#if 0
case PdcSetROP:
m_qt4painter->setCompositionMode(qt4compositionmode);
break;
@@ -195,13 +563,25 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
case PdcSetFont:
m_qt4painter->setFont( qt4font );
break;
+#endif
case PdcSetPen:
- m_qt4painter->setPen( qt4pen );
+ if (p) {
+ const TQPen* pen = p[0].pen;
+ if (pen) {
+ m_pen = *pen;
+ }
+ }
break;
case PdcSetBrush:
- m_qt4painter->setBrush( qt4brush );
+ if (p) {
+ const TQBrush* brush = p[0].brush;
+ if (brush) {
+ m_brush = *brush;
+ }
+ }
break;
#if 0
+#if 0
case PdcSetTabStops:
s >> i_16;
painter->setTabStops( i_16 );
@@ -333,8 +713,11 @@ int TQt3CairoPaintDevice::metric( int m ) const
else if (format == CAIRO_FORMAT_RGB24) {
val = 16777216;
}
+ else if (format == CAIRO_FORMAT_RGB16_565) {
+ val = 65536;
+ }
else {
- val = 16777216;
+ val = 65536;
}
break;
case TQPaintDeviceMetrics::PdmDepth:
@@ -345,8 +728,11 @@ int TQt3CairoPaintDevice::metric( int m ) const
else if (format == CAIRO_FORMAT_RGB24) {
val = 24;
}
+ else if (format == CAIRO_FORMAT_RGB16_565) {
+ val = 16;
+ }
else {
- val = 24;
+ val = 16;
}
break;
default: