[GB.CAIRO]

* NEW: Cairo.ShowPage() and Cairo.CopyPage() have been implemented.
* NEW: New classes for implementing some Cairo surfaces: CairoPdfSurface, 
  CairoPsSurface and CairoSvgSurface.

[GB.IMAGE]
* BUG: When deleting an image, free the temporary handle before the owner 
  handle, because the temporary owner may want to access the data while 
  freeing it.


git-svn-id: svn://localhost/gambas/trunk@3590 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2011-02-22 00:26:50 +00:00
parent 1628c4844b
commit ac03c9fc85
8 changed files with 307 additions and 9 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -8,7 +8,7 @@ Component=gb.image
Component=gb.gui Component=gb.gui
Description="Anti-aliased drawing with the Paint class" Description="Anti-aliased drawing with the Paint class"
Authors="Fabien Bodard\nBenoît Minisini" Authors="Fabien Bodard\nBenoît Minisini"
Environment="GB_GUI=gb.gtk" Environment="GB_GUI=gb.qt4"
TabSize=2 TabSize=2
Translate=1 Translate=1
Language=en Language=en

View file

@ -8,4 +8,5 @@ gblib_LTLIBRARIES = gb.cairo.la
gb_cairo_la_LIBADD = @CAIRO_LIB@ gb_cairo_la_LIBADD = @CAIRO_LIB@
gb_cairo_la_LDFLAGS = -module @LD_FLAGS@ gb_cairo_la_LDFLAGS = -module @LD_FLAGS@
gb_cairo_la_SOURCES = main.c main.h c_cairo.c c_cairo.h gb_cairo_la_SOURCES = main.c main.h c_cairo.c c_cairo.h c_surface.c c_surface.h

View file

@ -22,6 +22,7 @@
#define __C_CAIRO_C #define __C_CAIRO_C
#include "c_surface.h"
#include "c_cairo.h" #include "c_cairo.h"
typedef typedef
@ -46,6 +47,7 @@ CAIRO_DRAW *_current = NULL;
static void free_image(GB_IMG *img, void *image) static void free_image(GB_IMG *img, void *image)
{ {
fprintf(stderr, "free_image: %p %p (%d)\n", img, image, cairo_surface_get_reference_count((cairo_surface_t *)image));
cairo_surface_destroy((cairo_surface_t *)image); cairo_surface_destroy((cairo_surface_t *)image);
} }
@ -58,20 +60,18 @@ static void *temp_image(GB_IMG *img)
else else
image = cairo_image_surface_create_for_data(img->data, CAIRO_FORMAT_ARGB32, img->width, img->height, image = cairo_image_surface_create_for_data(img->data, CAIRO_FORMAT_ARGB32, img->width, img->height,
cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, img->width)); cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, img->width));
fprintf(stderr, "temp_image: %p -> %p (%d)\n", img, image, cairo_surface_get_reference_count(image));
return image; return image;
} }
static void sync_image(void *image)
{
}
static GB_IMG_OWNER _image_owner = { static GB_IMG_OWNER _image_owner = {
"gb.cairo", "gb.cairo",
GB_IMAGE_BGRP, GB_IMAGE_BGRP,
free_image, free_image,
free_image, free_image,
temp_image, temp_image,
sync_image, NULL,
}; };
static cairo_surface_t *check_image(void *img) static cairo_surface_t *check_image(void *img)
@ -506,6 +506,11 @@ BEGIN_METHOD(CAIRO_begin, GB_OBJECT device)
draw->surface = check_image(device); draw->surface = check_image(device);
draw->context = cairo_create(draw->surface); draw->context = cairo_create(draw->surface);
} }
else if (GB.Is(device, GB.FindClass("CairoSurface")))
{
draw->surface = ((CAIRO_SURFACE *)device)->surface;
draw->context = cairo_create(draw->surface);
}
else else
{ {
GB.Free(POINTER(&draw)); GB.Free(POINTER(&draw));
@ -996,6 +1001,21 @@ BEGIN_METHOD(Cairo_DrawText, GB_STRING text)
END_METHOD END_METHOD
BEGIN_METHOD_VOID(Cairo_ShowPage)
CHECK_CNT();
cairo_show_page(CNT);
END_METHOD
BEGIN_METHOD_VOID(Cairo_CopyPage)
CHECK_CNT();
cairo_copy_page(CNT);
END_METHOD
GB_DESC CairoDesc[] = GB_DESC CairoDesc[] =
{ {
GB_DECLARE("Cairo", 0), GB_VIRTUAL_CLASS(), GB_DECLARE("Cairo", 0), GB_VIRTUAL_CLASS(),
@ -1163,5 +1183,8 @@ GB_DESC CairoDesc[] =
GB_STATIC_METHOD("Text", NULL, Cairo_Text, "(Text)s"), GB_STATIC_METHOD("Text", NULL, Cairo_Text, "(Text)s"),
GB_STATIC_METHOD("DrawText", NULL, Cairo_DrawText, "(Text)s"), GB_STATIC_METHOD("DrawText", NULL, Cairo_DrawText, "(Text)s"),
GB_STATIC_METHOD("ShowPage", NULL, Cairo_ShowPage, NULL),
GB_STATIC_METHOD("CopyPage", NULL, Cairo_CopyPage, NULL),
GB_END_DECLARE GB_END_DECLARE
}; };

207
gb.cairo/src/c_surface.c Normal file
View file

@ -0,0 +1,207 @@
/***************************************************************************
c_surface.c
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************************/
#define __C_SURFACE_C
#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <cairo-svg.h>
#include "c_surface.h"
BEGIN_METHOD_VOID(CairoSurface_free)
GB.FreeString(&THIS->path);
cairo_surface_destroy(THIS->surface);
END_METHOD
BEGIN_PROPERTY(CairoSurface_Status)
GB.ReturnInteger(cairo_surface_status(THIS->surface));
END_PROPERTY
BEGIN_PROPERTY(CairoSurface_Path)
GB.ReturnString(THIS->path);
END_PROPERTY
BEGIN_METHOD(CairoSurface_Save, GB_STRING path)
GB.ReturnInteger(cairo_surface_write_to_png(THIS->surface, GB.FileName(STRING(path), LENGTH(path))));
END_METHOD
BEGIN_PROPERTY(CairoSurface_Resolution)
if (READ_PROPERTY)
{
double x, y;
cairo_surface_get_fallback_resolution(THIS->surface, &x, &y);
GB.ReturnFloat(MAX(x, y));
}
else
{
double r = VPROP(GB_FLOAT);
cairo_surface_set_fallback_resolution(THIS->surface, r, r);
}
END_PROPERTY
BEGIN_METHOD_VOID(CairoSurface_Finish)
cairo_surface_finish(THIS->surface);
END_METHOD
GB_DESC CairoSurfaceDesc[] =
{
GB_DECLARE("CairoSurface", sizeof(CAIRO_SURFACE)), GB_NOT_CREATABLE(),
GB_METHOD("_free", NULL, CairoSurface_free, NULL),
//GB_STATIC_METHOD("_call", "CairoSurface", CairoSurface_call, "(Path)s(Width)f(Height)f"),
GB_METHOD("Save", "i", CairoSurface_Save, "(Path)s"),
GB_METHOD("Finish", NULL, CairoSurface_Finish, NULL),
GB_PROPERTY_READ("Status", "i", CairoSurface_Status),
GB_PROPERTY_READ("Path", "s", CairoSurface_Path),
GB_PROPERTY("Resolution", "f", CairoSurface_Resolution),
GB_END_DECLARE
};
/**************************************************************************/
#define CM_TO_PT(_cm) ((_cm) / 25.4 * 72.0)
BEGIN_METHOD(CairoPdfSurface_new, GB_STRING path; GB_FLOAT width; GB_FLOAT height; GB_STRING version)
char *version = NULL;
if (!MISSING(version))
version = GB.ToZeroString(ARG(version));
THIS->path = GB.NewZeroString(GB.FileName(STRING(path), LENGTH(path)));
THIS->surface = cairo_pdf_surface_create(THIS->path, CM_TO_PT(VARG(width)), CM_TO_PT(VARG(height)));
if (version)
{
if (!strcmp(version, "1.4"))
cairo_pdf_surface_restrict_to_version(THIS->surface, CAIRO_PDF_VERSION_1_4);
else if (!strcmp(version, "1.5"))
cairo_pdf_surface_restrict_to_version(THIS->surface, CAIRO_PDF_VERSION_1_5);
}
END_METHOD
BEGIN_METHOD(CairoPdfSurface_Resize, GB_FLOAT width; GB_FLOAT height)
cairo_pdf_surface_set_size(THIS->surface, CM_TO_PT(VARG(width)), CM_TO_PT(VARG(height)));
END_METHOD
GB_DESC CairoPdfSurfaceDesc[] =
{
GB_DECLARE("CairoPdfSurface", sizeof(CAIRO_SURFACE)), GB_INHERITS("CairoSurface"),
GB_METHOD("_new", NULL, CairoPdfSurface_new, "(Path)s(Width)f(Height)f[(Version)s]"),
GB_METHOD("Resize", NULL, CairoPdfSurface_Resize, "(Width)f(Height)f"),
GB_END_DECLARE
};
/**************************************************************************/
BEGIN_METHOD(CairoPsSurface_new, GB_STRING path; GB_FLOAT width; GB_FLOAT height; GB_BOOLEAN eps; GB_STRING level)
char *level = NULL;
if (!MISSING(level))
level = GB.ToZeroString(ARG(level));
THIS->path = GB.NewZeroString(GB.FileName(STRING(path), LENGTH(path)));
THIS->surface = cairo_ps_surface_create(THIS->path, CM_TO_PT(VARG(width)), CM_TO_PT(VARG(height)));
if (level)
{
if (!strcmp(level, "2"))
cairo_ps_surface_restrict_to_level(THIS->surface, CAIRO_PS_LEVEL_2);
else if (!strcmp(level, "3"))
cairo_ps_surface_restrict_to_level(THIS->surface, CAIRO_PS_LEVEL_3);
}
cairo_ps_surface_set_eps(THIS->surface, VARGOPT(eps, FALSE));
END_METHOD
BEGIN_METHOD(CairoPsSurface_Resize, GB_FLOAT width; GB_FLOAT height)
cairo_ps_surface_set_size(THIS->surface, CM_TO_PT(VARG(width)), CM_TO_PT(VARG(height)));
END_METHOD
GB_DESC CairoPsSurfaceDesc[] =
{
GB_DECLARE("CairoPsSurface", sizeof(CAIRO_SURFACE)), GB_INHERITS("CairoSurface"),
GB_METHOD("_new", NULL, CairoPsSurface_new, "(Path)s(Width)f(Height)f[(Encapsulated)b(Level)s]"),
GB_METHOD("Resize", NULL, CairoPsSurface_Resize, "(Width)f(Height)f"),
GB_END_DECLARE
};
/**************************************************************************/
BEGIN_METHOD(CairoSvgSurface_new, GB_STRING path; GB_FLOAT width; GB_FLOAT height; GB_STRING version)
char *version = NULL;
if (!MISSING(version))
version = GB.ToZeroString(ARG(version));
THIS->path = GB.NewZeroString(GB.FileName(STRING(path), LENGTH(path)));
THIS->surface = cairo_svg_surface_create(THIS->path, CM_TO_PT(VARG(width)), CM_TO_PT(VARG(height)));
if (version)
{
if (!strcmp(version, "1.1"))
cairo_svg_surface_restrict_to_version(THIS->surface, CAIRO_SVG_VERSION_1_1);
else if (!strcmp(version, "1.2"))
cairo_svg_surface_restrict_to_version(THIS->surface, CAIRO_SVG_VERSION_1_2);
}
END_METHOD
GB_DESC CairoSvgSurfaceDesc[] =
{
GB_DECLARE("CairoSvgSurface", sizeof(CAIRO_SURFACE)), GB_INHERITS("CairoSurface"),
GB_METHOD("_new", NULL, CairoSvgSurface_new, "(Path)s(Width)f(Height)f[(Version)s]"),
GB_END_DECLARE
};

49
gb.cairo/src/c_surface.h Normal file
View file

@ -0,0 +1,49 @@
/***************************************************************************
c_surface.h
(c) 2000-2009 Benoît Minisini <gambas@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***************************************************************************/
#ifndef __C_SURFACE_H
#define __C_SURFACE_H
#include "main.h"
#ifndef __C_SURFACE_C
extern GB_DESC CairoSurfaceDesc[];
extern GB_DESC CairoPdfSurfaceDesc[];
extern GB_DESC CairoPsSurfaceDesc[];
extern GB_DESC CairoSvgSurfaceDesc[];
#else
#define THIS ((CAIRO_SURFACE *)_object)
#endif
typedef
struct {
GB_BASE ob;
cairo_surface_t *surface;
char *path;
}
CAIRO_SURFACE;
#endif

View file

@ -23,6 +23,7 @@
#define __MAIN_C #define __MAIN_C
#include "main.h" #include "main.h"
#include "c_surface.h"
#include "c_cairo.h" #include "c_cairo.h"
GB_INTERFACE GB EXPORT; GB_INTERFACE GB EXPORT;
@ -30,7 +31,11 @@ IMAGE_INTERFACE IMAGE EXPORT;
GB_DESC *GB_CLASSES[] EXPORT = GB_DESC *GB_CLASSES[] EXPORT =
{ {
CairoPatternDesc, CairoSurfaceDesc,
CairoPdfSurfaceDesc,
CairoPsSurfaceDesc,
CairoSvgSurfaceDesc,
CairoPatternDesc,
CairoExtentsDesc, CairoExtentsDesc,
CairoTextExtentsDesc, CairoTextExtentsDesc,
CairoFontExtentsDesc, CairoFontExtentsDesc,

View file

@ -543,8 +543,21 @@ void IMAGE_take(GB_IMG *img, GB_IMG_OWNER *owner, void *owner_handle, int width,
void IMAGE_delete(GB_IMG *img) void IMAGE_delete(GB_IMG *img)
{ {
IMAGE_take(img, &_image_owner, NULL, 0, 0, NULL); //IMAGE_take(img, &_image_owner, NULL, 0, 0, NULL);
// Release the temporary handle before the owner, because the temporary owner may write to the data before freeing!
if (img->temp_owner && img->temp_owner != img->owner && img->temp_handle)
(*img->temp_owner->release)(img, img->temp_handle);
(*img->owner->free)(img, img->owner_handle);
img->width = img->height = 0;
img->format = 0; img->format = 0;
img->temp_owner = NULL;
img->temp_handle = NULL;
img->owner = NULL;
img->owner_handle = NULL;
} }
void IMAGE_synchronize(GB_IMG *img) void IMAGE_synchronize(GB_IMG *img)