+Since version 1.11.0 Pycairo uses `Semantic Versioning
+<http://semver.org/>`__ i.e. the newest version is the latest stable one.
+
+.. _v1.15.1:
+
+1.15.1 - 2017-08-19
+-------------------
+
+Fixes:
+ * Improved support for Python filesystem paths including
+ :class:`os.PathLike`. See :class:`pathlike` for details.
+ * Various minor fixes
+
+Changes:
+ * Expose :class:`cairo.Path`
+
+Tests:
+ * Improved test coverage from ~70% to ~90%
+
+
.. _v1.15.0:
1.15.0 - 2017-07-24
Metadata-Version: 1.1
Name: pycairo
-Version: 1.15.0
+Version: 1.15.1
Summary: Python interface for cairo
Home-page: https://pycairo.readthedocs.io
Author: Christoph Reiter
.. image:: https://ci.appveyor.com/api/projects/status/9hurdbb19lg2i9xm/branch/master?svg=true
:target: https://ci.appveyor.com/project/lazka/pycairo/branch/master
+ .. image:: https://codecov.io/gh/pygobject/pycairo/branch/master/graph/badge.svg
+ :target: https://codecov.io/gh/pygobject/pycairo
+
Platform: UNKNOWN
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2
.. image:: https://ci.appveyor.com/api/projects/status/9hurdbb19lg2i9xm/branch/master?svg=true
:target: https://ci.appveyor.com/project/lazka/pycairo/branch/master
+
+.. image:: https://codecov.io/gh/pygobject/pycairo/branch/master/graph/badge.svg
+ :target: https://codecov.io/gh/pygobject/pycairo
Py_INCREF(&PycairoTextExtents_Type);
PyModule_AddObject(m, "TextExtents", (PyObject *)&PycairoTextExtents_Type);
+ Py_INCREF(&PycairoPath_Type);
+ PyModule_AddObject(m, "Path", (PyObject *)&PycairoPath_Type);
+
#ifdef CAIRO_HAS_SCRIPT_SURFACE
Py_INCREF(&PycairoScriptDevice_Type);
PyModule_AddObject(m, "ScriptDevice", (PyObject *)&PycairoScriptDevice_Type);
#define PYCAIRO_ENC_TEXT_FORMAT "et"
#define PYCAIRO_DATA_FORMAT "s"
-#define PYCAIRO_PyFilenameBase_Type PyBaseString_Type
-
#define PYCAIRO_Py_hash_t long
#else
#define PYCAIRO_ENC_TEXT_FORMAT "es"
#define PYCAIRO_DATA_FORMAT "y"
-#define PYCAIRO_PyFilenameBase_Type PyUnicode_Type
-
#define PYCAIRO_Py_hash_t Py_hash_t
#endif
static PyObject *
pycairo_get_group_target (PycairoContext *o) {
cairo_surface_t *surface = cairo_get_group_target (o->ctx);
- if (surface != NULL)
- return PycairoSurface_FromSurface (cairo_surface_reference (surface),
- NULL);
- Py_RETURN_NONE;
+ return PycairoSurface_FromSurface (cairo_surface_reference (surface), NULL);
}
static PyObject *
static PyObject *
script_device_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
- PyObject *file, *writer;
+ char *name = NULL;
+ PyObject *file;
cairo_device_t *device;
- if (!PyArg_ParseTuple(args, "O:ScriptDevice.__new__", &file))
- return NULL;
-
- if (PyObject_TypeCheck (file, &PYCAIRO_PyFilenameBase_Type)) {
- /* filename (str or unicode) argument */
- char *name = NULL; /* the encoded filename */
+ if (!PyArg_ParseTuple (args, "O:ScriptDevice.__new__", &file))
+ return NULL;
- if (!PyArg_ParseTuple(args,
- PYCAIRO_ENC_TEXT_FORMAT ":ScriptDevice.__new__",
- Py_FileSystemDefaultEncoding, &name))
- return NULL;
+ if (Pycairo_is_fspath (file)) {
+ if (!PyArg_ParseTuple (args, "O&:ScriptDevice.__new__",
+ Pycairo_fspath_converter, &name))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ device = cairo_script_create (name);
+ Py_END_ALLOW_THREADS;
+ PyMem_Free (name);
+ return PycairoDevice_FromDevice (device);
+ } else {
+ if (PyArg_ParseTuple (args, "O&:ScriptDevice.__new__",
+ Pycairo_writer_converter, &file)) {
Py_BEGIN_ALLOW_THREADS;
- device = cairo_script_create (name);
+ device = cairo_script_create_for_stream (_write_func, file);
Py_END_ALLOW_THREADS;
-
- PyMem_Free(name);
- return PycairoDevice_FromDevice (device);
- }
-
- /* else: file or file-like object argument */
- writer = PyObject_GetAttrString (file, "write");
- if (writer == NULL || !PyCallable_Check (writer)) {
- Py_XDECREF(writer);
- PyErr_SetString(PyExc_TypeError,
- "ScriptDevice argument 1 must be\n"
- " a filename (str), or\n"
- " a file object, or\n"
- " an object that has a \"write\" method (like StringIO)."
- );
+ return _device_create_with_object (device, file);
+ } else {
+ PyErr_Clear ();
+ PyErr_SetString (PyExc_TypeError,
+ "ScriptDevice takes one argument which must be "
+ "a filename, file object, or a file-like object "
+ "which has a \"write\" method (like StringIO)");
return NULL;
}
- Py_DECREF(writer);
-
- Py_BEGIN_ALLOW_THREADS;
- device = cairo_script_create_for_stream (_write_func, file);
- Py_END_ALLOW_THREADS;
-
- return _device_create_with_object (device, file);
+ }
}
static PyObject *
static PyObject *
font_options_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+
+ if (!PyArg_ParseTuple (args, ":FontOptions.__new__"))
+ return NULL;
+
return PycairoFontOptions_FromFontOptions (cairo_font_options_create());
}
glyph_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
double x, y;
unsigned long index;
- PyObject *tuple_args, *result;
+ PyObject *pyindex, *tuple_args, *result;
- if (!PyArg_ParseTupleAndKeywords (args, kwds, "kdd:Glyph.__new__",
- KWDS, &index, &x, &y))
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "Odd:Glyph.__new__",
+ KWDS, &pyindex, &x, &y))
+ return NULL;
+
+ if (_conv_pyobject_to_ulong (pyindex, &index) < 0)
return NULL;
tuple_args = Py_BuildValue ("((kdd))", index, x, y);
cairo_matrix_t *mx1 = &m1->matrix;
cairo_matrix_t *mx2 = &m2->matrix;
- if (!PyObject_TypeCheck(m2, &PycairoMatrix_Type) ||
- !(op == Py_EQ || op == Py_NE)) {
+ if (op != Py_EQ && op != Py_NE) {
+ PyErr_SetString(PyExc_TypeError, "Only support testing for == or !=");
+ return NULL;
+ }
+
+ if (!PyObject_TypeCheck(m2, &PycairoMatrix_Type)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
#include "private.h"
+/* Returns 1 if the object has the correct file type for a filesystem path.
+ * Parsing it with Pycairo_fspath_converter() might still fail.
+ */
+int
+Pycairo_is_fspath (PyObject *obj) {
+#if PY_MAJOR_VERSION < 3
+ return (PyString_Check (obj) || PyUnicode_Check (obj));
+#elif PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 6
+ PyObject *real = PyOS_FSPath (obj);
+ if (real == NULL) {
+ PyErr_Clear ();
+ return 0;
+ } else {
+ Py_DECREF (real);
+ return 1;
+ }
+#else
+ return (PyBytes_Check (obj) || PyUnicode_Check (obj));
+#endif
+}
+
+/* Converts a Python object to a cairo path. The result needs to be freed with
+ * PyMem_Free().
+ */
+int
+Pycairo_fspath_converter (PyObject *obj, char** result) {
+ char *internal, *buf;
+ PyObject *bytes;
+
+#if defined(MS_WINDOWS) && PY_MAJOR_VERSION < 3
+ PyObject *uni, *other;
+
+ if (PyString_Check (obj)) {
+ uni = PyString_AsDecodedObject (
+ obj, Py_FileSystemDefaultEncoding, "strict");
+ if (uni == NULL)
+ return 0;
+ } else if (PyUnicode_Check (obj)) {
+ uni = obj;
+ Py_INCREF (uni);
+ } else {
+ PyErr_SetString (PyExc_TypeError, "paths must be str/unicode");
+ return 0;
+ }
+
+ bytes = PyUnicode_AsMBCSString (uni);
+ if (bytes == NULL) {
+ Py_DECREF (uni);
+ return 0;
+ }
+
+ if (PyString_AsStringAndSize (bytes, &internal, NULL) == -1) {
+ Py_DECREF (uni);
+ Py_DECREF (bytes);
+ return 0;
+ }
+
+ /* PyUnicode_AsMBCSString doesn't do error handling, so we have to
+ * decode and compare again */
+ other = PyUnicode_DecodeMBCS (internal, PyString_Size (bytes), "strict");
+ if (other == NULL) {
+ Py_DECREF (uni);
+ Py_DECREF (bytes);
+ return 0;
+ }
+
+ if (PyUnicode_Compare (uni, other) != 0) {
+ Py_DECREF (uni);
+ Py_DECREF (bytes);
+ Py_DECREF (other);
+ PyErr_SetString (
+ PyExc_ValueError, "only ANSI paths supported on Windows");
+ return 0;
+ }
+
+ Py_DECREF (uni);
+ Py_DECREF (other);
+
+#elif defined(MS_WINDOWS) && PY_MAJOR_VERSION >= 3
+ PyObject *uni;
+
+ if (PyUnicode_FSDecoder (obj, &uni) == 0)
+ return 0;
+
+ bytes = PyUnicode_AsMBCSString (uni);
+ Py_DECREF (uni);
+ if (bytes == NULL)
+ return 0;
+
+ if (PyBytes_AsStringAndSize (bytes, &internal, NULL) == -1) {
+ Py_DECREF (bytes);
+ return 0;
+ }
+#elif !defined(MS_WINDOWS) && PY_MAJOR_VERSION < 3
+ if (PyUnicode_Check (obj)) {
+ bytes = PyUnicode_AsEncodedString (
+ obj, Py_FileSystemDefaultEncoding, "strict");
+ if (bytes == 0)
+ return 0;
+ } else if (PyString_Check (obj)) {
+ bytes = obj;
+ Py_INCREF (bytes);
+ } else {
+ PyErr_SetString (PyExc_TypeError, "paths must be str/unicode");
+ return 0;
+ }
+
+ if (PyString_AsStringAndSize (bytes, &internal, NULL) == -1) {
+ Py_DECREF (bytes);
+ return 0;
+ }
+#elif !defined(MS_WINDOWS) && PY_MAJOR_VERSION >= 3
+ if (PyUnicode_FSConverter (obj, &bytes) == 0)
+ return 0;
+
+ if (PyBytes_AsStringAndSize (bytes, &internal, NULL) == -1) {
+ Py_DECREF (bytes);
+ return 0;
+ }
+#else
+#error "unsupported"
+#endif
+
+ buf = PyMem_Malloc (strlen (internal) + 1);
+ if (buf == NULL) {
+ Py_DECREF (bytes);
+ PyErr_NoMemory ();
+ return 0;
+ }
+ strcpy (buf, internal);
+ Py_DECREF (bytes);
+ *result = buf;
+ return 1;
+}
+
+/* Verifies that the object has a callable write() method.
+ * Gives a borrowed reference.
+ */
+int
+Pycairo_writer_converter (PyObject *obj, PyObject** file) {
+ PyObject *attr;
+
+ attr = PyObject_GetAttrString (obj, "write");
+ if (attr == NULL)
+ return 0;
+
+ if (!PyCallable_Check (attr)) {
+ Py_DECREF (attr);
+ PyErr_SetString (
+ PyExc_TypeError, "'write' attribute not callable");
+ return 0;
+ }
+
+ Py_DECREF (attr);
+ *file = obj;
+ return 1;
+}
+
+int
+Pycairo_reader_converter (PyObject *obj, PyObject** file) {
+ PyObject *attr;
+
+ attr = PyObject_GetAttrString (obj, "read");
+ if (attr == NULL)
+ return 0;
+
+ if (!PyCallable_Check (attr)) {
+ Py_DECREF (attr);
+ PyErr_SetString (
+ PyExc_TypeError, "'read' attribute not callable");
+ return 0;
+ }
+
+ Py_DECREF (attr);
+ *file = obj;
+ return 1;
+}
+
+int
+Pycairo_fspath_none_converter (PyObject *obj, char** result) {
+ if (obj == Py_None) {
+ *result = NULL;
+ return 1;
+ }
+
+ return Pycairo_fspath_converter (obj, result);
+}
+
PyObject*
Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name) {
PyObject *value, *item;
Py_INCREF (res);
return res;
}
+
+/* NULL on error */
+static PyObject *
+_conv_pyobject_to_pylong (PyObject *pyobj) {
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check (pyobj)) {
+ return PyNumber_Long (pyobj);
+ } else if (!PyLong_Check (pyobj)) {
+ PyErr_SetString (PyExc_TypeError, "not of type int or long");
+ return NULL;
+ }
+ Py_INCREF (pyobj);
+ return pyobj;
+#else
+ if (!PyLong_Check (pyobj)) {
+ PyErr_SetString (PyExc_TypeError, "not of type int");
+ return NULL;
+ }
+ Py_INCREF (pyobj);
+ return pyobj;
+#endif
+}
+
+/* -1 on error */
+int
+_conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result) {
+ unsigned long temp;
+ PyObject *pylong;
+
+ pylong = _conv_pyobject_to_pylong (pyobj);
+ if (pylong == NULL)
+ return -1;
+
+ temp = PyLong_AsUnsignedLong (pylong);
+ if (PyErr_Occurred ())
+ return -1;
+
+ *result = temp;
+ return 0;
+}
static void
path_dealloc(PycairoPath *p) {
-#ifdef DEBUG
- printf("path_dealloc start\n");
-#endif
if (p->path) {
cairo_path_destroy(p->path);
p->path = NULL;
}
Py_TYPE(p)->tp_free(p);
-#ifdef DEBUG
- printf("path_dealloc end\n");
-#endif
}
static PyObject *
#include "pycairo.h"
#include "compat.h"
+int Pycairo_fspath_converter (PyObject *obj, char** result);
+int Pycairo_fspath_none_converter (PyObject *obj, char** result);
+int Pycairo_writer_converter (PyObject *obj, PyObject** file);
+int Pycairo_reader_converter (PyObject *obj, PyObject** file);
+int Pycairo_is_fspath (PyObject *obj);
cairo_glyph_t * _PycairoGlyphs_AsGlyphs (PyObject *py_object, int *num_glyphs);
int _PyGlyph_AsGlyph (PyObject *pyobj, cairo_glyph_t *glyph);
int _PyTextCluster_AsTextCluster (PyObject *pyobj,
cairo_text_cluster_t *cluster);
+int _conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result);
+
PyObject *_Pycairo_Get_Error(void);
PyObject* Pycairo_richcompare (void* a, void *b, int op);
PyErr_SetString(PyExc_TypeError, "Only support testing for == or !=");
return NULL;
}
- if (!PyObject_IsInstance((PyObject*)other,
- (PyObject*)&PycairoRectangleInt_Type)) {
- res = 0;
- }
- else if (
+
+ if (!PyObject_TypeCheck((PyObject*)other, &PycairoRectangleInt_Type)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ } else if (
self->rectangle_int.x == other->rectangle_int.x &&
self->rectangle_int.y == other->rectangle_int.y &&
self->rectangle_int.width == other->rectangle_int.width &&
for(i=0; i<rect_size; i++) {
PyObject *obj_tmp = PySequence_Fast_GET_ITEM(seq, i);
- if (PyObject_IsInstance(obj_tmp,
- (PyObject*)&PycairoRectangleInt_Type) != 1) {
+ if (!PyObject_TypeCheck(obj_tmp, &PycairoRectangleInt_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Must be RectangleInt");
Py_DECREF(seq);
PyMem_Free(rect);
return NULL;
PyErr_SetString(PyExc_TypeError, "Only support testing for == or !=");
return NULL;
}
- if (!PyObject_IsInstance((PyObject*)other, (PyObject*)&PycairoRegion_Type)) {
- res = 0;
+
+ if (!PyObject_TypeCheck((PyObject*)other, &PycairoRegion_Type)) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
} else {
res = cairo_region_equal (self->region, other->region);
}
if (!PyArg_ParseTuple (args, "O:Region.intersect", &other))
return NULL;
- if (PyObject_IsInstance(other, (PyObject*)&PycairoRegion_Type) == 1) {
+ if (PyObject_TypeCheck(other, &PycairoRegion_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_intersect(o->region,
((PycairoRegion *)other)->region);
Py_END_ALLOW_THREADS;
- } else if (PyObject_IsInstance(other,
- (PyObject*)&PycairoRectangleInt_Type) == 1) {
+ } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_intersect_rectangle(o->region,
&(((PycairoRectangleInt *)other)->rectangle_int));
if (!PyArg_ParseTuple (args, "O:Region.subtract", &other))
return NULL;
- if (PyObject_IsInstance(other, (PyObject*)&PycairoRegion_Type) == 1) {
+ if (PyObject_TypeCheck(other, &PycairoRegion_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_subtract(o->region,
((PycairoRegion *)other)->region);
Py_END_ALLOW_THREADS;
- } else if (PyObject_IsInstance(other,
- (PyObject*)&PycairoRectangleInt_Type) == 1) {
+ } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_subtract_rectangle(o->region,
&(((PycairoRectangleInt *)other)->rectangle_int));
if (!PyArg_ParseTuple (args, "O:Region.union", &other))
return NULL;
- if (PyObject_IsInstance(other, (PyObject*)&PycairoRegion_Type) == 1) {
+ if (PyObject_TypeCheck(other, &PycairoRegion_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_union(o->region,
((PycairoRegion *)other)->region);
Py_END_ALLOW_THREADS;
- } else if (PyObject_IsInstance(other,
- (PyObject*)&PycairoRectangleInt_Type) == 1) {
+ } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_union_rectangle(o->region,
&(((PycairoRectangleInt *)other)->rectangle_int));
if (!PyArg_ParseTuple (args, "O:Region.xorg", &other))
return NULL;
- if (PyObject_IsInstance(other, (PyObject*)&PycairoRegion_Type) == 1) {
+ if (PyObject_TypeCheck(other, &PycairoRegion_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_xor(o->region,
((PycairoRegion *)other)->region);
Py_END_ALLOW_THREADS;
- } else if (PyObject_IsInstance(other,
- (PyObject*)&PycairoRectangleInt_Type) == 1) {
+ } else if (PyObject_TypeCheck(other, &PycairoRectangleInt_Type)) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_xor_rectangle(o->region,
&(((PycairoRectangleInt *)other)->rectangle_int));
static PyObject *
surface_write_to_png (PycairoSurface *o, PyObject *args) {
cairo_status_t status;
+ char *name = NULL;
PyObject *file;
- if (!PyArg_ParseTuple(args, "O:Surface.write_to_png", &file))
+ if (!PyArg_ParseTuple (args, "O:Surface.write_to_png", &file))
return NULL;
- if (PyObject_TypeCheck (file, &PYCAIRO_PyFilenameBase_Type)) {
- /* filename (str or unicode) argument */
- char *name = NULL; /* the encoded filename */
-
- if (!PyArg_ParseTuple(args, PYCAIRO_ENC_TEXT_FORMAT ":Surface.write_to_png",
- Py_FileSystemDefaultEncoding, &name))
+ if (Pycairo_is_fspath (file)) {
+ if (!PyArg_ParseTuple (args, "O&:Surface.write_to_png",
+ Pycairo_fspath_converter, &name))
return NULL;
-
Py_BEGIN_ALLOW_THREADS;
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)) {
- Py_XDECREF(writer);
- PyErr_SetString(PyExc_TypeError,
-"Surface.write_to_png takes one argument which must be a filename (str), file "
-"object, or a file-like object which has a \"write\" method (like StringIO)");
+ PyMem_Free (name);
+ } else {
+ if (PyArg_ParseTuple (args, "O&:Surface.write_to_png",
+ Pycairo_writer_converter, &file)) {
+ Py_BEGIN_ALLOW_THREADS;
+ status = cairo_surface_write_to_png_stream (o->surface, _write_func,
+ file);
+ Py_END_ALLOW_THREADS;
+ } else {
+ PyErr_Clear ();
+ PyErr_SetString (PyExc_TypeError,
+ "Surface.write_to_png takes one argument which must be "
+ "a filename, file object, or a file-like object "
+ "which has a \"write\" method (like StringIO)");
return NULL;
}
- Py_DECREF(writer);
- Py_BEGIN_ALLOW_THREADS;
- status = cairo_surface_write_to_png_stream (o->surface, _write_func,
- file);
- Py_END_ALLOW_THREADS;
}
- RETURN_NULL_IF_CAIRO_ERROR(status);
+
+ RETURN_NULL_IF_CAIRO_ERROR (status);
Py_RETURN_NONE;
}
#endif /* CAIRO_HAS_PNG_FUNCTIONS */
PyObject *pyextents, *pymapped;
cairo_rectangle_int_t *extents;
cairo_surface_t *mapped_surface;
- int result;
if (!PyArg_ParseTuple(args, "O:Surface.map_to_image", &pyextents))
return NULL;
- result = PyObject_IsInstance (
- pyextents, (PyObject*)&PycairoRectangleInt_Type);
-
- if (result == -1) {
- return NULL;
- } else if (result == 1) {
+ if (PyObject_TypeCheck (pyextents, &PycairoRectangleInt_Type)) {
extents = &(((PycairoRectangleInt *)pyextents)->rectangle_int);
} else {
if (pyextents == Py_None) {
goto end;
}
ret = PYCAIRO_PyBytes_AsStringAndSize(pystr, &buffer, &str_length);
- if (ret == -1 || str_length < length) {
+ if (ret == -1 || str_length < (Py_ssize_t)length) {
PyErr_Clear();
goto end;
}
/* METH_CLASS */
static PyObject *
image_surface_create_from_png (PyTypeObject *type, PyObject *args) {
- cairo_surface_t *is;
- PyObject *reader, *file;
+ cairo_surface_t *image_surface;
+ PyObject *file;
+ char *name;
- if (!PyArg_ParseTuple(args, "O:ImageSurface.create_from_png", &file))
+ if (!PyArg_ParseTuple (args, "O:ImageSurface.create_from_png", &file))
return NULL;
- if (PyObject_TypeCheck (file, &PYCAIRO_PyFilenameBase_Type)) {
- char *name = NULL; /* the encoded filename */
-
- if (!PyArg_ParseTuple(args, PYCAIRO_ENC_TEXT_FORMAT ":Surface.create_from_png",
- Py_FileSystemDefaultEncoding, &name))
+ if (Pycairo_is_fspath (file)) {
+ if (!PyArg_ParseTuple(args, "O&:ImageSurface.create_from_png",
+ Pycairo_fspath_converter, &name))
return NULL;
Py_BEGIN_ALLOW_THREADS;
- is = cairo_image_surface_create_from_png (name);
+ image_surface = cairo_image_surface_create_from_png (name);
Py_END_ALLOW_THREADS;
-
PyMem_Free(name);
- return PycairoSurface_FromSurface (is, NULL);
- }
-
- /* file or file-like object argument */
- reader = PyObject_GetAttrString (file, "read");
- if (reader == NULL || !PyCallable_Check (reader)) {
- Py_XDECREF(reader);
- PyErr_SetString(PyExc_TypeError,
-"ImageSurface.create_from_png argument must be a filename (str), file object, "
-"or an object that has a \"read\" method (like StringIO)");
- return NULL;
+ return PycairoSurface_FromSurface (image_surface, NULL);
+ } else {
+ if (PyArg_ParseTuple (args, "O&:ImageSurface.create_from_png",
+ Pycairo_reader_converter, &file)) {
+ Py_BEGIN_ALLOW_THREADS;
+ image_surface = cairo_image_surface_create_from_png_stream (
+ _read_func, file);
+ Py_END_ALLOW_THREADS;
+ return PycairoSurface_FromSurface (image_surface, NULL);
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "ImageSurface.create_from_png argument must be a "
+ "filename (str), file object, or an object that has a "
+ "\"read\" method (like StringIO)");
+ return NULL;
+ }
}
- Py_DECREF(reader);
-
- Py_BEGIN_ALLOW_THREADS;
- is = cairo_image_surface_create_from_png_stream (_read_func, file);
- Py_END_ALLOW_THREADS;
- return PycairoSurface_FromSurface (is, NULL);
}
#endif /* CAIRO_HAS_PNG_FUNCTIONS */
static PyObject *
pdf_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
double width_in_points, height_in_points;
- PyObject *file, *writer;
+ PyObject *file;
cairo_surface_t *sfc;
+ char *name;
- if (!PyArg_ParseTuple(args, "Odd:PDFSurface.__new__",
- &file, &width_in_points, &height_in_points))
+ if (!PyArg_ParseTuple (args, "Odd:PDFSurface.__new__",
+ &file, &width_in_points, &height_in_points))
return NULL;
- if (file == Py_None) {
- Py_BEGIN_ALLOW_THREADS;
- 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, &PYCAIRO_PyFilenameBase_Type)) {
- /* filename (str or unicode) argument */
- char *name = NULL; /* the encoded filename */
-
- if (!PyArg_ParseTuple(args, PYCAIRO_ENC_TEXT_FORMAT "dd:PDFSurface.__new__",
- Py_FileSystemDefaultEncoding,
- &name, &width_in_points, &height_in_points))
+ if (Pycairo_is_fspath (file) || file == Py_None) {
+ if (!PyArg_ParseTuple (args, "O&dd:PDFSurface.__new__",
+ Pycairo_fspath_none_converter, &name,
+ &width_in_points, &height_in_points))
return NULL;
Py_BEGIN_ALLOW_THREADS;
sfc = cairo_pdf_surface_create (name, width_in_points, height_in_points);
Py_END_ALLOW_THREADS;
-
PyMem_Free(name);
return PycairoSurface_FromSurface (sfc, NULL);
+ } else {
+ if (PyArg_ParseTuple (args, "O&dd:PDFSurface.__new__",
+ Pycairo_writer_converter, &file,
+ &width_in_points, &height_in_points)) {
+ Py_BEGIN_ALLOW_THREADS;
+ sfc = cairo_pdf_surface_create_for_stream (
+ _write_func, file, width_in_points, height_in_points);
+ Py_END_ALLOW_THREADS;
+ return _surface_create_with_object (sfc, file);
+ } else {
+ PyErr_Clear ();
+ PyErr_SetString(PyExc_TypeError,
+ "PDFSurface argument 1 must be "
+ "None, or a filename (str), or "
+ "a file object, or an object that has a "
+ "\"write\" method (like StringIO).");
+ return NULL;
+ }
}
-
- /* file or file-like object argument */
- writer = PyObject_GetAttrString (file, "write");
- if (writer == NULL || !PyCallable_Check (writer)) {
- Py_XDECREF(writer);
- PyErr_SetString(PyExc_TypeError,
-"PDFSurface argument 1 must be\n"
-" None, or\n"
-" a filename (str), or\n"
-" a file object, or\n"
-" an object that has a \"write\" method (like StringIO)."
- );
- return NULL;
- }
- Py_DECREF(writer);
-
- Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_pdf_surface_create_for_stream (_write_func, file,
- width_in_points, height_in_points);
- Py_END_ALLOW_THREADS;
- return _surface_create_with_object (sfc, file);
}
static PyObject *
static PyObject *
ps_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
double width_in_points, height_in_points;
- PyObject *file, *writer;
+ PyObject *file;
cairo_surface_t *sfc;
+ char *name;
- if (!PyArg_ParseTuple(args, "Odd:PSSurface.__new__",
- &file, &width_in_points, &height_in_points))
+ if (!PyArg_ParseTuple (args, "Odd:PSSurface.__new__",
+ &file, &width_in_points, &height_in_points))
return NULL;
- if (file == Py_None) {
- Py_BEGIN_ALLOW_THREADS;
- 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, &PYCAIRO_PyFilenameBase_Type)) {
- /* filename (str or unicode) argument */
- char *name = NULL; /* the encoded filename */
-
- if (!PyArg_ParseTuple(args, PYCAIRO_ENC_TEXT_FORMAT "dd:PSSurface.__new__",
- Py_FileSystemDefaultEncoding,
- &name, &width_in_points, &height_in_points))
+ if (Pycairo_is_fspath (file) || file == Py_None) {
+ if (!PyArg_ParseTuple (args, "O&dd:PSSurface.__new__",
+ Pycairo_fspath_none_converter, &name,
+ &width_in_points, &height_in_points))
return NULL;
Py_BEGIN_ALLOW_THREADS;
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 {
+ if (PyArg_ParseTuple (args, "O&dd:PSSurface.__new__",
+ Pycairo_writer_converter, &file,
+ &width_in_points, &height_in_points)) {
+ Py_BEGIN_ALLOW_THREADS;
+ sfc = cairo_ps_surface_create_for_stream (
+ _write_func, file, width_in_points, height_in_points);
+ Py_END_ALLOW_THREADS;
+ return _surface_create_with_object (sfc, file);
+ } else {
+ PyErr_Clear ();
+ PyErr_SetString(PyExc_TypeError,
+ "PSSurface argument 1 must be "
+ "None, or a filename (str), or "
+ "a file object, or an object that has a "
+ "\"write\" method (like StringIO).");
+ return NULL;
+ }
}
- /* else: file or file-like object argument */
- writer = PyObject_GetAttrString (file, "write");
- if (writer == NULL || !PyCallable_Check (writer)) {
- Py_XDECREF(writer);
- PyErr_SetString(PyExc_TypeError,
-"PSSurface argument 1 must be\n"
-" None, or\n"
-" a filename (str), or\n"
-" a file object, or\n"
-" an object that has a \"write\" method (like StringIO)."
- );
- return NULL;
- }
- Py_DECREF(writer);
-
- Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_ps_surface_create_for_stream (_write_func, file,
- width_in_points, height_in_points);
- Py_END_ALLOW_THREADS;
- return _surface_create_with_object (sfc, file);
}
static PyObject *
static PyObject *
svg_surface_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
double width_in_points, height_in_points;
- PyObject *file, *writer;
+ PyObject *file;
cairo_surface_t *sfc;
+ char *name;
- if (!PyArg_ParseTuple(args, "Odd:SVGSurface.__new__",
- &file, &width_in_points, &height_in_points))
+ if (!PyArg_ParseTuple (args, "Odd:SVGSurface.__new__",
+ &file, &width_in_points, &height_in_points))
return NULL;
- if (file == Py_None) {
- Py_BEGIN_ALLOW_THREADS;
- 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, &PYCAIRO_PyFilenameBase_Type)) {
- /* filename (str or unicode) argument */
- char *name = NULL; /* the encoded filename */
-
- if (!PyArg_ParseTuple(args, PYCAIRO_ENC_TEXT_FORMAT "dd:SVGSurface.__new__",
- Py_FileSystemDefaultEncoding,
- &name, &width_in_points, &height_in_points))
+ if (Pycairo_is_fspath (file) || file == Py_None) {
+ if (!PyArg_ParseTuple (args, "O&dd:SVGSurface.__new__",
+ Pycairo_fspath_none_converter, &name,
+ &width_in_points, &height_in_points))
return NULL;
Py_BEGIN_ALLOW_THREADS;
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 {
+ if (PyArg_ParseTuple (args, "O&dd:SVGSurface.__new__",
+ Pycairo_writer_converter, &file,
+ &width_in_points, &height_in_points)) {
+ Py_BEGIN_ALLOW_THREADS;
+ sfc = cairo_svg_surface_create_for_stream (
+ _write_func, file, width_in_points, height_in_points);
+ Py_END_ALLOW_THREADS;
+ return _surface_create_with_object (sfc, file);
+ } else {
+ PyErr_Clear ();
+ PyErr_SetString(PyExc_TypeError,
+ "SVGSurface argument 1 must be "
+ "None, or a filename (str), or "
+ "a file object, or an object that has a "
+ "\"write\" method (like StringIO).");
+ return NULL;
+ }
}
- /* else: file or file-like object argument */
- writer = PyObject_GetAttrString (file, "write");
- if (writer == NULL || !PyCallable_Check (writer)) {
- Py_XDECREF(writer);
- PyErr_SetString(PyExc_TypeError,
-"SVGSurface argument 1 must be\n"
-" None, or\n"
-" a filename (str), or\n"
-" a file object, or\n"
-" an object that has a \"write\" method (like StringIO)."
- );
- return NULL;
- }
- Py_DECREF(writer);
-
- Py_BEGIN_ALLOW_THREADS;
- sfc = cairo_svg_surface_create_for_stream (_write_func, file,
- width_in_points, height_in_points);
- Py_END_ALLOW_THREADS;
- return _surface_create_with_object (sfc, file);
}
static PyObject *
This type only exists for documentation purposes. It represents
:obj:`python:str`/:obj:`python:unicode` under Python 2 and
:obj:`python3:str` under Python 3.
+
+
+.. class:: pathlike()
+
+ This type only exists for documentation purposes. It represents everything
+ Python allows as a filesystem path except on Windows where only ANSI paths
+ are supported. To use Unicode paths on Windows most functions take an
+ already open file object which you can create from a Unicode path and then
+ pass to pycairo instead.
+
+ .. versionadded:: 1.15.1
+ Older versions only supported a subset of :obj:`str` paths
.. class:: ScriptDevice(fobj)
:param fobj: a filename or writable file object.
- :type fobj: :obj:`text`, file or file-like object
+ :type fobj: :obj:`pathlike`, file or file-like object
Creates a output device for emitting the script, used when creating the
individual surfaces.
.. method:: write_to_png(fobj)
:param fobj: the file to write to
- :type fobj: filename (:obj:`text`), file or file-like object
+ :type fobj: filename (:obj:`pathlike`), file or file-like object
:raises: :exc:`MemoryError` if memory could not be allocated for the operation
:exc:`IOError` if an I/O error occurs while attempting to write
.. classmethod:: create_from_png(fobj)
- :param fobj: a filename, file, or file-like object of the PNG to load.
+ :param fobj:
+ a :obj:`pathlike`, file, or file-like object of the PNG to load.
:returns: a new *ImageSurface* initialized the contents to the given
PNG file.
.. 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, :obj:`text`, file or file-like object
+ :type fobj: None, :obj:`pathlike`, 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
.. 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, :obj:`text`, file or file-like object
+ :type fobj: None, :obj:`pathlike`, 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
.. 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, :obj:`text`, file or file-like object
+ :type fobj: None, :obj:`pathlike`, 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)
[flake8]
ignore=E402
-builtins=buffer
+builtins=buffer,unichr
+
+[coverage:run]
+include=
+ cairo/*
+ tests/*
from distutils.core import Extension, setup, Command, Distribution
-PYCAIRO_VERSION = '1.15.0'
+PYCAIRO_VERSION = '1.15.1'
CAIRO_VERSION_REQUIRED = '1.13.1'
XPYB_VERSION_REQUIRED = '1.3'
--- /dev/null
+# -*- coding: utf-8 -*-
+# Copyright 2017 Christoph Reiter
+#
+# 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.
+
+import os
+import sys
+
+from hypothesis.strategies import composite, sampled_from, lists, \
+ integers, binary, randoms
+
+
+class _PathLike(object):
+
+ def __init__(self, value):
+ self._value = value
+
+ def __fspath__(self):
+ return self._value
+
+
+@composite
+def fspaths(draw, allow_pathlike=True):
+ """A hypothesis strategy which gives valid path values.
+
+ Valid path values are everything which when passed to open() will not raise
+ ValueError or TypeError (but might raise OSError due to file system or
+ operating system restrictions).
+
+ Args:
+ allow_pathlike (bool):
+ If the result can be a pathlike (see :class:`os.PathLike`)
+ """
+
+ s = []
+
+ if os.name == "nt":
+ if sys.version_info[0] == 3:
+ unichr_ = chr
+ else:
+ unichr_ = unichr
+
+ hight_surrogate = integers(
+ min_value=0xD800, max_value=0xDBFF).map(lambda i: unichr_(i))
+ low_surrogate = integers(
+ min_value=0xDC00, max_value=0xDFFF).map(lambda i: unichr_(i))
+ uni_char = integers(
+ min_value=1, max_value=sys.maxunicode).map(lambda i: unichr_(i))
+ any_char = sampled_from([
+ draw(uni_char), draw(hight_surrogate), draw(low_surrogate)])
+ any_text = lists(any_char).map(lambda l: u"".join(l))
+
+ windows_path_text = any_text
+ s.append(windows_path_text)
+
+ def text_to_bytes(path):
+ fs_enc = sys.getfilesystemencoding()
+ try:
+ return path.encode(fs_enc, "surrogatepass")
+ except UnicodeEncodeError:
+ return path.encode(fs_enc, "replace")
+
+ windows_path_bytes = windows_path_text.map(text_to_bytes)
+ s.append(windows_path_bytes)
+ else:
+ unix_path_bytes = binary().map(lambda b: b.replace(b"\x00", b" "))
+ s.append(unix_path_bytes)
+
+ if sys.version_info[0] == 3:
+ unix_path_text = unix_path_bytes.map(
+ lambda b: b.decode(
+ sys.getfilesystemencoding(), "surrogateescape"))
+ else:
+ unix_path_text = unix_path_bytes.map(
+ lambda b: b.decode(
+ sys.getfilesystemencoding(), "ignore"))
+
+ r = draw(randoms())
+
+ def shuffle_text(t):
+ l = list(t)
+ r.shuffle(l)
+ return u"".join(l)
+
+ s.append(unix_path_text.map(shuffle_text))
+
+ result = draw(sampled_from(list(map(draw, s))))
+
+ if allow_pathlike and hasattr(os, "fspath"):
+ result = draw(sampled_from([result, _PathLike(result)]))
+
+ return result
import pytest
import py.test as test
-try:
- long
-except NameError:
- long = int
+
+def test_version():
+ cairo.cairo_version()
+ cairo.cairo_version_string()
def test_show_unicode_text():
shutil.rmtree(dirname)
-def test_ps_surface_level_to_string():
- level_id = cairo.PSSurface.level_to_string(cairo.PS_LEVEL_2)
- assert isinstance(level_id, str)
- assert cairo.PSSurface.ps_level_to_string(cairo.PS_LEVEL_2) == level_id
-
-
def test_surface_has_show_text_glyphs():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
assert not surface.has_show_text_glyphs()
surface.has_show_text_glyphs()
-def test_surface_create_for_rectangle():
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
- new = surface.create_for_rectangle(0, 0, 10, 10)
- assert new
- assert isinstance(new, cairo.Surface)
-
- with pytest.raises(cairo.Error) as excinfo:
- surface.create_for_rectangle(0, 0, 10, -1)
- assert excinfo.value.status == cairo.STATUS_INVALID_SIZE
-
-
-def test_context_in_clip():
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
- context = cairo.Context(surface)
- assert context.in_clip(50, 50)
- context.clip()
- assert not context.in_clip(50, 50)
- context.reset_clip()
- assert context.in_clip(50, 50)
-
-
-def test_surface_create_similar_image():
- surface = cairo.PDFSurface(None, 1, 1)
- image = surface.create_similar_image(cairo.FORMAT_ARGB32, 24, 42)
- assert image
- assert isinstance(image, cairo.ImageSurface)
- del surface
- assert image.get_width() == 24
- assert image.get_height() == 42
-
-
-def test_pdf_surface_restrict_to_version():
- surface = cairo.PDFSurface(None, 10, 10)
- surface.restrict_to_version(cairo.PDF_VERSION_1_4)
- surface.finish()
- with pytest.raises(cairo.Error):
- surface.restrict_to_version(cairo.PDF_VERSION_1_5)
-
-
-def test_pdf_version_to_string():
- ver = cairo.PDFSurface.version_to_string(cairo.PDF_VERSION_1_4)
- assert ver and isinstance(ver, str)
- with pytest.raises(ValueError):
- cairo.PDFSurface.version_to_string(-1)
-
-
def test_context():
- if cairo.HAS_IMAGE_SURFACE:
- f, w, h = cairo.FORMAT_ARGB32, 100, 100
- s = cairo.ImageSurface(f, w, h)
- ctx = cairo.Context(s)
- ctx.set_source_rgb(1.0, 1.0, 1.0)
- ctx.set_operator(cairo.OPERATOR_SOURCE)
- ctx.paint()
-
-
-def test_matrix():
- m = cairo.Matrix()
- m.rotate(10)
- m.scale(1.5, 2.5)
- m.translate(10, 20)
-
- with pytest.raises(TypeError):
- m * 42
-
- with pytest.raises(TypeError):
- m + 42
-
- assert m != 42
- assert m == m
- assert m != cairo.Matrix()
-
-
-def test_matrix_properties():
- m = cairo.Matrix(*range(6))
- assert [m.xx, m.yx, m.xy, m.yy, m.x0, m.y0] == list(range(6))
- m.xx = 42
- assert m.xx == 42
- m.scale(2, 2)
- assert m.xx == 84
-
-
-def test_path():
- # AttributeError: 'module' object has no attribute 'Path'
- test.raises(AttributeError, "p = cairo.Path()")
- # see examples/warpedtext.py
-
-
-def test_pattern():
- # TypeError: The Pattern type cannot be instantiated
- test.raises(TypeError, "p = cairo.Pattern()")
-
- r, g, b, a = 0.1, 0.2, 0.3, 0.4
- p = cairo.SolidPattern(r, g, b, a)
- assert p.get_rgba() == (r, g, b, a)
-
- # SurfacePattern
-
- # TypeError: The Gradient type cannot be instantiated
- test.raises(TypeError, "p = cairo.Gradient()")
-
- x0, y0, x1, y1 = 0.0, 0.0, 0.0, 1.0
- p = cairo.LinearGradient(x0, y0, x1, y1)
- assert p.get_linear_points() == (x0, y0, x1, y1)
- p.add_color_stop_rgba(1, 0, 0, 0, 1)
- p.add_color_stop_rgba(0, 1, 1, 1, 1)
-
- cx0, cy0, radius0, cx1, cy1, radius1 = 1.0, 1.0, 1.0, 2.0, 2.0, 1.0
- p = cairo.RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1)
- assert p.get_radial_circles() == (cx0, cy0, radius0, cx1, cy1, radius1)
- p.add_color_stop_rgba(0, 1, 1, 1, 1)
- p.add_color_stop_rgba(1, 0, 0, 0, 1)
-
-
-def test_pattern_filter():
- pattern = cairo.SolidPattern(1, 2, 3)
- assert pattern.get_filter() == cairo.FILTER_GOOD
- pattern.set_filter(cairo.FILTER_NEAREST)
- assert pattern.get_filter() == cairo.FILTER_NEAREST
+ f, w, h = cairo.FORMAT_ARGB32, 100, 100
+ s = cairo.ImageSurface(f, w, h)
+ ctx = cairo.Context(s)
+ ctx.set_source_rgb(1.0, 1.0, 1.0)
+ ctx.set_operator(cairo.OPERATOR_SOURCE)
+ ctx.paint()
def test_surface():
# TypeError: The Surface type cannot be instantiated
test.raises(TypeError, "s = cairo.Surface()")
- if cairo.HAS_IMAGE_SURFACE:
- f, w, h = cairo.FORMAT_ARGB32, 100, 100
- s = cairo.ImageSurface(f, w, h)
- assert s.get_format() == f
- assert s.get_width() == w
- assert s.get_height() == h
+ f, w, h = cairo.FORMAT_ARGB32, 100, 100
+ s = cairo.ImageSurface(f, w, h)
+ assert s.get_format() == f
+ assert s.get_width() == w
+ assert s.get_height() == h
- if cairo.HAS_PDF_SURFACE:
- f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
- s = cairo.PDFSurface(f, w, h)
+ f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
+ s = cairo.PDFSurface(f, w, h)
- if cairo.HAS_PS_SURFACE:
- f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
- s = cairo.PSSurface(f, w, h)
+ f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
+ s = cairo.PSSurface(f, w, h)
- if cairo.HAS_RECORDING_SURFACE:
- s = cairo.RecordingSurface(cairo.CONTENT_COLOR, None)
- s = cairo.RecordingSurface(cairo.CONTENT_COLOR, (1, 1, 10, 10))
+ s = cairo.RecordingSurface(cairo.CONTENT_COLOR, None)
+ s = cairo.RecordingSurface(cairo.CONTENT_COLOR, (1, 1, 10, 10))
- if cairo.HAS_SVG_SURFACE:
- f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
- s = cairo.SVGSurface(f, w, h)
+ f, w, h = tfi.TemporaryFile(mode='w+b'), 100, 100
+ s = cairo.SVGSurface(f, w, h)
def test_surface_destroy_before_context():
assert newbuf[0:1] == b"\x00"
-def test_image_surface_create_for_data():
- format_ = cairo.FORMAT_ARGB32
- surface = cairo.ImageSurface(format_, 3, 3)
- ctx = cairo.Context(surface)
- ctx.paint()
- surface.flush()
- buf = surface.get_data()
-
- new = cairo.ImageSurface.create_for_data(buf, format_, 3, 3)
- assert new.get_data() == buf
-
- with pytest.raises(ValueError):
- cairo.ImageSurface.create_for_data(buf, format_, 3, -1)
- with pytest.raises(ValueError):
- cairo.ImageSurface.create_for_data(buf, format_, -1, 3)
-
- with pytest.raises(cairo.Error) as excinfo:
- cairo.ImageSurface.create_for_data(buf, format_, 3, 3, 3)
-
- assert excinfo.value.status == cairo.STATUS_INVALID_STRIDE
-
-
def test_surface_file_obj_error():
class Fail(object):
assert cairo.SVG_VERSION_1_2 == 1
-def test_surface_get_set_mime_data():
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- assert surface.get_mime_data("foo") is None
- assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None
-
- surface.set_mime_data("foo", b"bar")
- assert surface.get_mime_data("foo") == b"bar"
- surface.set_mime_data("foo", None)
- assert surface.get_mime_data("foo") is None
-
- surface.set_mime_data(cairo.MIME_TYPE_JPEG, b"\x00quux\x00")
- assert surface.get_mime_data(cairo.MIME_TYPE_JPEG)[:] == b"\x00quux\x00"
- surface.set_mime_data(cairo.MIME_TYPE_JPEG, None)
- assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None
-
-
def test_surface_get_set_mime_data_references():
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
if sys.version_info[0] == 2:
assert sys.getrefcount(x) == 2
-def test_supports_mime_type():
- surface = cairo.PDFSurface(None, 3, 3)
- assert surface.supports_mime_type(cairo.MIME_TYPE_JPEG)
- assert not surface.supports_mime_type("nope")
-
-
-def test_font_options_copy_equal():
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- font_options = surface.get_font_options()
- font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
- new = font_options.copy()
- assert font_options.equal(new)
- assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT
- font_options.set_hint_metrics(cairo.HINT_METRICS_ON)
- assert not font_options.equal(new)
- assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT
-
-
-def test_font_options_hash():
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- font_options = surface.get_font_options()
- assert font_options.hash() == font_options.hash()
- assert isinstance(font_options.hash(), long)
-
-
-def test_font_options_merge():
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- font_options = surface.get_font_options()
- font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
- new = font_options.copy()
- new.set_hint_metrics(cairo.HINT_METRICS_ON)
- font_options.merge(new)
- assert font_options.get_hint_metrics() == cairo.HINT_METRICS_ON
-
-
-def test_font_options_hashable_protocol():
- # make sure __eq__ and __ne__ work
- surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
- font_options = surface.get_font_options()
- assert font_options == font_options.copy()
- assert not font_options != font_options.copy()
- font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
- different = font_options.copy()
- different.set_hint_metrics(cairo.HINT_METRICS_ON)
- assert font_options != different
- assert not font_options == different
- assert font_options != object()
-
- # make sure the other operators are undefined
- if sys.version_info[0] == 3:
- with pytest.raises(TypeError):
- font_options < font_options
- assert font_options.__gt__(font_options) is NotImplemented
-
-
def test_surface_mime_data_for_pdf():
jpeg_bytes = zlib.decompress(base64.b64decode(
b'eJz7f+P/AwYBLzdPNwZGRkYGDyBk+H+bwRnEowj8P8TAzcHACDJHkOH/EQYRIBsV'
context.paint()
surface.finish()
assert jpeg_bytes in file_like.getvalue()
-
-
-def test_svg_version_to_string():
- ver = cairo.SVGSurface.version_to_string(cairo.SVG_VERSION_1_1)
- assert ver and isinstance(ver, str)
- with pytest.raises(ValueError):
- cairo.SVGSurface.version_to_string(-1)
-
-
-def test_svg_surface_restrict_to_version():
- surface = cairo.SVGSurface(None, 10, 10)
- surface.restrict_to_version(cairo.SVG_VERSION_1_1)
- surface.finish()
- with pytest.raises(cairo.Error):
- surface.restrict_to_version(cairo.SVG_VERSION_1_2)
return cairo.Context(surface)
-def text_cmp_hash(context):
+def test_cmp_hash(context):
other = cairo.Context(context.get_target())
assert context != other
hash(context)
with pytest.raises(TypeError):
context.show_text_glyphs("", glyphs, object(), flags)
+
+
+def test_append_path(context):
+ context.line_to(1, 2)
+ p = context.copy_path()
+ context.new_path()
+ context.append_path(p)
+ assert str(context.copy_path()) == str(p)
+ with pytest.raises(TypeError):
+ context.append_path(object())
+
+
+def test_arc(context):
+ assert not list(context.copy_path())
+ context.arc(0, 0, 0, 0, 0)
+ assert list(context.copy_path())
+ with pytest.raises(TypeError):
+ context.arc(object())
+
+
+def test_arc_negative(context):
+ assert not list(context.copy_path())
+ context.arc_negative(0, 0, 0, 0, 0)
+ assert list(context.copy_path())
+ with pytest.raises(TypeError):
+ context.arc_negative(object())
+
+
+def test_clip_extents(context):
+ assert context.clip_extents() == (0.0, 0.0, 42.0, 42.0)
+
+
+def test_in_clip():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
+ context = cairo.Context(surface)
+ assert context.in_clip(50, 50)
+ context.clip()
+ assert not context.in_clip(50, 50)
+ context.reset_clip()
+ assert context.in_clip(50, 50)
+
+ with pytest.raises(TypeError):
+ context.in_clip(None, None)
+
+
+def test_device_to_user(context):
+ assert context.device_to_user(0, 0) == (0, 0)
+ with pytest.raises(TypeError):
+ context.device_to_user(None, None)
+
+
+def test_device_to_user_distance(context):
+ assert context.device_to_user_distance(0, 0) == (0, 0)
+ with pytest.raises(TypeError):
+ context.device_to_user_distance(None, None)
+
+
+def test_fill_extents(context):
+ context.line_to(1, 1)
+ context.line_to(1, 0)
+ context.line_to(0, 0)
+ context.line_to(0, 1)
+ context.line_to(1, 1)
+ assert context.fill_extents() == (0, 0, 1, 1)
+
+
+def test_curve_to(context):
+ with pytest.raises(TypeError):
+ context.curve_to(1, 2, 3, 4, 5, object())
+
+
+def test_set_get_dash(context):
+ assert context.get_dash() == ((), 0)
+ assert context.get_dash_count() == 0
+
+ context.set_dash([0, 1, 2, 3], 10)
+ assert context.get_dash() == ((0.0, 1.0, 2.0, 3.0), 4.0)
+ assert context.get_dash_count() == 4
+
+ with pytest.raises(TypeError):
+ context.set_dash()
+
+ with pytest.raises(TypeError):
+ context.set_dash(1, 10)
+
+ with pytest.raises(TypeError):
+ context.set_dash([object()], 1)
+
+
+def test_glyph_extents(context):
+ with pytest.raises(TypeError):
+ context.glyph_extents(None)
+ with pytest.raises(TypeError):
+ context.glyph_extents()
+
+
+def test_glyph_path(context):
+ with pytest.raises(TypeError):
+ context.glyph_path(None)
+ with pytest.raises(TypeError):
+ context.glyph_path()
+
+
+def test_in_stroke(context):
+ context.line_to(0, 0)
+ context.line_to(1, 1)
+ assert context.in_stroke(0, 0)
+ assert not context.in_stroke(0, 2)
+ with pytest.raises(TypeError):
+ context.in_stroke(object(), 0)
+
+
+def test_current_point(context):
+ assert not context.has_current_point()
+ assert context.get_current_point() == (0, 0)
+ context.move_to(10, 10)
+ assert context.has_current_point()
+ assert context.get_current_point() == (10, 10)
+
+
+def test_in_fill(context):
+ assert not context.in_fill(0.1, 0.1)
+ with pytest.raises(TypeError):
+ context.in_fill(0.1, object())
+
+
+def test_line_to(context):
+ with pytest.raises(TypeError):
+ context.line_to(0.1, object())
+
+
+def test_mask(context):
+ pattern = cairo.SolidPattern(0, 0, 0)
+ context.mask(pattern)
+ with pytest.raises(TypeError):
+ context.mask(object())
+
+
+def test_mask_surface(context):
+ context.mask_surface(context.get_target(), 0, 0)
+ with pytest.raises(TypeError):
+ context.mask_surface(object(), 0, 0)
+
+
+def test_paint_with_alpha(context):
+ context.paint_with_alpha(0.5)
+ with pytest.raises(TypeError):
+ context.paint_with_alpha(object())
+
+
+def test_path_extents(context):
+ context.line_to(1, 1)
+ context.line_to(1, 0)
+ context.line_to(0, 0)
+ context.line_to(0, 1)
+ context.line_to(1, 1)
+ assert context.path_extents() == (0.0, 0.0, 1.0, 1.0)
+
+
+def test_push_pop_group(context):
+ context.push_group()
+ context.pop_group()
+
+ context.push_group()
+ context.pop_group_to_source()
+
+ with pytest.raises(TypeError):
+ context.push_group_with_content(object())
+
+ context.push_group_with_content(cairo.Content.COLOR)
+ context.pop_group()
+
+ with pytest.raises(cairo.Error):
+ context.pop_group()
+
+
+def test_rectangle(context):
+ context.rectangle(1, 2, 4, 5)
+ assert context.path_extents() == (1.0, 2.0, 5.0, 7.0)
+ with pytest.raises(TypeError):
+ context.rectangle(1, 2, 3, object())
+
+
+def test_rotate(context):
+ context.rotate(0.3)
+ with pytest.raises(TypeError):
+ context.rotate(object())
+
+
+def test_rel_curve_to(context):
+ context.line_to(0, 0)
+ context.rel_curve_to(0, 0, 0, 0, 0, 0)
+ with pytest.raises(TypeError):
+ context.rel_curve_to(object(), 0, 0, 0, 0, 0)
+
+
+def test_move_to(context):
+ context.move_to(10, 10)
+ assert context.get_current_point() == (10, 10)
+ with pytest.raises(TypeError):
+ context.move_to(object(), 0)
+
+
+def test_rel_line_to(context):
+ context.line_to(0, 0)
+ context.rel_line_to(1, 1)
+ with pytest.raises(TypeError):
+ context.rel_line_to(object(), 0)
+
+
+def test_rel_move_to(context):
+ context.line_to(0, 0)
+ context.rel_move_to(1, 1)
+ with pytest.raises(TypeError):
+ context.rel_move_to(object(), 0)
+
+
+def test_save_restore(context):
+ context.save()
+ context.restore()
+
+
+def test_scale(context):
+ context.scale(2, 2)
+ with pytest.raises(TypeError):
+ context.scale(object(), 0)
+
+
+def test_select_font_face(context):
+ context.select_font_face("")
+ with pytest.raises(TypeError):
+ context.select_font_face(None)
+
+
+def test_set_antialias(context):
+ context.set_antialias(cairo.Antialias.SUBPIXEL)
+ assert context.get_antialias() == cairo.Antialias.SUBPIXEL
+ with pytest.raises(TypeError):
+ context.set_antialias(object())
+
+
+def test_set_fill_rule(context):
+ context.set_fill_rule(cairo.FillRule.EVEN_ODD)
+ assert context.get_fill_rule() == cairo.FillRule.EVEN_ODD
+ with pytest.raises(TypeError):
+ context.set_fill_rule(object())
+
+
+def test_set_font_face(context):
+ assert context.get_font_face()
+ context.set_font_face(None)
+ assert context.get_font_face()
+ ff = context.get_font_face()
+ context.set_font_face(ff)
+ assert context.get_font_face() == ff
+ with pytest.raises(TypeError):
+ context.set_font_face(object())
+
+
+def test_set_font_matrix(context):
+ m = cairo.Matrix()
+ context.set_font_matrix(m)
+ assert context.get_font_matrix() == m
+ with pytest.raises(TypeError):
+ context.set_font_matrix(object())
+
+
+def test_set_line_cap(context):
+ context.set_line_cap(cairo.LineCap.SQUARE)
+ assert context.get_line_cap() == cairo.LineCap.SQUARE
+ with pytest.raises(TypeError):
+ context.set_line_cap(object())
+
+
+def test_set_line_join(context):
+ context.set_line_join(cairo.LineJoin.BEVEL)
+ assert context.get_line_join() == cairo.LineJoin.BEVEL
+ with pytest.raises(TypeError):
+ context.set_line_join(object())
+
+
+def test_set_line_width(context):
+ context.set_line_width(42)
+ assert context.get_line_width() == 42
+ with pytest.raises(TypeError):
+ context.set_line_width(object())
+
+
+def test_set_matrix(context):
+ m = cairo.Matrix()
+ context.set_matrix(m)
+ assert context.get_matrix() == m
+ with pytest.raises(TypeError):
+ context.set_matrix(object())
+
+
+def test_set_miter_limit(context):
+ context.set_miter_limit(42)
+ assert context.get_miter_limit() == 42
+ with pytest.raises(TypeError):
+ context.set_miter_limit(object())
+
+
+def test_set_scaled_font(context):
+ context.set_scaled_font(context.get_scaled_font())
+ with pytest.raises(TypeError):
+ context.set_scaled_font(object())
+
+
+def test_set_font_options(context):
+ context.set_font_options(context.get_font_options())
+ with pytest.raises(TypeError):
+ context.set_font_options(object())
+
+
+def test_set_font_size(context):
+ context.set_font_size(42)
+ assert context.get_font_matrix() == cairo.Matrix(42, 0, 0, 42, 0, 0)
+ with pytest.raises(TypeError):
+ context.set_font_size(object())
+
+
+def test_set_source(context):
+ p = cairo.SolidPattern(0, 0, 0)
+ context.set_source(p)
+ assert context.get_source() == p
+ with pytest.raises(TypeError):
+ context.set_source(object())
+
+
+def test_set_source_rgb(context):
+ with pytest.raises(TypeError):
+ context.set_source_rgb(1, 1, object())
+
+
+def test_get_source_rgba(context):
+ context.set_source_rgba(1, 1, 1)
+ assert context.get_source().get_rgba() == (1, 1, 1, 1)
+ context.set_source_rgba(1, 1, 1, 0.5)
+ assert context.get_source().get_rgba() == (1, 1, 1, 0.5)
+ with pytest.raises(TypeError):
+ context.set_source_rgba(1, 1, object())
+
+
+def test_set_source_surface(context):
+ with pytest.raises(TypeError):
+ context.set_source_surface(object())
+
+
+def test_set_tolerance(context):
+ context.set_tolerance(42)
+ assert context.get_tolerance() == 42
+ with pytest.raises(TypeError):
+ context.set_tolerance(object())
+
+
+def test_show_glyphs(context):
+ with pytest.raises(TypeError):
+ context.show_glyphs()
+
+ with pytest.raises(TypeError):
+ context.show_glyphs(object())
+
+ context.show_glyphs([], 0)
+
+
+def test_show_text(context):
+ with pytest.raises(TypeError):
+ context.show_text()
+
+
+def test_stroke_extents(context):
+ assert context.stroke_extents() == (0.0, 0.0, 0.0, 0.0)
+
+
+def test_text_extents(context):
+ with pytest.raises(TypeError):
+ context.text_extents()
+
+
+def test_text_path(context):
+ context.text_path("foo")
+ with pytest.raises(TypeError):
+ context.text_path(object())
+
+
+def test_transform(context):
+ context.transform(cairo.Matrix())
+ with pytest.raises(TypeError):
+ context.transform(object())
+
+
+def test_translate(context):
+ context.translate(0.5, 0.5)
+ with pytest.raises(TypeError):
+ context.translate(0.5, object())
+
+
+def test_user_to_device(context):
+ assert context.user_to_device(0, 0) == (0, 0)
+ with pytest.raises(TypeError):
+ context.user_to_device(0, object())
+
+
+def test_user_to_device_distance(context):
+ assert context.user_to_device_distance(0, 0) == (0, 0)
+ with pytest.raises(TypeError):
+ context.user_to_device_distance(0, object())
+
+
+def test_context(context):
+ with pytest.raises(TypeError):
+ cairo.Context(None)
+
+ assert not context == object()
+
+
+def test_simple(context):
+ context.clip_preserve()
+ context.copy_page()
+ context.copy_path_flat()
+ context.fill()
+ context.fill_preserve()
+ context.font_extents()
+ context.identity_matrix()
+ context.new_sub_path()
+ context.show_page()
+ context.stroke_preserve()
+
+ assert context.get_dash_count() == 0
+ assert isinstance(context.get_font_matrix(), cairo.Matrix)
+
+ assert context.get_group_target()
+ context.get_line_width()
+
+ assert isinstance(context.get_tolerance(), float)
+ assert isinstance(context.get_miter_limit(), float)
+ assert isinstance(context.get_matrix(), cairo.Matrix)
# -*- coding: utf-8 -*-
+import os
import io
+import tempfile
+
import cairo
import pytest
assert dev == other
assert not dev != other
assert hash(dev) == hash(other)
+ assert dev != object()
def test_get_device():
with pytest.raises(TypeError):
cairo.ScriptDevice(None)
+ with pytest.raises(TypeError):
+ cairo.ScriptDevice()
+
+ with pytest.raises((ValueError, TypeError)):
+ cairo.ScriptDevice("\x00")
+
def test_script_device_mode():
assert hasattr(cairo, "ScriptMode")
assert mode == cairo.ScriptMode.ASCII
dev.set_mode(cairo.ScriptMode.BINARY)
assert dev.get_mode() == cairo.ScriptMode.BINARY
+ with pytest.raises(TypeError):
+ dev.set_mode(object())
def test_script_device_write_comment():
dev.flush()
assert b"pycairo foo" in f.getvalue()
assert b"pycairo bar" in f.getvalue()
+ with pytest.raises(TypeError):
+ dev.write_comment(object())
def test_from_recording_surface():
# No None allowed
with pytest.raises(TypeError):
dev.from_recording_surface(None)
+
+
+def test_device_acquire():
+ f = io.BytesIO()
+ dev = cairo.ScriptDevice(f)
+ dev.acquire()
+ dev.release()
+
+
+def test_script_device_to_path():
+ fd, fname = tempfile.mkstemp()
+ os.close(fd)
+ try:
+ cairo.ScriptDevice(fname).finish()
+ finally:
+ os.unlink(fname)
t()
with pytest.raises(TypeError):
+ t(object())
+
+ with pytest.raises(TypeError):
type("foo", (t,), {})
assert hasattr(t, "DEFAULT")
assert e.value.status == cairo.Status.WRITE_ERROR
assert type(e.value).__name__ == "cairo.IOError"
+ err = e.value
+ err.status = cairo.Status.DEVICE_FINISHED
+ assert err.status == cairo.Status.DEVICE_FINISHED
+
+ with pytest.raises(TypeError):
+ del err.status
+
+ str(cairo.Error())
+
def test_error_context():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
+import sys
+
import cairo
import pytest
+try:
+ long
+except NameError:
+ long = int
+
+
+@pytest.fixture
+def font_options():
+ surface = cairo.ImageSurface(0, 10, 10)
+ return surface.get_font_options()
+
+
+@pytest.fixture
+def font_face():
+ surface = cairo.ImageSurface(0, 10, 10)
+ context = cairo.Context(surface)
+ return context.get_font_face()
+
+
+@pytest.fixture
+def scaled_font(font_face, font_options):
+ return cairo.ScaledFont(
+ font_face, cairo.Matrix(), cairo.Matrix(), font_options)
+
+
+def test_font_options():
+ assert isinstance(cairo.FontOptions(), cairo.FontOptions)
+ with pytest.raises(TypeError):
+ cairo.FontOptions(object())
+
+
+def test_font_options_copy_equal():
+ surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
+ font_options = surface.get_font_options()
+ font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
+ new = font_options.copy()
+ assert font_options.equal(new)
+ assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT
+ font_options.set_hint_metrics(cairo.HINT_METRICS_ON)
+ assert not font_options.equal(new)
+ assert new.get_hint_metrics() == cairo.HINT_METRICS_DEFAULT
+ with pytest.raises(TypeError):
+ font_options.equal(object())
+
+
+def test_font_options_hash():
+ surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
+ font_options = surface.get_font_options()
+ assert font_options.hash() == font_options.hash()
+ assert isinstance(font_options.hash(), long)
+
+
+def test_font_options_merge():
+ surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
+ font_options = surface.get_font_options()
+ font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
+ new = font_options.copy()
+ new.set_hint_metrics(cairo.HINT_METRICS_ON)
+ font_options.merge(new)
+ assert font_options.get_hint_metrics() == cairo.HINT_METRICS_ON
+ with pytest.raises(TypeError):
+ font_options.merge(object())
+
+
+def test_font_options_hashable_protocol():
+ # make sure __eq__ and __ne__ work
+ surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
+ font_options = surface.get_font_options()
+ assert font_options == font_options.copy()
+ assert not font_options != font_options.copy()
+ font_options.set_hint_metrics(cairo.HINT_METRICS_DEFAULT)
+ different = font_options.copy()
+ different.set_hint_metrics(cairo.HINT_METRICS_ON)
+ assert font_options != different
+ assert not font_options == different
+ assert font_options != object()
+
+ # make sure the other operators are undefined
+ if sys.version_info[0] == 3:
+ with pytest.raises(TypeError):
+ font_options < font_options
+ assert font_options.__gt__(font_options) is NotImplemented
+
+
+def test_font_options_set_antialias(font_options):
+ font_options.set_antialias(cairo.Antialias.GRAY)
+ assert font_options.get_antialias() == cairo.Antialias.GRAY
+ with pytest.raises(TypeError):
+ font_options.set_antialias(object())
+
+
+def test_font_options_set_hint_metrics(font_options):
+ font_options.set_hint_metrics(cairo.HintMetrics.OFF)
+ assert font_options.get_hint_metrics() == cairo.HintMetrics.OFF
+ with pytest.raises(TypeError):
+ font_options.set_hint_metrics(object())
+
+
+def test_font_options_set_hint_style(font_options):
+ font_options.set_hint_style(cairo.HintStyle.SLIGHT)
+ assert font_options.get_hint_style() == cairo.HintStyle.SLIGHT
+ with pytest.raises(TypeError):
+ font_options.set_hint_style(object())
+
+
+def test_font_options_set_subpixel_order(font_options):
+ font_options.set_subpixel_order(cairo.SubpixelOrder.VRGB)
+ assert font_options.get_subpixel_order() == cairo.SubpixelOrder.VRGB
+ with pytest.raises(TypeError):
+ font_options.set_subpixel_order(object())
+
+
+def test_font_face(font_face):
+ with pytest.raises(TypeError):
+ cairo.FontFace()
+
+ assert font_face == font_face
+ assert font_face != object()
+
+
def test_font_face_cmp_hash():
surface = cairo.ImageSurface(0, 10, 10)
context = cairo.Context(surface)
hash(fo)
+def test_scaled_font(scaled_font):
+ with pytest.raises(TypeError):
+ cairo.ScaledFont()
+
+ assert scaled_font == scaled_font
+ assert scaled_font != object()
+
+
+def test_scaled_font_extents(scaled_font):
+ assert isinstance(scaled_font.extents(), tuple)
+
+
+def test_scaled_font_get_font_face(scaled_font):
+ assert isinstance(scaled_font.get_font_face(), cairo.FontFace)
+
+
+def test_scaled_font_get_scale_matrix(scaled_font):
+ assert isinstance(scaled_font.get_scale_matrix(), cairo.Matrix)
+
+
+def test_scaled_font_text_extents(scaled_font):
+ with pytest.raises(TypeError):
+ scaled_font.text_extents(object())
+
+
+def test_scaled_font_glyph_extents(scaled_font):
+ with pytest.raises(TypeError):
+ scaled_font.glyph_extents(object())
+ with pytest.raises(TypeError):
+ scaled_font.glyph_extents([object()])
+ with pytest.raises(TypeError):
+ scaled_font.glyph_extents()
+
+
+def test_toy_font_face():
+ with pytest.raises(TypeError):
+ cairo.ToyFontFace(object())
+
+
+def test_toy_font_get_family():
+ font_face = cairo.ToyFontFace("")
+ assert isinstance(font_face.get_family(), str)
+
+
def test_toy_font_get_slant():
font_face = cairo.ToyFontFace("")
assert font_face.get_slant() == cairo.FontSlant.NORMAL
assert isinstance(font_face.get_weight(), cairo.FontWeight)
-@pytest.fixture
-def font_options():
- surface = cairo.ImageSurface(0, 10, 10)
- return surface.get_font_options()
-
-
def test_font_options_get_antialias(font_options):
assert font_options.get_antialias() == cairo.Antialias.DEFAULT
assert isinstance(font_options.get_antialias(), cairo.Antialias)
assert len(glyphs) == 3
assert glyphs[0] != glyphs[1]
assert len(clusters) == 3
+
+ with pytest.raises(TypeError):
+ sf.text_to_glyphs(object())
assert context.glyph_extents([g])
context.glyph_path([g])
context.show_glyphs([(0, 0, 0)])
+
+ with pytest.raises(TypeError):
+ context.glyph_path([object()])
# -*- coding: utf-8 -*-
import math
+import os
+import sys
import pytest
import cairo
+import tempfile
pytest.importorskip("hypothesis")
-from hypothesis import given, strategies, assume
+from hypothesis import given, strategies, assume, settings
+from hypothesis.strategies import floats, integers
+
+from .hypothesis_fspaths import fspaths
+
+
+@pytest.fixture(scope='module')
+def tempdir_path():
+ dir_ = tempfile.mkdtemp()
+ try:
+ yield dir_
+ finally:
+ os.rmdir(dir_)
+
+
+def _to_temp_path(tempdir_path, p):
+ basename = os.path.basename(p)
+ if sys.version_info[0] == 3 and isinstance(basename, bytes):
+ tempdir_path = os.fsencode(tempdir_path)
+ res = os.path.join(tempdir_path, basename)
+ if not isinstance(p, (type(u""), type(b""))):
+ res = type(p)(res)
+ return res
+
+
+@given(path=fspaths())
+@settings(max_examples=5000)
+def test_fspaths(tempdir_path, path):
+ p = _to_temp_path(tempdir_path, path)
+
+ # filter out "."
+ assert not os.listdir(tempdir_path)
+ if os.path.exists(p):
+ return
+
+ # cairo uses fopen, which only supports ANSI paths under Windows.
+ # Make sure we fail if not ANSI and succeed otherwise
+ is_valid = True
+ if os.name == "nt":
+ temp = os.path.join(p)
+ if isinstance(temp, type(b"")):
+ if sys.version_info[0] == 3:
+ temp = os.fsdecode(temp)
+ else:
+ temp = temp.decode(sys.getfilesystemencoding(), "strict")
+ if isinstance(temp, type(u"")):
+ try:
+ if temp.encode("mbcs").decode("mbcs") != temp:
+ is_valid = False
+ except UnicodeEncodeError:
+ is_valid = False
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ try:
+ surface.write_to_png(p)
+ except (TypeError, ValueError):
+ assert not is_valid
+ assert not os.path.exists(p)
+ except cairo.Error:
+ assert not os.path.exists(p)
+ else:
+ assert is_valid
+ assert os.path.exists(p), os.listdir(tempdir_path)
+ os.unlink(p)
@given(strategies.floats(), strategies.floats())
surface.create_for_rectangle(x, y, w, h)
except cairo.Error as e:
assert e.status == cairo.Status.INVALID_SIZE
+
+
+@given(integers(), floats(allow_nan=False), floats(allow_nan=False))
+def test_glyph(index, x, y):
+ try:
+ g = cairo.Glyph(index, x, y)
+ except OverflowError:
+ pass
+ else:
+ assert g.index == index
+ assert g.x == x
+ assert g.y == y
+
+
+@given(floats(allow_nan=False), floats(allow_nan=False),
+ floats(allow_nan=False), floats(allow_nan=False))
+def test_rectangle(x, y, width, height):
+ r = cairo.Rectangle(x, y, width, height)
+ assert r.x == x
+ assert r.y == y
+ assert r.width == width
+ assert r.height == height
+
+
+@given(integers(), integers())
+def test_text_cluster(num_bytes, num_glyphs):
+ try:
+ tc = cairo.TextCluster(num_bytes, num_glyphs)
+ except OverflowError:
+ pass
+ else:
+ assert tc.num_bytes == num_bytes
+ assert tc.num_glyphs == num_glyphs
+
+
+@given(floats(allow_nan=False), floats(allow_nan=False),
+ floats(allow_nan=False), floats(allow_nan=False),
+ floats(allow_nan=False), floats(allow_nan=False))
+def test_text_extents(x_bearing, y_bearing, width, height, x_advance,
+ y_advance):
+ te = cairo.TextExtents(x_bearing, y_bearing, width, height, x_advance,
+ y_advance)
+ assert te.x_bearing == x_bearing
+ assert te.y_bearing == y_bearing
+ assert te.width == width
+ assert te.height == height
+ assert te.x_advance == x_advance
+ assert te.y_advance == y_advance
+
+
+@given(integers(), integers(), integers(), integers())
+def test_rect_int(x, y, width, height):
+ try:
+ r = cairo.RectangleInt(x, y, width, height)
+ except OverflowError:
+ pass
+ else:
+ assert r.x == x
+ assert r.y == y
+ assert r.width == width
+ assert r.height == height
+
+
+@given(integers())
+def test_enums(value):
+ try:
+ e = cairo.Antialias(value)
+ except OverflowError:
+ pass
+ else:
+ assert e == value
+
+
+@given(integers())
+def test_context_get_set_operator(value):
+ try:
+ op = cairo.Operator(value)
+ except OverflowError:
+ return
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ context = cairo.Context(surface)
+ try:
+ context.set_operator(op)
+ except OverflowError:
+ return
+ assert context.get_operator() == op
--- /dev/null
+import cairo
+import pytest
+
+
+def test_matrix():
+ m = cairo.Matrix()
+ m.rotate(10)
+ m.scale(1.5, 2.5)
+ m.translate(10, 20)
+
+ with pytest.raises(TypeError):
+ m * 42
+
+ with pytest.raises(TypeError):
+ m + 42
+
+ with pytest.raises(TypeError):
+ cairo.Matrix(object())
+
+ assert m != 42
+ assert m == m
+ assert m != cairo.Matrix()
+
+ assert repr(cairo.Matrix()) == "cairo.Matrix(1, 0, 0, 1, 0, 0)"
+
+
+def test_init_rotate():
+ r = cairo.Matrix.init_rotate(0)
+ assert cairo.Matrix() == r
+
+ with pytest.raises(TypeError):
+ cairo.Matrix.init_rotate(object())
+
+
+def test_invert():
+ m = cairo.Matrix(1, 1)
+ m.invert()
+ assert m == cairo.Matrix(1, -1, -0, 1, 0, 0)
+
+
+def test_matrix_properties():
+ m = cairo.Matrix(*range(6))
+ assert [m.xx, m.yx, m.xy, m.yy, m.x0, m.y0] == list(range(6))
+ m.xx = 42
+ assert m.xx == 42
+ m.scale(2, 2)
+ assert m.xx == 84
+
+
+def test_get_item():
+ m = cairo.Matrix(1, 2, 3, 4, 5, 6)
+ for i in range(6):
+ assert m[i] == i + 1
+ with pytest.raises(IndexError):
+ m[6]
+ with pytest.raises(IndexError):
+ m[-1]
+
+
+def test_multiply():
+ with pytest.raises(TypeError):
+ cairo.Matrix().multiply(object())
+
+ m = cairo.Matrix(1, 1, 0, 1)
+ assert m.multiply(m) == cairo.Matrix(1, 2, 0, 1, 0, 0)
+ assert m * m == m.multiply(m)
+
+
+def test_translate():
+ m = cairo.Matrix()
+ m.translate(1, 1)
+ assert m == cairo.Matrix(1, 0, 0, 1, 1, 1)
+ with pytest.raises(TypeError):
+ m.translate(1, object())
+
+
+def test_rotate():
+ m = cairo.Matrix()
+ with pytest.raises(TypeError):
+ m.rotate(object())
+
+
+def test_scale():
+ m = cairo.Matrix()
+ with pytest.raises(TypeError):
+ m.scale(object())
+ m.scale(2, 2)
+ assert m != cairo.Matrix()
+ m.scale(0.5, 0.5)
+ assert m == cairo.Matrix()
+
+
+def test_transform_distance():
+ m = cairo.Matrix()
+ assert m.transform_distance(1, 1) == (1, 1)
+ with pytest.raises(TypeError):
+ m.transform_distance(1, object())
+
+
+def test_transform_point():
+ m = cairo.Matrix()
+ assert m.transform_point(1, 1) == (1, 1)
+ with pytest.raises(TypeError):
+ m.transform_point(1, object())
--- /dev/null
+import cairo
+import pytest
+
+
+@pytest.fixture
+def context():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42)
+ return cairo.Context(surface)
+
+
+def test_path():
+ assert cairo.Path
+
+ with pytest.raises(TypeError):
+ cairo.Path()
+
+
+def test_path_str(context):
+ p = context.copy_path()
+ assert isinstance(p, cairo.Path)
+ assert str(p) == ""
+
+ context.line_to(1, 2)
+ p = context.copy_path()
+ assert str(p) == "move_to 1.000000 2.000000"
+
+ context.line_to(1, 2)
+ p = context.copy_path()
+ assert str(p) == "move_to 1.000000 2.000000\nline_to 1.000000 2.000000"
+
+ context.new_path()
+ context.curve_to(0, 1, 2, 3, 4, 5)
+ p = context.copy_path()
+ assert str(p) == (
+ "move_to 0.000000 1.000000\n"
+ "curve_to 0.000000 1.000000 2.000000 3.000000 4.000000 5.000000")
+
+ context.new_path()
+ context.line_to(1, 2)
+ context.close_path()
+ p = context.copy_path()
+ assert str(p) == (
+ "move_to 1.000000 2.000000\n"
+ "close path\n"
+ "move_to 1.000000 2.000000")
+
+
+def test_path_compare_hash(context):
+ p = context.copy_path()
+ assert p == p
+ hash(p)
+ assert not p != p
+ assert p != object()
+ assert not p < p
+ assert p <= p
+ assert p >= p
+ assert not p > p
+
+
+def test_path_iter(context):
+ context.line_to(1, 2)
+ context.line_to(2, 3)
+ context.curve_to(0, 1, 2, 3, 4, 5)
+ context.close_path()
+ p = context.copy_path()
+ i = iter(p)
+ assert list(i) == [
+ (0, (1.0, 2.0)),
+ (1, (2.0, 3.0)),
+ (2, (0.0, 1.0, 2.0, 3.0, 4.0, 5.0)),
+ (3, ()),
+ (0, (1.0, 2.0)),
+ ]
assert isinstance(pattern, cairo.RasterSourcePattern)
assert issubclass(cairo.RasterSourcePattern, cairo.Pattern)
+ with pytest.raises(TypeError):
+ cairo.RasterSourcePattern(object())
+
was_called = []
def acquire_callback(target, extents):
was_called.append("release")
return None
+ with pytest.raises(TypeError):
+ pattern.set_acquire()
+
pattern.set_acquire(None, release_callback)
assert pattern.get_acquire() == (None, release_callback)
assert pattern.get_filter() == cairo.Filter.GOOD
+def test_linear_gradient():
+ with pytest.raises(TypeError):
+ cairo.LinearGradient()
+
+
+def test_radial_gradient():
+ with pytest.raises(TypeError):
+ cairo.RadialGradient()
+
+
def test_gradient_get_color_stops():
pattern = cairo.LinearGradient(1, 2, 4, 5)
assert pattern.get_color_stops_rgba() == []
[(0.125, 0.25, 0.5, 0.75, 1.0), (1.0, 0.75, 0.5, 0.25, 0.125)]
+def test_gradient_add_color_stop_rgb():
+ pattern = cairo.LinearGradient(1, 2, 4, 5)
+ with pytest.raises(TypeError):
+ pattern.add_color_stop_rgb()
+
+
+def test_gradient_add_color_stop_rgba():
+ pattern = cairo.LinearGradient(1, 2, 4, 5)
+ with pytest.raises(TypeError):
+ pattern.add_color_stop_rgba()
+
+
+def test_solid_pattern():
+ with pytest.raises(TypeError):
+ cairo.SolidPattern()
+
+
def test_mesh_pattern():
mesh = cairo.MeshPattern()
assert isinstance(mesh, cairo.MeshPattern)
assert issubclass(cairo.MeshPattern, cairo.Pattern)
+ with pytest.raises(TypeError):
+ cairo.MeshPattern(object())
def test_mesh_pattern_example1():
pattern.get_path(9)
+def test_mesh_pattern_curve_to():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.curve_to(object())
+
+
+def test_mesh_pattern_get_control_point():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.get_control_point(object())
+
+
+def test_mesh_pattern_get_corner_color_rgba():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.get_corner_color_rgba(object())
+
+
+def test_mesh_pattern_get_path():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.get_path(object())
+
+
+def test_mesh_pattern_line_to():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.line_to(object())
+
+
+def test_mesh_pattern_move_to():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.move_to(object())
+
+
+def test_mesh_pattern_set_control_point():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.set_control_point(object())
+
+
+def test_mesh_pattern_set_corner_color_rgb():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.set_corner_color_rgb(object())
+
+
+def test_mesh_pattern_set_corner_color_rgba():
+ pattern = cairo.MeshPattern()
+ with pytest.raises(TypeError):
+ pattern.set_corner_color_rgba(object())
+
+
def test_mesh_pattern_example2():
pattern = cairo.MeshPattern()
pattern.begin_patch()
with pytest.raises(cairo.Error):
cairo.MeshPattern().set_corner_color_rgb(0, 0.125, 0.25, 0.5)
+
+
+def test_get_matrix():
+ pattern = cairo.SolidPattern(1, 2, 4)
+ assert isinstance(pattern.get_matrix(), cairo.Matrix)
+ pattern.set_matrix(cairo.Matrix())
+ with pytest.raises(TypeError):
+ pattern.set_matrix(object())
+
+
+def test_set_extend():
+ pattern = cairo.SolidPattern(1, 2, 4)
+ pattern.set_extend(42)
+ assert pattern.get_extend() == 42
+ with pytest.raises(TypeError):
+ pattern.set_extend(object())
+
+
+def test_set_filter():
+ pattern = cairo.SolidPattern(1, 2, 4)
+ with pytest.raises(TypeError):
+ pattern.set_filter(object())
+
+
+def test_pattern():
+ with pytest.raises(TypeError):
+ cairo.Pattern()
+
+ r, g, b, a = 0.1, 0.2, 0.3, 0.4
+ p = cairo.SolidPattern(r, g, b, a)
+ assert p.get_rgba() == (r, g, b, a)
+
+ assert not p == object()
+ hash(p)
+
+ with pytest.raises(TypeError):
+ cairo.Gradient()
+
+ x0, y0, x1, y1 = 0.0, 0.0, 0.0, 1.0
+ p = cairo.LinearGradient(x0, y0, x1, y1)
+ assert p.get_linear_points() == (x0, y0, x1, y1)
+ p.add_color_stop_rgba(1, 0, 0, 0, 1)
+ p.add_color_stop_rgba(0, 1, 1, 1, 1)
+
+ cx0, cy0, radius0, cx1, cy1, radius1 = 1.0, 1.0, 1.0, 2.0, 2.0, 1.0
+ p = cairo.RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1)
+ assert p.get_radial_circles() == (cx0, cy0, radius0, cx1, cy1, radius1)
+ p.add_color_stop_rgba(0, 1, 1, 1, 1)
+ p.add_color_stop_rgba(1, 0, 0, 0, 1)
+
+
+def test_pattern_filter():
+ pattern = cairo.SolidPattern(1, 2, 3)
+ assert pattern.get_filter() == cairo.FILTER_GOOD
+ pattern.set_filter(cairo.FILTER_NEAREST)
+ assert pattern.get_filter() == cairo.FILTER_NEAREST
+
+
+def test_surface_pattern():
+ with pytest.raises(TypeError):
+ cairo.SurfacePattern(object())
import pytest
+def test_region():
+ with pytest.raises(TypeError):
+ cairo.Region(object())
+
+ with pytest.raises(TypeError):
+ cairo.Region(object(), object())
+
+ with pytest.raises(TypeError):
+ cairo.Region([object()])
+
+
+def test_get_rectangle():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ with pytest.raises(ValueError):
+ r.get_rectangle(-1)
+ with pytest.raises(ValueError):
+ r.get_rectangle(1)
+ assert r.get_rectangle(0) == rect
+ with pytest.raises(TypeError):
+ r.get_rectangle(object())
+
+
+def test_contains_point():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ assert r.contains_point(0, 0)
+ assert not r.contains_point(0, 20)
+ with pytest.raises(TypeError):
+ r.contains_point(0, object())
+
+
+def test_intersect():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ r.intersect(r)
+ r.intersect(rect)
+ with pytest.raises(TypeError):
+ r.intersect(object())
+ with pytest.raises(TypeError):
+ r.intersect()
+
+ assert r.__eq__(object()) == NotImplemented
+ assert rect.__eq__(object()) == NotImplemented
+
+
+def test_equal():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ assert r.equal(r)
+ with pytest.raises(TypeError):
+ r.equal(object())
+ with pytest.raises(TypeError):
+ r.equal()
+
+
+def test_subtract():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ r.subtract(r)
+ with pytest.raises(TypeError):
+ r.subtract(object())
+ with pytest.raises(TypeError):
+ r.subtract()
+
+
+def test_union():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ r.union(r)
+ r.union(rect)
+ with pytest.raises(TypeError):
+ r.union(object())
+ with pytest.raises(TypeError):
+ r.union()
+
+
+def test_xor():
+ rect = cairo.RectangleInt(0, 0, 10, 10)
+ r = cairo.Region(rect)
+ r.xor(r)
+ r.xor(rect)
+ with pytest.raises(TypeError):
+ r.xor(object())
+ with pytest.raises(TypeError):
+ r.xor()
+
+
+def test_translate():
+ r = cairo.Region()
+ r.translate(1, 1)
+ with pytest.raises(TypeError):
+ r.translate(1, object())
+
+
def test_region_contains_rectangle():
rect = cairo.RectangleInt(1, 2, 10, 13)
region = cairo.Region()
assert region.contains_rectangle(rect) == cairo.RegionOverlap.OUT
assert isinstance(region.contains_rectangle(rect), cairo.RegionOverlap)
+ with pytest.raises(TypeError):
+ region.contains_rectangle(object())
def test_region_cmp_hash():
assert not region != other
assert region != differ
+ with pytest.raises(TypeError):
+ region < region
+
+ with pytest.raises(TypeError):
+ region > region
+
rect = cairo.RectangleInt(1, 2, 10, 13)
same = cairo.RectangleInt(1, 2, 10, 13)
other = cairo.RectangleInt(2, 2, 10, 13)
assert rect == same
assert rect != other
+
+ with pytest.raises(TypeError):
+ rect < same
+
+ with pytest.raises(TypeError):
+ rect > same
ctx = cairo.Context(main)
assert ctx.get_target() == main
assert not ctx.get_target() != main
+ assert main != object()
assert hash(ctx.get_target()) == hash(main)
# we implement some hackery to change the underlying object after unmap
main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
image = main.map_to_image(None)
+ with pytest.raises(TypeError):
+ type(image)()
+
other = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
with pytest.raises(ValueError):
other.unmap_image(image)
with pytest.raises(cairo.Error):
cairo.Context(image)
+ with pytest.raises(TypeError):
+ main.map_to_image(object())
+
+ with pytest.raises(TypeError):
+ main.map_to_image()
+
+ gced = main.map_to_image(None)
+ del gced
+
def test_surface_map_to_image_data():
main = cairo.ImageSurface(cairo.Format.RGB24, 2, 1)
main = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
tee = cairo.TeeSurface(main)
assert isinstance(tee, cairo.TeeSurface)
-
+ with pytest.raises(TypeError):
+ cairo.TeeSurface(object())
+ with pytest.raises(TypeError):
+ tee.add(object())
+ with pytest.raises(TypeError):
+ tee.remove(object())
+ with pytest.raises(TypeError):
+ tee.index(object())
# the API is horrible, passing a wrong arg sets the surface to an error
# state instead of returning the status.
s1 = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
assert all(isinstance(v, cairo.PDFVersion) for v in versions)
+def test_pdf_set_size():
+ fileobj = io.BytesIO()
+ surface = cairo.PDFSurface(fileobj, 128, 128)
+ surface.set_size(10, 10)
+ with pytest.raises(TypeError):
+ surface.set_size(10, object())
+
+
+def test_pdf_surface():
+ fd, fname = tempfile.mkstemp()
+ os.close(fd)
+ try:
+ cairo.PDFSurface(fname, 10, 10).finish()
+ finally:
+ os.unlink(fname)
+
+ with pytest.raises(TypeError):
+ cairo.PDFSurface()
+
+ with pytest.raises((ValueError, TypeError)):
+ cairo.PDFSurface("\x00")
+
+ with pytest.raises(TypeError):
+ cairo.PDFSurface(object(), 100, 100)
+
+
+def test_svg_version_to_string():
+ ver = cairo.SVGSurface.version_to_string(cairo.SVG_VERSION_1_1)
+ assert ver and isinstance(ver, str)
+ with pytest.raises(ValueError):
+ cairo.SVGSurface.version_to_string(-1)
+ with pytest.raises(TypeError):
+ cairo.SVGSurface.version_to_string(object())
+
+
+def test_svg_surface_restrict_to_version():
+ surface = cairo.SVGSurface(None, 10, 10)
+ surface.restrict_to_version(cairo.SVG_VERSION_1_1)
+ surface.finish()
+ with pytest.raises(cairo.Error):
+ surface.restrict_to_version(cairo.SVG_VERSION_1_2)
+ with pytest.raises(TypeError):
+ surface.restrict_to_version(object())
+
+
+def test_pdf_surface_restrict_to_version():
+ surface = cairo.PDFSurface(None, 10, 10)
+ surface.restrict_to_version(cairo.PDF_VERSION_1_4)
+ surface.finish()
+ with pytest.raises(cairo.Error):
+ surface.restrict_to_version(cairo.PDF_VERSION_1_5)
+ with pytest.raises(TypeError):
+ surface.restrict_to_version(object())
+
+
+def test_pdf_version_to_string():
+ ver = cairo.PDFSurface.version_to_string(cairo.PDF_VERSION_1_4)
+ assert ver and isinstance(ver, str)
+ with pytest.raises(ValueError):
+ cairo.PDFSurface.version_to_string(-1)
+ with pytest.raises(TypeError):
+ cairo.PDFSurface.version_to_string(object())
+
+
+def test_ps_surface_misc():
+ surface = cairo.PSSurface(None, 10, 10)
+ surface.dsc_begin_page_setup()
+ surface.dsc_begin_setup()
+
+
+def test_ps_surface_dsc_comment():
+ surface = cairo.PSSurface(None, 10, 10)
+ surface.dsc_comment("%%Title: My excellent document")
+ with pytest.raises(cairo.Error):
+ surface.dsc_comment("")
+ with pytest.raises(TypeError):
+ surface.dsc_comment(object())
+
+
+def test_ps_get_eps():
+ surface = cairo.PSSurface(None, 10, 10)
+ assert isinstance(surface.get_eps(), bool)
+ surface.set_eps(True)
+ assert surface.get_eps()
+ with pytest.raises(TypeError):
+ surface.set_eps(object())
+
+
+def test_ps_set_size():
+ surface = cairo.PSSurface(None, 10, 10)
+ surface.set_size(10, 10)
+ with pytest.raises(TypeError):
+ surface.set_size(10, object())
+
+
+def test_ps_restrict_to_level():
+ surface = cairo.PSSurface(None, 10, 10)
+ surface.restrict_to_level(cairo.PSLevel.LEVEL_2)
+ with pytest.raises(TypeError):
+ surface.restrict_to_level(object())
+
+
+def test_ps_surface_level_to_string():
+ level_id = cairo.PSSurface.level_to_string(cairo.PS_LEVEL_2)
+ assert isinstance(level_id, str)
+ assert cairo.PSSurface.ps_level_to_string(cairo.PS_LEVEL_2) == level_id
+ with pytest.raises(ValueError):
+ cairo.PSSurface.level_to_string(-1)
+ with pytest.raises(TypeError):
+ cairo.PSSurface.level_to_string(object())
+
+
def test_ps_surface_get_levels():
levels = cairo.PSSurface.get_levels()
assert isinstance(levels, list)
assert all(isinstance(v, cairo.PSLevel) for v in levels)
+def test_ps_surface():
+ assert isinstance(cairo.PSSurface(None, 10, 10), cairo.PSSurface)
+
+ fd, fname = tempfile.mkstemp()
+ os.close(fd)
+ try:
+ cairo.PSSurface(fname, 10, 10).finish()
+ finally:
+ os.unlink(fname)
+
+ with pytest.raises(TypeError):
+ cairo.PSSurface()
+
+ with pytest.raises((ValueError, TypeError)):
+ cairo.PSSurface("\x00", 100, 100)
+
+ with pytest.raises(TypeError):
+ cairo.PSSurface(object(), 100, 100)
+
+
+def test_scg_surface():
+ fd, fname = tempfile.mkstemp()
+ os.close(fd)
+ try:
+ cairo.SVGSurface(fname, 10, 10).finish()
+ finally:
+ os.unlink(fname)
+
+ with pytest.raises(TypeError):
+ cairo.SVGSurface()
+
+ with pytest.raises((ValueError, TypeError)):
+ cairo.SVGSurface("\x00", 10, 10)
+
+ with pytest.raises(TypeError):
+ cairo.SVGSurface(object(), 100, 100)
+
+
def test_svg_surface_get_versions():
versions = cairo.SVGSurface.get_versions()
assert isinstance(versions, list)
with pytest.raises(cairo.Error):
surface.set_device_scale(1, 0)
+ with pytest.raises(TypeError):
+ surface.set_device_scale(1, object())
+
+
+def test_surface_create_for_rectangle():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
+ new = surface.create_for_rectangle(0, 0, 10, 10)
+ assert new
+ assert isinstance(new, cairo.Surface)
+
+ with pytest.raises(cairo.Error) as excinfo:
+ surface.create_for_rectangle(0, 0, 10, -1)
+ assert excinfo.value.status == cairo.STATUS_INVALID_SIZE
+
+ with pytest.raises(TypeError):
+ surface.create_for_rectangle(0, 0, 10, object())
+
+
+def test_surface_create_similar_image():
+ surface = cairo.PDFSurface(None, 1, 1)
+ image = surface.create_similar_image(cairo.FORMAT_ARGB32, 24, 42)
+ assert image
+ assert isinstance(image, cairo.ImageSurface)
+ del surface
+ assert image.get_width() == 24
+ assert image.get_height() == 42
+ surface = cairo.PDFSurface(None, 1, 1)
+ with pytest.raises(TypeError):
+ surface.create_similar_image(cairo.FORMAT_ARGB32, 24, object())
+
+
+def test_surface_get_set_mime_data():
+ surface = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
+ assert surface.get_mime_data("foo") is None
+ assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None
+
+ surface.set_mime_data("foo", b"bar")
+ assert surface.get_mime_data("foo") == b"bar"
+ surface.set_mime_data("foo", None)
+ assert surface.get_mime_data("foo") is None
+
+ surface.set_mime_data(cairo.MIME_TYPE_JPEG, b"\x00quux\x00")
+ assert surface.get_mime_data(cairo.MIME_TYPE_JPEG)[:] == b"\x00quux\x00"
+ surface.set_mime_data(cairo.MIME_TYPE_JPEG, None)
+ assert surface.get_mime_data(cairo.MIME_TYPE_JPEG) is None
+ with pytest.raises(TypeError):
+ surface.set_mime_data(cairo.MIME_TYPE_JPEG, object())
+ with pytest.raises(TypeError):
+ surface.get_mime_data(object())
+
+
+def test_supports_mime_type():
+ surface = cairo.PDFSurface(None, 3, 3)
+ assert surface.supports_mime_type(cairo.MIME_TYPE_JPEG)
+ assert not surface.supports_mime_type("nope")
+ with pytest.raises(TypeError):
+ surface.supports_mime_type(object())
+
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="not png support")
def test_image_surface_create_for_data_array():
width, height = 255, 255
data = array.array('B', [0] * width * height * 4)
os.unlink(filename)
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="not png support")
def test_image_surface_write_to_png_filename_and_obj_compare():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128)
fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
os.unlink(filename)
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="not png support")
def test_image_surface_png_obj_roundtrip():
fileobj = io.BytesIO()
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128)
fileobj.seek(0)
new_surface = cairo.ImageSurface.create_from_png(fileobj)
assert surface.get_data() == new_surface.get_data()
+ with pytest.raises(TypeError):
+ cairo.ImageSurface.create_from_png()
+ with pytest.raises((ValueError, TypeError)):
+ cairo.ImageSurface.create_from_png("\x00")
+ with pytest.raises(TypeError):
+ cairo.ImageSurface.create_from_png(object())
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="not png support")
def test_image_surface_png_file_roundtrip():
fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
os.close(fd)
os.unlink(filename)
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="not png support")
def test_image_surface_write_to_png_error():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128)
with pytest.raises(TypeError):
surface.write_to_png(42)
+ with pytest.raises((ValueError, TypeError)):
+ surface.write_to_png("\x00")
def test_surface_from_stream_closed_before_finished():
dev.flush()
assert b"42" in f.getvalue()
assert b"paint" in f.getvalue()
+ with pytest.raises(TypeError):
+ cairo.ScriptSurface()
def test_script_device_device_ref():
dev = cairo.ScriptDevice(f)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
script = cairo.ScriptSurface.create_for_target(dev, surface)
+ with pytest.raises(TypeError):
+ cairo.ScriptSurface.create_for_target(dev, object())
assert isinstance(script, cairo.ScriptSurface)
ctx = cairo.Context(script)
ctx.set_source_rgb(0.25, 0.5, 1.0)
ctx.paint()
surface.flush()
assert bytes(surface.get_data()) == image_data
+
+
+def test_misc():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ surface.copy_page()
+ surface.mark_dirty()
+ surface.show_page()
+
+
+@pytest.fixture
+def surface():
+ return cairo.ImageSurface(cairo.Format.ARGB32, 10, 10)
+
+
+@pytest.fixture
+def image_surface():
+ return cairo.ImageSurface(cairo.Format.ARGB32, 10, 10)
+
+
+def test_create_similar(surface):
+ similar = surface.create_similar(cairo.Content.COLOR, 10, 10)
+ assert isinstance(similar, cairo.Surface)
+ with pytest.raises(TypeError):
+ surface.create_similar()
+
+
+def test_get_device_offset(surface):
+ surface.set_device_offset(1, 1)
+ assert surface.get_device_offset() == (1, 1)
+ with pytest.raises(TypeError):
+ surface.set_device_offset(1, object())
+
+
+def test_get_fallback_resolution(surface):
+ surface.set_fallback_resolution(42, 42)
+ assert surface.get_fallback_resolution() == (42, 42)
+ with pytest.raises(TypeError):
+ surface.set_fallback_resolution(42, object())
+
+
+def test_mark_dirty_rectangle(surface):
+ surface.mark_dirty_rectangle(0, 0, 10, 10)
+ with pytest.raises(TypeError):
+ surface.mark_dirty_rectangle(0, 0, 10, object())
+
+
+def test_write_to_png(image_surface):
+ with pytest.raises(TypeError):
+ image_surface.write_to_png()
+
+ with pytest.raises((ValueError, TypeError)) as excinfo:
+ image_surface.write_to_png("\x00")
+ excinfo.match(r'.* (null|NUL) .*')
+
+ with pytest.raises(TypeError):
+ image_surface.write_to_png(object())
+
+
+def test_image_surface():
+ with pytest.raises(TypeError):
+ cairo.ImageSurface(cairo.FORMAT_ARGB32, 3, object())
+
+
+def test_image_surface_create_for_data():
+ format_ = cairo.FORMAT_ARGB32
+ surface = cairo.ImageSurface(format_, 3, 3)
+ ctx = cairo.Context(surface)
+ ctx.paint()
+ surface.flush()
+ buf = surface.get_data()
+
+ new = cairo.ImageSurface.create_for_data(buf, format_, 3, 3)
+ assert new.get_data() == buf
+
+ with pytest.raises(ValueError):
+ cairo.ImageSurface.create_for_data(buf, format_, 3, -1)
+ with pytest.raises(ValueError):
+ cairo.ImageSurface.create_for_data(buf, format_, -1, 3)
+
+ with pytest.raises(ValueError):
+ cairo.ImageSurface.create_for_data(buf, format_, 0, 0, -1)
+
+ with pytest.raises(cairo.Error) as excinfo:
+ cairo.ImageSurface.create_for_data(buf, format_, 3, 3, 3)
+
+ assert excinfo.value.status == cairo.STATUS_INVALID_STRIDE
+
+ with pytest.raises(TypeError):
+ cairo.ImageSurface.create_for_data(buf, format_, 3, object())
+
+
+def test_image_surface_stride_for_width():
+ v = cairo.ImageSurface.format_stride_for_width(cairo.Format.ARGB32, 10)
+ assert v == 40
+
+ with pytest.raises(TypeError):
+ cairo.ImageSurface.format_stride_for_width(
+ cairo.Format.ARGB32, object())
+
+
+def test_image_surface_get_stride(image_surface):
+ assert image_surface.get_stride() == 40
+
+
+def test_recording_surface():
+ with pytest.raises(TypeError):
+ cairo.RecordingSurface(cairo.CONTENT_COLOR, object())
+
+ with pytest.raises(TypeError):
+ cairo.RecordingSurface()
+
+ surface = cairo.RecordingSurface(cairo.CONTENT_COLOR, None)
+ assert surface.ink_extents() == (0.0, 0.0, 0.0, 0.0)
numpy = pytest.importorskip("numpy")
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="no png support")
def test_image_surface_create_for_data_numpy_array():
width, height = 255, 255
data = numpy.ndarray(shape=(height, width), dtype=numpy.uint32)
os.unlink(filename)
-@pytest.mark.skipif(not cairo.HAS_PNG_FUNCTIONS, reason="no png support")
def test_image_surface_get_data_to_numpy_array():
w, h = 128, 128
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)