diff options
author | Steve Chaplin <> | 2010-09-14 20:30:18 +0800 |
---|---|---|
committer | Steve Chaplin <> | 2010-09-14 20:30:18 +0800 |
commit | 04ae0c94d1e73ff39d731a44229a6eb079018666 (patch) | |
tree | 5d150e51b412578ba925c521b3d6c34b0262e381 | |
parent | 6714d1cd7f8546a04f9d596407826d3f078ee994 (diff) |
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.rst | 8 | ||||
-rw-r--r-- | src/context.c | 4 | ||||
-rw-r--r-- | src/surface.c | 103 | ||||
-rwxr-xr-x | test/unicode.py | 28 |
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() |