diff options
Diffstat (limited to 'tdegtk/tqtcairopainter.cpp')
-rw-r--r-- | tdegtk/tqtcairopainter.cpp | 320 |
1 files changed, 286 insertions, 34 deletions
diff --git a/tdegtk/tqtcairopainter.cpp b/tdegtk/tqtcairopainter.cpp index 8f917e1..05e9a0a 100644 --- a/tdegtk/tqtcairopainter.cpp +++ b/tdegtk/tqtcairopainter.cpp @@ -27,9 +27,11 @@ #include "tqimage.h" #include "tqfile.h" #include "tqpaintdevicemetrics.h" + #undef Qt #define CAIRO_PIXEL_OFFSET (0.5) +#define CAIRO_FONT_SIZE_FUDGE_FACTOR (1.4) #define SET_BIT(x, y) (x |= 1 << y) #define TEST_BIT(x, y) ((x & (1 << y)) >> y) @@ -219,7 +221,7 @@ void TQt3CairoPaintDevice::updatePen(bool backgroundStroke) { 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)); + cairo_set_source_rgba(m_painter, tqRed(color)/255.0, tqGreen(color)/255.0, tqBlue(color)/255.0, tqAlpha(color)/255.0); } void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t fillMethod) { @@ -229,7 +231,7 @@ void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t if (backgroundStroke) { TQRgb color = m_bgColor.rgb(); - cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color)); + cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color)/255.0, tqGreen(color)/255.0, tqBlue(color)/255.0, tqAlpha(color)/255.0); cairo_set_source(m_painter, pattern); cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT); cairo_pattern_destroy(pattern); @@ -308,7 +310,7 @@ void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t 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); + brushImage.setPixel(y, x, (TEST_BIT(pat[byte], bit))?color:0x00000000); bit--; if (bit < 0) { bit = 7; @@ -325,6 +327,9 @@ void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t cairo_surface_t* brushSurface = TQImageToCairoSurface(brushImage); cairo_pattern_t* pattern = cairo_pattern_create_for_surface(brushSurface); + cairo_matrix_t brush_translation_matrix; + cairo_matrix_init_translate(&brush_translation_matrix, m_brushOrigin.x(), m_brushOrigin.y()); + cairo_pattern_set_matrix(pattern, &brush_translation_matrix); cairo_set_source(m_painter, pattern); cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT); cairo_pattern_destroy(pattern); @@ -332,7 +337,7 @@ void TQt3CairoPaintDevice::updateBrush(bool backgroundStroke, cairo_fill_rule_t } else { TQRgb color = m_brush.color().rgb(); - cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color), tqGreen(color), tqBlue(color), tqAlpha(color)); + cairo_pattern_t* pattern = cairo_pattern_create_rgba(tqRed(color)/255.0, tqGreen(color)/255.0, tqBlue(color)/255.0, tqAlpha(color)/255.0); cairo_set_source(m_painter, pattern); cairo_pattern_set_extend(cairo_get_source(m_painter), CAIRO_EXTEND_REPEAT); cairo_pattern_destroy(pattern); @@ -364,7 +369,7 @@ void TQt3CairoPaintDevice::drawPolygon(const TQPointArray* pointarray, bool wind if ((m_brush.style() != TQBrush::NoBrush) && fill) { first = true; for (i=0;i<pointarray->count();i++) { - pointarray->point(i, &x, &y ); + pointarray->point(i, &x, &y); if (first) { cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); first = false; @@ -381,7 +386,7 @@ void TQt3CairoPaintDevice::drawPolygon(const TQPointArray* pointarray, bool wind if (m_pen.style() != TQPen::NoPen) { first = true; for (i=0;i<pointarray->count();i++) { - pointarray->point(i, &x, &y ); + pointarray->point(i, &x, &y); if (first) { cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); first = false; @@ -537,6 +542,144 @@ void TQt3CairoPaintDevice::drawChord(int x, int y, int w, int h, int a, int alen return; } +void TQt3CairoPaintDevice::pangoSetupTextPath(PangoLayout *layout, const char* text) { + PangoFontDescription *desc; + + pango_layout_set_text(layout, text, -1); + + desc = pango_font_description_new(); + + // FIXME + // overline and a handful of other flags are not supported by Pango! + TQString family = m_font.family(); +// bool bold = m_font.bold(); + bool italic = m_font.italic(); + bool underline = m_font.underline(); +// bool overline = m_font.overline(); + bool strikeout = m_font.strikeOut(); +// bool fixedPitch = m_font.fixedPitch(); + int stretch = m_font.stretch(); + int weight = m_font.weight(); + + int pixelSize = m_font.pixelSize(); + bool usePixelSize = (pixelSize>=0); + float pointSizeFloat = m_font.pointSizeFloat(); + bool usePointSize = (pointSizeFloat>=0); + + TQFont::StyleStrategy qt3fontstrategy = m_font.styleStrategy(); + + PangoWeight pangoWeight; + switch (weight) { + case TQFont::Light: + pangoWeight = PANGO_WEIGHT_LIGHT; + break; + case TQFont::Normal: + pangoWeight = PANGO_WEIGHT_NORMAL; + break; + case TQFont::DemiBold: + pangoWeight = PANGO_WEIGHT_SEMIBOLD; + break; + case TQFont::Bold: + pangoWeight = PANGO_WEIGHT_BOLD; + break; + case TQFont::Black: + pangoWeight = PANGO_WEIGHT_HEAVY; + break; + } + + PangoStretch pangoStretch; + switch (stretch) { + case TQFont::UltraCondensed: + pangoStretch = PANGO_STRETCH_ULTRA_CONDENSED; + break; + case TQFont::ExtraCondensed: + pangoStretch = PANGO_STRETCH_EXTRA_CONDENSED; + break; + case TQFont::Condensed: + pangoStretch = PANGO_STRETCH_CONDENSED; + break; + case TQFont::SemiCondensed: + pangoStretch = PANGO_STRETCH_SEMI_CONDENSED; + break; + case TQFont::Unstretched: + pangoStretch = PANGO_STRETCH_NORMAL; + break; + case TQFont::SemiExpanded: + pangoStretch = PANGO_STRETCH_SEMI_EXPANDED; + break; + case TQFont::Expanded: + pangoStretch = PANGO_STRETCH_EXPANDED; + break; + case TQFont::ExtraExpanded: + pangoStretch = PANGO_STRETCH_EXTRA_EXPANDED; + break; + case TQFont::UltraExpanded: + pangoStretch = PANGO_STRETCH_ULTRA_EXPANDED; + break; + } + + pango_font_description_set_family(desc, family.ascii()); + if (usePixelSize) { + pango_font_description_set_absolute_size(desc, pixelSize*PANGO_SCALE); + } + if (usePointSize) { + pango_font_description_set_absolute_size(desc, pointSizeFloat*PANGO_SCALE*CAIRO_FONT_SIZE_FUDGE_FACTOR); + } + pango_font_description_set_style(desc, (italic)?PANGO_STYLE_ITALIC:PANGO_STYLE_NORMAL); + pango_font_description_set_weight(desc, pangoWeight); + pango_font_description_set_stretch(desc, pangoStretch); + +#if 0 + if (qt3fontstrategy & TQFont::PreferDefault) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::PreferBitmap) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::PreferDevice) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::PreferMatch) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::PreferQuality) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::PreferAntialias) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::NoAntialias) // FIXME Set Cairo/Pango to follow this hint + if (qt3fontstrategy & TQFont::OpenGLCompatible) // FIXME Set Cairo/Pango to follow this hint +#endif + + pango_layout_set_font_description(layout, desc); + + PangoAttrList* attr_list = pango_attr_list_new(); + pango_attr_list_insert(attr_list, pango_attr_underline_new((underline)?PANGO_UNDERLINE_SINGLE:PANGO_UNDERLINE_NONE)); + pango_attr_list_insert(attr_list, pango_attr_strikethrough_new(strikeout)); + pango_layout_set_attributes(layout, attr_list); + pango_attr_list_unref(attr_list); + + pango_font_description_free(desc); +} + +void TQt3CairoPaintDevice::drawText(TQPainter *p, int x, int y, const TQString &str, int pos, int len, TQPainter::TextDirection dir, bool baseline) { + if ((!m_painter) || (!p)) { + return; + } + + PangoLayout *layout; + layout = pango_cairo_create_layout(m_painter); + + TQFont::StyleStrategy qt3fontstrategy = m_font.styleStrategy(); + pangoSetupTextPath(layout, str.utf8()); + + int baseline_y = pango_layout_get_baseline(layout)/PANGO_SCALE; + cairo_new_path(m_painter); + cairo_move_to(m_painter, x, (baseline)?y-baseline_y:y); + updatePen(FALSE); + + pango_cairo_update_layout(m_painter, layout); + pango_cairo_layout_path(m_painter, layout); + + if ((qt3fontstrategy & TQFont::PreferOutline) || (qt3fontstrategy & TQFont::ForceOutline)) { + cairo_stroke_preserve(m_painter); + } + else { + cairo_fill(m_painter); + } + + g_object_unref(layout); +} + /*! \class TQt3CairoPaintDevice tdeqt4painter.h \brief The TQt3CairoPaintDevice class is a paint device that translates @@ -575,8 +718,6 @@ TQt3CairoPaintDevice::~TQt3CairoPaintDevice() bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) { - Q_UNUSED(pt); - unsigned int i; double x; @@ -602,14 +743,6 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) x2 = p[1].point->x(); y2 = 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(); @@ -681,7 +814,7 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) } else { #if defined(QT_CHECK_RANGE) - tqWarning( "TQt3CairoPaintDevice::cmd: TQPainter::begin must be called before PdcDrawRect" ); + tqWarning( "TQt3CairoPaintDevice::cmd: TQPainter::begin must be called before PdcDrawRect" ); #endif } break; @@ -730,14 +863,30 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) cairo_restore(m_painter); } break; -#if 0 case PdcDrawLineSegments: - index = 0; - count = -1; - lineCount = (count == -1) ? (qt4polygon.size() - index) / 2 : count; - m_qt4painter->drawLines(qt4polygon.constData() + index * 2, lineCount); + if (m_painter) { + cairo_save(m_painter); + if (p) { + int x; + int y; + int x2; + int y2; + const TQPointArray* pointarray = p[0].ptarr; + if (pointarray) { + if (m_pen.style() != TQPen::NoPen) { + for (i=0;i<pointarray->count();i=i+2) { + pointarray->point(i+0, &x, &y); + pointarray->point(i+1, &x2, &y2); + cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + cairo_line_to(m_painter, x2+CAIRO_PIXEL_OFFSET, y2+CAIRO_PIXEL_OFFSET); + dualStrokePen(); + } + } + } + } + cairo_restore(m_painter); + } break; -#endif case PdcDrawPolyline: if (p) { drawPolygon(p[0].ptarr, false, false, true); @@ -748,22 +897,56 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) drawPolygon(p[0].ptarr, p[1].ival, true, true); } break; -#if 0 case PdcDrawCubicBezier: - index = 0; - path.moveTo(qt4polygon.at(index)); - path.cubicTo(qt4polygon.at(index+1), qt4polygon.at(index+2), qt4polygon.at(index+3)); - m_qt4painter->strokePath(path, m_qt4painter->pen()); + if (m_painter) { + cairo_save(m_painter); + if (p) { + int x; + int y; + int x2; + int y2; + int x3; + int y3; + int x4; + int y4; + const TQPointArray* pointarray = p[0].ptarr; + if (pointarray) { + if (m_pen.style() != TQPen::NoPen) { + for (i=0;i<pointarray->count();i=i+4) { + pointarray->point(i+0, &x, &y); + pointarray->point(i+1, &x2, &y2); + pointarray->point(i+2, &x3, &y3); + pointarray->point(i+3, &x4, &y4); + cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET); + cairo_curve_to(m_painter, x2+CAIRO_PIXEL_OFFSET, y2+CAIRO_PIXEL_OFFSET, x3+CAIRO_PIXEL_OFFSET, y3+CAIRO_PIXEL_OFFSET, x4+CAIRO_PIXEL_OFFSET, y4+CAIRO_PIXEL_OFFSET); + dualStrokePen(); + } + } + } + } + cairo_restore(m_painter); + } break; +#if 0 case PdcDrawText: + // NOTE + // drawText baseline = FALSE for this! m_qt4painter->drawText( qt4point1, qt4string ); break; case PdcDrawTextFormatted: m_qt4painter->drawText( qt4rect, qt4formattedtextflags, qt4string ); break; +#endif case PdcDrawText2: - m_qt4painter->drawText( qt4point1, qt4string ); + if (m_painter) { + cairo_save(m_painter); + if (p) { + TQString string = *p[1].str; + drawText(pt, p[0].rect->x()+CAIRO_PIXEL_OFFSET, p[0].rect->y()+CAIRO_PIXEL_OFFSET, string, 0, -1, TQPainter::Auto, TRUE); + } + } break; +#if 0 case PdcDrawText2Formatted: m_qt4painter->drawText( qt4rect, qt4formattedtextflags, qt4string ); break; @@ -791,6 +974,7 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) m_painter = cairo_create(m_surface); m_pen = TQPen(); m_brush = TQBrush(); + m_brushOrigin = TQPoint(0,0); } break; case PdcEnd: @@ -818,17 +1002,85 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p ) m_bgColorMode = (TQt::BGMode)p[0].ival; } break; -#if 0 case PdcSetROP: - m_qt4painter->setCompositionMode(qt4compositionmode); + if ((p) && (m_painter)) { + cairo_operator_t cairoCompositionMode = CAIRO_OPERATOR_OVER; + TQt::RasterOp rop = (TQt::RasterOp)p[0].ival; + switch (rop) { + case TQPainter::CopyROP: + cairoCompositionMode=CAIRO_OPERATOR_OVER; + break; + case TQPainter::OrROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::XorROP: + // While this is not a 'real' XOR, if the source color is white (1.0) it should work well enough (i.e. reverse itself on a second application)... + cairoCompositionMode=CAIRO_OPERATOR_DIFFERENCE; + break; + case TQPainter::NotAndROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NotCopyROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NotOrROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NotXorROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::AndROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NotROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::ClearROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::SetROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NopROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::AndNotROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::OrNotROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NandROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + case TQPainter::NorROP: + tqWarning("TDEQt4PaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", rop); + break; + default: + cairoCompositionMode=CAIRO_OPERATOR_OVER; +#if defined(QT_CHECK_RANGE) + tqWarning( "TDEQt4PaintDevice::cmd: Unhandled raster operation %d", rop ); +#endif + } + cairo_set_operator(m_painter, cairoCompositionMode); + } break; case PdcSetBrushOrigin: - m_qt4painter->setBrushOrigin( qt4point1 ); + if (p) { + const TQPoint* point = p[0].point; + if (point) { + m_brushOrigin = *point; + } + } break; case PdcSetFont: - m_qt4painter->setFont( qt4font ); + if (p) { + const TQFont* font = p[0].font; + if (font) { + m_font = *font; + } + } break; -#endif case PdcSetPen: if (p) { const TQPen* pen = p[0].pen; |