From c2a1262df888a6c2913c608614f00dbb41233321 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 15 Sep 2012 23:02:11 -0500 Subject: Rectangle drawing via Cairo now functions --- tdegtk/Makefile.am | 18 +- tdegtk/tqtcairopainter.cpp | 434 ++++++++++++++++++++++++++++++++++++++++++--- tdegtk/tqtcairopainter.h | 35 ++-- 3 files changed, 448 insertions(+), 39 deletions(-) (limited to 'tdegtk') diff --git a/tdegtk/Makefile.am b/tdegtk/Makefile.am index cc3eef3..208c447 100644 --- a/tdegtk/Makefile.am +++ b/tdegtk/Makefile.am @@ -7,8 +7,7 @@ source_h = \ $(srcdir)/tdegtk-draw.h \ $(srcdir)/tdegtk-engine.h \ $(srcdir)/tdegtk-support.h \ - $(srcdir)/tdegtk-types.h \ - $(srcdir)/tqtcairopainter.h + $(srcdir)/tdegtk-types.h source_c = \ $(srcdir)/exponential-blur.c \ @@ -18,8 +17,7 @@ source_c = \ $(srcdir)/tdegtk-draw.c \ $(srcdir)/tdegtk-engine.c \ $(srcdir)/tdegtk-support.c \ - $(srcdir)/tdegtk-theme.c \ - $(srcdir)/tqtcairopainter.cpp + $(srcdir)/tdegtk-theme.c enginedir = $(libdir)/gtk-3.0/$(GTK_VERSION)/theming-engines engine_LTLIBRARIES = libtdegtk.la @@ -27,8 +25,18 @@ engine_LTLIBRARIES = libtdegtk.la libtdegtk_la_SOURCES = $(source_h) $(source_c) libtdegtk_la_CFLAGS = $(TDEGTK_CFLAGS) -libtdegtk_la_CXXFLAGS = $(TDEGTK_CXXFLAGS) -I/usr/include/tqt -I/usr/include/tqt3 $(TDEGTK_CFLAGS) libtdegtk_la_LIBADD = $(TDEGTK_LIBADD) libtdegtk_la_LDFLAGS = $(TDEGTK_LDFLAGS) + +lib_LTLIBRARIES = libtqtcairo.la + +libtqtcairo_la_SOURCES = tqtcairopainter.h tqtcairopainter.cpp + +libtqtcairo_la_CFLAGS = $(TDEGTK_CFLAGS) +libtqtcairo_la_CXXFLAGS = $(TDEGTK_CXXFLAGS) -I/usr/include/tqt -I/usr/include/tqt3 $(TDEGTK_CFLAGS) + +libtqtcairo_la_LIBADD = $(TDEGTK_LIBADD) + +libtqtcairo_la_LDFLAGS = $(TDEGTK_LDFLAGS) 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; xconvertToImage(); + } + + 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;ix(); + 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; @@ -156,36 +515,45 @@ 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,12 +563,24 @@ 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; @@ -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: diff --git a/tdegtk/tqtcairopainter.h b/tdegtk/tqtcairopainter.h index aa45e9b..fa051c2 100644 --- a/tdegtk/tqtcairopainter.h +++ b/tdegtk/tqtcairopainter.h @@ -24,22 +24,37 @@ #define TQT_NO_COMPAT_NAMES #include "ntqpaintdevice.h" #include "ntqbuffer.h" +#include "ntqcolor.h" +#include "ntqpen.h" +#include "ntqbrush.h" #include class Q_EXPORT TQt3CairoPaintDevice : public TQPaintDevice // picture class { -public: - TQt3CairoPaintDevice( cairo_surface_t * ); - ~TQt3CairoPaintDevice(); + public: + TQt3CairoPaintDevice( cairo_surface_t * ); + ~TQt3CairoPaintDevice(); + + protected: + bool cmd( int, TQPainter *, TQPDevCmdParam * ); + int metric( int ) const; + + private: + void updatePen(bool backgroundStroke=FALSE); + void dualStrokePen(); -protected: - bool cmd( int, TQPainter *, TQPDevCmdParam * ); - int metric( int ) const; - -private: - cairo_surface_t *m_surface; - cairo_t *m_painter; + void updateBrush(bool backgroundStroke=FALSE); + void dualStrokeBrush(); + + private: + cairo_surface_t *m_surface; + cairo_t *m_painter; + + TQColor m_bgColor; + TQt::BGMode m_bgColorMode; + TQPen m_pen; + TQBrush m_brush; }; #endif // TDEQT4PAINTER_H -- cgit v1.2.1