Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial revision

svn path=/trunk/libgdiplus/; revision=22640
  • Loading branch information...
commit 739500173f75772c7ed94f52f5012bd2788618c7 0 parents
Miguel de Icaza migueldeicaza authored
5 AUTHORS
@@ -0,0 +1,5 @@
+Alexandre Pigolkine
+Duncan Mak
+Jordi Mas
+Miguel de Icaza
+Ravindra Kumar
1  COPYING
@@ -0,0 +1 @@
+Libgdiplus is available under the terms of the MIT X11 license.
4 ChangeLog
@@ -0,0 +1,4 @@
+2004-01-31 Miguel de Icaza <miguel@ximian.com>
+
+ * Initial release, split from the Mono's MCS package.
+
9 Makefile.am
@@ -0,0 +1,9 @@
+SUBDIRS = src
+
+pkgconfigdir = $(libdir)/pkgconfig
+
+pkgconfig_DATA= libgdiplus.pc
+
+DISTCLEANFILES= libgdiplus.pc
+
+EXTRA_DIST = libgdiplus.pc.in
1  NEWS
@@ -0,0 +1 @@
+First release of libgdiplus, spun off from Mono's C# library.
7 README
@@ -0,0 +1,7 @@
+libgdiplus: An Open Source implementation of the GDI+ API.
+This is part of the Mono project
+
+Requirements:
+
+ This requires Cairo to build.
+
32 configure.in
@@ -0,0 +1,32 @@
+AC_INIT(README)
+AC_CANONICAL_SYSTEM
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(libgdiplus,0.1)
+
+AM_MAINTAINER_MODE
+AM_PROG_LIBTOOL
+
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+if test "x$PKG_CONFIG" = "xno"; then
+ AC_MSG_ERROR([You need to install pkg-config])
+fi
+if pkg-config --atleast-version 2.2.3 glib-2.0; then
+ echo GLIB 2.0 installation OK
+else
+ AC_MSG_ERROR("Did not find Glib >= 2.2.3");
+fi
+
+if pkg-config --atleast-version 0.1.17 cairo; then
+ echo Cairo installation OK
+else
+ AC_MSG_ERROR("Did not find Cairo 0.1.17");
+fi
+GDIPLUS_LIBS=`pkg-config --libs cairo glib-2.0`
+AC_SUBST(GDIPLUS_LIBS)
+AC_SUBST(GDIPLUS_CFLAGS)
+GDIPLUS_CFLAGS=`pkg-config --cflags cairo glib-2.0`
+AC_OUTPUT([
+Makefile
+libgdiplus.pc
+src/Makefile])
+
12 libgdiplus.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+
+Name: libgdiplus
+Description: GDI+ implementation
+Version: @VERSION@
+Requires: glib-2.0 gmodule-2.0 gthread-2.0 cairo-0.1.17
+Libs: -L${libdir} -lgdiplus @GDIPLUS_LIBS@
+Cflags: -I${includedir} @GDIPLUS_CFLAGS@
20 src/Makefile.am
@@ -0,0 +1,20 @@
+lib_LTLIBRARIES = libgdiplus.la
+
+libgdiplus_la_SOURCES = \
+ bitmap.c \
+ brush.c \
+ gdip.h \
+ gdip_win32.c \
+ gdip_win32.h \
+ general.c \
+ graphics.c \
+ graphics-path.c \
+ graphics-path.h \
+ image.c \
+ matrix.c \
+ pen.c \
+ solidbrush.c
+
+libgdiplus_la_LIBADD = $(GDIPLUS_LIBS)
+
+INCLUDES = $(GDIPLUS_CFLAGS)
363 src/bitmap.c
@@ -0,0 +1,363 @@
+/*
+ * bitmap.c
+ *
+ * Copyright (c) 2003 Alexandre Pigolkine
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ */
+
+#include <glib.h>
+#include "gdip.h"
+#include "gdip_win32.h"
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void
+gdip_bitmap_init (GpBitmap *bitmap)
+{
+ gdip_image_init (&bitmap->image);
+ bitmap->image.type = imageBitmap;
+ bitmap->cairo_format = 0;
+ bitmap->data.Width = 0;
+ bitmap->data.Height = 0;
+ bitmap->data.Stride = 0;
+ bitmap->data.PixelFormat = 0;
+ bitmap->data.Scan0 = 0;
+ bitmap->data.Reserved = 0;
+
+ bitmap->hBitmapDC = 0;
+ bitmap->hInitialBitmap = 0;
+ bitmap->hBitmap = 0;
+}
+
+GpBitmap *
+gdip_bitmap_new ()
+{
+ GpBitmap *result = (GpBitmap *) GdipAlloc (sizeof(GpBitmap));
+ gdip_bitmap_init (result);
+ return result;
+}
+
+/*
+ * This should only be called from GdipDisposeImage, and it should *not* free
+ * the structure, that one is freed by GdipDisposeImage
+ */
+void
+gdip_bitmap_dispose (GpBitmap *bitmap)
+{
+ if (bitmap->data.own_scan0 == TRUE)
+ GdipFree (bitmap->data.Scan0);
+}
+
+void
+gdip_bitmap_fill_info_header (GpBitmap *bitmap, PBITMAPINFOHEADER bmi)
+{
+ int bitmapLen = bitmap->data.Stride * bitmap->data.Height;
+ memset (bmi, 0, 40);
+ bmi->biSize = sizeof (BITMAPINFOHEADER);
+ bmi->biWidth = bitmap->data.Width;
+ bmi->biHeight = -bitmap->data.Height;
+ bmi->biPlanes = 1;
+ bmi->biBitCount = 32;
+ bmi->biCompression = BI_RGB;
+ bmi->biSizeImage = bitmapLen;
+}
+
+void
+gdip_bitmap_save_bmp (const char *name, GpBitmap *bitmap)
+{
+ BITMAPFILEHEADER bmfh;
+ BITMAPINFOHEADER bmi;
+ int bitmapLen = bitmap->data.Stride * bitmap->data.Height;
+ FILE *fp;
+
+ bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
+ bmfh.bfType = BFT_BITMAP;
+ bmfh.bfOffBits = (14 + 40 + 0 * 4);
+ bmfh.bfSize = (bmfh.bfOffBits + bitmapLen);
+ fp = fopen (name, "w+b");
+ fwrite (&bmfh, 1, sizeof (bmfh), fp);
+ gdip_bitmap_fill_info_header (bitmap, &bmi);
+ bmi.biHeight = -bmi.biHeight;
+ fwrite (&bmi, 1, sizeof (bmi), fp);
+ fwrite (bitmap->data.Scan0, 1, bitmapLen, fp);
+ fclose (fp);
+}
+
+void *
+gdip_bitmap_create_Win32_HDC (GpBitmap *bitmap)
+{
+ void * result = 0;
+ void * hdc = CreateCompatibleDC_pfn (0);
+ void * hbitmap = 0, * holdbitmap = 0;
+ void * hdcDesc = GetDC_pfn (0);
+
+ hbitmap = CreateCompatibleBitmap_pfn (hdcDesc, bitmap->data.Width, bitmap->data.Height);
+ if (hbitmap != 0) {
+ BITMAPINFO bmi;
+ gdip_bitmap_fill_info_header (bitmap, &bmi.bmiHeader);
+ /* _saveBmp ("file1.bmp", bitmap); */
+ SetDIBits_pfn (hdc, hbitmap, 0, bitmap->data.Height, bitmap->data.Scan0, &bmi, 0);
+ holdbitmap = SelectObject_pfn (hdc, hbitmap);
+ bitmap->hBitmapDC = hdc;
+ bitmap->hInitialBitmap = holdbitmap;
+ bitmap->hBitmap = hbitmap;
+ result = hdc;
+ }
+ else {
+ DeleteDC_pfn (hdc);
+ }
+ ReleaseDC_pfn (0, hdcDesc);
+ return result;
+}
+
+void
+gdip_bitmap_destroy_Win32_HDC (GpBitmap *bitmap, void *hdc)
+{
+ if (bitmap->hBitmapDC == hdc) {
+
+ BITMAPINFO bmi;
+ int res = 0;
+ unsigned long *array, *end;
+
+ SelectObject_pfn (bitmap->hBitmapDC, bitmap->hInitialBitmap);
+
+ gdip_bitmap_fill_info_header (bitmap, &bmi.bmiHeader);
+ res = GetDIBits_pfn (bitmap->hBitmapDC, bitmap->hBitmap, 0, bitmap->data.Height, bitmap->data.Scan0, &bmi, 0);
+ if (bitmap->cairo_format == CAIRO_FORMAT_ARGB32) {
+ array = bitmap->data.Scan0;
+ end = array + (bmi.bmiHeader.biSizeImage >> 2);
+ while (array < end) {
+ *array |= 0xff000000;
+ ++array;
+ }
+ }
+ /* _saveBmp ("file2.bmp", bitmap); */
+
+ DeleteObject_pfn (bitmap->hBitmap);
+ DeleteDC_pfn (bitmap->hBitmapDC);
+ bitmap->hBitmapDC = 0;
+ bitmap->hInitialBitmap = 0;
+ bitmap->hBitmap = 0;
+ }
+}
+
+GpStatus
+GdipCreateBitmapFromScan0 (int width, int height, int stride, int format, void *scan0, GpBitmap **bitmap)
+{
+ GpBitmap *result = 0;
+ int cairo_format = 0;
+ bool own_scan0 = FALSE;
+
+ if (stride == 0)
+ return InvalidParameter;
+
+ switch (format) {
+ case Format24bppRgb:
+ cairo_format = CAIRO_FORMAT_RGB24;
+ break;
+ case Format32bppArgb:
+ cairo_format = CAIRO_FORMAT_ARGB32;
+ break;
+ default:
+ *bitmap = 0;
+ return NotImplemented;
+ }
+
+ if (scan0 == NULL) {
+ scan0 = GdipAlloc (stride * height);
+ own_scan0 = TRUE;
+ }
+
+ result = gdip_bitmap_new ();
+ result->cairo_format = cairo_format;
+ result->data.Width = width;
+ result->data.Height = height;
+ result->data.Stride = stride;
+ result->data.PixelFormat = format;
+ result->data.Scan0 = scan0;
+ result->data.own_scan0 = own_scan0;
+
+ *bitmap = result;
+ return Ok;
+}
+
+GpStatus
+GdipCreateBitmapFromGraphics (int width, int height, GpGraphics *graphics, GpBitmap **bitmap)
+{
+ GpBitmap *result = 0;
+ int bmpSize = 0;
+ int cairo_format = 0;
+ int stride = width;
+
+ /*
+ * FIXME: should get the stride based on the format of the graphics object.
+ */
+ fprintf (stderr, "GdipCreateBitmapFromGraphics: This routine has not been checked for stride size\n");
+ while (stride % 4)
+ stride++;
+
+ stride *= 4;
+ cairo_format = CAIRO_FORMAT_ARGB32;
+ bmpSize = stride * height;
+ result = gdip_bitmap_new ();
+ result->cairo_format = cairo_format;
+ result->data.Width = width;
+ result->data.Height = height;
+ result->data.Stride = stride;
+ result->data.PixelFormat = Format32bppArgb;
+ result->data.Scan0 = GdipAlloc (bmpSize);
+ result->data.Reserved = 1;
+ *bitmap = result;
+ return Ok;
+}
+
+GpStatus
+GdipCloneBitmapAreaI (int x, int y, int width, int height, int format, GpBitmap *original, GpBitmap **bitmap)
+{
+ GpBitmap *result = 0;
+ int bmpSize = original->data.Height * original->data.Stride;
+
+ /*
+ * FIXME: Convert format if needed and copy only specified rectangle
+ */
+ result = gdip_bitmap_new ();
+ result->cairo_format = original->cairo_format;
+ result->data.Width = original->data.Width;
+ result->data.Height = original->data.Height;
+ result->data.Stride = original->data.Stride;
+ result->data.PixelFormat = original->data.PixelFormat;
+ result->data.Scan0 = GdipAlloc (bmpSize);
+ memmove (result->data.Scan0, original->data.Scan0, bmpSize);
+ result->data.Reserved = 1;
+
+ *bitmap = result;
+ return Ok;
+}
+
+static int
+ChangePixelFormat (GpBitmap *bitmap, GdipBitmapData *destData)
+{
+ int sourcePixelIncrement = (bitmap->data.PixelFormat == Format32bppArgb) ? 1 : 0;
+ int destinationPixelIncrement = (destData->PixelFormat == Format32bppArgb) ? 1 : 0;
+ char * curSrc = bitmap->data.Scan0;
+ char * curDst = 0;
+ int i, j;
+
+ /*
+ printf("ChangePixelFormat to %d. Src inc %d, Dest Inc %d\n",
+ destData->PixelFormat, sourcePixelIncrement, destinationPixelIncrement);
+ */
+ if (bitmap->data.PixelFormat == destData->PixelFormat) return 0;
+
+ if (destData->PixelFormat != Format32bppArgb && destData->PixelFormat != Format24bppRgb) {
+ fprintf (stderr, "This pixel format is not supported %d\n", destData->PixelFormat);
+ return 0;
+ }
+ destData->Width = bitmap->data.Width;
+ destData->Height = bitmap->data.Height;
+ destData->Stride = ((destData->PixelFormat == Format32bppArgb ) ? 4 : 3 ) * bitmap->data.Width;
+ destData->Scan0 = GdipAlloc (destData->Stride * bitmap->data.Height);
+ destData->Reserved = 1;
+ curSrc = bitmap->data.Scan0;
+ curDst = (char *)destData->Scan0;
+ for ( i = 0; i < bitmap->data.Height; i++) {
+ for( j = 0; j < bitmap->data.Width; j++) {
+ *curDst++ = *curSrc++;
+ *curDst++ = *curSrc++;
+ *curDst++ = *curSrc++;
+ curSrc += sourcePixelIncrement;
+ curDst += destinationPixelIncrement;
+ }
+ }
+ return 1;
+}
+
+GpStatus
+GdipBitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, GdipBitmapData *result)
+{
+ if (bitmap == 0){
+ printf ("Bitmap is null\n");
+ return InvalidParameter;
+ }
+
+ /* Special case: the entire image is requested */
+ if (rc->left == 0 && rc->right == bitmap->data.Width &&
+ rc->top == 0 && rc->bottom == bitmap->data.Height &&
+ format == bitmap->data.PixelFormat){
+ *result = bitmap->data;
+ result->Reserved = result->Reserved & ~1;
+ return Ok;
+ }
+
+ if (bitmap->data.PixelFormat != format) {
+ GdipBitmapData convert;
+ convert.PixelFormat = format;
+ if (!ChangePixelFormat (bitmap, &convert)) {
+ printf ("Requesting format change, not supported yet %d %d\n", bitmap->data.PixelFormat, format);
+ return InvalidParameter;
+ }
+ result->Width = convert.Width;
+ result->Height = convert.Height;
+ result->Stride = convert.Stride;
+ result->PixelFormat = convert.PixelFormat;
+ result->Reserved = convert.Reserved;
+ result->Scan0 = convert.Scan0;
+ }
+ else {
+ result->Width = bitmap->data.Width;
+ result->Height = bitmap->data.Height;
+ result->Stride = bitmap->data.Stride;
+ result->PixelFormat = bitmap->data.PixelFormat;
+ result->Reserved = bitmap->data.Reserved;
+ result->Scan0 = bitmap->data.Scan0;
+ }
+
+ return Ok;
+}
+
+GpStatus
+____BitmapLockBits (GpBitmap *bitmap, Rect *rc, int flags, int format, int *width, int *height, int *stride, int *fptr, int *res, int *scan0)
+{
+ GdipBitmapData d;
+ int s;
+
+ s = GdipBitmapLockBits (bitmap, rc, flags, format, &d);
+ *width = d.Width;
+ *height = d.Height;
+ *stride = d.Stride;
+ *fptr = d.PixelFormat;
+ *res = d.Reserved;
+ *scan0 = (int)d.Scan0;
+
+ return s;
+}
+
+GpStatus
+GdipBitmapUnlockBits (GpBitmap *bitmap, GdipBitmapData *bitmap_data)
+{
+ if (bitmap_data->Reserved & 1)
+ GdipFree (bitmap_data->Scan0);
+ return Ok;
+}
+
71 src/brush.c
@@ -0,0 +1,71 @@
+/*
+ * brush.c
+ *
+ * Copyright (c) 2003 Alexandre Pigolkine
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ */
+
+#include "gdip.h"
+
+void
+gdip_brush_setup (GpGraphics *graphics, GpBrush *brush)
+{
+ GpBrushType type;
+ GdipGetBrushType (brush, &type);
+
+ if (type == BrushTypeSolidColor) {
+ GpSolidFill *solid = brush;
+ gdip_solidfill_setup (graphics, solid);
+ }
+}
+
+GpBrush *
+gdip_brush_new (void)
+{
+ GpBrush *result = (GpBrush *) GdipAlloc (sizeof (GpBrush));
+
+ return result;
+}
+
+GpStatus
+GdipCloneBrush (GpBrush *brush, GpBrush **clonedBrush)
+{
+ GpBrushType type;
+ GdipGetBrushType (brush, &type);
+
+ if (type == BrushTypeSolidColor)
+ return gdip_solidfill_clone (brush, clonedBrush);
+ else
+ return NotImplemented;
+}
+
+GpStatus
+GdipDeleteBrush (GpBrush *brush)
+{
+ GdipFree (brush);
+ return Ok;
+}
+
+GpStatus
+GdipGetBrushType (GpBrush *brush, GpBrushType *type)
+{
+ *type = brush->type;
+ return Ok;
+}
439 src/gdip.h
@@ -0,0 +1,439 @@
+/*
+ * gdip.h
+ *
+ * Authors:
+ * Alexandre Pigolkine (pigolkine@gmx.de)
+ * Duncan Mak (duncan@ximian.com)
+ * Miguel de Icaza (miguel@ximian.com)
+ *
+ * Copyright (C) Novell, Inc. 2003.
+ */
+
+#ifndef _GDIP_H
+#define _GDIP_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <cairo.h>
+#ifndef CAIRO_HAS_XLIB_SURFACE
+#include <cairo-xlib.h>
+#endif
+#include <mono/io-layer/uglify.h>
+
+/*
+ * Constants
+ *
+ */
+#define PI 3.14159265358979323846
+#define DEGTORAD PI / 180.0
+
+typedef unsigned char byte;
+typedef int bool;
+
+/*
+ * Enums
+ *
+ */
+
+typedef enum {
+ Ok = 0,
+ GenericError = 1,
+ InvalidParameter = 2,
+ OutOfMemory = 3,
+ ObjectBusy = 4,
+ InsufficientBuffer = 5,
+ NotImplemented = 6,
+ Win32Error = 7,
+ WrongState = 8,
+ Aborted = 9,
+ FileNotFound = 10,
+ ValueOverflow = 11,
+ AccessDenied = 12,
+ UnknownImageFormat = 13,
+ FontFamilyNotFound = 14,
+ FontStyleNotFound = 15,
+ NotTrueTypeFont = 16,
+ UnsupportedGdiplusVersion = 17,
+ GdiplusNotInitialized = 18,
+ PropertyNotFound = 19,
+ PropertyNotSupported = 20
+} GpStatus;
+
+typedef enum {
+ MatrixOrderPrepend = 0,
+ MatrixOrderAppend = 1
+} MatrixOrder, GpMatrixOrder;
+
+typedef enum {
+ UnitWorld = 0,
+ UnitDisplay = 1,
+ UnitPixel = 2,
+ UnitPoint = 3,
+ UnitInch = 4,
+ UnitDocument = 5,
+ UnitMillimeter = 6
+} GpUnit, Unit;
+
+typedef enum {
+ Alpha = 262144,
+ Canonical = 2097152,
+ DontCare = 0,
+ Extended = 1048576,
+ Format16bppArgb1555 = 397319,
+ Format16bppGrayScale = 1052676,
+ Format16bppRgb555 = 135173,
+ Format16bppRgb565 = 135174,
+ Format1bppIndexed = 196865,
+ Format24bppRgb = 137224,
+ Format32bppArgb = 2498570,
+ Format32bppPArgb = 925707,
+ Format32bppRgb = 139273,
+ Format48bppRgb = 1060876,
+ Format4bppIndexed = 197634,
+ Format64bppArgb = 3424269,
+ Format64bppPArgb = 1851406,
+ Format8bppIndexed = 198659,
+ Gdi = 131072,
+ Indexed = 65536,
+ Max = 15,
+ PAlpha = 524288,
+ Undefined = 0
+} PixelFormat;
+
+typedef enum {
+ ReadOnly = 1,
+ ReadWrite = 3,
+ UserInputBuffer = 4,
+ WriteOnly = 2
+} ImageLockMode;
+
+typedef enum {
+ FillModeAlternate,
+ FillModeWinding
+} GpFillMode;
+
+typedef enum {
+ DashStyleSolid = 0, /* solid line */
+ DashStyleDash = 1, /* dashed line */
+ DashStyleDot = 2, /* dotted line */
+ DashStyleDashDot = 3, /* alt. dash-dot */
+ DashStyleDashDotDot = 4, /* alt. dash-dot-dot */
+ DashStyleCustom = 5 /* user-defined */
+} GpDashStyle;
+
+typedef enum {
+ LineJoinMiter = 0, /* sharp corner */
+ LineJoinBevel = 1, /* round corner */
+ LineJoinRound = 2, /* circular, smooth, circular arc */
+ LineJoinMiterClipped = 3 /* miter, sharp or beveled corner */
+} GpLineJoin;
+
+typedef enum {
+ imageUndefined,
+ imageBitmap,
+ imageMetafile
+} ImageType;
+
+typedef enum {
+ gtUndefined,
+ gtX11Drawable,
+ gtMemoryBitmap
+} GraphicsType;
+
+typedef enum {
+ LineCapFlat = 0,
+ LineCapSquare = 1,
+ LineCapRound = 2,
+ LineCapTriangle = 3,
+ LineCapNoAnchor = 0x10,
+ LineCapSquareAnchor = 0x11,
+ LineCapRoundAnchor = 0x12,
+ LineCapDiamondAnchor = 0x13,
+ LineCapArrowAnchor = 0x14,
+ LineCapCustom = 0xff
+} GpLineCap;
+
+typedef enum {
+ PenAlignmentCenter = 0,
+ PenAlignmentInset = 1
+} GpPenAlignment, PenAlignment;
+
+typedef enum {
+ BrushTypeSolidColor = 0,
+ BrushTypeHatchFill = 1,
+ BrushTypeTextureFill = 2,
+ BrushTypePathGradient = 3,
+ BrushTypeLinearGradient = 4
+} GpBrushType, BrushType;
+
+typedef enum {
+ PathPointTypeStart = 0,
+ PathPointTypeLine = 1,
+ PathPointTypeBezier = 3,
+ PathPointTypePathTypeMask = 0x7,
+ PathPointTypePathDashMode = 0x10,
+ PathPointTypePathMarker = 0x20,
+ PathPointTypeCloseSubpath = 0x80,
+ PathPointTypeBezier3 = 3
+} GpPathPointType, PathPointType;
+
+typedef enum {
+ WarpModePerspective = 0,
+ WarpModeBilinear = 1
+} GpWarpMode, WarpMode;
+/*
+ * Structures
+ *
+ */
+typedef struct {
+ unsigned int Width;
+ unsigned int Height;
+ int Stride;
+ int PixelFormat;
+ bool own_scan0;
+ void *Scan0;
+ unsigned int Reserved;
+} GdipBitmapData, BitmapData;
+
+typedef struct {
+ int left, top, right, bottom;
+} GpRect, Rect;
+
+typedef struct {
+ float left, top, right, bottom;
+} GpRectF, RectF;
+
+typedef struct {
+ int X, Y;
+} GpPoint, Point;
+
+typedef struct {
+ float X, Y;
+} GpPointF, PointF;
+
+typedef struct {
+ cairo_t *ct;
+ cairo_matrix_t *copy_of_ctm;
+ void *hdc;
+ int hdc_busy_count;
+ void *image;
+ int type;
+} GpGraphics;
+
+typedef cairo_matrix_t GpMatrix;
+
+typedef struct {
+ int color;
+ GpBrushType type;
+} GpBrush, GpSolidFill;
+
+typedef struct {
+ int color;
+ GpBrush *brush;
+ float width;
+ float miter_limit;
+ GpLineJoin line_join;
+ GpDashStyle dash_style;
+ GpLineCap line_cap;
+ GpPenAlignment mode;
+ float dash_offset;
+ int dash_count;
+ int own_dash_array;
+ float *dash_array;
+ GpUnit unit;
+ GpMatrix *matrix;
+} GpPen;
+
+typedef struct {
+ cairo_matrix_t *matrix;
+} GpState;
+
+typedef struct {
+ ImageType type;
+ cairo_surface_t *surface;
+ GpGraphics *graphics; /* created by GdipGetImageGraphicsContext */
+} GpImage;
+
+typedef struct {
+ GpImage image;
+ int cairo_format;
+ BitmapData data;
+ void *hBitmapDC;
+ void *hInitialBitmap;
+ void *hBitmap;
+} GpBitmap;
+
+typedef struct {
+ GpFillMode fill_mode;
+ int count;
+ GByteArray *types;
+ GArray *points;
+} GpPath;
+
+typedef struct {
+ int Count;
+ PointF *Points;
+ byte *Types;
+} GpPathData;
+
+/*
+ * Functions
+ *
+ */
+void gdip_image_init (GpImage *image);
+void *gdip_image_create_Win32_HDC (GpImage *image);
+void gdip_image_destroy_Win32_HDC (GpImage *image, void *hdc);
+
+void gdip_bitmap_init (GpBitmap *bitmap);
+GpBitmap *gdip_bitmap_new (void);
+void gdip_bitmap_dispose (GpBitmap *bitmap);
+
+void *gdip_bitmap_create_Win32_HDC (GpBitmap *bitmap);
+void gdip_bitmap_destroy_Win32_HDC (GpBitmap *bitmap, void *hdc);
+
+void *_get_gdi32Handle (void);
+void *_get_user32Handle (void);
+
+void gdip_graphics_init (GpGraphics *graphics);
+GpGraphics *gdip_graphics_new (void);
+void gdip_graphics_attach_bitmap (GpGraphics *graphics, GpBitmap *image);
+void gdip_graphics_detach_bitmap (GpGraphics *graphics, GpBitmap *image);
+
+/* Brush */
+void gdip_brush_setup (GpGraphics *graphics, GpBrush *brush);
+GpBrush *gdip_brush_new (void);
+
+/* Solid fill */
+void gdip_solidfill_init (GpSolidFill *brush);
+void gdip_solidfill_setup (GpGraphics *graphics, GpBrush *brush);
+GpStatus gdip_solidfill_clone (GpBrush *brush, GpBrush **clonedBrush);
+GpSolidFill *gdip_solidfill_new (void);
+
+/* Pen */
+void gdip_pen_init (GpPen *pen);
+GpPen *gdip_pen_new (void);
+void gdip_pen_setup (GpGraphics *graphics, GpPen *pen);
+
+extern Display *GDIP_display;
+
+void initializeGdipWin32 (void);
+
+/* Bitmap */
+GpStatus GdipCreateBitmapFromScan0 (int width, int height, int strideIn, int format, void *scan0, GpBitmap **bitmap);
+GpStatus GdipCreateBitmapFromGraphics (int width, int height, GpGraphics *graphics, GpBitmap **bitmap);
+GpStatus GdipBitmapLockBits (GpBitmap *bmp, Rect *rc, int flags, int format, GdipBitmapData *result);
+GpStatus GdipBitmapUnlockBits (GpBitmap *bmp, GdipBitmapData *bmpData);
+
+/* Graphics */
+GpStatus GdipCreateFromHDC (int hDC, GpGraphics **graphics);
+GpStatus GdipDeleteGraphics (GpGraphics *graphics);
+GpStatus GdipGetDC (GpGraphics *graphics, int *hDC);
+GpStatus GdipReleaseDC (GpGraphics *graphics, int hDC);
+GpStatus GdipRestoreGraphics (GpGraphics *graphics, unsigned int graphicsState);
+GpStatus GdipSaveGraphics(GpGraphics *graphics, unsigned int * state);
+GpStatus GdipRotateWorldTransform (GpGraphics *graphics, float angle, GpMatrixOrder order);
+GpStatus GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, GpMatrixOrder order);
+GpStatus GdipDrawBezier (GpGraphics *graphics, GpPen *pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+GpStatus GdipDrawBezierI (GpGraphics *graphics, GpPen *pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
+GpStatus GdipDrawBeziers (GpGraphics *graphics, GpPen *pen, GpPointF *points, int count);
+GpStatus GdipDrawBeziersI (GpGraphics *graphics, GpPen *pen, GpPoint *points, int count);
+GpStatus GdipDrawEllipse (GpGraphics *graphics, GpPen *pen, float x, float y, float width, float height);
+GpStatus GdipDrawLine (GpGraphics *graphics, GpPen *pen, float x1, float y1, float x2, float y2);
+GpStatus GdipDrawLineI (GpGraphics *graphics, GpPen *pen, int x1, int y1, int x2, int y2);
+GpStatus GdipDrawLines (GpGraphics *graphics, GpPen *pen, GpPointF *points, int count);
+GpStatus GdipDrawLinesI (GpGraphics *graphics, GpPen *pen, GpPoint *points, int count);
+GpStatus GdipDrawPie (GpGraphics *graphics, GpPen *pen, float x, float y, float width, float height, float startAngle, float sweepAngle);
+GpStatus GdipDrawPieI (GpGraphics *graphics, GpPen *pen, int x, int y, int width, int height, float startAngle, float sweepAngle);
+GpStatus GdipDrawPolygon (GpGraphics *graphics, GpPen *pen, GpPointF *points, int count);
+GpStatus GdipDrawPolygonI (GpGraphics *graphics, GpPen *pen, GpPoint *points, int count);
+GpStatus GdipDrawRectangle (GpGraphics *graphics, GpPen *pen, float x, float y, float width, float height);
+GpStatus GdipDrawRectangleI (GpGraphics *graphics, GpPen *pen, int x, int y, int width, int height);
+GpStatus GdipFillEllipse (GpGraphics *graphics, GpBrush *brush, float x, float y, float width, float height);
+GpStatus GdipFillEllipseI (GpGraphics *graphics, GpBrush *brush, int x, int y, int width, int height);
+GpStatus GdipFillRectangle (GpGraphics *graphics, GpBrush *brush, float x1, float y1, float x2, float y2);
+GpStatus GdipFillPolygon (GpGraphics *graphics, GpBrush *brush, GpPointF *points, int count, GpFillMode fillMode);
+GpStatus GdipFillPolygonI (GpGraphics *graphics, GpBrush *brush, GpPoint *points, int count, GpFillMode fillMode);
+GpStatus GdipFillPolygon2 (GpGraphics *graphics, GpBrush *brush, GpPointF *points, int count);
+GpStatus GdipFillPolygon2I (GpGraphics *graphics, GpBrush *brush, GpPoint *points, int count);
+GpStatus GdipSetRenderingOrigin (GpGraphics *graphics, int x, int y);
+GpStatus GdipGetRenderingOrigin (GpGraphics *graphics, int *x, int *y);
+
+/* Status */
+GpStatus gdip_get_status (cairo_status_t status);
+
+/* Brush */
+GpStatus GdipCloneBrush (GpBrush *brush, GpBrush **clonedBrush);
+GpStatus GdipDeleteBrush (GpBrush *brush);
+GpStatus GdipGetBrushType (GpBrush *brush, GpBrushType *brushType);
+
+/* Solidfill Brush */
+GpStatus GdipGetSolidFillColor (GpSolidFill *brush, int *color);
+
+/* Pen */
+GpStatus GdipCreatePen1 (int argb, float width, GpUnit unit, GpPen **pen);
+GpStatus GdipCreatePen2 (GpBrush *brush, float width, GpUnit unit, GpPen **pen);
+GpStatus GdipClonePen (GpPen *pen, GpPen **clonedpen);
+GpStatus GdipSetPenWidth (GpPen *pen, float width);
+GpStatus GdipGetPenWidth (GpPen *pen, float *width);
+GpStatus GdipSetPenBrushFill (GpPen *pen, GpBrush *brush);
+GpStatus GdipGetPenBrushFill (GpPen *pen, GpBrush **brush);
+GpStatus GdipSetPenColor (GpPen *pen, int color);
+GpStatus GdipGetPenColor (GpPen *pen, int *color);;
+GpStatus GdipSetPenDashStyle (GpPen *pen, GpDashStyle dashStyle);
+GpStatus GdipGetPenDashStyle (GpPen *pen, GpDashStyle *dashStyle);
+GpStatus GdipSetPenDashOffset (GpPen *pen, float offset);
+GpStatus GdipGetPenDashOffset (GpPen *pen, float *offset);
+GpStatus GdipSetPenDashCount (GpPen *pen, int count);
+GpStatus GdipGetPenDashCount (GpPen *pen, int *count);
+GpStatus GdipSetPenDashArray (GpPen *pen, float *dash, int count);
+GpStatus GdipGetPenDashArray (GpPen *pen, float **dash, int *count);
+GpStatus GdipSetPenDashCompoundArray (GpPen *pen, float *dash, int count);
+GpStatus GdipGetPenDashCompoundArray (GpPen *pen, float **dash, int *count);
+GpStatus GdipGetPenDashCompoundCount (GpPen *pen, int *count);
+GpStatus GdipSetPenMode (GpPen *pen, GpPenAlignment penMode);
+GpStatus GdipGetPenMode (GpPen *pen, GpPenAlignment *penMode);
+GpStatus GdipSetPenUnit (GpPen *pen, GpUnit unit);
+GpStatus GdipGetPenUnit (GpPen *pen, GpUnit *unit);
+GpStatus GdipDeletePen (GpPen *pen);
+GpStatus GdipSetPenMiterLimit (GpPen *pen, float miterLimit);
+GpStatus GdipGetPenMiterLimit (GpPen *pen, float *miterLimit);
+GpStatus GdipSetPenLineCap (GpPen *pen, GpLineCap lineCap);
+GpStatus GdipGetPenLineCap (GpPen *pen, GpLineCap *lineCap);
+GpStatus GdipSetPenLineJoin (GpPen *pen, GpLineJoin lineJoin);
+GpStatus GdipGetPenLineJoin (GpPen *pen, GpLineJoin *lineJoin);
+
+/* Text */
+GpStatus GdipDrawString (GpGraphics *graphics, const char *string, int len, void *font, RectF *rc, void *format, GpBrush *brush);
+
+/* Matrix */
+GpStatus GdipCreateMatrix (GpMatrix **matrix);
+GpStatus GdipCreateMatrix2 (float m11, float m12, float m21, float m22, float dx, float dy, GpMatrix **matrix);
+GpStatus GdipCreateMatrix3 (const GpRectF *rect, const GpPointF *dstplg, GpMatrix **matrix);
+GpStatus GdipCreateMatrix3I (const GpRect *rect, const GpPoint *dstplg, GpMatrix **matrix);
+GpStatus GdipCloneMatrix (GpMatrix *matrix, GpMatrix **cloneMatrix);
+GpStatus GdipDeleteMatrix (GpMatrix *matrix);
+GpStatus GdipSetMatrixElements (GpMatrix *matrix, float m11, float m12, float m21, float m22, float dx, float dy);
+GpStatus GdipMultiplyMatrix (GpMatrix *matrix, GpMatrix *matrix2, GpMatrixOrder order);
+GpStatus GdipTranslateMatrix (GpMatrix *matrix, float offsetX, float offsetY, GpMatrixOrder order);
+GpStatus GdipScaleMatrix (GpMatrix *matrix, float scaleX, float scaleY, GpMatrixOrder order);
+GpStatus GdipRotateMatrix(GpMatrix *matrix, float angle, GpMatrixOrder order);
+GpStatus GdipShearMatrix (GpMatrix *matrix, float shearX, float shearY, GpMatrixOrder order);
+GpStatus GdipInvertMatrix (GpMatrix *matrix);
+GpStatus GdipTransformMatrixPoints (GpMatrix *matrix, GpPointF *pts, int count);
+GpStatus GdipTransformMatrixPointsI (GpMatrix *matrix, GpPoint *pts, int count);
+GpStatus GdipVectorTransformMatrixPoints (GpMatrix *matrix, GpPointF *pts, int count);
+GpStatus GdipVectorTransformMatrixPointsI (GpMatrix *matrix, GpPoint *pts, int count);
+GpStatus GdipGetMatrixElements (GpMatrix *matrix, float *matrixOut);
+GpStatus GdipIsMatrixInvertible (GpMatrix *matrix, int *result);
+GpStatus GdipIsMatrixIdentity (GpMatrix *matrix, int *result);
+GpStatus GdipIsMatrixEqual (GpMatrix *matrix, GpMatrix *matrix2, int *result);
+
+/* Path*/
+#include "graphics-path.h"
+
+/* Memory */
+void *GdipAlloc (int size);
+void GdipFree (void *ptr);
+
+#endif /* _GDIP_H */
180 src/gdip_win32.c
@@ -0,0 +1,180 @@
+/*
+ * gdip_win32.c
+ *
+ * Copyright (c) 2003 Alexandre Pigolkine
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ */
+
+#include "gdip_win32.h"
+#include <dlfcn.h>
+
+static void * gdi32Handle = 0;
+static void * user32Handle = 0;
+
+static void _load_gdi32 (void)
+{
+ if (gdi32Handle == 0) {
+ gdi32Handle = dlopen ("libgdi32.dll.so", 1);
+ if (gdi32Handle == 0) {
+ gdi32Handle = dlopen ("/usr/local/lib/libgdi32.dll.so", 1);
+ }
+ if (gdi32Handle == 0) {
+ gdi32Handle = dlopen ("/usr/lib/libgdi32.dll.so", 1);
+ }
+ }
+}
+
+static void _load_user32 (void)
+{
+ if (user32Handle == 0) {
+ user32Handle = dlopen ("libuser32.dll.so", 1);
+ if (user32Handle == 0) {
+ user32Handle = dlopen ("/usr/local/lib/libuser32.dll.so", 1);
+ }
+ if (user32Handle == 0) {
+ user32Handle = dlopen ("/usr/lib/libuser32.dll.so", 1);
+ }
+ }
+}
+
+void *_get_gdi32Handle (void)
+{
+ _load_gdi32 ();
+ return gdi32Handle;
+}
+
+void *_get_user32Handle (void)
+{
+ _load_user32 ();
+ return user32Handle;
+}
+
+DC* DC_GetDCPtr_gdip (int hdc)
+{
+ return 0;
+}
+
+void GDI_ReleaseObj_gdip (int hdc)
+{
+}
+
+void* __stdcall CreateCompatibleDC_gdip (void * hdc)
+{
+ return 0;
+}
+
+void* __stdcall CreateCompatibleBitmap_gdip (void * hdc, int width, int height)
+{
+ return 0;
+}
+
+void* __stdcall GetDC_gdip (void * hwnd)
+{
+ return 0;
+}
+
+void* __stdcall SelectObject_gdip (void * hdc, void *object)
+{
+ return 0;
+}
+
+void __stdcall DeleteDC_gdip (void * hdc)
+{
+}
+
+int __stdcall DeleteObject_gdip (void * obj)
+{
+ return 0;
+}
+
+void __stdcall ReleaseDC_gdip (void *hwnd, void * hdc)
+{
+}
+
+int __stdcall GetDIBits_gdip (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse)
+{
+ return 0;
+}
+
+int __stdcall SetDIBits_gdip (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse)
+{
+ return 0;
+}
+
+void* (__stdcall *CreateCompatibleDC_pfn) (void * hdc);
+void* (__stdcall *CreateCompatibleBitmap_pfn) (void * hdc, int width, int height);
+void* (__stdcall *GetDC_pfn) (void * hwnd);
+
+void* (__stdcall *SelectObject_pfn) (void * hdc, void *object);
+
+void (__stdcall *DeleteDC_pfn) (void * hdc);
+int (__stdcall *DeleteObject_pfn) (void * obj);
+void (__stdcall *ReleaseDC_pfn) (void *hwnd, void * hdc);
+
+int (__stdcall *GetDIBits_pfn) (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse);
+int (__stdcall *SetDIBits_pfn) (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse);
+
+DC* (*DC_GetDCPtr_pfn) (int hdc);
+void (*GDI_ReleaseObj_pfn) (int hdc);
+
+#define CHECK_FUNCTION(name) if (name##_pfn == 0) name##_pfn = name##_gdip;
+void initializeGdipWin32 (void)
+{
+ void * gdi32Handle = _get_gdi32Handle ();
+ void * user32Handle = _get_user32Handle ();
+
+ if (gdi32Handle != 0 && user32Handle != 0) {
+ CreateCompatibleDC_pfn = dlsym (gdi32Handle,"CreateCompatibleDC");
+ CreateCompatibleBitmap_pfn = dlsym (gdi32Handle,"CreateCompatibleBitmap");
+ SelectObject_pfn = dlsym (gdi32Handle,"SelectObject");
+ DeleteDC_pfn = dlsym (gdi32Handle,"DeleteDC");
+ DeleteObject_pfn = dlsym (gdi32Handle,"DeleteObject");
+ SetDIBits_pfn = dlsym (gdi32Handle,"SetDIBits");
+ GetDIBits_pfn = dlsym (gdi32Handle,"GetDIBits");
+
+ GetDC_pfn = dlsym (user32Handle,"GetDC");
+ ReleaseDC_pfn = dlsym (user32Handle, "ReleaseDC");
+
+ DC_GetDCPtr_pfn = dlsym(gdi32Handle,"DC_GetDCPtr");
+ GDI_ReleaseObj_pfn = dlsym(gdi32Handle,"GDI_ReleaseObj");
+ }
+ CHECK_FUNCTION (CreateCompatibleDC);
+ CHECK_FUNCTION (CreateCompatibleBitmap);
+ CHECK_FUNCTION (SelectObject);
+ CHECK_FUNCTION (DeleteDC);
+ CHECK_FUNCTION (DeleteObject);
+ CHECK_FUNCTION (SetDIBits);
+ CHECK_FUNCTION (GetDIBits);
+ CHECK_FUNCTION (GetDC);
+ CHECK_FUNCTION (ReleaseDC);
+
+ CHECK_FUNCTION (DC_GetDCPtr);
+ CHECK_FUNCTION (GDI_ReleaseObj);
+}
+
+DC *_get_DC_by_HDC (int hDC)
+{
+ return DC_GetDCPtr_pfn (hDC);
+}
+
+void _release_hdc (int hdc)
+{
+ GDI_ReleaseObj_pfn (hdc);
+}
114 src/gdip_win32.h
@@ -0,0 +1,114 @@
+/*
+ * gdip_win32.h
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ */
+
+#ifndef _GDIP_WIN32_H
+#define _GDIP_WIN32_H
+
+#include <cairo.h>
+#ifndef CAIRO_HAS_XLIB_SURFACE
+#include <cairo-xlib.h>
+#endif
+#include <mono/io-layer/uglify.h>
+
+/* sizeof (GDIOBJHDR) = 12 (2 + 2 + 4 + 4) */
+/* offsetof (DC, physDev) = 20 (12 + 4 + 4) */
+typedef struct tagGDIOBJHDR {
+ short next;
+ short wMagic;
+ long dwCount;
+ void* funcs;
+} GDIOBJHDR;
+
+typedef struct tagX11DRV_PDEVICE
+{
+ void* hdc;
+ void *dc; /* direct pointer to DC, should go away */
+ GC gc; /* X Window GC */
+ Drawable drawable;
+} X11DRV_PDEVICE;
+
+typedef struct tagDC {
+ GDIOBJHDR header;
+ void* hSelf; /* Handle to this DC */
+ void *funcs; /* DC function table */
+ X11DRV_PDEVICE *physDev; /* Physical device (driver-specific) */
+} DC;
+
+typedef struct {
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+ BYTE rgbReserved;
+} RGBQUAD, *LPRGBQUAD;
+
+typedef struct
+{
+ DWORD biSize;
+ LONG biWidth;
+ LONG biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ DWORD biCompression;
+ DWORD biSizeImage;
+ LONG biXPelsPerMeter;
+ LONG biYPelsPerMeter;
+ DWORD biClrUsed;
+ DWORD biClrImportant;
+} BITMAPINFOHEADER, *PBITMAPINFOHEADER, *LPBITMAPINFOHEADER;
+
+ /* biCompression */
+#define BI_RGB 0
+#define BI_RLE8 1
+#define BI_RLE4 2
+#define BI_BITFIELDS 3
+
+typedef struct {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[1];
+} BITMAPINFO, *PBITMAPINFO, *LPBITMAPINFO;
+
+#ifdef __GNUC__
+# pragma pack(2)
+#endif
+typedef struct
+{
+ WORD bfType;
+ DWORD bfSize;
+ WORD bfReserved1;
+ WORD bfReserved2;
+ DWORD bfOffBits;
+} BITMAPFILEHEADER, *PBITMAPFILEHEADER, *LPBITMAPFILEHEADER;
+#ifdef __GNUC__
+# pragma pack()
+#endif
+
+#define BFT_BITMAP 0x4d42
+
+#ifdef __GNUC__
+# define __stdcall __attribute__((__stdcall__))
+#else
+# define __stdcall
+#endif
+
+extern void* (__stdcall *CreateCompatibleDC_pfn) (void * hdc);
+extern void* (__stdcall *CreateCompatibleBitmap_pfn) (void * hdc, int width, int height);
+extern void* (__stdcall *GetDC_pfn) (void * hwnd);
+
+extern void* (__stdcall *SelectObject_pfn) (void * hdc, void *object);
+
+extern void (__stdcall *DeleteDC_pfn) (void * hdc);
+extern int (__stdcall *DeleteObject_pfn) (void * obj);
+extern void (__stdcall *ReleaseDC_pfn) (void *hwnd, void * hdc);
+
+extern int (__stdcall *GetDIBits_pfn) (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse);
+extern int (__stdcall *SetDIBits_pfn) (void *hdc, void *hbitmap, unsigned startScan, unsigned scanLines, void *bitmapBits, PBITMAPINFO pbmi, unsigned int colorUse);
+
+
+DC *_get_DC_by_HDC (int hDC);
+void _release_hdc (int hdc);
+
+#endif /* _GDIP_WIN32_H */
149 src/general.c
@@ -0,0 +1,149 @@
+/*
+ * general.c
+ *
+ * Copyright (c) 2003 Alexandre Pigolkine
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ * Duncan Mak (duncan@ximian.com)
+ */
+
+#include "gdip.h"
+#include <dlfcn.h>
+#include <cairo.h>
+
+/* Startup / shutdown */
+
+struct startupInput
+{
+ unsigned int version;
+ void * ptr;
+ int threadOpt;
+ int codecOpt;
+};
+
+
+struct startupOutput
+{
+ void *hook;
+ void *unhook;
+};
+
+Display *GDIP_display = 0;
+int closeDisplay = 0;
+
+static void * x11drvHandle = 0;
+
+static void _load_x11drv ()
+{
+ if (x11drvHandle == 0) {
+ x11drvHandle = dlopen ("libx11drv.dll.so", 1);
+ if (x11drvHandle == 0) {
+ x11drvHandle = dlopen ("/usr/local/lib/libx11drv.dll.so", 1);
+ }
+ if (x11drvHandle == 0) {
+ x11drvHandle = dlopen ("/usr/lib/libx11drv.dll.so", 1);
+ }
+ }
+}
+
+static void _unload_x11drv ()
+{
+ if (x11drvHandle != 0) {
+ dlclose (x11drvHandle);
+ }
+}
+
+Display *_get_wine_display ()
+{
+ Display * result = 0;
+ _load_x11drv ();
+ if (x11drvHandle != 0) {
+ Display **addr = dlsym(x11drvHandle,"gdi_display");
+ if (addr) {
+ result = *addr;
+ }
+ }
+ return result;
+}
+
+GpStatus
+GdiplusStartup(unsigned long *token, const struct startupInput *input, struct startupOutput *output)
+{
+ GDIP_display = _get_wine_display ();
+ if (GDIP_display == 0){
+ GDIP_display = XOpenDisplay(0);
+ closeDisplay = 1;
+ }
+
+ /* printf ("GdiplusStartup. GDIP_Display %p\n", GDIP_display); */
+ initializeGdipWin32 ();
+ *token = 1;
+ return Ok;
+}
+
+void
+GdiplusShutdown(unsigned long *token)
+{
+ if (closeDisplay) {
+ XCloseDisplay(GDIP_display);
+ }
+ _unload_x11drv ();
+}
+
+
+/* Memory */
+void *
+GdipAlloc (int size)
+{
+ return malloc (size);
+}
+
+void
+GdipFree (void *ptr)
+{
+ free (ptr);
+}
+
+/* Helpers */
+GpStatus
+gdip_get_status (cairo_status_t status)
+{
+ if (status == CAIRO_STATUS_SUCCESS)
+ return Ok;
+
+ else {
+ switch (status) {
+
+ case CAIRO_STATUS_NO_MEMORY:
+ return OutOfMemory;
+
+ case CAIRO_STATUS_INVALID_MATRIX:
+ case CAIRO_STATUS_INVALID_RESTORE:
+ case CAIRO_STATUS_INVALID_POP_GROUP:
+ return InvalidParameter;
+
+ case CAIRO_STATUS_NO_CURRENT_POINT:
+ case CAIRO_STATUS_NO_TARGET_SURFACE:
+ return WrongState;
+
+ default:
+ return GenericError;
+ }
+ }
+}
761 src/graphics-path.c
@@ -0,0 +1,761 @@
+/*
+ * graphics-path.c
+ *
+ * Author: Duncan Mak (duncan@ximian.com)
+ *
+ * Copyright (C) 2003, Novell Inc.
+ *
+ */
+
+#include <math.h>
+#include "gdip.h"
+#include "graphics-path.h"
+
+static GArray *
+array_to_g_array (const GpPointF *pt, int length)
+{
+ GArray *p = g_array_sized_new (FALSE, TRUE, sizeof (GpPointF), length);
+ g_array_append_vals (p, pt, length);
+ return p;
+}
+
+static GpPointF *
+g_array_to_array (GArray *p)
+{
+ int length = p->len;
+ GpPointF *pts = (GpPointF *) GdipAlloc (sizeof (GpPointF) * length);
+
+ memcpy (pts, p->data, p->len * sizeof (GpPointF));
+
+ return pts;
+}
+
+static byte *
+g_byte_array_to_array (GByteArray *p)
+{
+ int length = p->len;
+ byte *types = (byte *) GdipAlloc (sizeof (byte) * length);
+
+ memcpy (types, p->data, p->len * sizeof (byte));
+
+ return types;
+}
+
+static GByteArray *
+array_to_g_byte_array (const byte *types, int count)
+{
+ GByteArray *p = g_byte_array_sized_new (count);
+ g_byte_array_append (p, types, count);
+ return p;
+}
+
+static GpPointF *
+int_to_float (const GpPoint *pts, int count)
+{
+ GpPointF *p = (GpPointF *) GdipAlloc (sizeof (GpPointF) * count);
+ GpPoint *tmp = (GpPoint *) pts;
+ int i;
+
+ for (i = 0; i < count; i++, p++, tmp++) {
+ p->X = (float) tmp->X;
+ p->Y = (float) tmp->Y;
+ }
+
+ return p;
+}
+
+static void
+append (GpPath *path, float x, float y, GpPathPointType type)
+{
+ byte t = (byte) type;
+ GpPointF pt;
+ pt.X = x;
+ pt.Y = y;
+
+ g_array_append_val (path->points, pt);
+ g_byte_array_append (path->types, &t, 1);
+ path->count++;
+}
+
+static void
+append_point (GpPath *path, GpPointF pt, GpPathPointType type)
+{
+ append (path, pt.X, pt.Y, type);
+}
+
+static void
+append_bezier (GpPath *path, float x1, float y1, float x2, float y2, float x3, float y3)
+{
+ append (path, x1, y1, PathPointTypeBezier3);
+ append (path, x2, y2, PathPointTypeBezier3);
+ append (path, x3, y3, PathPointTypeBezier3);
+}
+
+GpStatus
+GdipCreatePath (GpFillMode brushMode, GpPath **path)
+{
+ *path = (GpPath *) GdipAlloc (sizeof (GpPath));
+
+ (*path)->fill_mode = brushMode;
+ (*path)->points = g_array_new (FALSE, FALSE, sizeof (GpPointF));
+ (*path)->types = g_byte_array_new ();
+ (*path)->count = 0;
+
+ return Ok;
+}
+
+GpStatus
+GdipCreatePath2 (const GpPointF *points, const byte *types,
+ int count, GpFillMode fillMode, GpPath **path)
+{
+ GArray *pts = array_to_g_array (points, count);
+ GByteArray *t = array_to_g_byte_array (types, count);
+
+ *path = (GpPath *) GdipAlloc (sizeof (GpPath));
+ (*path)->fill_mode = fillMode;
+ (*path)->count = count;
+ (*path)->points = pts;
+ (*path)->types = t;
+
+ return Ok;
+}
+
+GpStatus
+GdipClonePath (GpPath *path, GpPath **clonePath)
+{
+ *clonePath = (GpPath *) GdipAlloc (sizeof (GpPath));
+ (*clonePath)->fill_mode = path->fill_mode;
+ (*clonePath)->count = path->count;
+ (*clonePath)->points = path->points;
+ (*clonePath)->types = path->types;
+
+ return Ok;
+}
+
+GpStatus
+GdipDeletePath (GpPath *path)
+{
+ if (path->count != 0) {
+ if (path->points != NULL)
+ g_array_free (path->points, TRUE);
+
+ if (path->types != NULL)
+ g_byte_array_free (path->types, TRUE);
+ }
+
+ GdipFree (path);
+ return Ok;
+}
+
+GpStatus
+GdipResetPath (GpPath *path)
+{
+ path->points = NULL;
+ path->types = NULL;
+ path->count = 0;
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPointCount (GpPath *path, int *count)
+{
+ *count = path->count;
+ return Ok;
+}
+
+GpStatus
+GdipGetPathTypes (GpPath *path, byte *types, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ types [i] = path->types->data [i];
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPathPoints (GpPath *path, GpPointF *points, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ GpPointF point = g_array_index (path->points, GpPointF, i);
+ points [i].X = point.X;
+ points [i].Y = point.Y;
+ }
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPathPointsI (GpPath *path, GpPoint *points, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ GpPoint point = g_array_index (path->points, GpPoint, i);
+ points [i].X = (int) point.X;
+ points [i].Y = (int) point.Y;
+ }
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPathFillMode (GpPath *path, GpFillMode *fillmode)
+{
+ *fillmode = path->fill_mode;
+
+ return Ok;
+}
+
+GpStatus
+GdipSetPathFillMode (GpPath *path, GpFillMode fillmode)
+{
+ path->fill_mode = fillmode;
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPathData (GpPath *path, GpPathData *pathData)
+{
+ pathData->Count = path->count;
+ pathData->Points = g_array_to_array (path->points);
+ pathData->Types = g_byte_array_to_array (path->types);
+
+ return Ok;
+}
+
+GpStatus
+GdipStartPathFigure (GpPath *path)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipClosePathFigure (GpPath *path)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipClosePathFigures (GpPath *path)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipSetPathMarker (GpPath *path)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipClearPathMarkers (GpPath *path)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipReversePath (GpPath *path)
+{
+ int length= path->count;
+ GByteArray *types = g_byte_array_sized_new (length);
+ GArray *points = g_array_sized_new (FALSE, TRUE, sizeof (GpPointF), length);
+ int i;
+ for (i = length; i > 0; i--) {
+ byte t = g_array_index (path->types, byte, i);
+ GpPointF pt = g_array_index (path->points, GpPointF, i);
+
+ g_byte_array_append (types, &t, 1);
+ g_array_append_val (points, pt);
+ }
+ path->points = points;
+ path->types = types;
+
+ return Ok;
+}
+
+GpStatus
+GdipGetPathLastPoint (GpPath *path, GpPointF *lastPoint)
+{
+ *lastPoint = g_array_index (path->points, GpPointF, path->count);
+ return Ok;
+}
+
+GpStatus
+GdipAddPathLine (GpPath *path, float x1, float y1, float x2, float y2)
+{
+ append (path, x1, y1, PathPointTypeStart);
+ append (path, x2, y2, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathLine2 (GpPath *path, const GpPointF *points, int count)
+{
+ int i;
+ GpPointF *tmp = (GpPointF *) points;
+
+ for (i = 0; i < count; i++, tmp++)
+ append_point (path, *tmp, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathArc (GpPath *path, float x, float y,
+ float width, float height, float startAngle, float sweepAngle)
+{
+ float rx = width / 2;
+ float ry = height / 2;
+
+ /* center */
+ int cx = x + rx;
+ int cy = y + ry;
+
+ /* angles in radians */
+ float alpha = startAngle * PI / 180;
+ float beta = sweepAngle * PI / 180;
+
+ float delta = beta - alpha;
+ float bcp = 4.0 / 3 * (1 - cos (delta / 2)) / sin (delta /2);
+
+ float sin_alpha = sin (alpha);
+ float sin_beta = sin (beta);
+ float cos_alpha = cos (alpha);
+ float cos_beta = cos (beta);
+
+ append (path,
+ cx + rx * cos_alpha,
+ cy + ry * sin_alpha,
+ PathPointTypeStart);
+
+ append_bezier (path,
+ cx + rx * (cos_alpha - bcp * sin_alpha),
+ cy + ry * (sin_alpha + bcp * cos_alpha),
+ cx + rx * (cos_beta + bcp * sin_beta),
+ cy + ry * (sin_beta - bcp * cos_beta),
+ cx + rx * cos_beta,
+ cy + ry * sin_beta);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathBezier (GpPath *path,
+ float x1, float y1, float x2, float y2,
+ float x3, float y3, float x4, float y4)
+{
+ append (path, x1, y1, PathPointTypeStart);
+ append_bezier (path, x2, y2, x3, y3, x4, y4);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathBeziers (GpPath *path, const GpPointF *points, int count)
+{
+ int i;
+ GpPointF *tmp = (GpPointF *) points;
+
+ append_point (path, *tmp, PathPointTypeStart);
+ tmp++;
+
+ for (i = 1; i < count; i++, tmp++)
+ append_point (path, *tmp, PathPointTypeBezier3);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathCurve (GpPath *path, const GpPointF *points, int count)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathCurve2 (GpPath *path, const GpPointF *points, int count, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathCurve3 (GpPath *path, const GpPointF *points, int count,
+ int offset, int numberOfSegments, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathClosedCurve (GpPath *path, const GpPointF *points, int count)
+{
+ return GdipAddPathClosedCurve2 (path, points, count, 0.5);
+}
+
+GpStatus
+GdipAddPathClosedCurve2 (GpPath *path, const GpPointF *points, int count, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathRectangle (GpPath *path, float x, float y, float width, float height)
+{
+ append (path, x, y, PathPointTypeLine);
+ append (path, x + width, y, PathPointTypeLine);
+ append (path, x + width, y + height, PathPointTypeLine);
+ append (path, x, y + height, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathRectangles (GpPath *path, const GpRectF *rects, int count)
+{
+ int i;
+ for (i = 0; i < count; i++, rects++) {
+ float x = rects->left;
+ float y = rects->top;
+ float width = rects->right - rects->left;
+ float height = rects->bottom - rects->top;
+ GdipAddPathRectangle (path, x, y, width, height);
+ }
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathEllipse (GpPath *path, float x, float y, float width, float height)
+{
+ float C1 = 0.552285;
+ double rx = width / 2;
+ double ry = height / 2;
+ double cx = x + rx;
+ double cy = y + ry;
+
+ /* origin */
+ append (path, cx + rx, cy, PathPointTypeStart);
+
+ /* quadrant I */
+ append_bezier (path,
+ cx + rx, cy - C1 * ry,
+ cx + C1 * rx, cy - ry,
+ cx, cy - ry);
+
+ /* quadrant II */
+ append_bezier (path,
+ cx - C1 * rx, cy - ry,
+ cx - rx, cy - C1 * ry,
+ cx - rx, cy);
+
+ /* quadrant III */
+ append_bezier (path,
+ cx - rx, cy + C1 * ry,
+ cx - C1 * rx, cy + ry,
+ cx, cy + ry);
+
+ /* quadrant IV */
+ append_bezier (path,
+ cx + C1 * rx, cy + ry,
+ cx + rx, cy + C1 * ry,
+ cx + rx, cy);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathPie (GpPath *path, float x, float y, float width, float height, float startAngle, float sweepAngle)
+{
+ float rx = width / 2;
+ float ry = height / 2;
+ int cx = x + rx;
+ int cy = y + ry;
+
+ /* angles in radians */
+ float alpha = startAngle * PI / 180;
+ float beta = sweepAngle * PI / 180;
+
+ float delta = beta - alpha;
+ float bcp = 4.0 / 3 * (1 - cos (delta / 2)) / sin (delta /2);
+
+ float sin_alpha = sin (alpha);
+ float sin_beta = sin (beta);
+ float cos_alpha = cos (alpha);
+ float cos_beta = cos (beta);
+
+ /* move to center */
+ append (path, cx, cy, PathPointTypeStart);
+
+
+ /* draw pie edge */
+ append (path, cx + rx * cos_alpha, cy + ry * sin_alpha,
+ PathPointTypeLine);
+
+ /* draw arc */
+ append_bezier (path,
+ cx + rx * (cos_alpha - bcp * sin_alpha),
+ cy + ry * (sin_alpha + bcp * cos_alpha),
+ cx + rx * (cos_beta + bcp * sin_beta),
+ cy + ry * (sin_beta - bcp * cos_beta),
+ cx + rx * cos_beta,
+ cy + ry * sin_beta);
+
+ /* draw pie edge */
+ append (path, cx, cy, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathPolygon (GpPath *path, const GpPointF *points, int count)
+{
+ int i;
+ GpPointF *tmp = (GpPointF *) points;
+
+ append_point (path, *tmp, PathPointTypeStart);
+ tmp ++;
+
+ for (i = 1; i < count; i++, tmp++)
+ append_point (path, *tmp, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathPath (GpPath *path, GpPath *addingPath, bool connect)
+{
+ /* XXX:need to understand the connect argument */
+
+ return NotImplemented;
+}
+
+/* XXX: This one is really hard. They really translate a string into
+bezier points and what not */
+/*
+ * GpStatus
+ * GdipAddString (GpPath *path, const char *string, int length,
+ * const GpFontFamily *family, int style, float emSize,
+const GpRectF *layoutRect,
+ * const GpStringFormat *format)
+ * {
+ * return NotImplemented;
+ * }
+ */
+
+/*
+ * GpStatus
+ * GdipAddString (GpPath *path, const char *string, int length,
+ * const GpFontFamily *family, int style, float emSize,
+const GpRect *layoutRect,
+ * const GpStringFormat *format)
+ * {
+ * return NotImplemented;
+ * }
+ */
+
+GpStatus
+GdipAddPathLineI (GpPath *path, int x1, int y1, int x2, int y2)
+{
+ append (path, x1, y1, PathPointTypeStart);
+ append (path, x2, y2, PathPointTypeLine);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathLine2I (GpPath* path, const GpPoint *points, int count)
+{
+ int i;
+ GpPointF *tmp = int_to_float (points, count);
+
+ append_point (path, *tmp, PathPointTypeStart);
+ tmp++;
+
+ for (i = 1; i < count; i++, tmp++)
+ append_point (path, *tmp, PathPointTypeLine);
+
+ GdipFree (tmp);
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathArcI (GpPath *path, int x, int y, int width, int height, float startAngle, float sweepAngle)
+{
+ return GdipAddPathArc (path, x, y, width, height, startAngle, sweepAngle);
+}
+
+GpStatus
+GdipAddPathBezierI (GpPath *path, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
+{
+ return GdipAddPathBezier (path, x1, y1, x2, y2, x3, y3, x4, y4);
+}
+
+GpStatus
+GdipAddPathBeziersI (GpPath *path, const GpPoint *points, int count)
+{
+ GpPointF *tmp = int_to_float (points, count);
+ Status s = GdipAddPathBeziers (path, tmp, count);
+
+ GdipFree (tmp);
+
+ return s;
+}
+
+GpStatus
+GdipAddPathCurveI (GpPath *path, const GpPoint *points, int count)
+{
+ return GdipAddPathCurve2I (path, points, count, 0.5);
+}
+
+GpStatus
+GdipAddPathCurve2I (GpPath *path, const GpPoint *points, int count, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathCurve3I (GpPath *path, const GpPoint *points,
+ int count, int offset, int numberOfSegments, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathClosedCurveI (GpPath *path, const GpPoint *points, int count)
+{
+ return GdipAddPathClosedCurve2I (path, points, count, 0.5);
+}
+
+GpStatus
+GdipAddPathClosedCurve2I (GpPath *path, const GpPoint *points, int count, float tension)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipAddPathRectangleI (GpPath *path, int x, int y, int width, int height)
+{
+ return GdipAddPathRectangle (path, x, y, width, height);
+}
+
+GpStatus
+GdipAddPathRectanglesI (GpPath *path, const GpRect *rects, int count)
+{
+ int i;
+ for (i = 0; i < count; i++, rects++) {
+ float x = (float) rects->left;
+ float y = (float) rects->top;
+ float width = (float) (rects->right - rects->left);
+ float height = (float) (rects->bottom - rects->top);
+ GdipAddPathRectangle (path, x, y, width, height);
+ }
+
+ return Ok;
+}
+
+GpStatus
+GdipAddPathEllipseI (GpPath *path, int x, int y, int width, int height)
+{
+ return GdipAddPathEllipse (path, x, y, width, height);
+}
+
+GpStatus
+GdipAddPathPieI (GpPath *path, int x, int y, int width, int height, float startAngle, float sweepAngle)
+{
+ return GdipAddPathPie (path, x, y, width, height, startAngle, sweepAngle);
+}
+
+GpStatus
+GdipAddPathPolygonI (GpPath *path, const GpPoint *points, int count)
+{
+ GpPointF *tmp = int_to_float (points, count);
+
+ Status s = GdipAddPathPolygon (path, tmp, count);
+
+ GdipFree (tmp);
+
+ return s;
+}
+
+GpStatus
+GdipFlattenPath (GpPath *path, GpMatrix *matrix, float flatness)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipWindingModeOutline (GpPath *path, GpMatrix *matrix, float flatness)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipWidenPath (GpPath *nativePath, GpPen *pen, GpMatrix *matrix, float flatness)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipWarpPath (GpPath *nativePath, GpMatrix *matrix, const GpPointF *points, int count,
+ float src, float srcy, float srcwidth, float srcheight,
+ WarpMode warpMode, float flatness)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipTransformPath (GpPath* path, GpMatrix *matrix)
+{
+ PointF *points = g_array_to_array (path->points);
+ int count = path->count;
+
+ Status s = GdipTransformMatrixPoints (matrix, points, count);
+
+ path->points = array_to_g_array (points, count);
+
+ GdipFree (points);
+
+ return s;
+}
+
+GpStatus
+GdipGetPathWorldBounds (GpPath *path, GpRectF *bounds, const GpMatrix *matrix, const GpPen *pen)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipGetPathWorldBoundsI (GpPath *path, GpRect *bounds, const GpMatrix *matrix, const GpPen *pen)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipIsVisiblePathPoint (GpPath *path, float x, float y, GpGraphics *graphics, bool *result)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipIsVisiblePathPointI (GpPath *path, int x, int y, GpGraphics *graphics, bool *result)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipIsOutlineVisiblePathPoint (GpPath *path, float x, float y, GpGraphics *graphics, bool *result)
+{
+ return NotImplemented;
+}
+
+GpStatus
+GdipIsOutlineVisiblePathPointI (GpPath *path, int x, int y, GpGraphics *graphics, bool *result)
+{
+ return NotImplemented;
+}
82 src/graphics-path.h
@@ -0,0 +1,82 @@
+/*
+ * graphics-path.h
+ *
+ * Author:
+ * Duncan Mak (duncan@ximian.com)
+ *
+ * Copyright (C) Novell, Inc. 2003.
+ */
+
+
+#ifndef _GRAPHICS_PATH_H_
+#define _GRAPHICS_PATH_H_
+
+#include "gdip.h"
+
+GpStatus GdipCreatePath (GpFillMode brushMode, GpPath **path);
+GpStatus GdipCreatePath2 (const GpPointF *points, const byte *types, int count, GpFillMode fillMode, GpPath **path);
+GpStatus GdipClonePath (GpPath *path, GpPath **clonePath);
+GpStatus GdipDeletePath (GpPath *path);
+GpStatus GdipResetPath (GpPath *path);
+GpStatus GdipGetPointCount (GpPath *path, int *count);
+GpStatus GdipGetPathTypes (GpPath *path, byte *types, int count);
+GpStatus GdipGetPathPoints (GpPath *path, GpPointF *points, int count);
+GpStatus GdipGetPathPointsI (GpPath *path, GpPoint *points, int count);
+GpStatus GdipGetPathFillMode (GpPath *path, GpFillMode *fillmode);
+GpStatus GdipSetPathFillMode (GpPath *path, GpFillMode fillmode);
+GpStatus GdipGetPathData (GpPath *path, GpPathData *pathData);
+GpStatus GdipStartPathFigure (GpPath *path);
+GpStatus GdipClosePathFigure (GpPath *path);
+GpStatus GdipClosePathFigures (GpPath *path);
+GpStatus GdipSetPathMarker (GpPath *path);
+GpStatus GdipClearPathMarker (GpPath *path);
+GpStatus GdipReversePath (GpPath *path);
+GpStatus GdipGetPathLastPoint (GpPath *path, GpPointF *lastPoint);
+GpStatus GdipAddPathLine (GpPath *path, float x1, float y1, float x2, float y2);
+GpStatus GdipAddPathLine2 (GpPath *path, const GpPointF *points, int count);
+GpStatus GdipAddPathArc (GpPath *path, float x, float y, float width, float height, float startAngle, float sweepAngle);
+GpStatus GdipAddPathBezier (GpPath *path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+GpStatus GdipAddPathBeziers (GpPath *path, const GpPointF *points, int count);
+GpStatus GdipAddPathCurve (GpPath *path, const GpPointF *points, int count);
+GpStatus GdipAddPathCurve2 (GpPath *path, const GpPointF *points, int count, float tension);
+GpStatus GdipAddPathCurve3 (GpPath *path, const GpPointF *points, int count, int offset, int numberOfSegments, float tension);
+GpStatus GdipAddPathClosedCurve (GpPath *path, const GpPointF *points, int count);
+GpStatus GdipAddPathClosedCurve2 (GpPath *path, const GpPointF *points, int count, float tension);
+GpStatus GdipAddPathRectangle (GpPath *path, float x, float y, float width, float height);
+GpStatus GdipAddPathRectangles (GpPath *path, const GpRectF *rects, int count);
+GpStatus GdipAddPathEllipse (GpPath *path, float x, float y, float width, float height);
+GpStatus GdipAddPathPie (GpPath *path, float x, float y, float width, float height, float startAngle, float sweepAngle);
+GpStatus GdipAddPathPolygon (GpPath *path, const GpPointF *points, int count);
+GpStatus GdipAddPathPath (GpPath *path, GpPath *addingPath, bool connect);
+
+GpStatus GdipAddPathLineI (GpPath *path, int x1, int y1, int x2, int y2);
+GpStatus GdipAddPathLine2I (GpPath *path, const GpPoint *points, int count);
+GpStatus GdipAddPathArcI (GpPath *path, int x, int y, int width, int height, float startAngle, float sweepAngle);
+GpStatus GdipAddPathBezierI (GpPath *path, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
+GpStatus GdipAddPathBeziersI (GpPath *path, const GpPoint *points, int count);
+GpStatus GdipAddPathCurveI (GpPath *path, const GpPoint *points, int count);
+GpStatus GdipAddPathCurve2I (GpPath *path, const GpPoint *points, int count, float tension);
+GpStatus GdipAddPathCurve3I (GpPath *path, const GpPoint *points, int count, int offset, int numberOfSegments, float tension);
+GpStatus GdipAddPathClosedCurveI (GpPath *path, const GpPoint *points, int count);
+GpStatus GdipAddPathClosedCurve2I (GpPath *path, const GpPoint *points, int count, float tension);
+GpStatus GdipAddPathRectangleI (GpPath *path, int x, int y, int width, int height);
+GpStatus GdipAddPathRectanglesI (GpPath *path, const GpRect *rects, int count);
+GpStatus GdipAddPathEllipseI (GpPath *path, int x, int y, int width, int height);
+GpStatus GdipAddPathPieI (GpPath *path, int x, int y, int width, int height, float startAngle, float sweepAngle);
+GpStatus GdipAddPathPolygonI (GpPath *path, const GpPoint *points, int count);
+GpStatus GdipFlattenPath (GpPath *path, GpMatrix *matrix, float flatness);
+GpStatus GdipWindingModeOutline (GpPath *path, GpMatrix *matrix, float flatness);
+GpStatus GdipWidenPath (GpPath *nativePath, GpPen *pen, GpMatrix *matrix, float flatness);
+GpStatus GdipWarpPath (GpPath *nativePath, GpMatrix *matrix, const GpPointF *points, int count,
+ float src, float srcy, float srcwidth, float srcheight, WarpMode warpMode, float flatness);
+GpStatus GdipTransformPath (GpPath* path, GpMatrix *matrix);
+GpStatus GdipGetPathWorldBounds (GpPath *path, GpRectF *bounds, const GpMatrix *matrix, const GpPen *pen);
+GpStatus GdipGetPathWorldBoundsI (GpPath *path, GpRect *bounds, const GpMatrix *matrix, const GpPen *pen);
+GpStatus GdipIsVisiblePathPoint (GpPath *path, float x, float y, GpGraphics *graphics, bool *result);
+GpStatus GdipIsVisiblePathPointI (GpPath *path, int x, int y, GpGraphics *graphics, bool *result);
+GpStatus GdipIsOutlineVisiblePathPoint (GpPath *path, float x, float y, GpGraphics *graphics, bool *result);
+GpStatus GdipIsOutlineVisiblePathPointI (GpPath *path, int x, int y, GpGraphics *graphics, bool *result);
+
+
+
+#endif /* _GRAPHICS_PATH_H_ */
845 src/graphics.c
@@ -0,0 +1,845 @@
+/*
+ * graphics.c
+ *
+ * Copyright (c) 2003 Alexandre Pigolkine, Novell Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Alexandre Pigolkine(pigolkine@gmx.de)
+ * Duncan Mak (duncan@ximian.com)
+ *
+ */
+
+#include "gdip.h"
+#include "gdip_win32.h"
+#include <math.h>
+#include <glib.h>
+
+void
+gdip_graphics_init (GpGraphics *graphics)
+{
+ graphics->ct = cairo_create ();
+ graphics->copy_of_ctm = cairo_matrix_create ();
+ cairo_matrix_set_identity (graphics->copy_of_ctm);
+ graphics->hdc = 0;
+ graphics->hdc_busy_count = 0;
+ graphics->image = 0;
+ graphics->type = gtUndefined;
+ /* cairo_select_font (graphics->ct, "serif:12"); */
+ cairo_select_font (graphics->ct, "serif:12", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+}
+
+GpGraphics *
+gdip_graphics_new ()
+{
+ GpGraphics *result = (GpGraphics *) GdipAlloc (sizeof (GpGraphics));
+ gdip_graphics_init (result);
+ return result;
+}
+
+void
+gdip_graphics_attach_bitmap (GpGraphics *graphics, GpBitmap *image)
+{
+ cairo_set_target_image (graphics->ct, image->data.Scan0, image->cairo_format,
+ image->data.Width, image->data.Height, image->data.Stride);
+ graphics->image = image;
+ graphics->type = gtMemoryBitmap;
+}
+
+void
+gdip_graphics_detach_bitmap (GpGraphics *graphics, GpBitmap *image)
+{
+ printf ("Implement graphics_detach_bitmap");
+ /* FIXME: implement me */
+}
+
+#define C1 0.552285
+static void
+make_ellipse (GpGraphics *graphics, float x, float y, float width, float height)
+{
+ double rx = width / 2;
+ double ry = height / 2;
+ double cx = x + rx;
+ double cy = y + ry;
+
+ cairo_move_to (graphics->ct, cx + rx, cy);
+
+ /* an approximate of the ellipse by drawing a curve in each
+ * quartrant */
+ cairo_curve_to (graphics->ct,
+ cx + rx, cy - C1 * ry,
+ cx + C1 * rx, cy - ry,
+ cx, cy - ry);
+
+ cairo_curve_to (graphics->ct,
+ cx - C1 * rx, cy - ry,
+ cx - rx, cy - C1 * ry,
+ cx - rx, cy);
+
+ cairo_curve_to (graphics->ct,
+ cx - rx, cy + C1 * ry,
+ cx - C1 * rx, cy + ry,
+ cx, cy + ry);
+
+ cairo_curve_to (graphics->ct,
+ cx + C1 * rx, cy + ry,
+ cx + rx, cy + C1 * ry,
+ cx + rx, cy);
+
+ cairo_close_path (graphics->ct);
+}
+
+static void
+make_polygon (GpGraphics *graphics, GpPointF *points, int count)
+{
+ int i;
+ cairo_move_to (graphics->ct, points [0].X, points [0].Y);
+
+ for (i = 0; i < count; i++)
+ cairo_line_to (graphics->ct, points [i].X, points [i].Y);
+
+ /*
+ * Draw a line from the last point back to the first point if
+ * they're not the same
+ */
+ if (points [0].X != points [count].X && points [0].Y != points [count].Y)
+ cairo_line_to (graphics->ct, points [0].X, points [0].Y);
+
+ cairo_close_path (graphics->ct);
+}
+
+static void
+make_polygon_from_integers (GpGraphics *graphics, GpPoint *points, int count)
+{
+ int i;
+ cairo_move_to (graphics->ct, points [0].X, points [0].Y);
+
+ for (i = 0; i < count; i++)
+ cairo_line_to (graphics->ct, points [i].X, points [i].Y);
+
+ /*
+ * Draw a line from the last point back to the first point if
+ * they're not the same
+ */
+ if (points [0].X != points [count].X && points [0].Y != points [count].Y)
+ cairo_line_to (graphics->ct, points [0].X, points [0].Y);
+
+ cairo_close_path (graphics->ct);
+}
+
+/*
+ * Based on the algorithm described in
+ * http://www.stillhq.com/ctpfaq/2002/03/c1088.html#AEN1212
+ */
+static void
+make_pie (GpGraphics *graphics, float x, float y,
+ float width, float height, float startAngle, float sweepAngle)
+{
+ float rx = width / 2;
+ float ry = height / 2;
+ int cx = x + rx;
+ int cy = y + ry;
+
+ /* angles in radians */
+ float alpha = startAngle * PI / 180;
+ float beta = sweepAngle * PI / 180;
+
+ float delta = beta - alpha;
+ float bcp = 4.0 / 3 * (1 - cos (delta / 2)) / sin (delta /2);
+
+ float sin_alpha = sin (alpha);
+ float sin_beta = sin (beta);
+ float cos_alpha = cos (alpha);
+ float cos_beta = cos (beta);
+
+ /* move to center */
+ cairo_move_to (graphics->ct, cx, cy);
+
+ /* draw pie edge */
+ cairo_line_to (graphics->ct,
+ cx + rx * cos_alpha,
+ cy + ry * sin_alpha);
+
+ cairo_curve_to (graphics->ct,
+ cx + rx * (cos_alpha - bcp * sin_alpha),
+ cy + ry * (sin_alpha + bcp * cos_alpha),
+ cx + rx * (cos_beta + bcp * sin_beta),
+ cy + ry * (sin_beta - bcp * cos_beta),
+ cx + rx * cos_beta,
+ cy + ry * sin_beta);
+
+ /* draws line back to center */
+ cairo_close_path (graphics->ct);
+}
+
+static void
+make_arc (GpGraphics *graphics, float x, float y, float width,
+ float height, float startAngle, float sweepAngle)
+{
+ float rx = width / 2;
+ float ry = height / 2;
+
+ /* center */
+ int cx = x + rx;
+ int cy = y + ry;
+
+ /* angles in radians */
+ float alpha = startAngle * PI / 180;
+ float beta = sweepAngle * PI / 180;
+
+ float delta = beta - alpha;
+ float bcp = 4.0 / 3 * (1 - cos (delta / 2)) / sin (delta /2);
+
+ float sin_alpha = sin (alpha);
+ float sin_beta = sin (beta);
+ float cos_alpha = cos (alpha);
+ float cos_beta = cos (beta);
+
+ /* move to pie edge */
+ cairo_move_to (graphics->ct,
+ cx + rx * cos_alpha,
+ cy + ry * sin_alpha);
+
+ cairo_curve_to (graphics->ct,
+ cx + rx * (cos_alpha - bcp * sin_alpha),
+ cy + ry * (sin_alpha + bcp * cos_alpha),
+ cx + rx * (cos_beta + bcp * sin_beta),
+ cy + ry * (sin_beta - bcp * cos_beta),
+ cx + rx * cos_beta,
+ cy + ry * sin_beta);
+}
+
+static cairo_fill_rule_t
+convert_fill_mode (GpFillMode fill_mode)
+{
+ if (fill_mode == FillModeAlternate)
+ return CAIRO_FILL_RULE_EVEN_ODD;
+ else
+ return CAIRO_FILL_RULE_WINDING;
+}
+
+
+GpStatus
+GdipCreateFromHDC (int hDC, GpGraphics **graphics)
+{
+ DC* dc = _get_DC_by_HDC (hDC);
+
+ /* printf ("GdipCreateFromHDC. in %d, DC %p\n", hDC, dc); */
+ if (dc == 0) return NotImplemented;
+
+ *graphics = gdip_graphics_new ();
+ cairo_set_target_drawable ((*graphics)->ct, GDIP_display, dc->physDev->drawable);
+ _release_hdc (hDC);
+ (*graphics)->hdc = (void*)hDC;
+ (*graphics)->type = gtX11Drawable;
+ /* printf ("GdipCreateFromHDC. graphics %p, ct %p\n", (*graphics), (*graphics)->ct); */
+ return Ok;
+}
+
+GpStatus
+GdipDeleteGraphics (GpGraphics *graphics)
+{
+ /* FIXME: attention to surface (image, etc.) */
+ /* printf ("GdipDeleteGraphics. graphics %p\n", graphics); */
+ cairo_matrix_destroy (graphics->copy_of_ctm);
+ cairo_destroy (graphics->ct);
+ GdipFree (graphics);
+ return Ok;
+}
+
+GpStatus
+GdipGetDC (GpGraphics *graphics, int *hDC)
+{
+ if (graphics->hdc == 0) {
+ if (graphics->image != 0) {
+ /* Create DC */
+ graphics->hdc = gdip_image_create_Win32_HDC (graphics->image);
+ if (graphics->hdc != 0) {
+ ++graphics->hdc_busy_count;
+ }
+ }
+ }
+ *hDC = (int)graphics->hdc;
+ return Ok;
+}
+
+GpStatus
+GdipReleaseDC (GpGraphics *graphics, int hDC)
+{
+ if (graphics->hdc != (void *)hDC) return InvalidParameter;
+ if (graphics->hdc_busy_count > 0) {
+ --graphics->hdc_busy_count;
+ if (graphics->hdc_busy_count == 0) {
+ /* Destroy DC */
+ gdip_image_destroy_Win32_HDC (graphics->image, (void*)hDC);
+ graphics->hdc = 0;
+ }
+ }
+ return Ok;
+}
+
+/* FIXME: the stack implementation is probably not suitable */
+#define MAX_GRAPHICS_STATE_STACK 100
+
+GpState saved_stack [MAX_GRAPHICS_STATE_STACK];
+int current_stack_pos = 0;
+
+GpStatus
+GdipRestoreGraphics (GpGraphics *graphics, unsigned int graphicsState)
+{
+ if (graphicsState < MAX_GRAPHICS_STATE_STACK) {
+ cairo_matrix_copy (graphics->copy_of_ctm, saved_stack[graphicsState].matrix);
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ current_stack_pos = graphicsState;
+ }
+ else {
+ return InvalidParameter;
+ }
+ return Ok;
+}
+
+GpStatus
+GdipSaveGraphics(GpGraphics *graphics, unsigned int *state)
+{
+ if (current_stack_pos < MAX_GRAPHICS_STATE_STACK) {
+ saved_stack[current_stack_pos].matrix = cairo_matrix_create ();
+ cairo_matrix_copy (saved_stack[current_stack_pos].matrix, graphics->copy_of_ctm);
+ *state = current_stack_pos;
+ ++current_stack_pos;
+ }
+ else {
+ return OutOfMemory;
+ }
+ return Ok;
+}
+GpStatus
+GdipResetWorldTransform (GpGraphics *graphics)
+{
+ GpStatus s = cairo_matrix_set_identity (graphics->copy_of_ctm);
+
+ if (s != Ok)
+ return s;
+ else {
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ return Ok;
+ }
+}
+
+GpStatus
+GdipSetWorldTransform (GpGraphics *graphics, GpMatrix *matrix)
+{
+ graphics->copy_of_ctm = matrix;
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ return Ok;
+}
+
+GpStatus
+GdipGetWorldTransform (GpGraphics *graphics, GpMatrix *matrix)
+{
+ cairo_current_matrix (graphics->ct, matrix);
+ return Ok;
+}
+
+GpStatus
+GdipMultiplyWorldTransform (GpGraphics *graphics, GpMatrix *matrix, GpMatrixOrder order)
+{
+ Status s = GdipMultiplyMatrix (graphics->copy_of_ctm, matrix, order);
+
+ if (s != Ok)
+ return s;
+
+ else {
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ return Ok;
+ }
+}
+
+GpStatus
+GdipRotateWorldTransform (GpGraphics *graphics, float angle, GpMatrixOrder order)
+{
+ GpStatus s = GdipRotateMatrix (graphics->copy_of_ctm, angle, order);
+
+ if (s != Ok)
+ return s;
+ else {
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ return Ok;
+ }
+}
+
+GpStatus
+GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, GpMatrixOrder order)
+{
+ GpStatus s = GdipTranslateMatrix (graphics->copy_of_ctm, dx, dy, order);
+
+ if (s != Ok)
+ return s;
+ else {
+ cairo_set_matrix (graphics->ct, graphics->copy_of_ctm);
+ return Ok;
+ }
+}
+
+GpStatus
+GdipDrawArc (GpGraphics *graphics, GpPen *pen,
+ float x, float y, float width, float height,
+ float startAngle, float sweepAngle)
+{
+ gdip_pen_setup (graphics, pen);
+
+ float delta = sweepAngle - startAngle;
+
+ if (delta < 180)
+ make_arc (graphics, x, y, width, height, startAngle, sweepAngle);
+
+ else {
+ make_arc (graphics, x, y, width, height, startAngle, startAngle + 180);
+ make_arc (graphics, x, y, width, height, startAngle + 180, sweepAngle);
+ }
+
+ cairo_stroke (graphics->ct);
+
+ return gdip_get_status (cairo_status (graphics->ct));
+}
+
+GpStatus
+GdipDrawArcI (GpGraphics *graphics, GpPen *pen,
+ int x, int y, int width, int height,
+ float startAngle, float sweepAngle)
+{
+ gdip_pen_setup (graphics, pen);
+
+ float delta = sweepAngle - startAngle;
+
+ if (delta < 180)
+ make_arc (graphics, x, y, width, height, startAngle, sweepAngle);
+
+ else {
+ make_arc (graphics, x, y, width, height, startAngle, startAngle + 180);
+ make_arc (graphics, x, y, width, height, startAngle + 180, sweepAngle);
+ }
+
+ cairo_stroke (graphics->ct);
+
+ return gdip_get_status (cairo_status (graphics->ct));
+}
+
+GpStatus
+GdipDrawBezier (GpGraphics *graphics, GpPen *pen,
+ float x1, float y1, float x2, float y2,
+ float x3, float y3, float x4, float y4)
+{
+ gdip_pen_setup (graphics, pen);
+
+ cairo_move_to (graphics->ct, x1, y1);
+ cairo_curve_to (graphics->ct, x2, y2, x3, y3, x4, y4);
+ cairo_stroke (graphics->ct);
+
+ return gdip_get_status (cairo_status (graphics->ct));
+}
+
+GpStatus GdipDrawBezierI (GpGraphics *graphics, GpPen *pen,
+ int x1, int y1, int x2, int y2,
+ int x3, int y3, int x4, int y4)
+{
+ return GdipDrawBezier (graphics, pen,
+ x1, y1, x2, y2, x3, y3, x4, y4);
+}
+
+GpStatus
+GdipDrawBeziers (GpGraphics *graphics, GpPen *pen,
+ GpPointF *points, int count)
+{
+ int i, j, k;
+
+ if (count == 0)
+ return Ok;
+
+ gdip_pen_setup (graphics, pen);
+
+ cairo_move_to (graphics->ct, points [0].X, points [0].Y);
+
+ for (i = 0; i < count - 3; i += 3) {
+ j = i + 1;
+ k = i + 2;
+ cairo_curve_to (graphics->ct,
+ points [i].X, points [i].Y,
+ points [j].X, points [j].Y,
+ points [k].X, points [k].Y);
+ }
+
+ cairo_stroke (graphics->ct);
+
+ return gdip_get_status (cairo_status (graphics->ct));
+}
+
+GpStatus
+GdipDrawBeziersI (GpGraphics *graphics, GpPen *pen,
+ GpPoint *points, int count)
+{
+ int i, j, k;
+
+ if (count == 0)
+ return Ok;
+
+ gdip_pen_setup (graphics, pen);
+
+ cairo_move_to (graphics->ct, points [0].X, points [0].Y);
+
+ for (i = 0; i < count - 3; i += 3) {
+ j = i + 1;
+ k = i + 2;
+ cairo_curve_to (graphics->ct,
+ points [i].X, points [i].Y,
+ points [j].X, points [j].Y,
+ points [k].X, points [k].Y);
+ }
+
+ cairo_stroke (graphics->ct);