[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:
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 |
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
207
gb.cairo/src/c_surface.c
Normal 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
49
gb.cairo/src/c_surface.h
Normal 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
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue