|
|
|
@ -36,6 +36,12 @@
|
|
|
|
|
#define SET_BIT(x, y) (x |= 1 << y)
|
|
|
|
|
#define TEST_BIT(x, y) ((x & (1 << y)) >> y)
|
|
|
|
|
|
|
|
|
|
// Little endian
|
|
|
|
|
#define ARGB_A_BYTE_NUMBER 3
|
|
|
|
|
#define ARGB_R_BYTE_NUMBER 2
|
|
|
|
|
#define ARGB_G_BYTE_NUMBER 1
|
|
|
|
|
#define ARGB_B_BYTE_NUMBER 0
|
|
|
|
|
|
|
|
|
|
cairo_surface_t* TQImageToCairoSurface(TQImage origimg) {
|
|
|
|
|
cairo_surface_t* ret;
|
|
|
|
|
|
|
|
|
@ -98,24 +104,135 @@ void TQt3CairoPaintDevice::resetIntermediateSurface() {
|
|
|
|
|
m_intermediateSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void standardAlphaToPremultipliedAlpha(unsigned char *a, unsigned char *r, unsigned char *g, unsigned char *b) {
|
|
|
|
|
register double alpha_adjust;
|
|
|
|
|
|
|
|
|
|
alpha_adjust = (*a / 255.0);
|
|
|
|
|
*r = char( *r * alpha_adjust );
|
|
|
|
|
*g = char( *g * alpha_adjust );
|
|
|
|
|
*b = char( *b * alpha_adjust );
|
|
|
|
|
*a = char( *a * 1.0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void premultipliedAlphaToStandardAlpha(unsigned char *a, unsigned char *r, unsigned char *g, unsigned char *b) {
|
|
|
|
|
register double alpha_adjust;
|
|
|
|
|
|
|
|
|
|
alpha_adjust = (*a / 255.0);
|
|
|
|
|
*r = char( *r / alpha_adjust );
|
|
|
|
|
*g = char( *g / alpha_adjust );
|
|
|
|
|
*b = char( *b / alpha_adjust );
|
|
|
|
|
*a = char( *a / 1.0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TQt3CairoPaintDevice::transferIntermediateSurface() {
|
|
|
|
|
bool overlayMerge = true;
|
|
|
|
|
cairo_surface_flush(m_intermediateSurface);
|
|
|
|
|
|
|
|
|
|
if (m_rop != TQPainter::CopyROP) {
|
|
|
|
|
overlayMerge = false;
|
|
|
|
|
cairo_surface_flush(m_surface);
|
|
|
|
|
cairo_surface_flush(m_intermediateSurface);
|
|
|
|
|
register int height = cairo_image_surface_get_height(m_surface);
|
|
|
|
|
register int width = cairo_image_surface_get_width(m_surface);
|
|
|
|
|
register int stride = cairo_format_stride_for_width(cairo_image_surface_get_format(m_surface), width);
|
|
|
|
|
cairo_surface_t *usableDeviceSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
|
|
|
|
cairo_t *copyPainter = cairo_create(usableDeviceSurface);
|
|
|
|
|
cairo_set_source_surface(copyPainter, m_surface, 0, 0);
|
|
|
|
|
cairo_set_operator(copyPainter, CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_paint(copyPainter);
|
|
|
|
|
cairo_surface_flush(usableDeviceSurface);
|
|
|
|
|
cairo_destroy(copyPainter);
|
|
|
|
|
unsigned char* device_surface_data = cairo_image_surface_get_data(usableDeviceSurface);
|
|
|
|
|
unsigned char* intermediate_surface_data = cairo_image_surface_get_data(m_intermediateSurface);
|
|
|
|
|
register int x;
|
|
|
|
|
register int y;
|
|
|
|
|
register long long offset;
|
|
|
|
|
register unsigned char devicePixel_a;
|
|
|
|
|
register unsigned char devicePixel_r;
|
|
|
|
|
register unsigned char devicePixel_g;
|
|
|
|
|
register unsigned char devicePixel_b;
|
|
|
|
|
register unsigned char intermediatePixel_a;
|
|
|
|
|
register unsigned char intermediatePixel_r;
|
|
|
|
|
register unsigned char intermediatePixel_g;
|
|
|
|
|
register unsigned char intermediatePixel_b;
|
|
|
|
|
register unsigned char combinedPixel_a;
|
|
|
|
|
register unsigned char combinedPixel_r;
|
|
|
|
|
register unsigned char combinedPixel_g;
|
|
|
|
|
register unsigned char combinedPixel_b;
|
|
|
|
|
// Execute the desired raster operation
|
|
|
|
|
// WARNING
|
|
|
|
|
// This is VERY SLOW
|
|
|
|
|
for (y=0; y<height; y++) {
|
|
|
|
|
for (x=0; x<stride; x=x+4) {
|
|
|
|
|
offset = (y*stride)+x;
|
|
|
|
|
|
|
|
|
|
// Convert from premultiplied ARGB
|
|
|
|
|
premultipliedAlphaToStandardAlpha(intermediate_surface_data+offset+ARGB_A_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_R_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_G_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_B_BYTE_NUMBER);
|
|
|
|
|
intermediatePixel_a = (*(intermediate_surface_data+offset+ARGB_A_BYTE_NUMBER));
|
|
|
|
|
intermediatePixel_r = (*(intermediate_surface_data+offset+ARGB_R_BYTE_NUMBER));
|
|
|
|
|
intermediatePixel_g = (*(intermediate_surface_data+offset+ARGB_G_BYTE_NUMBER));
|
|
|
|
|
intermediatePixel_b = (*(intermediate_surface_data+offset+ARGB_B_BYTE_NUMBER));
|
|
|
|
|
if (intermediatePixel_a != 0) {
|
|
|
|
|
// Alpha channel of intermediate pixel was set; gather data for bitwise operation
|
|
|
|
|
premultipliedAlphaToStandardAlpha(device_surface_data+offset+ARGB_A_BYTE_NUMBER, device_surface_data+offset+ARGB_R_BYTE_NUMBER, device_surface_data+offset+ARGB_G_BYTE_NUMBER, device_surface_data+offset+ARGB_B_BYTE_NUMBER);
|
|
|
|
|
devicePixel_a = (*(device_surface_data+offset+ARGB_A_BYTE_NUMBER));
|
|
|
|
|
devicePixel_r = (*(device_surface_data+offset+ARGB_R_BYTE_NUMBER));
|
|
|
|
|
devicePixel_g = (*(device_surface_data+offset+ARGB_G_BYTE_NUMBER));
|
|
|
|
|
devicePixel_b = (*(device_surface_data+offset+ARGB_B_BYTE_NUMBER));
|
|
|
|
|
|
|
|
|
|
// Perform requested bitwise operation
|
|
|
|
|
if (m_rop == TQPainter::XorROP) {
|
|
|
|
|
combinedPixel_a = devicePixel_a;
|
|
|
|
|
combinedPixel_r = devicePixel_r ^ intermediatePixel_r;
|
|
|
|
|
combinedPixel_g = devicePixel_g ^ intermediatePixel_g;
|
|
|
|
|
combinedPixel_b = devicePixel_b ^ intermediatePixel_b;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tqWarning("TQt3CairoPaintDevice::cmd: Unhandled raster operation [Was attempting to use raster operation %d\n\r", m_rop);
|
|
|
|
|
combinedPixel_a = devicePixel_a;
|
|
|
|
|
combinedPixel_r = devicePixel_r;
|
|
|
|
|
combinedPixel_g = devicePixel_g;
|
|
|
|
|
combinedPixel_b = devicePixel_b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert to premultiplied ARGB
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_A_BYTE_NUMBER)) = combinedPixel_a;
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_R_BYTE_NUMBER)) = combinedPixel_r;
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_G_BYTE_NUMBER)) = combinedPixel_g;
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_B_BYTE_NUMBER)) = combinedPixel_b;
|
|
|
|
|
standardAlphaToPremultipliedAlpha(intermediate_surface_data+offset+ARGB_A_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_R_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_G_BYTE_NUMBER, intermediate_surface_data+offset+ARGB_B_BYTE_NUMBER);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Lossless copy of premultiplied ARGB pixel values
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_A_BYTE_NUMBER)) = (*(device_surface_data+offset+ARGB_A_BYTE_NUMBER));
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_R_BYTE_NUMBER)) = (*(device_surface_data+offset+ARGB_R_BYTE_NUMBER));
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_G_BYTE_NUMBER)) = (*(device_surface_data+offset+ARGB_G_BYTE_NUMBER));
|
|
|
|
|
(*(intermediate_surface_data+offset+ARGB_B_BYTE_NUMBER)) = (*(device_surface_data+offset+ARGB_B_BYTE_NUMBER));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cairo_surface_mark_dirty(m_intermediateSurface);
|
|
|
|
|
cairo_surface_destroy(usableDeviceSurface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_clipRegionEnabled) {
|
|
|
|
|
// Clipping disabled
|
|
|
|
|
cairo_set_source_surface(m_devicePainter, m_intermediateSurface, 0, 0);
|
|
|
|
|
cairo_set_operator(m_devicePainter, CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_set_operator(m_devicePainter, overlayMerge?CAIRO_OPERATOR_OVER:CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_paint(m_devicePainter);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// Clipping enabled
|
|
|
|
|
cairo_surface_t* maskSurface = TQImageToCairoSurface(m_clipRegion);
|
|
|
|
|
cairo_mask_surface(m_devicePainter, maskSurface, 0, 0);
|
|
|
|
|
cairo_set_operator(m_devicePainter, overlayMerge?CAIRO_OPERATOR_OVER:CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_fill(m_devicePainter);
|
|
|
|
|
cairo_surface_destroy(maskSurface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear intermediate surface
|
|
|
|
|
cairo_save(m_painter);
|
|
|
|
|
cairo_set_operator(m_painter, CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_set_source_rgba(m_painter, 0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
cairo_paint(m_painter);
|
|
|
|
|
cairo_restore(m_painter);
|
|
|
|
@ -1183,6 +1300,7 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
|
|
|
|
|
m_bgColorMode = TQt::TransparentMode;
|
|
|
|
|
resetIntermediateSurface();
|
|
|
|
|
m_painter = cairo_create(m_intermediateSurface);
|
|
|
|
|
cairo_set_operator(m_painter, CAIRO_OPERATOR_OVER);
|
|
|
|
|
m_devicePainter = cairo_create(m_surface);
|
|
|
|
|
m_pen = TQPen();
|
|
|
|
|
m_brush = TQBrush();
|
|
|
|
@ -1192,6 +1310,7 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
|
|
|
|
|
cairo_matrix_init_identity(&m_worldMatrix);
|
|
|
|
|
cairo_matrix_init_identity(&m_viewportMatrix);
|
|
|
|
|
setCairoTransformations();
|
|
|
|
|
m_rop = TQPainter::CopyROP;
|
|
|
|
|
m_clipRegion = TQImage();
|
|
|
|
|
m_clipRegionEnabled = false;
|
|
|
|
|
m_worldMatrixStack.clear();
|
|
|
|
@ -1230,65 +1349,8 @@ bool TQt3CairoPaintDevice::cmd( int c, TQPainter *pt, TQPDevCmdParam *p )
|
|
|
|
|
break;
|
|
|
|
|
case PdcSetROP:
|
|
|
|
|
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);
|
|
|
|
|
m_rop = rop;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PdcSetBrushOrigin:
|
|
|
|
|