[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]
Re: [XaraXtreme-dev] Cairo Port
- From: Jonas Diemer <diemer@xxxxxx>
- Date: Wed, 09 May 2007 16:45:38 +0200
- Subject: Re: [XaraXtreme-dev] Cairo Port
Hi,
thanks for pointing me to some ressources - I hadn't stumbled across
them yet. They will be a nice reading while I am travelling :-)
I have managed to actually draw something with Cairo now. It's only very
basic path drawing, and it looks pretty bad still. But at least I got
something on the screen.
I attached my changes to Carl's git-tree, in case anyone is interested.
Jonas
>From 2208eb750e865a3304ef6306813b7055e173d249 Mon Sep 17 00:00:00 2001
From: Jonas Diemer <jonas@JonasPC.(none)>
Date: Wed, 9 May 2007 16:39:25 +0200
Subject: [PATCH] Implemented very basic drawing with Cairo.
---
GDraw/gconsts.h | 12 +++-
GDraw/gdraw-cairo.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 150 insertions(+), 10 deletions(-)
diff --git a/GDraw/gconsts.h b/GDraw/gconsts.h
index b651780..ab6b359 100644
--- a/GDraw/gconsts.h
+++ b/GDraw/gconsts.h
@@ -104,6 +104,9 @@ service marks of Xara Group Ltd. All rights in these marks are reserved.
#ifndef INC_GCONSTS
#define INC_GCONSTS
+
+#include <cairo.h>
+
#if !defined(__WXMSW__)
const BYTE PT_CLOSEFIGURE = 1;
const BYTE PT_LINETO = 2;
@@ -234,11 +237,14 @@ enum DitherStyle {
/////////////////////////////////////////////////////////////////////////////////////////////////
+// struct GCONTEXT {
+// DWORD Valid ; // Valid if set to C90FDAA2.
+// DWORD Data[1] ;
+// } ;
struct GCONTEXT {
- DWORD Valid ; // Valid if set to C90FDAA2.
- DWORD Data[1] ;
+ DWORD Valid ; // Valid if set to C90FDAA2.
+ cairo_t *cr ;
} ;
-
struct DitherBlock {
diff --git a/GDraw/gdraw-cairo.cpp b/GDraw/gdraw-cairo.cpp
index e50ed64..44890d0 100644
--- a/GDraw/gdraw-cairo.cpp
+++ b/GDraw/gdraw-cairo.cpp
@@ -22,12 +22,23 @@
#include <stdio.h>
+#include <cairo.h>
+
#include "camtypes.h"
#include "gdraw.h"
#include "GVersion.h"
#define STUB(func) fprintf (stderr, "FIXME: Need a cairo-based implementation of " func " here.\n")
+
+double toFloat(long long int x){
+ return ((double) x) / (1<<16);
+}
+
+INT32 toFixed16(double x){
+ return (INT32) (x * (1<<16));
+}
+
DWORD
GDraw_GetVersion (void)
{
@@ -69,6 +80,10 @@ INT32
GDraw_Initialise (pGCONTEXT pContext, pcGCONTEXT pOldContext)
{
STUB ("GDraw_Initialise");
+
+ pContext->cr = NULL;
+ pContext->Valid = 0;
+
return 0;
}
@@ -257,15 +272,23 @@ GColour_SetHalftoneOrigin ( pGCONTEXT pContext, INT32 x,INT32 y )
INT32
GColour_SetColour ( pGCONTEXT pContext,COLORREF Colour )
{
- STUB ("GColour_SetColour");
- return 0;
+ if (pContext->cr == NULL) return 0;
+
+ cairo_set_source_rgb (pContext->cr, GetRValue(Colour), GetGValue(Colour), GetBValue(Colour));
+
+ return 1;
}
INT32
GColour_SetSolidColour ( pGCONTEXT pContext,COLORREF Colour,UINT32 BPP,UINT32 Format16BPP)
{
STUB ("GColour_SetSolidColour");
- return 0;
+ // TODO: Does this need to behave different than SetColour?
+
+ if (pContext->cr == NULL) return 0;
+ cairo_set_source_rgb (pContext->cr, GetRValue(Colour), GetGValue(Colour), GetBValue(Colour));
+
+ return 1;
}
INT32
@@ -780,7 +803,51 @@ GDraw_SetDIBitmap (
)
{
STUB ("GDraw_SetDIBitmap");
- return 0;
+ if (Format16BPP != 2) { return 0;}
+ if (Bitmap == NULL) { return 0;}
+
+// printf("Format: %d, %d x %d, compression: 0x%x\n",
+// Format16BPP, BitmapInfo->biWidth, BitmapInfo->biHeight, BitmapInfo->biCompression);
+
+ cairo_surface_t *surface = cairo_image_surface_create_for_data(
+ Bitmap,
+ CAIRO_FORMAT_ARGB32,
+ BitmapInfo->biWidth,
+ BitmapInfo->biHeight,
+ 4*BitmapInfo->biWidth );
+
+ cairo_matrix_t mat;
+ cairo_pattern_t* sourcePattern;
+
+ if ( pContext->cr != NULL ){
+ // store part of the state
+ cairo_get_matrix(pContext->cr, &mat);
+ sourcePattern = cairo_get_source(pContext->cr);
+ cairo_pattern_reference(sourcePattern);
+
+ // destroy and recreace cairo_t. This is the only way to assign a new surface to a cairo_t...
+ cairo_destroy( pContext->cr );
+ pContext->cr = cairo_create(surface);
+
+ // restore part of the state
+ cairo_set_matrix(pContext->cr, &mat);
+ cairo_set_source(pContext->cr, sourcePattern);
+ cairo_pattern_destroy(sourcePattern); // not sure
+ }else{
+ // FIrst time, so only create the context
+ pContext->cr = cairo_create(surface);
+ }
+
+ // Delete image TODO: improve this
+ UINT32* IntPtr = (UINT32*) Bitmap;
+ *(IntPtr++) = 0x000000FF ;
+ for (int i=0; i < BitmapInfo->biWidth; i++){
+ for (int j=0; j < BitmapInfo->biHeight; j++){
+ *(IntPtr++) = 0xFFFFFFFF;//0x00000000;
+ }
+ }
+
+ return 1;
}
INT32
@@ -799,7 +866,34 @@ INT32
GDraw_SetMatrix ( pGCONTEXT pContext,pcGMATRIX Matrix )
{
STUB ("GDraw_SetMatrix");
- return 0;
+
+ if (pContext->cr == NULL) return 0;
+
+
+ cairo_matrix_t mat;
+ mat.xx = toFloat(Matrix->AX);
+ mat.xy = toFloat(Matrix->AY);
+ mat.yx = toFloat(Matrix->BX);
+ mat.yy = toFloat(Matrix->BY);
+ mat.x0 = toFloat(Matrix->CX)/(1<<16);
+ mat.y0 = toFloat(Matrix->CY)/(1<<16);
+
+ mat.xx *= 4;
+ mat.xy *= 4;
+ mat.yx *= 4;
+ mat.yy *= 4;
+ mat.x0 *= 4;
+ mat.y0 *= 4;
+
+ cairo_set_matrix(pContext->cr, &mat);
+ /*
+ cairo_get_matrix(pContext->cr, &mat);
+ printf("Xara Matrix: AX=%d, AY=%d, BX=%d, BY=%d, CX=%lld, CY=%lld\n",
+ Matrix->AX, Matrix->AY, Matrix->BX, Matrix->BY, Matrix->CX, Matrix->CY);
+ printf("Cairo matrix: xx=%f, xy=%f, yx=%f, yy=%f, x0=%f, y0=%f\n",
+ mat.xx, mat.xy, mat.yx, mat.yy, mat.x0, mat.y0);*/
+
+ return 1;
}
INT32
@@ -855,6 +949,7 @@ INT32
GDraw_SetFlatness ( pGCONTEXT pContext,UINT32 Flatness )
{
STUB ("GDraw_SetFlatness");
+// printf("Context: valid=%d, data[0]=%d\n",pContext->Valid, pContext->Data[0]);
return 0;
}
@@ -920,7 +1015,18 @@ GDraw_StrokePath (
)
{
STUB ("GDraw_StrokePath");
- return 0;
+ if (pContext->cr == NULL) return 0;
+ if (Length <= 0) return 0;
+
+
+ cairo_set_line_width (pContext->cr, toFloat(LineWidth));
+ cairo_move_to(pContext->cr, toFloat(Points[0].x), toFloat(Points[0].y));
+ for (int i=1; i<Length; i++){
+ cairo_line_to(pContext->cr, toFloat(Points[i].x), toFloat(Points[i].y));
+ }
+ cairo_stroke(pContext->cr);
+
+ return 1;
}
INT32
@@ -1137,7 +1243,35 @@ INT32
GDraw_GetChangedBBox ( pcGCONTEXT pContext, pRECT Rectangle )
{
STUB ("GDraw_GetChangedBBox");
- return 0;
+
+ // determine the size of the 'changed' rectangle where pixels have been plotted.
+ // for now, this is the full surface
+ //
+ // This condition must be met:
+ //(UsedRect.right >= UsedRect.left) && (UsedRect.bottom >= UsedRect.top ))
+
+
+ if (pContext->cr == NULL) return 0;
+
+ // TODO: This doesn't seem to be perfect yet...
+ cairo_surface_t* target = cairo_get_target(pContext->cr);
+
+ // The full image has changed
+ double left = 0;
+ double bottom = 0;
+ double right = cairo_image_surface_get_width(target);
+ double top = cairo_image_surface_get_height(target);
+
+ cairo_device_to_user(pContext->cr, &left, &bottom);
+ cairo_device_to_user(pContext->cr, &right, &top);
+
+
+ Rectangle->left = toFixed16(left);
+ Rectangle->bottom = toFixed16(bottom);
+ Rectangle->right = toFixed16(right);
+ Rectangle->top = toFixed16(top);
+
+ return 1;
}
INT32
--
1.4.4.2