You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1019 lines
26 KiB
1019 lines
26 KiB
/****************************************************************************
|
|
**
|
|
** Implementation of TQt3CairoPaintDevice class
|
|
**
|
|
** Copyright (C) 2012 Timothy Pearson. All rights reserved.
|
|
**
|
|
** This file is part of the TDE Qt4 style interface
|
|
**
|
|
** This file may be used under the terms of the GNU General
|
|
** Public License versions 2.0 or 3.0 as published by the Free
|
|
** Software Foundation and appearing in the files LICENSE.GPL2
|
|
** and LICENSE.GPL3 included in the packaging of this file.
|
|
**
|
|
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
|
|
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
|
|
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
|
|
** herein.
|
|
**
|
|
**********************************************************************/
|
|
|
|
#include "tqtcairopainter.h"
|
|
|
|
#define TQT_NO_COMPAT_NAMES
|
|
#include "tqpainter.h"
|
|
#include "tqpixmap.h"
|
|
#include "tqbitmap.h"
|
|
#include "tqimage.h"
|
|
#include "tqfile.h"
|
|
#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(cairo_fill_rule_t fillMethod) {
|
|
if (m_bgColorMode == TQt::OpaqueMode) {
|
|
// Draw background
|
|
cairo_save(m_painter);
|
|
updateBrush(TRUE, fillMethod);
|
|
cairo_fill(m_painter);
|
|
cairo_restore(m_painter);
|
|
}
|
|
// Draw foreground
|
|
updateBrush(FALSE, fillMethod);
|
|
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, cairo_fill_rule_t fillMethod) {
|
|
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);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
/*!
|
|
\class TQt3CairoPaintDevice tdeqt4painter.h
|
|
\brief The TQt3CairoPaintDevice class is a paint device that translates
|
|
Qt paint events to a TQt painter.
|
|
|
|
\ingroup graphics
|
|
\ingroup shared
|
|
|
|
*/
|
|
|
|
/*!
|
|
Constructs TQt3CairoPaintDevice on an existing QPainter
|
|
*/
|
|
|
|
TQt3CairoPaintDevice::TQt3CairoPaintDevice( cairo_surface_t *cairosurface )
|
|
: TQPaintDevice( TQInternal::Picture | TQInternal::ExternalDevice ), m_painter(NULL)
|
|
{
|
|
m_surface = cairosurface;
|
|
}
|
|
|
|
/*!
|
|
Destroys the TQt3CairoPaintDevice.
|
|
*/
|
|
TQt3CairoPaintDevice::~TQt3CairoPaintDevice()
|
|
{
|
|
if (m_painter) {
|
|
cairo_destroy(m_painter);
|
|
m_painter = NULL;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
Implementation of the function forwarded above to the internal data struct.
|
|
*/
|
|
|
|
bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
|
|
{
|
|
Q_UNUSED(pt);
|
|
|
|
unsigned int i;
|
|
|
|
double x;
|
|
double y;
|
|
double x2;
|
|
double y2;
|
|
double width;
|
|
double height;
|
|
|
|
int index;
|
|
int count;
|
|
int lineCount;
|
|
|
|
// Convert data types
|
|
if (p) {
|
|
if ((c == PdcDrawPoint) || (c == PdcMoveTo) || (c == PdcLineTo) || (c == PdcSetBrushOrigin)) {
|
|
x = p[0].point->x();
|
|
y = p[0].point->y();
|
|
}
|
|
if (c == PdcDrawLine) {
|
|
x = p[0].point->x();
|
|
y = p[0].point->y();
|
|
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();
|
|
width = p[0].rect->width();
|
|
height = p[0].rect->height();
|
|
}
|
|
}
|
|
|
|
// Perform drawing operation
|
|
switch ( c ) { // exec cmd
|
|
case PdcNOP:
|
|
break;
|
|
case PdcDrawPoint:
|
|
if (m_painter) {
|
|
cairo_save(m_painter);
|
|
if (m_pen.style() != TQPen::NoPen) {
|
|
cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET);
|
|
cairo_line_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET);
|
|
updatePen(FALSE);
|
|
cairo_set_line_cap(m_painter, CAIRO_LINE_CAP_ROUND);
|
|
cairo_stroke(m_painter);
|
|
}
|
|
cairo_restore(m_painter);
|
|
}
|
|
break;
|
|
case PdcMoveTo:
|
|
if (m_painter) {
|
|
cairo_save(m_painter);
|
|
if (m_pen.style() != TQPen::NoPen) {
|
|
cairo_move_to(m_painter, x+CAIRO_PIXEL_OFFSET, y+CAIRO_PIXEL_OFFSET);
|
|
}
|
|
cairo_restore(m_painter);
|
|
}
|
|
break;
|
|
case PdcLineTo:
|
|
if (m_painter) {
|
|
cairo_save(m_painter);
|
|
if (m_pen.style() != TQPen::NoPen) {
|
|
cairo_line_to(m_painter, x2+CAIRO_PIXEL_OFFSET, y2+CAIRO_PIXEL_OFFSET);
|
|
dualStrokePen();
|
|
}
|
|
cairo_restore(m_painter);
|
|
}
|
|
break;
|
|
case PdcDrawLine:
|
|
if (m_painter) {
|
|
cairo_save(m_painter);
|
|
if (m_pen.style() != TQPen::NoPen) {
|
|
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;
|
|
case PdcDrawRect:
|
|
if (m_painter) {
|
|
cairo_save(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(CAIRO_FILL_RULE_EVEN_ODD);
|
|
}
|
|
cairo_restore(m_painter);
|
|
}
|
|
else {
|
|
#if defined(QT_CHECK_RANGE)
|
|
tqWarning( "TQt3CairoPaintDevice::cmd: TQPainter::begin must be called before PdcDrawRect" );
|
|
#endif
|
|
}
|
|
break;
|
|
case PdcDrawRoundRect:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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;
|
|
lineCount = (count == -1) ? (qt4polygon.size() - index) / 2 : count;
|
|
m_qt4painter->drawLines(qt4polygon.constData() + index * 2, lineCount);
|
|
break;
|
|
#endif
|
|
case PdcDrawPolyline:
|
|
if (p) {
|
|
drawPolygon(p[0].ptarr, false, false, true);
|
|
}
|
|
break;
|
|
case PdcDrawPolygon:
|
|
if (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());
|
|
break;
|
|
case PdcDrawText:
|
|
m_qt4painter->drawText( qt4point1, qt4string );
|
|
break;
|
|
case PdcDrawTextFormatted:
|
|
m_qt4painter->drawText( qt4rect, qt4formattedtextflags, qt4string );
|
|
break;
|
|
case PdcDrawText2:
|
|
m_qt4painter->drawText( qt4point1, qt4string );
|
|
break;
|
|
case PdcDrawText2Formatted:
|
|
m_qt4painter->drawText( qt4rect, qt4formattedtextflags, qt4string );
|
|
break;
|
|
case PdcDrawPixmap:
|
|
m_qt4painter->drawPixmap( qt4rect, qt4pixmap );
|
|
break;
|
|
#if 0
|
|
case PdcDrawImage: {
|
|
TQImage image;
|
|
if ( d->formatMajor < 4 ) {
|
|
s >> p >> image;
|
|
painter->drawImage( p, image );
|
|
} else {
|
|
s >> r >> image;
|
|
painter->drawImage( r, image );
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
#endif
|
|
case PdcBegin:
|
|
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();
|
|
}
|
|
break;
|
|
case PdcEnd:
|
|
if (m_painter) {
|
|
cairo_destroy(m_painter);
|
|
m_painter = NULL;
|
|
}
|
|
break;
|
|
case PdcSave:
|
|
cairo_save(m_painter);
|
|
break;
|
|
case PdcRestore:
|
|
cairo_restore(m_painter);
|
|
break;
|
|
case PdcSetBkColor:
|
|
if (p) {
|
|
const TQColor* color = p[0].color;
|
|
if (color) {
|
|
m_bgColor = *color;
|
|
}
|
|
}
|
|
break;
|
|
case PdcSetBkMode:
|
|
if (p) {
|
|
m_bgColorMode = (TQt::BGMode)p[0].ival;
|
|
}
|
|
break;
|
|
#if 0
|
|
case PdcSetROP:
|
|
m_qt4painter->setCompositionMode(qt4compositionmode);
|
|
break;
|
|
case PdcSetBrushOrigin:
|
|
m_qt4painter->setBrushOrigin( qt4point1 );
|
|
break;
|
|
case PdcSetFont:
|
|
m_qt4painter->setFont( qt4font );
|
|
break;
|
|
#endif
|
|
case PdcSetPen:
|
|
if (p) {
|
|
const TQPen* pen = p[0].pen;
|
|
if (pen) {
|
|
m_pen = *pen;
|
|
}
|
|
}
|
|
break;
|
|
case PdcSetBrush:
|
|
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 );
|
|
break;
|
|
case PdcSetTabArray:
|
|
s >> i_16;
|
|
if ( i_16 == 0 ) {
|
|
painter->setTabArray( 0 );
|
|
} else {
|
|
int *ta = new int[i_16];
|
|
TQ_CHECK_PTR( ta );
|
|
for ( int i=0; i<i_16; i++ ) {
|
|
s >> i1_16;
|
|
ta[i] = i1_16;
|
|
}
|
|
painter->setTabArray( ta );
|
|
delete [] ta;
|
|
}
|
|
break;
|
|
case PdcSetVXform:
|
|
s >> i_8;
|
|
#ifndef QT_NO_TRANSFORMATIONS
|
|
painter->setViewXForm( i_8 );
|
|
#endif
|
|
break;
|
|
case PdcSetWindow:
|
|
s >> r;
|
|
#ifndef QT_NO_TRANSFORMATIONS
|
|
painter->setWindow( r );
|
|
#endif
|
|
break;
|
|
case PdcSetViewport:
|
|
s >> r;
|
|
#ifndef QT_NO_TRANSFORMATIONS
|
|
painter->setViewport( r );
|
|
#endif
|
|
break;
|
|
#endif
|
|
case PdcSetWXform:
|
|
m_qt4painter->setWorldMatrixEnabled( p[0].ival );
|
|
break;
|
|
case PdcSetWMatrix:
|
|
m_qt4painter->setWorldMatrix( qt4matrix, p[1].ival );
|
|
break;
|
|
#if 0
|
|
#ifndef QT_NO_TRANSFORMATIONS
|
|
case PdcSaveWMatrix:
|
|
painter->saveWorldMatrix();
|
|
break;
|
|
case PdcRestoreWMatrix:
|
|
painter->restoreWorldMatrix();
|
|
break;
|
|
#endif
|
|
#endif
|
|
case PdcSetClip:
|
|
m_qt4painter->setClipping( p[0].ival );
|
|
break;
|
|
case PdcSetClipRegion:
|
|
m_qt4painter->setClipRegion( qt4region, Qt::ReplaceClip );
|
|
break;
|
|
#endif
|
|
default:
|
|
#if defined(QT_CHECK_RANGE)
|
|
tqWarning( "TQt3CairoPaintDevice::cmd: Invalid command %d", c );
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*!
|
|
Internal implementation of the virtual TQPaintDevice::metric()
|
|
function.
|
|
|
|
Use the TQPaintDeviceMetrics class instead.
|
|
|
|
A picture has the following hard-coded values: dpi=72,
|
|
numcolors=16777216 and depth=24.
|
|
|
|
\a m is the metric to get.
|
|
*/
|
|
|
|
int TQt3CairoPaintDevice::metric( int m ) const
|
|
{
|
|
int val;
|
|
|
|
if (m_surface) {
|
|
double x_pixels_per_inch;
|
|
double y_pixels_per_inch;
|
|
cairo_format_t format;
|
|
switch ( m ) {
|
|
// ### hard coded dpi and color depth values !
|
|
case TQPaintDeviceMetrics::PdmWidth:
|
|
val = cairo_image_surface_get_width(m_surface);
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmHeight:
|
|
val = cairo_image_surface_get_height(m_surface);
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmWidthMM:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = ((cairo_image_surface_get_width(m_surface)/x_pixels_per_inch)*25.4);
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmHeightMM:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = ((cairo_image_surface_get_height(m_surface)/y_pixels_per_inch)*25.4);
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmDpiX:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = x_pixels_per_inch;
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmPhysicalDpiX:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = x_pixels_per_inch;
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmDpiY:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = y_pixels_per_inch;
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmPhysicalDpiY:
|
|
cairo_surface_get_fallback_resolution(m_surface, &x_pixels_per_inch, &y_pixels_per_inch);
|
|
val = y_pixels_per_inch;
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmNumColors:
|
|
format = cairo_image_surface_get_format(m_surface);
|
|
if (format == CAIRO_FORMAT_ARGB32) {
|
|
val = INT_MAX;
|
|
}
|
|
else if (format == CAIRO_FORMAT_RGB24) {
|
|
val = 16777216;
|
|
}
|
|
else if (format == CAIRO_FORMAT_RGB16_565) {
|
|
val = 65536;
|
|
}
|
|
else {
|
|
val = 65536;
|
|
}
|
|
break;
|
|
case TQPaintDeviceMetrics::PdmDepth:
|
|
format = cairo_image_surface_get_format(m_surface);
|
|
if (format == CAIRO_FORMAT_ARGB32) {
|
|
val = 32;
|
|
}
|
|
else if (format == CAIRO_FORMAT_RGB24) {
|
|
val = 24;
|
|
}
|
|
else if (format == CAIRO_FORMAT_RGB16_565) {
|
|
val = 16;
|
|
}
|
|
else {
|
|
val = 16;
|
|
}
|
|
break;
|
|
default:
|
|
val = 0;
|
|
#if defined(QT_CHECK_RANGE)
|
|
tqWarning( "TQt3CairoPaintDevice::metric: Invalid metric command" );
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
val = 0;
|
|
#if defined(QT_CHECK_RANGE)
|
|
tqWarning( "TQt3CairoPaintDevice::metric: No Cairo surface available" );
|
|
#endif
|
|
}
|
|
return val;
|
|
}
|
|
|