summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Chaplin <>2010-09-14 20:30:18 +0800
committerSteve Chaplin <>2010-09-14 20:30:18 +0800
commit04ae0c94d1e73ff39d731a44229a6eb079018666 (patch)
tree5d150e51b412578ba925c521b3d6c34b0262e381
parent6714d1cd7f8546a04f9d596407826d3f078ee994 (diff)
downloadpy2cairo-04ae0c94d1e73ff39d731a44229a6eb079018666.tar.gz
Improve unicode support for filenames passed to
cairo.PDFSurface, cairo.PSSurface, cairo.SVGSurface, Surface.write_to_png(), Surface.create_from_png(). Bug #29582.
-rw-r--r--doc/reference/surfaces.rst8
-rw-r--r--src/context.c4
-rw-r--r--src/surface.c103
-rwxr-xr-xtest/unicode.py28
4 files changed, 109 insertions, 34 deletions
diff --git a/doc/reference/surfaces.rst b/doc/reference/surfaces.rst
index 261fc1e..038656d 100644
--- a/doc/reference/surfaces.rst
+++ b/doc/reference/surfaces.rst
@@ -227,7 +227,7 @@ class Surface()
.. method:: write_to_png(fobj)
:param fobj: the file to write to
- :type fobj: str, file or file-like object
+ :type fobj: filename (str or unicode), file or file-like object
:raises: *MemoryError* if memory could not be allocated for the operation
*IOError* if an I/O error occurs while attempting to write the file
@@ -341,7 +341,7 @@ multi-page vector surface backend.
.. class:: PDFSurface(fobj, width_in_points, height_in_points)
:param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *PDFSurface* that may be queried and used as a source, without generating a temporary file.
- :type fobj: None, str, file or file-like object
+ :type fobj: None, str, unicode, file or file-like object
:param width_in_points: width of the surface, in points
(1 point == 1/72.0 inch)
:type width_in_points: float
@@ -383,7 +383,7 @@ is a multi-page vector surface backend.
.. class:: PSSurface(fobj, width_in_points, height_in_points)
:param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *PSSurface* that may be queried and used as a source, without generating a temporary file.
- :type fobj: None, str, file or file-like object
+ :type fobj: None, str, unicode, file or file-like object
:param width_in_points: width of the surface, in points
(1 point == 1/72.0 inch)
:type width_in_points: float
@@ -586,7 +586,7 @@ multi-page vector surface backend
.. class:: SVGSurface(fobj, width_in_points, height_in_points)
:param fobj: a filename or writable file object. None may be used to specify no output. This will generate a *SVGSurface* that may be queried and used as a source, without generating a temporary file.
- :type fobj: None, str, file or file-like object
+ :type fobj: None, str, unicode, file or file-like object
:param width_in_points: width of the surface, in points (1 point == 1/72.0 inch)
:type width_in_points: float
:param height_in_points: height of the surface, in points (1 point == 1/72.0 inch)
diff --git a/src/context.c b/src/context.c
index 93b369f..f6e76c7 100644
--- a/src/context.c
+++ b/src/context.c
@@ -1016,7 +1016,7 @@ pycairo_set_operator(PycairoContext *o, PyObject *args) {
static PyObject *
pycairo_set_scaled_font(PycairoContext *o, PyObject *args) {
PycairoScaledFont *f;
- if (!PyArg_ParseTuple( args, "O!:Context.set_scaled_font",
+ if (!PyArg_ParseTuple (args, "O!:Context.set_scaled_font",
&PycairoScaledFont_Type, &f))
return NULL;
@@ -1029,7 +1029,7 @@ static PyObject *
pycairo_set_source (PycairoContext *o, PyObject *args) {
PycairoPattern *p;
- if (!PyArg_ParseTuple( args, "O!:Context.set_source",
+ if (!PyArg_ParseTuple (args, "O!:Context.set_source",
&PycairoPattern_Type, &p))
return NULL;
diff --git a/src/surface.c b/src/surface.c
index 3c1b11d..2888e9c 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -280,18 +280,28 @@ surface_show_page (PycairoSurface *o) {
}
#ifdef CAIRO_HAS_PNG_FUNCTIONS
-/* METH_O */
static PyObject *
-surface_write_to_png (PycairoSurface *o, PyObject *file) {
+surface_write_to_png (PycairoSurface *o, PyObject *args) {
cairo_status_t status;
+ PyObject *file;
+
+ if (!PyArg_ParseTuple(args, "O:Surface.write_to_png", &file))
+ return NULL;
+
+ if (PyObject_TypeCheck (file, &PyBaseString_Type)) {
+ /* filename (str or unicode) argument */
+ char *name = NULL; // the encoded filename
+
+ if (!PyArg_ParseTuple(args, "et:Surface.write_to_png",
+ Py_FileSystemDefaultEncoding, &name))
+ return NULL;
- if (PyObject_TypeCheck (file, &PyString_Type)) {
- /* string (filename) argument */
Py_BEGIN_ALLOW_THREADS;
- status = cairo_surface_write_to_png (o->surface,
- PyString_AsString(file));
+ status = cairo_surface_write_to_png (o->surface, name);
Py_END_ALLOW_THREADS;
+ PyMem_Free(name);
+
} else { /* file or file-like object argument */
PyObject* writer = PyObject_GetAttrString (file, "write");
if (writer == NULL || !PyCallable_Check (writer)) {
@@ -338,7 +348,7 @@ static PyMethodDef surface_methods[] = {
METH_VARARGS},
{"show_page", (PyCFunction)surface_show_page, METH_NOARGS},
#ifdef CAIRO_HAS_PNG_FUNCTIONS
- {"write_to_png", (PyCFunction)surface_write_to_png, METH_O },
+ {"write_to_png", (PyCFunction)surface_write_to_png, METH_VARARGS},
#endif
{NULL, NULL, 0, NULL},
};
@@ -406,6 +416,7 @@ image_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
NULL);
}
+/* METH_CLASS */
static PyObject *
image_surface_create_for_data (PyTypeObject *type, PyObject *args) {
cairo_surface_t *surface;
@@ -415,7 +426,7 @@ image_surface_create_for_data (PyTypeObject *type, PyObject *args) {
Py_ssize_t buffer_len;
PyObject *obj;
- if (!PyArg_ParseTuple(args, "Oiii|i:Surface.create_for_data",
+ if (!PyArg_ParseTuple(args, "Oiii|i:ImageSurface.create_for_data",
&obj, &format, &width, &height, &stride))
return NULL;
@@ -480,16 +491,27 @@ _read_func (void *closure, unsigned char *data, unsigned int length) {
return status;
}
-/* METH_O | METH_CLASS */
+/* METH_CLASS */
static PyObject *
-image_surface_create_from_png (PyTypeObject *type, PyObject *file) {
- PyObject* reader;
+image_surface_create_from_png (PyTypeObject *type, PyObject *args) {
cairo_surface_t *is;
+ PyObject *reader, *file;
+
+ if (!PyArg_ParseTuple(args, "O:ImageSurface.create_from_png", &file))
+ return NULL;
if (PyObject_TypeCheck (file, &PyBaseString_Type)) {
+ char *name = NULL; // the encoded filename
+
+ if (!PyArg_ParseTuple(args, "et:Surface.create_from_png",
+ Py_FileSystemDefaultEncoding, &name))
+ return NULL;
+
Py_BEGIN_ALLOW_THREADS;
- is = cairo_image_surface_create_from_png (PyString_AsString(file));
+ is = cairo_image_surface_create_from_png (name);
Py_END_ALLOW_THREADS;
+
+ PyMem_Free(name);
return PycairoSurface_FromSurface (is, NULL);
}
@@ -607,7 +629,7 @@ static PyMethodDef image_surface_methods[] = {
METH_VARARGS | METH_CLASS},
#ifdef CAIRO_HAS_PNG_FUNCTIONS
{"create_from_png", (PyCFunction)image_surface_create_from_png,
- METH_O | METH_CLASS},
+ METH_VARARGS | METH_CLASS},
#endif
{"format_stride_for_width",
(PyCFunction)image_surface_format_stride_for_width,
@@ -684,18 +706,27 @@ pdf_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
if (file == Py_None) {
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_pdf_surface_create (NULL,
- width_in_points, height_in_points);
+ sfc = cairo_pdf_surface_create (NULL, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
return PycairoSurface_FromSurface (sfc, NULL);
+
}else if (PyObject_TypeCheck (file, &PyBaseString_Type)) {
- /* string (filename) argument */
+ /* filename (str or unicode) argument */
+ char *name = NULL; // the encoded filename
+
+ if (!PyArg_ParseTuple(args, "etdd:PDFSurface.__new__",
+ Py_FileSystemDefaultEncoding,
+ &name, &width_in_points, &height_in_points))
+ return NULL;
+
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_pdf_surface_create (PyString_AsString(file),
- width_in_points, height_in_points);
+ sfc = cairo_pdf_surface_create (name, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
+
+ PyMem_Free(name);
return PycairoSurface_FromSurface (sfc, NULL);
}
+
/* file or file-like object argument */
writer = PyObject_GetAttrString (file, "write");
if (writer == NULL || !PyCallable_Check (writer)) {
@@ -798,16 +829,24 @@ ps_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
if (file == Py_None) {
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_ps_surface_create (NULL,
- width_in_points, height_in_points);
+ sfc = cairo_ps_surface_create (NULL, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
return PycairoSurface_FromSurface (sfc, NULL);
+
}else if (PyObject_TypeCheck (file, &PyBaseString_Type)) {
- /* string (filename) argument */
+ /* filename (str or unicode) argument */
+ char *name = NULL; // the encoded filename
+
+ if (!PyArg_ParseTuple(args, "etdd:PSSurface.__new__",
+ Py_FileSystemDefaultEncoding,
+ &name, &width_in_points, &height_in_points))
+ return NULL;
+
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_ps_surface_create (PyString_AsString(file),
- width_in_points, height_in_points);
+ sfc = cairo_ps_surface_create (name, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
+
+ PyMem_Free(name);
return PycairoSurface_FromSurface (sfc, NULL);
}
/* else: file or file-like object argument */
@@ -991,16 +1030,24 @@ svg_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
if (file == Py_None) {
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_svg_surface_create (NULL,
- width_in_points, height_in_points);
+ sfc = cairo_svg_surface_create (NULL, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
return PycairoSurface_FromSurface (sfc, NULL);
+
}else if (PyObject_TypeCheck (file, &PyBaseString_Type)) {
- /* string (filename) argument */
+ /* filename (str or unicode) argument */
+ char *name = NULL; // the encoded filename
+
+ if (!PyArg_ParseTuple(args, "etdd:SVGSurface.__new__",
+ Py_FileSystemDefaultEncoding,
+ &name, &width_in_points, &height_in_points))
+ return NULL;
+
Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_svg_surface_create (PyString_AsString(file),
- width_in_points, height_in_points);
+ sfc = cairo_svg_surface_create (name, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
+
+ PyMem_Free(name);
return PycairoSurface_FromSurface (sfc, NULL);
}
/* else: file or file-like object argument */
diff --git a/test/unicode.py b/test/unicode.py
new file mode 100755
index 0000000..a9c89f3
--- /dev/null
+++ b/test/unicode.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# test unicode filenames
+
+import math
+import cairo
+
+WIDTH, HEIGHT = 256, 256
+
+#f = open(u"ēxāmple.pdf","w")
+#surface = cairo.PDFSurface (f, WIDTH, HEIGHT)
+
+surface = cairo.PDFSurface (u"a1ēxāmple.pdf", WIDTH, HEIGHT)
+
+ctx = cairo.Context (surface)
+ctx.scale (WIDTH, HEIGHT)
+pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
+pat.add_color_stop_rgba (1, 0.7, 0, 0, 0.5)
+pat.add_color_stop_rgba (0, 0.9, 0.7, 0.2, 1)
+ctx.rectangle (0, 0, 1, 1)
+ctx.set_source (pat)
+ctx.fill ()
+ctx.translate (0.1, 0.1)
+
+surface.write_to_png (u"a2ēxāmple.png")
+surface.show_page()
+surface.flush()
+surface.finish()