summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in1
-rw-r--r--NEWS49
-rw-r--r--PKG-INFO2
-rw-r--r--README.rst6
-rwxr-xr-xcairo/__init__.py2
-rw-r--r--cairo/cairomodule.c181
-rw-r--r--cairo/compat.h12
-rw-r--r--cairo/context.c10
-rw-r--r--cairo/enums.c418
-rw-r--r--cairo/error.c3
-rw-r--r--cairo/font.c18
-rw-r--r--cairo/pattern.c4
-rw-r--r--cairo/private.h40
-rw-r--r--cairo/region.c5
-rw-r--r--cairo/surface.c49
-rw-r--r--docs/conf.py3
-rw-r--r--docs/examples.rst9
-rw-r--r--docs/faq.rst41
-rw-r--r--docs/index.rst3
-rw-r--r--docs/integration.rst44
-rw-r--r--docs/pycairo_c_api.rst122
-rw-r--r--docs/reference/constants.rst711
-rw-r--r--docs/reference/context.rst164
-rw-r--r--docs/reference/enums.rst666
-rw-r--r--docs/reference/exceptions.rst2
-rw-r--r--docs/reference/index.rst2
-rw-r--r--docs/reference/legacy_constants.rst490
-rw-r--r--docs/reference/matrix.rst8
-rw-r--r--docs/reference/paths.rst2
-rw-r--r--docs/reference/patterns.rst17
-rw-r--r--docs/reference/region.rst3
-rw-r--r--docs/reference/surfaces.rst35
-rw-r--r--docs/reference/text.rst43
-rw-r--r--docs/resources.rst67
-rw-r--r--docs/tutorial.rst114
-rw-r--r--examples/cairo_snippets/c_to_python.py35
-rw-r--r--examples/cairo_snippets/snippets/__init__.py42
-rw-r--r--examples/cairo_snippets/snippets/arc.py41
-rw-r--r--examples/cairo_snippets/snippets/arc_negative.py42
-rw-r--r--examples/cairo_snippets/snippets/clip.py31
-rw-r--r--examples/cairo_snippets/snippets/curve_rectangle.py95
-rw-r--r--examples/cairo_snippets/snippets/curve_to.py31
-rw-r--r--examples/cairo_snippets/snippets/ellipse.py35
-rw-r--r--examples/cairo_snippets/snippets/fill_and_stroke.py23
-rw-r--r--examples/cairo_snippets/snippets/fill_and_stroke2.py33
-rw-r--r--examples/cairo_snippets/snippets/glyph_path.py38
-rw-r--r--examples/cairo_snippets/snippets/gradient.py34
-rw-r--r--examples/cairo_snippets/snippets/gradient_mask.py23
-rw-r--r--examples/cairo_snippets/snippets/group.py32
-rw-r--r--examples/cairo_snippets/snippets/hering.py38
-rw-r--r--examples/cairo_snippets/snippets/path.py16
-rw-r--r--examples/cairo_snippets/snippets/set_line_cap.py48
-rw-r--r--examples/cairo_snippets/snippets/set_line_join.py38
-rw-r--r--examples/cairo_snippets/snippets/show_glyphs.py29
-rw-r--r--examples/cairo_snippets/snippets/spiral.py20
-rw-r--r--examples/cairo_snippets/snippets/text.py42
-rw-r--r--examples/cairo_snippets/snippets/text_align_center.py46
-rw-r--r--examples/cairo_snippets/snippets/text_extents.py46
-rw-r--r--examples/cairo_snippets/snippets/warpedtext.py90
-rw-r--r--examples/cairo_snippets/snippets_gtk.py158
-rw-r--r--examples/cairo_snippets/snippets_pdf.py73
-rw-r--r--examples/cairo_snippets/snippets_png.py79
-rw-r--r--examples/cairo_snippets/snippets_ps.py72
-rw-r--r--examples/cairo_snippets/snippets_svg.py69
-rw-r--r--examples/gradient.py33
-rw-r--r--examples/gtk/cairo-demo.py79
-rw-r--r--examples/gtk/cairo-knockout.py96
-rw-r--r--examples/gtk/hangman.py257
-rw-r--r--examples/gtk/lsystem.py123
-rw-r--r--examples/gtk/png_view.py25
-rw-r--r--examples/gtk/text.py30
-rw-r--r--examples/hering.py55
-rw-r--r--examples/manual_tests/isurface_create_for_data1.py32
-rw-r--r--examples/manual_tests/isurface_create_for_data2.py30
-rw-r--r--examples/manual_tests/isurface_create_from_png.py56
-rw-r--r--examples/manual_tests/isurface_get_data.py50
-rw-r--r--examples/manual_tests/pygame-test1.py65
-rw-r--r--examples/manual_tests/pygame-test2.py49
-rw-r--r--examples/manual_tests/surface_create_for_stream.py81
-rw-r--r--examples/manual_tests/surface_write_to_png.py73
-rwxr-xr-xexamples/manual_tests/unicodeFilenames.py31
-rwxr-xr-xexamples/manual_tests/unicodeText.py31
-rw-r--r--examples/pygame-demo.py54
-rw-r--r--examples/spiral.py36
-rw-r--r--examples/warpedtext.py85
-rw-r--r--setup.cfg3
-rwxr-xr-xsetup.py10
-rw-r--r--tests/test_api.py56
-rw-r--r--tests/test_context.py33
-rw-r--r--tests/test_enums.py107
-rw-r--r--tests/test_font.py40
-rw-r--r--tests/test_pattern.py12
-rw-r--r--tests/test_region.py8
-rw-r--r--tests/test_surface.py121
-rw-r--r--tests/test_surface_numpy.py65
-rw-r--r--tests/test_surface_pygame.py14
96 files changed, 3627 insertions, 2958 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 26e7009..a22942c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,6 +2,7 @@ include COPYING*
include NEWS
include README.rst
include MANIFEST.in
+include setup.cfg
recursive-include docs *.py Makefile *.rst *.css
prune docs/_build
recursive-include tests *.py README
diff --git a/NEWS b/NEWS
index 37e2bed..294c469 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,38 @@
+1.13.0 - 2017-05-03
+-------------------
+
+New Features:
+ * The buffer returned by :meth:`ImageSurface.get_data` under Python 2 now
+ implements the character buffer interface to make it work with
+ pygame.image.frombuffer(). :pr:`29`
+ * All C enum types now have their own corresponding Python enum type:
+ :class:`Antialias`, :class:`Content`, :class:`Extend`, :class:`FillRule`,
+ :class:`Filter`, :class:`FontSlant`, :class:`FontWeight`, :class:`Format`,
+ :class:`HintMetrics`, :class:`HintStyle`, :class:`LineCap`,
+ :class:`LineJoin`, :class:`Operator`, :class:`PDFVersion`,
+ :class:`PSLevel`, :class:`PathDataType`, :class:`RegionOverlap`,
+ :class:`SVGVersion`, :class:`Status`, :class:`SubpixelOrder`. :bug:`26`
+
+ All relevant constants are now an alias to attributes of those types e.g.
+ :data:`ANTIALIAS_DEFAULT` is the same as :attr:`Antialias.DEFAULT`.
+
+ All functions returning enum values now return instances of the new types
+ e.g. :meth:`Context.get_antialias` returns a :class:`Antialias`.
+
+ :attr:`Error.status` is now a :class:`Status`.
+ * All included examples now work with Python 2 & 3
+ * All included examples using GTK+ have been ported to GTK+ 3/PyGObject 3
+
+Fixes:
+ * Fix the signature of the :class:`ImageSurface` buffer interface for Python 2
+ (int -> Py_ssize_t)
+ * setup.py: Ensure "-fno-strict-aliasing" is used with Python 2.
+
+Testing:
+ * Added travis-ci tests for flake8 and sphinx. :pr:`30`, :pr:`32`
+ * The test suite now has optional tests for numpy and pygame integration.
+
+
1.12.0 - 2017-04-18
-------------------
@@ -6,15 +41,15 @@ General:
* Use C90 and enforce it on travis-ci. :bug:`5`, :fdobug:`22940`
Constants:
- * Add various new :ref:`constants_OPERATOR`, :ref:`constants_ANTIALIAS` and
- :ref:`constants_FORMAT` constants. :bug:`1`
- * Add :data:`HAS_MIME_SURFACE` and :ref:`constants_MIME_TYPE`. :bug:`7`,
+ * Add various new cairo.OPERATOR_*, cairo.ANTIALIAS_* and
+ cairo.FORMAT_* constants. :bug:`1`
+ * Add :data:`HAS_MIME_SURFACE` and cairo.MIME_TYPE_*. :bug:`7`,
:fdobug:`58771`
- * Add :ref:`constants_PDF_VERSION`. :pr:`16`
- * Add :ref:`constants_SVG_VERSION`
+ * Add cairo.PDF_VERSION_*. :pr:`16`
+ * Add cairo.SVG_VERSION_*
:exc:`Error`:
- * Add a :data:`Error.status` attribute exposing :ref:`constants_STATUS`
+ * Add a :data:`Error.status` attribute exposing cairo.STATUS_*
* Add :exc:`CairoError` alias for :exc:`Error` for cairocffi compatibility
:class:`Matrix`:
@@ -100,7 +135,7 @@ New Features:
* :class:`cairo.RecordingSurface` (:fdobug:`36854`,
`Torsten Landschoff <t.landschoff@gmx.net>`__)
* :class:`cairo.Region`, :class:`cairo.RectangleInt` and
- :ref:`cairo.REGION_OVERLAP <constants_REGION_OVERLAP>`
+ cairo.REGION_OVERLAP_*
(:fdobug:`44336`, `Bug Fly <mozbugbox@yahoo.com.au>`__)
Bug Fixes:
diff --git a/PKG-INFO b/PKG-INFO
index 6185a1b..49443ff 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: pycairo
-Version: 1.12.0
+Version: 1.13.0
Summary: python interface for cairo
Home-page: UNKNOWN
Author: UNKNOWN
diff --git a/README.rst b/README.rst
index 9ef68e6..bf5f71a 100644
--- a/README.rst
+++ b/README.rst
@@ -11,9 +11,9 @@ Features of the Pycairo bindings:
* Queries the error status of objects and translates them to exceptions.
* Provides a C API that can be used by other Python extensions.
-Pycairo depends on **cairo >= 1.10.2** and works with **Python 2.7+** as well
-as **Python 3.3+**. Pycairo is licensed under the **LGPLv2.1** as well as the
-**MPLv1.1**.
+Pycairo depends on **cairo >= 1.12** and works with **Python 2.7+** as well as
+**Python 3.3+**. Pycairo, including this documentation, is licensed under the
+**LGPLv2.1** as well as the **MPLv1.1**.
If Pycairo is not what you need, have a look at `cairocffi
<https://cairocffi.readthedocs.io>`__, which is an API compatible package
diff --git a/cairo/__init__.py b/cairo/__init__.py
index 821a1f2..dd86f6a 100755
--- a/cairo/__init__.py
+++ b/cairo/__init__.py
@@ -1 +1 @@
-from ._cairo import *
+from ._cairo import * # noqa: F401,F403
diff --git a/cairo/cairomodule.c b/cairo/cairomodule.c
index 75fb4c0..f5dd61d 100644
--- a/cairo/cairomodule.c
+++ b/cairo/cairomodule.c
@@ -35,18 +35,6 @@
#include "config.h"
#include "private.h"
-/* to read CAIRO_PS_LEVEL_* constants */
-#ifdef CAIRO_HAS_PS_SURFACE
-# include <cairo-ps.h>
-#endif
-/* to read CAIRO_PDF_VERSION_* constants */
-#ifdef CAIRO_HAS_PDF_SURFACE
-# include <cairo-pdf.h>
-#endif
-/* to read CAIRO_SVG_VERSION_* constants */
-#ifdef CAIRO_HAS_SVG_SURFACE
-# include <cairo-svg.h>
-#endif
/* for XCB api */
#if defined(CAIRO_HAS_XCB_SURFACE) && defined(HAVE_XPYB)
@@ -327,6 +315,9 @@ PYCAIRO_MOD_INIT(_cairo)
if (m == NULL)
return PYCAIRO_MOD_ERROR_VAL;
+ if(init_enums(m) < 0)
+ return PYCAIRO_MOD_ERROR_VAL;
+
PyModule_AddStringConstant(m, "version", VERSION);
PyModule_AddObject(m, "version_info",
Py_BuildValue("(iii)",
@@ -534,171 +525,6 @@ PYCAIRO_MOD_INIT(_cairo)
PyModule_AddIntConstant(m, "HAS_MIME_SURFACE", 0);
#endif
-#define CONSTANT(x) PyModule_AddIntConstant(m, #x, CAIRO_##x)
- CONSTANT(ANTIALIAS_DEFAULT);
- CONSTANT(ANTIALIAS_NONE);
- CONSTANT(ANTIALIAS_GRAY);
- CONSTANT(ANTIALIAS_SUBPIXEL);
- CONSTANT(ANTIALIAS_FAST);
- CONSTANT(ANTIALIAS_GOOD);
- CONSTANT(ANTIALIAS_BEST);
-
- CONSTANT(CONTENT_COLOR);
- CONSTANT(CONTENT_ALPHA);
- CONSTANT(CONTENT_COLOR_ALPHA);
-
- CONSTANT(EXTEND_NONE);
- CONSTANT(EXTEND_REPEAT);
- CONSTANT(EXTEND_REFLECT);
- CONSTANT(EXTEND_PAD);
-
- CONSTANT(FILL_RULE_WINDING);
- CONSTANT(FILL_RULE_EVEN_ODD);
-
- CONSTANT(FILTER_FAST);
- CONSTANT(FILTER_GOOD);
- CONSTANT(FILTER_BEST);
- CONSTANT(FILTER_NEAREST);
- CONSTANT(FILTER_BILINEAR);
- CONSTANT(FILTER_GAUSSIAN);
-
- CONSTANT(FONT_WEIGHT_NORMAL);
- CONSTANT(FONT_WEIGHT_BOLD);
-
- CONSTANT(FONT_SLANT_NORMAL);
- CONSTANT(FONT_SLANT_ITALIC);
- CONSTANT(FONT_SLANT_OBLIQUE);
-
- CONSTANT(FORMAT_INVALID);
- CONSTANT(FORMAT_ARGB32);
- CONSTANT(FORMAT_RGB24);
- CONSTANT(FORMAT_A8);
- CONSTANT(FORMAT_A1);
- CONSTANT(FORMAT_RGB16_565);
- CONSTANT(FORMAT_RGB30);
-
- CONSTANT(HINT_METRICS_DEFAULT);
- CONSTANT(HINT_METRICS_OFF);
- CONSTANT(HINT_METRICS_ON);
-
- CONSTANT(HINT_STYLE_DEFAULT);
- CONSTANT(HINT_STYLE_NONE);
- CONSTANT(HINT_STYLE_SLIGHT);
- CONSTANT(HINT_STYLE_MEDIUM);
- CONSTANT(HINT_STYLE_FULL);
-
- CONSTANT(LINE_CAP_BUTT);
- CONSTANT(LINE_CAP_ROUND);
- CONSTANT(LINE_CAP_SQUARE);
-
- CONSTANT(LINE_JOIN_MITER);
- CONSTANT(LINE_JOIN_ROUND);
- CONSTANT(LINE_JOIN_BEVEL);
-
- CONSTANT(OPERATOR_CLEAR);
-
- CONSTANT(OPERATOR_SOURCE);
- CONSTANT(OPERATOR_OVER);
- CONSTANT(OPERATOR_IN);
- CONSTANT(OPERATOR_OUT);
- CONSTANT(OPERATOR_ATOP);
-
- CONSTANT(OPERATOR_DEST);
- CONSTANT(OPERATOR_DEST_OVER);
- CONSTANT(OPERATOR_DEST_IN);
- CONSTANT(OPERATOR_DEST_OUT);
- CONSTANT(OPERATOR_DEST_ATOP);
-
- CONSTANT(OPERATOR_XOR);
- CONSTANT(OPERATOR_ADD);
- CONSTANT(OPERATOR_SATURATE);
-
- CONSTANT(OPERATOR_MULTIPLY);
- CONSTANT(OPERATOR_SCREEN);
- CONSTANT(OPERATOR_OVERLAY);
- CONSTANT(OPERATOR_DARKEN);
- CONSTANT(OPERATOR_LIGHTEN);
- CONSTANT(OPERATOR_COLOR_DODGE);
- CONSTANT(OPERATOR_COLOR_BURN);
- CONSTANT(OPERATOR_HARD_LIGHT);
- CONSTANT(OPERATOR_SOFT_LIGHT);
- CONSTANT(OPERATOR_DIFFERENCE);
- CONSTANT(OPERATOR_EXCLUSION);
- CONSTANT(OPERATOR_HSL_HUE);
- CONSTANT(OPERATOR_HSL_SATURATION);
- CONSTANT(OPERATOR_HSL_COLOR);
- CONSTANT(OPERATOR_HSL_LUMINOSITY);
-
- CONSTANT(PATH_MOVE_TO);
- CONSTANT(PATH_LINE_TO);
- CONSTANT(PATH_CURVE_TO);
- CONSTANT(PATH_CLOSE_PATH);
-
-#ifdef CAIRO_HAS_PDF_SURFACE
- CONSTANT(PDF_VERSION_1_4);
- CONSTANT(PDF_VERSION_1_5);
-#endif
-
- CONSTANT(REGION_OVERLAP_IN);
- CONSTANT(REGION_OVERLAP_OUT);
- CONSTANT(REGION_OVERLAP_PART);
-
-#ifdef CAIRO_HAS_PS_SURFACE
- CONSTANT(PS_LEVEL_2);
- CONSTANT(PS_LEVEL_3);
-#endif
-
-#ifdef CAIRO_HAS_SVG_SURFACE
- CONSTANT(SVG_VERSION_1_1);
- CONSTANT(SVG_VERSION_1_2);
-#endif
-
- CONSTANT(SUBPIXEL_ORDER_DEFAULT);
- CONSTANT(SUBPIXEL_ORDER_RGB);
- CONSTANT(SUBPIXEL_ORDER_BGR);
- CONSTANT(SUBPIXEL_ORDER_VRGB);
- CONSTANT(SUBPIXEL_ORDER_VBGR);
-
- CONSTANT(STATUS_SUCCESS);
- CONSTANT(STATUS_NO_MEMORY);
- CONSTANT(STATUS_INVALID_RESTORE);
- CONSTANT(STATUS_INVALID_POP_GROUP);
- CONSTANT(STATUS_NO_CURRENT_POINT);
- CONSTANT(STATUS_INVALID_MATRIX);
- CONSTANT(STATUS_INVALID_STATUS);
- CONSTANT(STATUS_NULL_POINTER);
- CONSTANT(STATUS_INVALID_STRING);
- CONSTANT(STATUS_INVALID_PATH_DATA);
- CONSTANT(STATUS_READ_ERROR);
- CONSTANT(STATUS_WRITE_ERROR);
- CONSTANT(STATUS_SURFACE_FINISHED);
- CONSTANT(STATUS_SURFACE_TYPE_MISMATCH);
- CONSTANT(STATUS_PATTERN_TYPE_MISMATCH);
- CONSTANT(STATUS_INVALID_CONTENT);
- CONSTANT(STATUS_INVALID_FORMAT);
- CONSTANT(STATUS_INVALID_VISUAL);
- CONSTANT(STATUS_FILE_NOT_FOUND);
- CONSTANT(STATUS_INVALID_DASH);
- CONSTANT(STATUS_INVALID_DSC_COMMENT);
- CONSTANT(STATUS_INVALID_INDEX);
- CONSTANT(STATUS_CLIP_NOT_REPRESENTABLE);
- CONSTANT(STATUS_TEMP_FILE_ERROR);
- CONSTANT(STATUS_INVALID_STRIDE);
- CONSTANT(STATUS_FONT_TYPE_MISMATCH);
- CONSTANT(STATUS_USER_FONT_IMMUTABLE);
- CONSTANT(STATUS_USER_FONT_ERROR);
- CONSTANT(STATUS_NEGATIVE_COUNT);
- CONSTANT(STATUS_INVALID_CLUSTERS);
- CONSTANT(STATUS_INVALID_SLANT);
- CONSTANT(STATUS_INVALID_WEIGHT);
- CONSTANT(STATUS_INVALID_SIZE);
- CONSTANT(STATUS_USER_FONT_NOT_IMPLEMENTED);
- CONSTANT(STATUS_DEVICE_TYPE_MISMATCH);
- CONSTANT(STATUS_DEVICE_ERROR);
- CONSTANT(STATUS_INVALID_MESH_CONSTRUCTION);
- CONSTANT(STATUS_DEVICE_FINISHED);
- CONSTANT(STATUS_LAST_STATUS);
-
#define STRCONSTANT(x) PyModule_AddStringConstant(m, #x, CAIRO_##x)
STRCONSTANT(MIME_TYPE_JP2);
@@ -708,7 +534,6 @@ PYCAIRO_MOD_INIT(_cairo)
STRCONSTANT(MIME_TYPE_UNIQUE_ID);
#undef STRCONSTANT
-#undef CONSTANT
#if PY_MAJOR_VERSION >= 3
/* Create a Capsule containing the CAPI pointer */
diff --git a/cairo/compat.h b/cairo/compat.h
index e001339..de6fd37 100644
--- a/cairo/compat.h
+++ b/cairo/compat.h
@@ -45,9 +45,15 @@
#define PYCAIRO_PyUnicode_FromString PyString_FromString
#define PYCAIRO_PyUnicode_Join _PyString_Join
#define PYCAIRO_PyUnicode_InternFromString PyString_InternFromString
+#define PYCAIRO_PyUnicode_Astring PyString_AsString
+#define PYCAIRO_PyUnicode_FromFormat PyString_FromFormat
+
+#define PYCAIRO_PyNumber_Long PyNumber_Int
#define PYCAIRO_PyBytes_AsStringAndSize PyString_AsStringAndSize
+#define PYCAIRO_PyLong_Type PyInt_Type
+#define PYCAIRO_PyLongObject PyIntObject
#define PYCAIRO_PyLong_FromLong PyInt_FromLong
#define PYCAIRO_PyLong_AsLong PyInt_AsLong
@@ -65,9 +71,15 @@
#define PYCAIRO_PyUnicode_FromString PyUnicode_FromString
#define PYCAIRO_PyUnicode_Join PyUnicode_Join
#define PYCAIRO_PyUnicode_InternFromString PyUnicode_InternFromString
+#define PYCAIRO_PyUnicode_Astring _PyUnicode_AsString
+#define PYCAIRO_PyUnicode_FromFormat PyUnicode_FromFormat
+
+#define PYCAIRO_PyNumber_Long PyNumber_Long
#define PYCAIRO_PyBytes_AsStringAndSize PyBytes_AsStringAndSize
+#define PYCAIRO_PyLong_Type PyLong_Type
+#define PYCAIRO_PyLongObject PyLongObject
#define PYCAIRO_PyLong_FromLong PyLong_FromLong
#define PYCAIRO_PyLong_AsLong PyLong_AsLong
diff --git a/cairo/context.c b/cairo/context.c
index b6a6d55..8418961 100644
--- a/cairo/context.c
+++ b/cairo/context.c
@@ -311,7 +311,7 @@ pycairo_font_extents (PycairoContext *o) {
static PyObject *
pycairo_get_antialias (PycairoContext *o) {
- return PYCAIRO_PyLong_FromLong (cairo_get_antialias (o->ctx));
+ RETURN_INT_ENUM (Antialias, cairo_get_antialias (o->ctx));
}
static PyObject *
@@ -358,7 +358,7 @@ pycairo_get_dash_count (PycairoContext *o) {
static PyObject *
pycairo_get_fill_rule (PycairoContext *o) {
- return PYCAIRO_PyLong_FromLong(cairo_get_fill_rule (o->ctx));
+ RETURN_INT_ENUM(FillRule, cairo_get_fill_rule (o->ctx));
}
static PyObject *
@@ -393,12 +393,12 @@ pycairo_get_group_target (PycairoContext *o) {
static PyObject *
pycairo_get_line_cap (PycairoContext *o) {
- return PYCAIRO_PyLong_FromLong(cairo_get_line_cap (o->ctx));
+ RETURN_INT_ENUM(LineCap, cairo_get_line_cap (o->ctx));
}
static PyObject *
pycairo_get_line_join (PycairoContext *o) {
- return PYCAIRO_PyLong_FromLong(cairo_get_line_join (o->ctx));
+ RETURN_INT_ENUM(LineJoin, cairo_get_line_join (o->ctx));
}
static PyObject *
@@ -420,7 +420,7 @@ pycairo_get_miter_limit (PycairoContext *o) {
static PyObject *
pycairo_get_operator (PycairoContext *o) {
- return PYCAIRO_PyLong_FromLong (cairo_get_operator (o->ctx));
+ RETURN_INT_ENUM(Operator, cairo_get_operator (o->ctx));
}
static PyObject *
diff --git a/cairo/enums.c b/cairo/enums.c
new file mode 100644
index 0000000..4120e39
--- /dev/null
+++ b/cairo/enums.c
@@ -0,0 +1,418 @@
+/* -*- mode: C; c-basic-offset: 2 -*-
+ *
+ * Pycairo - Python bindings for cairo
+ *
+ * Copyright © 2017 Christoph Reiter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#include "config.h"
+#include "private.h"
+
+
+/* For the CAIRO_SVG_VERSION_* defines */
+#ifdef CAIRO_HAS_SVG_SURFACE
+# include <cairo-svg.h>
+#endif
+/* For the CAIRO_PDF_VERSION_* defines */
+#ifdef CAIRO_HAS_PDF_SURFACE
+# include <cairo-pdf.h>
+#endif
+/* For the CAIRO_PS_LEVEL_* defines */
+#ifdef CAIRO_HAS_PS_SURFACE
+# include <cairo-ps.h>
+#endif
+
+typedef struct {
+ PYCAIRO_PyLongObject base;
+} Pycairo_IntEnumObject;
+
+static PyObject *
+int_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *dummy;
+
+ if (!PyArg_ParseTuple (args, "O", &dummy))
+ return NULL;
+
+ return PYCAIRO_PyLong_Type.tp_new(type, args, kwds);
+}
+
+PyObject *
+int_enum_create(PyTypeObject *type, long value) {
+ PyObject *args, *result;
+
+ args = Py_BuildValue("(l)", value);
+ if (args == NULL)
+ return NULL;
+ result = int_enum_new(type, args, NULL);
+ Py_DECREF(args);
+ return result;
+}
+
+static const char *map_name = "__map";
+
+static PyObject*
+enum_type_register_constant(PyTypeObject *type, const char* name, long value) {
+ PyObject *value_map;
+ PyObject *int_obj, *name_obj, *en;
+
+ /* Get/Create the int->name mapping */
+ value_map = PyDict_GetItemString(type->tp_dict, map_name);
+ if (value_map == NULL) {
+ value_map = PyDict_New();
+ PyDict_SetItemString(type->tp_dict, map_name, value_map);
+ Py_DECREF(value_map);
+ }
+
+ /* Add int->name pair to the mapping */
+ int_obj = PYCAIRO_PyLong_FromLong(value);
+ name_obj = PYCAIRO_PyUnicode_FromString (name);
+ if (PyDict_SetItem(value_map, int_obj, name_obj) < 0) {
+ Py_DECREF(int_obj);
+ Py_DECREF(name_obj);
+ return NULL;
+ }
+ Py_DECREF(int_obj);
+ Py_DECREF(name_obj);
+
+ /* Create a new enum instance of the right type and add to the class */
+ en = int_enum_create(type, value);
+ if (en == NULL || PyDict_SetItemString(type->tp_dict, name, en) < 0)
+ return NULL;
+
+ return en;
+}
+
+/* If returns NULL no error is set */
+static PyObject *
+int_enum_get_name(PyObject *obj) {
+ PyObject *value_map, *name_obj;
+
+ value_map = PyDict_GetItemString(Py_TYPE(obj)->tp_dict, map_name);
+ if(value_map == NULL)
+ return NULL;
+
+ name_obj = PyDict_GetItem(value_map, obj);
+ if(name_obj == NULL)
+ return NULL;
+
+ return PYCAIRO_PyUnicode_FromFormat("%s.%s", Py_TYPE(obj)->tp_name,
+ PYCAIRO_PyUnicode_Astring(name_obj));
+}
+
+static PyObject *
+int_enum_repr(PyObject *obj)
+{
+ PyObject *name_obj;
+
+ name_obj = int_enum_get_name(obj);
+ if(name_obj == NULL)
+ return PYCAIRO_PyLong_Type.tp_repr(obj);
+
+ return name_obj;
+}
+
+static PyObject *
+int_enum_reduce(PyObject *self)
+{
+ PyObject *num = PYCAIRO_PyNumber_Long (self);
+ if (num == NULL)
+ return NULL;
+ return Py_BuildValue ("(O, (N))", &PYCAIRO_PyLong_Type, num);
+}
+
+static PyMethodDef int_enum_methods[] = {
+ {"__reduce__", (PyCFunction)int_enum_reduce, METH_NOARGS},
+ {NULL, NULL, 0},
+};
+
+PyTypeObject Pycairo_IntEnum_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "cairo._IntEnum",
+ sizeof(Pycairo_IntEnumObject),
+};
+
+#define DEFINE_ENUM(n) \
+ PyTypeObject Pycairo_##n##_Type = { \
+ PyVarObject_HEAD_INIT(NULL, 0) \
+ "cairo." #n, \
+ sizeof(Pycairo_IntEnumObject), \
+ };
+
+DEFINE_ENUM(Antialias)
+DEFINE_ENUM(Content)
+DEFINE_ENUM(Extend)
+DEFINE_ENUM(FillRule)
+DEFINE_ENUM(Filter)
+DEFINE_ENUM(FontSlant)
+DEFINE_ENUM(FontWeight)
+DEFINE_ENUM(Format)
+DEFINE_ENUM(HintMetrics)
+DEFINE_ENUM(HintStyle)
+DEFINE_ENUM(LineCap)
+DEFINE_ENUM(LineJoin)
+DEFINE_ENUM(Operator)
+DEFINE_ENUM(PathDataType)
+DEFINE_ENUM(RegionOverlap)
+DEFINE_ENUM(Status)
+DEFINE_ENUM(SubpixelOrder)
+#ifdef CAIRO_HAS_SVG_SURFACE
+DEFINE_ENUM(SVGVersion)
+#endif
+#ifdef CAIRO_HAS_PDF_SURFACE
+DEFINE_ENUM(PDFVersion)
+#endif
+#ifdef CAIRO_HAS_PS_SURFACE
+DEFINE_ENUM(PSLevel)
+#endif
+
+#undef DEFINE_ENUM
+
+static int
+init_enum_type (PyObject *module, const char *name, PyTypeObject *type) {
+ type->tp_base = &Pycairo_IntEnum_Type;
+ type->tp_flags = Py_TPFLAGS_DEFAULT;
+
+ if (PyType_Ready(type) < 0)
+ return -1;
+
+ Py_INCREF(type);
+ if (PyModule_AddObject(module, name, (PyObject *)type) < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+init_enums (PyObject *module) {
+ PyObject *ev;
+
+ Pycairo_IntEnum_Type.tp_repr = (reprfunc)int_enum_repr;
+ Pycairo_IntEnum_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
+ Pycairo_IntEnum_Type.tp_methods = int_enum_methods;
+ Pycairo_IntEnum_Type.tp_base = &PYCAIRO_PyLong_Type;
+ Pycairo_IntEnum_Type.tp_new = (newfunc)int_enum_new;
+
+ if (PyType_Ready(&Pycairo_IntEnum_Type) < 0)
+ return -1;
+
+#define ENUM(t) \
+ if (init_enum_type(module, #t, &Pycairo_##t##_Type) < 0) \
+ return -1;
+
+#define CONSTANT(t, a, b) \
+ ev = enum_type_register_constant(&Pycairo_##t##_Type, #b, CAIRO_##a##_##b); \
+ if (ev == NULL || PyModule_AddObject(module, #a "_" #b, ev) < 0) \
+ return -1;
+
+ ENUM(Antialias);
+ CONSTANT(Antialias, ANTIALIAS, DEFAULT);
+ CONSTANT(Antialias, ANTIALIAS, NONE);
+ CONSTANT(Antialias, ANTIALIAS, GRAY);
+ CONSTANT(Antialias, ANTIALIAS, SUBPIXEL);
+ CONSTANT(Antialias, ANTIALIAS, FAST);
+ CONSTANT(Antialias, ANTIALIAS, GOOD);
+ CONSTANT(Antialias, ANTIALIAS, BEST);
+
+ ENUM(Content);
+ CONSTANT(Content, CONTENT, COLOR);
+ CONSTANT(Content, CONTENT, ALPHA);
+ CONSTANT(Content, CONTENT, COLOR_ALPHA);
+
+ ENUM(Extend);
+ CONSTANT(Extend, EXTEND, NONE);
+ CONSTANT(Extend, EXTEND, REPEAT);
+ CONSTANT(Extend, EXTEND, REFLECT);
+ CONSTANT(Extend, EXTEND, PAD);
+
+ ENUM(FillRule);
+ CONSTANT(FillRule, FILL_RULE, WINDING);
+ CONSTANT(FillRule, FILL_RULE, EVEN_ODD);
+
+ ENUM(Filter);
+ CONSTANT(Filter, FILTER, FAST);
+ CONSTANT(Filter, FILTER, GOOD);
+ CONSTANT(Filter, FILTER, BEST);
+ CONSTANT(Filter, FILTER, NEAREST);
+ CONSTANT(Filter, FILTER, BILINEAR);
+ CONSTANT(Filter, FILTER, GAUSSIAN);
+
+ ENUM(FontWeight)
+ CONSTANT(FontWeight, FONT_WEIGHT, NORMAL);
+ CONSTANT(FontWeight, FONT_WEIGHT, BOLD);
+
+ ENUM(FontSlant);
+ CONSTANT(FontSlant, FONT_SLANT, NORMAL);
+ CONSTANT(FontSlant, FONT_SLANT, ITALIC);
+ CONSTANT(FontSlant, FONT_SLANT, OBLIQUE);
+
+ ENUM(Format);
+ CONSTANT(Format, FORMAT, INVALID);
+ CONSTANT(Format, FORMAT, ARGB32);
+ CONSTANT(Format, FORMAT, RGB24);
+ CONSTANT(Format, FORMAT, A8);
+ CONSTANT(Format, FORMAT, A1);
+ CONSTANT(Format, FORMAT, RGB16_565);
+ CONSTANT(Format, FORMAT, RGB30);
+
+ ENUM(HintMetrics);
+ CONSTANT(HintMetrics, HINT_METRICS, DEFAULT);
+ CONSTANT(HintMetrics, HINT_METRICS, OFF);
+ CONSTANT(HintMetrics, HINT_METRICS, ON);
+
+ ENUM(HintStyle);
+ CONSTANT(HintStyle, HINT_STYLE, DEFAULT);
+ CONSTANT(HintStyle, HINT_STYLE, NONE);
+ CONSTANT(HintStyle, HINT_STYLE, SLIGHT);
+ CONSTANT(HintStyle, HINT_STYLE, MEDIUM);
+ CONSTANT(HintStyle, HINT_STYLE, FULL);
+
+ ENUM(LineCap);
+ CONSTANT(LineCap, LINE_CAP, BUTT);
+ CONSTANT(LineCap, LINE_CAP, ROUND);
+ CONSTANT(LineCap, LINE_CAP, SQUARE);
+
+ ENUM(LineJoin);
+ CONSTANT(LineJoin, LINE_JOIN, MITER);
+ CONSTANT(LineJoin, LINE_JOIN, ROUND);
+ CONSTANT(LineJoin, LINE_JOIN, BEVEL);
+
+ ENUM(Operator);
+ CONSTANT(Operator, OPERATOR, CLEAR);
+ CONSTANT(Operator, OPERATOR, SOURCE);
+ CONSTANT(Operator, OPERATOR, OVER);
+ CONSTANT(Operator, OPERATOR, IN);
+ CONSTANT(Operator, OPERATOR, OUT);
+ CONSTANT(Operator, OPERATOR, ATOP);
+ CONSTANT(Operator, OPERATOR, DEST);
+ CONSTANT(Operator, OPERATOR, DEST_OVER);
+ CONSTANT(Operator, OPERATOR, DEST_IN);
+ CONSTANT(Operator, OPERATOR, DEST_OUT);
+ CONSTANT(Operator, OPERATOR, DEST_ATOP);
+ CONSTANT(Operator, OPERATOR, XOR);
+ CONSTANT(Operator, OPERATOR, ADD);
+ CONSTANT(Operator, OPERATOR, SATURATE);
+ CONSTANT(Operator, OPERATOR, MULTIPLY);
+ CONSTANT(Operator, OPERATOR, SCREEN);
+ CONSTANT(Operator, OPERATOR, OVERLAY);
+ CONSTANT(Operator, OPERATOR, DARKEN);
+ CONSTANT(Operator, OPERATOR, LIGHTEN);
+ CONSTANT(Operator, OPERATOR, COLOR_DODGE);
+ CONSTANT(Operator, OPERATOR, COLOR_BURN);
+ CONSTANT(Operator, OPERATOR, HARD_LIGHT);
+ CONSTANT(Operator, OPERATOR, SOFT_LIGHT);
+ CONSTANT(Operator, OPERATOR, DIFFERENCE);
+ CONSTANT(Operator, OPERATOR, EXCLUSION);
+ CONSTANT(Operator, OPERATOR, HSL_HUE);
+ CONSTANT(Operator, OPERATOR, HSL_SATURATION);
+ CONSTANT(Operator, OPERATOR, HSL_COLOR);
+ CONSTANT(Operator, OPERATOR, HSL_LUMINOSITY);
+
+ ENUM(Status);
+ CONSTANT(Status, STATUS, SUCCESS);
+ CONSTANT(Status, STATUS, NO_MEMORY);
+ CONSTANT(Status, STATUS, INVALID_RESTORE);
+ CONSTANT(Status, STATUS, INVALID_POP_GROUP);
+ CONSTANT(Status, STATUS, NO_CURRENT_POINT);
+ CONSTANT(Status, STATUS, INVALID_MATRIX);
+ CONSTANT(Status, STATUS, INVALID_STATUS);
+ CONSTANT(Status, STATUS, NULL_POINTER);
+ CONSTANT(Status, STATUS, INVALID_STRING);
+ CONSTANT(Status, STATUS, INVALID_PATH_DATA);
+ CONSTANT(Status, STATUS, READ_ERROR);
+ CONSTANT(Status, STATUS, WRITE_ERROR);
+ CONSTANT(Status, STATUS, SURFACE_FINISHED);
+ CONSTANT(Status, STATUS, SURFACE_TYPE_MISMATCH);
+ CONSTANT(Status, STATUS, PATTERN_TYPE_MISMATCH);
+ CONSTANT(Status, STATUS, INVALID_CONTENT);
+ CONSTANT(Status, STATUS, INVALID_FORMAT);
+ CONSTANT(Status, STATUS, INVALID_VISUAL);
+ CONSTANT(Status, STATUS, FILE_NOT_FOUND);
+ CONSTANT(Status, STATUS, INVALID_DASH);
+ CONSTANT(Status, STATUS, INVALID_DSC_COMMENT);
+ CONSTANT(Status, STATUS, INVALID_INDEX);
+ CONSTANT(Status, STATUS, CLIP_NOT_REPRESENTABLE);
+ CONSTANT(Status, STATUS, TEMP_FILE_ERROR);
+ CONSTANT(Status, STATUS, INVALID_STRIDE);
+ CONSTANT(Status, STATUS, FONT_TYPE_MISMATCH);
+ CONSTANT(Status, STATUS, USER_FONT_IMMUTABLE);
+ CONSTANT(Status, STATUS, USER_FONT_ERROR);
+ CONSTANT(Status, STATUS, NEGATIVE_COUNT);
+ CONSTANT(Status, STATUS, INVALID_CLUSTERS);
+ CONSTANT(Status, STATUS, INVALID_SLANT);
+ CONSTANT(Status, STATUS, INVALID_WEIGHT);
+ CONSTANT(Status, STATUS, INVALID_SIZE);
+ CONSTANT(Status, STATUS, USER_FONT_NOT_IMPLEMENTED);
+ CONSTANT(Status, STATUS, DEVICE_TYPE_MISMATCH);
+ CONSTANT(Status, STATUS, DEVICE_ERROR);
+ CONSTANT(Status, STATUS, INVALID_MESH_CONSTRUCTION);
+ CONSTANT(Status, STATUS, DEVICE_FINISHED);
+ CONSTANT(Status, STATUS, LAST_STATUS);
+
+ ENUM(PathDataType);
+ CONSTANT(PathDataType, PATH, MOVE_TO);
+ CONSTANT(PathDataType, PATH, LINE_TO);
+ CONSTANT(PathDataType, PATH, CURVE_TO);
+ CONSTANT(PathDataType, PATH, CLOSE_PATH);
+
+ ENUM(RegionOverlap);
+ CONSTANT(RegionOverlap, REGION_OVERLAP, IN);
+ CONSTANT(RegionOverlap, REGION_OVERLAP, OUT);
+ CONSTANT(RegionOverlap, REGION_OVERLAP, PART);
+
+ ENUM(SubpixelOrder);
+ CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, DEFAULT);
+ CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, RGB);
+ CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, BGR);
+ CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, VRGB);
+ CONSTANT(SubpixelOrder, SUBPIXEL_ORDER, VBGR);
+
+#ifdef CAIRO_HAS_SVG_SURFACE
+ ENUM(SVGVersion);
+ CONSTANT(SVGVersion, SVG, VERSION_1_1);
+ CONSTANT(SVGVersion, SVG, VERSION_1_2);
+#endif
+
+#ifdef CAIRO_HAS_PDF_SURFACE
+ ENUM(PDFVersion);
+ CONSTANT(PDFVersion, PDF, VERSION_1_4);
+ CONSTANT(PDFVersion, PDF, VERSION_1_5);
+#endif
+
+#ifdef CAIRO_HAS_PS_SURFACE
+ ENUM(PSLevel);
+ CONSTANT(PSLevel, PS, LEVEL_2);
+ CONSTANT(PSLevel, PS, LEVEL_3);
+#endif
+
+#undef ENUM
+#undef CONSTANT
+
+ return 0;
+}
diff --git a/cairo/error.c b/cairo/error.c
index e869717..3d2b191 100644
--- a/cairo/error.c
+++ b/cairo/error.c
@@ -54,7 +54,8 @@ Pycairo_Set_Error(cairo_status_t status)
{
PyObject *args, *v;
- args = Py_BuildValue("(si)", status_to_string(status), status);
+ args = Py_BuildValue("(sO)", status_to_string(status),
+ CREATE_INT_ENUM(Status, status));
v = PyObject_Call(_Pycairo_Get_Error(), args, NULL);
Py_DECREF(args);
if (v != NULL) {
diff --git a/cairo/font.c b/cairo/font.c
index b420c60..45c1d52 100644
--- a/cairo/font.c
+++ b/cairo/font.c
@@ -170,12 +170,12 @@ toy_font_get_family (PycairoToyFontFace *o) {
static PyObject *
toy_font_get_slant (PycairoToyFontFace *o) {
- return PYCAIRO_PyLong_FromLong (cairo_toy_font_face_get_slant (o->font_face));
+ RETURN_INT_ENUM (FontSlant, cairo_toy_font_face_get_slant (o->font_face));
}
static PyObject *
toy_font_get_weight (PycairoToyFontFace *o) {
- return PYCAIRO_PyLong_FromLong (cairo_toy_font_face_get_weight (o->font_face));
+ RETURN_INT_ENUM (FontWeight, cairo_toy_font_face_get_weight (o->font_face));
}
static PyMethodDef toy_font_face_methods[] = {
@@ -466,25 +466,25 @@ font_options_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
static PyObject *
font_options_get_antialias (PycairoFontOptions *o) {
- return PYCAIRO_PyLong_FromLong (cairo_font_options_get_antialias (o->font_options));
+ RETURN_INT_ENUM (Antialias, cairo_font_options_get_antialias (o->font_options));
}
static PyObject *
font_options_get_hint_metrics (PycairoFontOptions *o) {
- return PYCAIRO_PyLong_FromLong (cairo_font_options_get_hint_metrics
- (o->font_options));
+ RETURN_INT_ENUM (HintMetrics,
+ cairo_font_options_get_hint_metrics (o->font_options));
}
static PyObject *
font_options_get_hint_style (PycairoFontOptions *o) {
- return PYCAIRO_PyLong_FromLong (cairo_font_options_get_hint_style
- (o->font_options));
+ RETURN_INT_ENUM (HintStyle,
+ cairo_font_options_get_hint_style (o->font_options));
}
static PyObject *
font_options_get_subpixel_order (PycairoFontOptions *o) {
- return PYCAIRO_PyLong_FromLong (cairo_font_options_get_subpixel_order
- (o->font_options));
+ RETURN_INT_ENUM (SubpixelOrder,
+ cairo_font_options_get_subpixel_order (o->font_options));
}
static PyObject *
diff --git a/cairo/pattern.c b/cairo/pattern.c
index f59c307..050c9ab 100644
--- a/cairo/pattern.c
+++ b/cairo/pattern.c
@@ -111,7 +111,7 @@ pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
static PyObject *
pattern_get_extend (PycairoPattern *o) {
- return PYCAIRO_PyLong_FromLong (cairo_pattern_get_extend (o->pattern));
+ RETURN_INT_ENUM (Extend, cairo_pattern_get_extend (o->pattern));
}
static PyObject *
@@ -152,7 +152,7 @@ pattern_get_filter (PycairoPattern *o) {
filter = cairo_pattern_get_filter (o->pattern);
Py_END_ALLOW_THREADS;
- return PYCAIRO_PyLong_FromLong (filter);
+ RETURN_INT_ENUM (Filter, filter);
}
static PyObject *
diff --git a/cairo/private.h b/cairo/private.h
index febbeb4..4b93c87 100644
--- a/cairo/private.h
+++ b/cairo/private.h
@@ -193,4 +193,44 @@ int Pycairo_Check_Status (cairo_status_t status);
PyObject *error_get_type(void);
+/* int enums */
+
+int init_enums(PyObject *module);
+PyObject *int_enum_create(PyTypeObject *type, long value);
+
+#define DECL_ENUM(name) PyTypeObject Pycairo_##name##_Type;
+
+#define CREATE_INT_ENUM(type_name, value) \
+ (int_enum_create(&Pycairo_##type_name##_Type, value))
+
+#define RETURN_INT_ENUM(type_name, value) \
+ return CREATE_INT_ENUM(type_name, value);
+
+DECL_ENUM(Antialias)
+DECL_ENUM(Content)
+DECL_ENUM(Extend)
+DECL_ENUM(FillRule)
+DECL_ENUM(Filter)
+DECL_ENUM(FontSlant)
+DECL_ENUM(FontWeight)
+DECL_ENUM(Format)
+DECL_ENUM(HintMetrics)
+DECL_ENUM(HintStyle)
+DECL_ENUM(LineCap)
+DECL_ENUM(LineJoin)
+DECL_ENUM(Operator)
+DECL_ENUM(PathDataType)
+DECL_ENUM(RegionOverlap)
+DECL_ENUM(Status)
+DECL_ENUM(SubpixelOrder)
+#ifdef CAIRO_HAS_SVG_SURFACE
+DECL_ENUM(SVGVersion)
+#endif
+#ifdef CAIRO_HAS_PDF_SURFACE
+DECL_ENUM(PDFVersion)
+#endif
+#ifdef CAIRO_HAS_PS_SURFACE
+DECL_ENUM(PSLevel)
+#endif
+
#endif /* _PYCAIRO_PRIVATE_H_ */
diff --git a/cairo/region.c b/cairo/region.c
index 2f9d133..0c47982 100644
--- a/cairo/region.c
+++ b/cairo/region.c
@@ -295,7 +295,7 @@ region_num_rectangles (PycairoRegion *o) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_num_rectangles(o->region);
Py_END_ALLOW_THREADS;
- return Py_BuildValue("i", res);
+ return PYCAIRO_PyLong_FromLong(res);
}
@@ -360,7 +360,8 @@ region_contains_rectangle (PycairoRegion *o, PyObject *args) {
Py_BEGIN_ALLOW_THREADS;
res = cairo_region_contains_rectangle(o->region, &(rect_int->rectangle_int));
Py_END_ALLOW_THREADS;
- return Py_BuildValue("i", res);
+
+ RETURN_INT_ENUM(RegionOverlap, res);
}
diff --git a/cairo/surface.c b/cairo/surface.c
index 1aacff7..bf86774 100644
--- a/cairo/surface.c
+++ b/cairo/surface.c
@@ -242,7 +242,7 @@ surface_flush (PycairoSurface *o) {
static PyObject *
surface_get_content (PycairoSurface *o) {
- return PYCAIRO_PyLong_FromLong (cairo_surface_get_content (o->surface));
+ RETURN_INT_ENUM (Content, cairo_surface_get_content (o->surface));
}
static PyObject *
@@ -788,7 +788,7 @@ image_surface_get_data (PycairoImageSurface *o) {
static PyObject *
image_surface_get_format (PycairoImageSurface *o) {
- return PYCAIRO_PyLong_FromLong (cairo_image_surface_get_format (o->surface));
+ RETURN_INT_ENUM (Format, cairo_image_surface_get_format (o->surface));
}
static PyObject *
@@ -809,9 +809,9 @@ image_surface_get_width (PycairoImageSurface *o) {
#if PY_MAJOR_VERSION < 3
/* Buffer interface functions, used by ImageSurface.get_data() */
-static int
-image_surface_buffer_getreadbuf (PycairoImageSurface *o, int segment,
- const void **ptr) {
+static Py_ssize_t
+image_surface_buffer_getreadbuf (PycairoImageSurface *o, Py_ssize_t segment,
+ const void **ptr) {
cairo_surface_t *surface = o->surface;
int height, stride;
@@ -826,9 +826,9 @@ image_surface_buffer_getreadbuf (PycairoImageSurface *o, int segment,
return height * stride;
}
-static int
-image_surface_buffer_getwritebuf (PycairoImageSurface *o, int segment,
- const void **ptr) {
+static Py_ssize_t
+image_surface_buffer_getwritebuf (PycairoImageSurface *o, Py_ssize_t segment,
+ const void **ptr) {
cairo_surface_t *surface = o->surface;
int height, stride;
@@ -843,8 +843,8 @@ image_surface_buffer_getwritebuf (PycairoImageSurface *o, int segment,
return height * stride;
}
-static int
-image_surface_buffer_getsegcount (PycairoImageSurface *o, int *lenp) {
+static Py_ssize_t
+image_surface_buffer_getsegcount (PycairoImageSurface *o, Py_ssize_t *lenp) {
if (lenp) {
/* report the sum of the sizes (in bytes) of all segments */
cairo_surface_t *surface = o->surface;
@@ -855,12 +855,28 @@ image_surface_buffer_getsegcount (PycairoImageSurface *o, int *lenp) {
return 1; /* surface data is all in one segment */
}
+static Py_ssize_t
+image_surface_buffer_getcharbuffer (PycairoImageSurface *o,
+ Py_ssize_t segment,
+ char **ptrptr) {
+ Py_ssize_t segment_size;
+
+ if (segment != 0) {
+ PyErr_SetString(PyExc_SystemError,
+ "accessing non-existent ImageSurface segment");
+ return -1;
+ }
+
+ image_surface_buffer_getsegcount (o, &segment_size);
+ return segment_size;
+}
+
/* See Python C API Manual 10.7 */
static PyBufferProcs image_surface_as_buffer = {
(readbufferproc) image_surface_buffer_getreadbuf,
(writebufferproc)image_surface_buffer_getwritebuf,
(segcountproc) image_surface_buffer_getsegcount,
- (charbufferproc) NULL,
+ (charbufferproc) image_surface_buffer_getcharbuffer,
};
#endif
@@ -907,7 +923,12 @@ PyTypeObject PycairoImageSurface_Type = {
#else
0, /* tp_as_buffer */
#endif
+#if PY_MAJOR_VERSION < 3
+ Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
+#else
Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
@@ -1019,7 +1040,7 @@ pdf_get_versions (PyObject *self) {
return NULL;
for (i=0; i < num_versions; i++) {
- num = PYCAIRO_PyLong_FromLong (versions[i]);
+ num = CREATE_INT_ENUM (PDFVersion, versions[i]);
if (num == NULL) {
Py_DECREF (list);
return NULL;
@@ -1275,7 +1296,7 @@ ps_get_levels (PyObject *self) {
return NULL;
for (i=0; i < num_levels; i++) {
- num = PYCAIRO_PyLong_FromLong (levels[i]);
+ num = CREATE_INT_ENUM (PSLevel, levels[i]);
if (num == NULL) {
Py_DECREF (list);
return NULL;
@@ -1532,7 +1553,7 @@ svg_get_versions (PyObject *self) {
return NULL;
for (i=0; i < num_versions; i++) {
- num = PYCAIRO_PyLong_FromLong (versions[i]);
+ num = CREATE_INT_ENUM (SVGVersion, versions[i]);
if (num == NULL) {
Py_DECREF (list);
return NULL;
diff --git a/docs/conf.py b/docs/conf.py
index afcb93c..dc9f9b8 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -11,7 +11,7 @@ intersphinx_mapping = {
source_suffix = '.rst'
master_doc = 'index'
project = u'Pycairo'
-copyright = u'2008, Steve Chaplin'
+html_show_copyright = False
exclude_patterns = ['_build']
pygments_style = 'sphinx'
html_theme = "sphinx_rtd_theme"
@@ -33,3 +33,4 @@ extlinks = {
'bug': ('https://github.com/pygobject/pycairo/issues/%s', '#'),
'pr': ('https://github.com/pygobject/pycairo/pull/%s', '#pr-'),
}
+suppress_warnings = ["image.nonlocal_uri"]
diff --git a/docs/examples.rst b/docs/examples.rst
new file mode 100644
index 0000000..259d391
--- /dev/null
+++ b/docs/examples.rst
@@ -0,0 +1,9 @@
+========
+Examples
+========
+
+The Git repository and release tarball contain various examples showing
+various features of cairo and integration with pygame and GTK+ in the
+"examples" directory:
+
+ https://github.com/pygobject/pycairo/tree/master/examples
diff --git a/docs/faq.rst b/docs/faq.rst
deleted file mode 100644
index 2cd986d..0000000
--- a/docs/faq.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-***
-FAQ
-***
-
-.. currentmodule:: cairo
-
-
-Pycairo FAQ - Frequently Asked Questions
-========================================
-
-Q: Can I subclass pycairo classes?
-
-A: Cairo, the C library, is not an object oriented library, so a Python
-binding can never be a truly object oriented interface to cairo. One way to
-write the Python bindings for cairo would be as a single long list of module
-functions - this would be the most accurate representation of the underlying C
-library. Pycairo (and most other cairo language bindings?) instead chose to
-implement the bindings using Context, Surface, Pattern, etc classes. An
-advantage is that the classes organise cairo into groups of similar functions.
-A disadvantage is that creates an illusion that cairo is object oriented
-library, and people are then tempted to create subclasses to override cairo
-methods. When in fact there are no methods to override, just cairo functions
-which can't be overridden.
-
-The cairo documentation Appendix A "Creating a language binding for cairo"
-section "Memory Management" describes why deriving from a Surface creates
-problems and is best avoided.
-
-cairo.Context can be subclassed.
-All other pycairo subclasses cannot be subclassed.
-
-
-Q: How do I use pycairo with numpy?
-
-A: See test/isurface_create_for_data2.py
-
-
-Q: How do I use pycairo with pygame?
-
-A: See test/pygame-test1.py
- test/pygame-test2.py
diff --git a/docs/index.rst b/docs/index.rst
index 9787be0..0217d36 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -8,9 +8,10 @@ Pycairo - Python bindings for cairo
:hidden:
changelog
+ Tutorial <tutorial>
reference/index
pycairo_c_api
- faq
+ resources
.. currentmodule:: cairo
.. title:: Overview
diff --git a/docs/integration.rst b/docs/integration.rst
new file mode 100644
index 0000000..2d45f45
--- /dev/null
+++ b/docs/integration.rst
@@ -0,0 +1,44 @@
+================================
+Integration with other Libraries
+================================
+
+NumPy & ImageSurface
+--------------------
+
+Creating an ImageSurface from a NumPy array:
+ .. code:: python
+
+ import numpy
+ import cairo
+
+ width, height = 255, 255
+ data = numpy.ndarray(shape=(height, width), dtype=numpy.uint32)
+ surface = cairo.ImageSurface.create_for_data(
+ data, cairo.FORMAT_ARGB32, width, height)
+
+Creating a NumPy array from an ImageSurface:
+ .. code:: python
+
+ import numpy
+ import cairo
+
+ width, height = 255, 255
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ buf = surface.get_data()
+ data = numpy.ndarray(shape=(width, height),
+ dtype=numpy.uint32,
+ buffer=buf)
+
+
+Pygame & ImageSurface
+---------------------
+
+Creating a pygame.image from an ImageSurface:
+ .. code:: python
+
+ import pygame
+ import cairo
+
+ width, height = 255, 255
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ image = pygame.image.frombuffer(buf, (width, height), "ARGB")
diff --git a/docs/pycairo_c_api.rst b/docs/pycairo_c_api.rst
index fda0b0d..2d73b24 100644
--- a/docs/pycairo_c_api.rst
+++ b/docs/pycairo_c_api.rst
@@ -54,68 +54,66 @@ Example showing how to import the pycairo API::
Pycairo Objects
===============
-Objects::
-
- PycairoContext
- PycairoFontFace
- PycairoToyFontFace
- PycairoFontOptions
- PycairoMatrix
- PycairoPath
- PycairoPattern
- PycairoRegion
- PycairoRectangleInt
- PycairoSolidPattern
- PycairoSurfacePattern
- PycairoGradient
- PycairoLinearGradient
- PycairoRadialGradient
- PycairoScaledFont
- PycairoSurface
- PycairoImageSurface
- PycairoPDFSurface
- PycairoPSSurface
- PycairoRecordingSurface
- PycairoSVGSurface
- PycairoWin32Surface
- PycairoXCBSurface
- PycairoXlibSurface
+
+.. c:type:: PycairoContext
+.. c:type:: PycairoFontFace
+.. c:type:: PycairoToyFontFace
+.. c:type:: PycairoFontOptions
+.. c:type:: PycairoMatrix
+.. c:type:: PycairoPath
+.. c:type:: PycairoPattern
+.. c:type:: PycairoRegion
+.. c:type:: PycairoRectangleInt
+.. c:type:: PycairoSolidPattern
+.. c:type:: PycairoSurfacePattern
+.. c:type:: PycairoGradient
+.. c:type:: PycairoLinearGradient
+.. c:type:: PycairoRadialGradient
+.. c:type:: PycairoScaledFont
+.. c:type:: PycairoSurface
+.. c:type:: PycairoImageSurface
+.. c:type:: PycairoPDFSurface
+.. c:type:: PycairoPSSurface
+.. c:type:: PycairoRecordingSurface
+.. c:type:: PycairoSVGSurface
+.. c:type:: PycairoWin32Surface
+.. c:type:: PycairoXCBSurface
+.. c:type:: PycairoXlibSurface
Pycairo Types
=============
-Types::
-
- PyTypeObject *Context_Type;
- PyTypeObject *FontFace_Type;
- PyTypeObject *ToyFontFace_Type;
- PyTypeObject *FontOptions_Type;
- PyTypeObject *Matrix_Type;
- PyTypeObject *Path_Type;
- PyTypeObject *Pattern_Type;
- PyTypeObject *Region_Type;
- PyTypeObject *RectangleInt_Type;
- PyTypeObject *SolidPattern_Type;
- PyTypeObject *SurfacePattern_Type;
- PyTypeObject *Gradient_Type;
- PyTypeObject *LinearGradient_Type;
- PyTypeObject *RadialGradient_Type;
- PyTypeObject *ScaledFont_Type;
- PyTypeObject *Surface_Type;
- PyTypeObject *ImageSurface_Type;
- PyTypeObject *PDFSurface_Type;
- PyTypeObject *PSSurface_Type;
- PyTypeObject *RecordingSurface_Type;
- PyTypeObject *SVGSurface_Type;
- PyTypeObject *Win32Surface_Type;
- PyTypeObject *XCBSurface_Type;
- PyTypeObject *XlibSurface_Type;
+
+.. c:type:: PyTypeObject *Context_Type
+.. c:type:: PyTypeObject *FontFace_Type
+.. c:type:: PyTypeObject *ToyFontFace_Type
+.. c:type:: PyTypeObject *FontOptions_Type
+.. c:type:: PyTypeObject *Matrix_Type
+.. c:type:: PyTypeObject *Path_Type
+.. c:type:: PyTypeObject *Pattern_Type
+.. c:type:: PyTypeObject *Region_Type
+.. c:type:: PyTypeObject *RectangleInt_Type
+.. c:type:: PyTypeObject *SolidPattern_Type
+.. c:type:: PyTypeObject *SurfacePattern_Type
+.. c:type:: PyTypeObject *Gradient_Type
+.. c:type:: PyTypeObject *LinearGradient_Type
+.. c:type:: PyTypeObject *RadialGradient_Type
+.. c:type:: PyTypeObject *ScaledFont_Type
+.. c:type:: PyTypeObject *Surface_Type
+.. c:type:: PyTypeObject *ImageSurface_Type
+.. c:type:: PyTypeObject *PDFSurface_Type
+.. c:type:: PyTypeObject *PSSurface_Type
+.. c:type:: PyTypeObject *RecordingSurface_Type
+.. c:type:: PyTypeObject *SVGSurface_Type
+.. c:type:: PyTypeObject *Win32Surface_Type
+.. c:type:: PyTypeObject *XCBSurface_Type
+.. c:type:: PyTypeObject *XlibSurface_Type
Functions
=========
-.. c:function:: cairo_t * PycairoContext_GET(obj)
+.. c:macro:: cairo_t * PycairoContext_GET(PycairoContext *obj)
get the C cairo_t \* object out of the PycairoContext \*obj
@@ -151,3 +149,21 @@ Functions
.. c:function:: int Pycairo_Check_Status(cairo_status_t status)
+
+
+Cairo Types
+===========
+
+These are only listed here so they can be referenced in the documentation.
+
+.. c:type:: cairo_t
+ cairo_status_t
+ cairo_surface_t
+ cairo_scaled_font_t
+ cairo_rectangle_int_t
+ cairo_region_t
+ cairo_pattern_t
+ cairo_matrix_t
+ cairo_font_options_t
+ cairo_path_t
+ cairo_font_face_t
diff --git a/docs/reference/constants.rst b/docs/reference/constants.rst
index 98885c3..1a84d8d 100644
--- a/docs/reference/constants.rst
+++ b/docs/reference/constants.rst
@@ -1,4 +1,4 @@
-<.. _constants:
+.. _constants:
******************************
Module Functions and Constants
@@ -67,715 +67,6 @@ cairo.HAS
.. versionadded:: 1.12.0
-.. _constants_ANTIALIAS:
-
-cairo.ANTIALIAS
----------------
-ANTIALIAS specifies the type of antialiasing to do when rendering text or
-shapes.
-
-.. data:: ANTIALIAS_DEFAULT
-
- Use the default antialiasing for the subsystem and target device
-
-.. data:: ANTIALIAS_NONE
-
- Use a bilevel alpha mask
-
-.. data:: ANTIALIAS_GRAY
-
- Perform single-color antialiasing (using shades of gray for black text on a
- white background, for example).
-
-.. data:: ANTIALIAS_SUBPIXEL
-
- Perform antialiasing by taking advantage of the order of subpixel elements
- on devices such as LCD panels.
-
-.. data:: ANTIALIAS_FAST
-
- Hint that the backend should perform some antialiasing but prefer speed
- over quality.
-
- .. versionadded:: 1.12.0
-
-.. data:: ANTIALIAS_GOOD
-
- The backend should balance quality against performance.
-
- .. versionadded:: 1.12.0
-
-.. data:: ANTIALIAS_BEST
-
- Hint that the backend should render at the highest quality, sacrificing
- speed if necessary.
-
- .. versionadded:: 1.12.0
-
-
-.. _constants_CONTENT:
-
-cairo.CONTENT
--------------
-These constants are used to describe the content that a :class:`Surface` will
-contain, whether color information, alpha information (translucence
-vs. opacity), or both.
-
-.. data:: CONTENT_COLOR
-
- The surface will hold color content only.
-
-.. data:: CONTENT_ALPHA
-
- The surface will hold alpha content only.
-
-.. data:: CONTENT_COLOR_ALPHA
-
- The surface will hold color and alpha content.
-
-
-.. _constants_EXTEND:
-
-cairo.EXTEND
-------------
-These constants are used to describe how :class:`Pattern` color/alpha will be
-determined for areas "outside" the pattern's natural area, (for example,
-outside the surface bounds or outside the gradient geometry).
-
-The default extend mode is *EXTEND_NONE* for :class:`SurfacePattern` and
-*EXTEND_PAD* for :class:`Gradient` patterns.
-
-.. data:: EXTEND_NONE
-
- pixels outside of the source pattern are fully transparent
-
-.. data:: EXTEND_REPEAT
-
- the pattern is tiled by repeating
-
-.. data:: EXTEND_REFLECT
-
- the pattern is tiled by reflecting at the edges (Implemented for surface
- patterns since 1.6)
-
-.. data:: EXTEND_PAD
-
- pixels outside of the pattern copy the closest pixel from the source (Since
- 1.2; but only implemented for surface patterns since 1.6)
-
-New entries may be added in future versions.
-
-
-.. _constants_FILL_RULE:
-
-cairo.FILL_RULE
----------------
-These constants are used to select how paths are filled. For both fill
-rules, whether or not a point is included in the fill is determined by taking
-a ray from that point to infinity and looking at intersections with the
-path. The ray can be in any direction, as long as it doesn't pass through the
-end point of a segment or have a tricky intersection such as intersecting
-tangent to the path. (Note that filling is not actually implemented in this
-way. This is just a description of the rule that is applied.)
-
-The default fill rule is *FILL_RULE_WINDING*.
-
-.. data:: FILL_RULE_WINDING
-
- If the path crosses the ray from left-to-right, counts +1. If the path
- crosses the ray from right to left, counts -1. (Left and right are
- determined from the perspective of looking along the ray from the starting
- point.) If the total count is non-zero, the point will be filled.
-
-.. data:: FILL_RULE_EVEN_ODD
-
- Counts the total number of intersections, without regard to the orientation
- of the contour. If the total number of intersections is odd, the point will
- be filled.
-
-New entries may be added in future versions.
-
-
-.. _constants_FILTER:
-
-cairo.FILTER
-------------
-These constants are used to indicate what filtering should be applied when
-reading pixel values from patterns. See :meth:`Pattern.set_filter` for
-indicating the desired filter to be used with a particular pattern.
-
-.. data:: FILTER_FAST
-
- A high-performance filter, with quality similar *FILTER_NEAREST*
-
-.. data:: FILTER_GOOD
-
- A reasonable-performance filter, with quality similar to *FILTER_BILINEAR*
-
-.. data:: FILTER_BEST
-
- The highest-quality available, performance may not be suitable for
- interactive use.
-
-.. data:: FILTER_NEAREST
-
- Nearest-neighbor filtering
-
-.. data:: FILTER_BILINEAR
-
- Linear interpolation in two dimensions
-
-.. data:: FILTER_GAUSSIAN
-
- This filter value is currently unimplemented, and should not be used in
- current code.
-
-
-.. _constants_FONT_SLANT:
-
-cairo.FONT_SLANT
-----------------
-These constants specify variants of a :class:`FontFace` based on their slant.
-
-.. data:: FONT_SLANT_NORMAL
-
- Upright font style
-
-.. data:: FONT_SLANT_ITALIC
-
- Italic font style
-
-.. data:: FONT_SLANT_OBLIQUE
-
- Oblique font style
-
-
-.. _constants_FONT_WEIGHT:
-
-cairo.FONT_WEIGHT
------------------
-These constants specify variants of a :class:`FontFace` based on their weight.
-
-.. data:: FONT_WEIGHT_NORMAL
-
- Normal font weight
-
-.. data:: FONT_WEIGHT_BOLD
-
- Bold font weight
-
-
-.. _constants_FORMAT:
-
-cairo.FORMAT
-------------
-These constants are used to identify the memory format of
-:class:`ImageSurface` data.
-
-New entries may be added in future versions.
-
-.. data:: FORMAT_INVALID
-
- no such format exists or is supported.
-
- .. versionadded:: 1.12.0
-
-.. data:: FORMAT_ARGB32
-
- each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then red,
- then green, then blue. The 32-bit quantities are stored
- native-endian. Pre-multiplied alpha is used. (That is, 50% transparent red
- is 0x80800000, not 0x80ff0000.)
-
-.. data:: FORMAT_RGB24
-
- each pixel is a 32-bit quantity, with the upper 8 bits unused. Red, Green,
- and Blue are stored in the remaining 24 bits in that order.
-
-.. data:: FORMAT_A8
-
- each pixel is a 8-bit quantity holding an alpha value.
-
-.. data:: FORMAT_A1
-
- each pixel is a 1-bit quantity holding an alpha value. Pixels are packed
- together into 32-bit quantities. The ordering of the bits matches the
- endianess of the platform. On a big-endian machine, the first pixel is in
- the uppermost bit, on a little-endian machine the first pixel is in the
- least-significant bit.
-
-.. data:: FORMAT_RGB16_565
-
- each pixel is a 16-bit quantity with red in the upper 5 bits, then green in
- the middle 6 bits, and blue in the lower 5 bits.
-
-.. data:: FORMAT_RGB30
-
- like :data:`FORMAT_RGB24` but with 10bpc.
-
- .. versionadded:: 1.12.0
-
-
-.. _constants_HINT_METRICS:
-
-cairo.HINT_METRICS
-------------------
-These constants specify whether to hint font metrics; hinting font metrics
-means quantizing them so that they are integer values in device space. Doing
-this improves the consistency of letter and line spacing, however it also
-means that text will be laid out differently at different zoom factors.
-
-.. data:: HINT_METRICS_DEFAULT
-
- Hint metrics in the default manner for the font backend and target device
-
-.. data:: HINT_METRICS_OFF
-
- Do not hint font metrics
-
-.. data:: HINT_METRICS_ON
-
- Hint font metrics
-
-
-.. _constants_HINT_STYLE:
-
-cairo.HINT_STYLE
-----------------
-These constants specify the type of hinting to do on font outlines. Hinting is
-the process of fitting outlines to the pixel grid in order to improve the
-appearance of the result. Since hinting outlines involves distorting them, it
-also reduces the faithfulness to the original outline shapes. Not all of the
-outline hinting styles are supported by all font backends.
-
-.. data:: HINT_STYLE_DEFAULT
-
- Use the default hint style for font backend and target device
-
-.. data:: HINT_STYLE_NONE
-
- Do not hint outlines
-
-.. data:: HINT_STYLE_SLIGHT
-
- Hint outlines slightly to improve contrast while retaining good fidelity to
- the original shapes.
-
-.. data:: HINT_STYLE_MEDIUM
-
- Hint outlines with medium strength giving a compromise between fidelity to
- the original shapes and contrast
-
-.. data:: HINT_STYLE_FULL
-
- Hint outlines to maximize contrast
-
-New entries may be added in future versions.
-
-
-.. _constants_LINE_CAP:
-
-cairo.LINE_CAP
---------------
-These constants specify how to render the endpoints of the path when stroking.
-
-The default line cap style is *LINE_CAP_BUTT*
-
-.. data:: LINE_CAP_BUTT
-
- start(stop) the line exactly at the start(end) point
-
-.. data:: LINE_CAP_ROUND
-
- use a round ending, the center of the circle is the end point
-
-.. data:: LINE_CAP_SQUARE
-
- use squared ending, the center of the square is the end point
-
-
-.. _constants_LINE_JOIN:
-
-cairo.LINE_JOIN
----------------
-These constants specify how to render the junction of two lines when stroking.
-
-The default line join style is *LINE_JOIN_MITER*
-
-.. data:: LINE_JOIN_MITER
-
- use a sharp (angled) corner, see :meth:`Context.set_miter_limit`
-
-.. data:: LINE_JOIN_ROUND
-
- use a rounded join, the center of the circle is the joint point
-
-.. data:: LINE_JOIN_BEVEL
-
- use a cut-off join, the join is cut off at half the line width from the
- joint point
-
-
-.. _constants_OPERATOR:
-
-cairo.OPERATOR
---------------
-These constants are used to set the compositing operator for all cairo drawing
-operations.
-
-The default operator is *OPERATOR_OVER*.
-
-The operators marked as *unbounded* modify their destination even outside of
-the mask layer (that is, their effect is not bound by the mask layer).
-However, their effect can still be limited by way of clipping.
-
-To keep things simple, the operator descriptions here document the behavior
-for when both source and destination are either fully transparent or fully
-opaque. The actual implementation works for translucent layers too.
-
-For a more detailed explanation of the effects of each operator, including the
-mathematical definitions, see https://cairographics.org/operators.
-
-.. data:: OPERATOR_CLEAR
-
- clear destination layer (bounded)
-
-.. data:: OPERATOR_SOURCE
-
- replace destination layer (bounded)
-
-.. data:: OPERATOR_OVER
-
- draw source layer on top of destination layer (bounded)
-
-.. data:: OPERATOR_IN
-
- draw source where there was destination content (unbounded)
-
-.. data:: OPERATOR_OUT
-
- draw source where there was no destination content (unbounded)
-
-.. data:: OPERATOR_ATOP
-
- draw source on top of destination content and only there
-
-.. data:: OPERATOR_DEST
-
- ignore the source
-
-.. data:: OPERATOR_DEST_OVER
-
- draw destination on top of source
-
-.. data:: OPERATOR_DEST_IN
-
- leave destination only where there was source content (unbounded)
-
-.. data:: OPERATOR_DEST_OUT
-
- leave destination only where there was no source content
-
-.. data:: OPERATOR_DEST_ATOP
-
- leave destination on top of source content and only there (unbounded)
-
-.. data:: OPERATOR_XOR
-
- source and destination are shown where there is only one of them
-
-.. data:: OPERATOR_ADD
-
- source and destination layers are accumulated
-
-.. data:: OPERATOR_SATURATE
-
- like over, but assuming source and dest are disjoint geometries
-
-.. data:: OPERATOR_MULTIPLY
-
- source and destination layers are multiplied. This causes the result to be
- at least as dark as the darker inputs.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_SCREEN
-
- source and destination are complemented and multiplied. This causes the
- result to be at least as light as the lighter inputs.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_OVERLAY
-
- multiplies or screens, depending on the lightness of the destination
- color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_DARKEN
-
- replaces the destination with the source if it is darker, otherwise keeps
- the source.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_LIGHTEN
-
- replaces the destination with the source if it is lighter, otherwise keeps
- the source.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_COLOR_DODGE
-
- brightens the destination color to reflect the source color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_COLOR_BURN
-
- darkens the destination color to reflect the source color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_HARD_LIGHT
-
- Multiplies or screens, dependent on source color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_SOFT_LIGHT
-
- Darkens or lightens, dependent on source color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_DIFFERENCE
-
- Takes the difference of the source and destination color.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_EXCLUSION
-
- Produces an effect similar to difference, but with lower contrast.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_HSL_HUE
-
- Creates a color with the hue of the source and the saturation and
- luminosity of the target.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_HSL_SATURATION
-
- Creates a color with the saturation of the source and the hue and
- luminosity of the target. Painting with this mode onto a gray area
- produces no change.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_HSL_COLOR
-
- Creates a color with the hue and saturation of the source and the
- luminosity of the target. This preserves the gray levels of the target and
- is useful for coloring monochrome images or tinting color images.
-
- .. versionadded:: 1.12.0
-
-.. data:: OPERATOR_HSL_LUMINOSITY
-
- Creates a color with the luminosity of the source and the hue and
- saturation of the target. This produces an inverse effect to
- :data:`OPERATOR_HSL_COLOR`
-
- .. versionadded:: 1.12.0
-
-
-.. _constants_PATH:
-
-cairo.PATH
-----------
-These constants are used to describe the type of one portion of a path when
-represented as a :class:`Path`.
-
-.. See #cairo_path_data_t for details.
-
-.. data:: PATH_MOVE_TO
-
- A move-to operation
-
-.. data:: PATH_LINE_TO
-
- A line-to operation
-
-.. data:: PATH_CURVE_TO
-
- A curve-to operation
-
-.. data:: PATH_CLOSE_PATH
-
- A close-path operation
-
-
-.. _constants_PS_LEVEL:
-
-cairo.PS_LEVEL
---------------
-These constants are used to describe the language level of the PostScript
-Language Reference that a generated PostScript file will conform to. Note:
-the constants are only defined when cairo has been compiled with PS support
-enabled.
-
-.. data:: PS_LEVEL_2
-
- The language level 2 of the PostScript specification.
-
-.. data:: PS_LEVEL_3
-
- The language level 3 of the PostScript specification.
-
-
-.. _constants_PDF_VERSION:
-
-cairo.PDF_VERSION
------------------
-
-These constants are used to describe the version number of the PDF
-specification that a generated PDF file will conform to.
-
-.. data:: PDF_VERSION_1_4
-
- The version 1.4 of the PDF specification.
-
- .. versionadded:: 1.12.0
-
-
-.. data:: PDF_VERSION_1_5
-
- The version 1.5 of the PDF specification.
-
- .. versionadded:: 1.12.0
-
-
-.. _constants_SVG_VERSION:
-
-cairo.SVG_VERSION
------------------
-
-These constants are used to describe the version number of the SVG
-specification that a generated SVG file will conform to.
-
-.. data:: SVG_VERSION_1_1
-
- The version 1.1 of the SVG specification.
-
- .. versionadded:: 1.12.0
-
-
-.. data:: SVG_VERSION_1_2
-
- The version 1.2 of the SVG specification.
-
- .. versionadded:: 1.12.0
-
-
-.. _constants_SUBPIXEL_ORDER:
-
-cairo.SUBPIXEL_ORDER
---------------------
-The subpixel order specifies the order of color elements within each pixel on
-the display device when rendering with an antialiasing mode of
-:data:`ANTIALIAS_SUBPIXEL`.
-
-.. data:: SUBPIXEL_ORDER_DEFAULT
-
- Use the default subpixel order for for the target device
-
-.. data:: SUBPIXEL_ORDER_RGB
-
- Subpixel elements are arranged horizontally with red at the left
-
-.. data:: SUBPIXEL_ORDER_BGR
-
- Subpixel elements are arranged horizontally with blue at the left
-
-.. data:: SUBPIXEL_ORDER_VRGB
-
- Subpixel elements are arranged vertically with red at the top
-
-.. data:: SUBPIXEL_ORDER_VBGR
-
- Subpixel elements are arranged vertically with blue at the top
-
-
-.. _constants_REGION_OVERLAP:
-
-cairo.REGION_OVERLAP
---------------------
-
-.. data:: REGION_OVERLAP_IN
-
- The contents are entirely inside the region.
-
-.. data:: REGION_OVERLAP_OUT
-
- The contents are entirely outside the region.
-
-.. data:: REGION_OVERLAP_PART
-
- The contents are partially inside and partially outside the region.
-
-
-.. _constants_STATUS:
-
-cairo.STATUS
-------------
-
-.. data:: STATUS_SUCCESS
- STATUS_NO_MEMORY
- STATUS_INVALID_RESTORE
- STATUS_INVALID_POP_GROUP
- STATUS_NO_CURRENT_POINT
- STATUS_INVALID_MATRIX
- STATUS_INVALID_STATUS
- STATUS_NULL_POINTER
- STATUS_INVALID_STRING
- STATUS_INVALID_PATH_DATA
- STATUS_READ_ERROR
- STATUS_WRITE_ERROR
- STATUS_SURFACE_FINISHED
- STATUS_SURFACE_TYPE_MISMATCH
- STATUS_PATTERN_TYPE_MISMATCH
- STATUS_INVALID_CONTENT
- STATUS_INVALID_FORMAT
- STATUS_INVALID_VISUAL
- STATUS_FILE_NOT_FOUND
- STATUS_INVALID_DASH
- STATUS_INVALID_DSC_COMMENT
- STATUS_INVALID_INDEX
- STATUS_CLIP_NOT_REPRESENTABLE
- STATUS_TEMP_FILE_ERROR
- STATUS_INVALID_STRIDE
- STATUS_FONT_TYPE_MISMATCH
- STATUS_USER_FONT_IMMUTABLE
- STATUS_USER_FONT_ERROR
- STATUS_NEGATIVE_COUNT
- STATUS_INVALID_CLUSTERS
- STATUS_INVALID_SLANT
- STATUS_INVALID_WEIGHT
- STATUS_INVALID_SIZE
- STATUS_USER_FONT_NOT_IMPLEMENTED
- STATUS_DEVICE_TYPE_MISMATCH
- STATUS_DEVICE_ERROR
- STATUS_INVALID_MESH_CONSTRUCTION
- STATUS_DEVICE_FINISHED
- STATUS_LAST_STATUS
-
-
.. _constants_MIME_TYPE:
cairo.MIME_TYPE
diff --git a/docs/reference/context.rst b/docs/reference/context.rst
index 9d28825..b5300dc 100644
--- a/docs/reference/context.rst
+++ b/docs/reference/context.rst
@@ -29,7 +29,6 @@ Cairo Context
:exc:`cairo.Error`
:meth:`.copy_page`
:meth:`Context.copy_page`
- :ref:`LINE_CAP <constants_LINE_CAP>`
class Context()
@@ -139,7 +138,7 @@ safely be changed, without loosing the current state. Use
Establishes a new clip region by intersecting the current clip region
with the current path as it would be filled by :meth:`Context.fill` and
- according to the current :ref:`FILL RULE <constants_FILL_RULE>` (see
+ according to the current :class:`fill rule <cairo.FillRule>` (see
:meth:`Context.set_fill_rule`).
After :meth:`.clip`, the current path will be cleared from the
@@ -158,8 +157,8 @@ safely be changed, without loosing the current state. Use
.. method:: clip_extents()
- :returns: (x1, y1, x2, y2)
- :rtype: (float, float, float, float)
+ :returns: (x1, y1, x2, y2), all float
+ :rtype: tuple
* *x1*: left of the resulting extents
* *y1*: top of the resulting extents
@@ -175,7 +174,7 @@ safely be changed, without loosing the current state. Use
Establishes a new clip region by intersecting the current clip region
with the current path as it would be filled by :meth:`Context.fill` and
- according to the current :ref:`FILL RULE <constants_FILL_RULE>` (see
+ according to the current :class:`fill rule <cairo.FillRule>` (see
:meth:`Context.set_fill_rule`).
Unlike :meth:`Context.clip`, :meth:`.clip_preserve` preserves the path
@@ -218,8 +217,8 @@ safely be changed, without loosing the current state. Use
.. method:: copy_clip_rectangle_list()
:returns: the current clip region as a list of rectangles in user
- coordinates
- :rtype: list of 4-tuples of float
+ coordinates. Returns a list of 4-tuples of float.
+ :rtype: list
(The status in the list may be %CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to
indicate that the clip region cannot be represented as a list of
@@ -290,8 +289,8 @@ safely be changed, without loosing the current state. Use
:type x: float
:param y: Y value of coordinate
:type y: float
- :returns: (x, y)
- :rtype: (float, float)
+ :returns: (x, y), both float
+ :rtype: tuple
Transform a coordinate from device space to user space by multiplying
the given point by the inverse of the current transformation matrix
@@ -303,8 +302,8 @@ safely be changed, without loosing the current state. Use
:type dx: float
:param dy: Y component of a distance vector
:type dy: float
- :returns: (dx, dy)
- :rtype: (float, float)
+ :returns: (dx, dy), both float
+ :rtype: tuple
Transform a distance vector from device space to user space. This
function is similar to :meth:`Context.device_to_user` except that the
@@ -314,15 +313,15 @@ safely be changed, without loosing the current state. Use
.. method:: fill()
A drawing operator that fills the current path according to the current
- :ref:`FILL RULE <constants_FILL_RULE>`, (each sub-path is implicitly
+ :class:`fill rule <cairo.FillRule>`, (each sub-path is implicitly
closed before being filled). After :meth:`.fill`, the current path will
be cleared from the :class:`Context`. See :meth:`Context.set_fill_rule`
and :meth:`Context.fill_preserve`.
.. method:: fill_extents()
- :returns: (x1, y1, x2, y2)
- :rtype: (float, float, float, float)
+ :returns: (x1, y1, x2, y2), all float
+ :rtype: tuple
* *x1*: left of the resulting extents
* *y1*: top of the resulting extents
@@ -350,7 +349,7 @@ safely be changed, without loosing the current state. Use
.. method:: fill_preserve()
A drawing operator that fills the current path according to the current
- :ref:`FILL RULE <constants_FILL_RULE>`, (each sub-path is implicitly
+ :class:`fill rule <cairo.FillRule>`, (each sub-path is implicitly
closed before being filled). Unlike :meth:`Context.fill`,
:meth:`.fill_preserve` preserves the path within the :class:`Context`.
@@ -358,20 +357,22 @@ safely be changed, without loosing the current state. Use
.. method:: font_extents()
- :returns: (ascent, descent, height, max_x_advance, max_y_advance)
- :rtype: (float, float, float, float, float)
+ :returns: (ascent, descent, height, max_x_advance, max_y_advance),
+ all float
+ :rtype: tuple
Gets the font extents for the currently selected font.
.. method:: get_antialias()
- :returns: the current :ref:`ANTIALIAS <constants_ANTIALIAS>` mode,
+ :returns: the current antialias mode,
as set by :meth:`Context.set_antialias`.
+ :rtype: cairo.Antialias
.. method:: get_current_point()
- :returns: (x, y)
- :rtype: (float, float)
+ :returns: (x, y), both float
+ :rtype: tuple
* *x*: X coordinate of the current point
* *y*: Y coordinate of the current point
@@ -405,10 +406,10 @@ safely be changed, without loosing the current state. Use
.. method:: get_dash()
:returns: (dashes, offset)
- :rtype: (tuple, float)
+ :rtype: tuple
- * *dashes*: return value for the dash array
- * *offset*: return value for the current dash offset
+ * *dashes*: return value as a tuple for the dash array
+ * *offset*: return value as float for the current dash offset
Gets the current dash array.
@@ -425,8 +426,9 @@ safely be changed, without loosing the current state. Use
.. method:: get_fill_rule()
- :returns: the current :ref:`FILL RULE <constants_FILL_RULE>`, as
+ :returns: the current fill rule, as
set by :meth:`Context.set_fill_rule`.
+ :rtype: cairo.FillRule
.. method:: get_font_face()
@@ -461,13 +463,15 @@ safely be changed, without loosing the current state. Use
.. method:: get_line_cap()
- :returns: the current :ref:`LINE_CAP <constants_LINE_CAP>` style, as
+ :returns: the current line cap style, as
set by :meth:`Context.set_line_cap`.
+ :rtype: cairo.LineCap
.. method:: get_line_join()
- :returns: the current :ref:`LINE_JOIN <constants_LINE_JOIN>` style, as
+ :returns: the current line join style, as
set by :meth:`Context.set_line_join`.
+ :rtype: cairo.LineJoin
.. method:: get_line_width()
@@ -491,8 +495,9 @@ safely be changed, without loosing the current state. Use
.. method:: get_operator()
- :returns: the current compositing :ref:`OPERATOR <constants_OPERATOR>`
+ :returns: the current compositing operator
for a :class:`Context`.
+ :rtype: cairo.Operator
.. method:: get_scaled_font()
@@ -516,12 +521,12 @@ safely be changed, without loosing the current state. Use
.. method:: glyph_extents(glyphs, [num_glyphs])
- :param glyphs: glyphs
- :type glyphs: a sequence of (int, float, float)
+ :param glyphs: glyphs, a sequence of (int, float, float)
:param num_glyphs: number of glyphs to measure, defaults to using all
:type num_glyphs: int
- :returns: x_bearing, y_bearing, width, height, x_advance, y_advance
- :rtype: 6-tuple of float
+ :returns: (x_bearing, y_bearing, width, height, x_advance, y_advance),
+ 6-tuple of float
+ :rtype: tuple
Gets the extents for an array of glyphs. The extents describe a
user-space rectangle that encloses the "inked" portion of the glyphs,
@@ -534,8 +539,7 @@ safely be changed, without loosing the current state. Use
.. method:: glyph_path(glyphs[, num_glyphs])
- :param glyphs: glyphs to show
- :type glyphs: a sequence of (int, float, float)
+ :param glyphs: glyphs to show, a sequence of (int, float, float)
:param num_glyphs: number of glyphs to show, defaults to showing all
:type num_glyphs: int
@@ -667,8 +671,8 @@ safely be changed, without loosing the current state. Use
.. method:: path_extents()
- :returns: (x1, y1, x2, y2)
- :rtype: (float, float, float, float)
+ :returns: (x1, y1, x2, y2), all float
+ :rtype: tuple
* *x1*: left of the resulting extents
* *y1*: top of the resulting extents
@@ -757,10 +761,10 @@ safely be changed, without loosing the current state. Use
changes to the graphics state will not be visible outside the group,
(the pop_group functions call :meth:`Context.restore`).
- By default the intermediate group will have a :ref:`CONTENT
- <constants_CONTENT>` type of cairo.CONTENT_COLOR_ALPHA. Other content
- types can be chosen for the group by using
- :meth:`Context.push_group_with_content` instead.
+ By default the intermediate group will have a :class:`cairo.Content`
+ type of :attr:`cairo.Content.COLOR_ALPHA`. Other content types can be
+ chosen for the group by using :meth:`Context.push_group_with_content`
+ instead.
As an example, here is how one might fill and stroke a path with
translucence, but without any portion of the fill being visible
@@ -778,7 +782,7 @@ safely be changed, without loosing the current state. Use
.. method:: push_group_with_content(content)
- :param content: a :ref:`CONTENT <constants_CONTENT>` indicating the
+ :param cairo.Content content: a content indicating the
type of group that will be created
Temporarily redirects drawing to an intermediate surface known as a
@@ -928,10 +932,10 @@ safely be changed, without loosing the current state. Use
:param family: a font family name
:type family: text
- :param slant: the :ref:`FONT_SLANT <constants_FONT_SLANT>` of the font,
- defaults to :data:`cairo.FONT_SLANT_NORMAL`.
- :param weight: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` of the
- font, defaults to :data:`cairo.FONT_WEIGHT_NORMAL`.
+ :param cairo.FontSlant slant: the font slant of the font,
+ defaults to :attr:`cairo.FontSlant.NORMAL`.
+ :param cairo.FontWeight weight: the font weight of the
+ font, defaults to :attr:`cairo.FontWeight.NORMAL`.
Note: The :meth:`.select_font_face` function call is part of what the
cairo designers call the "toy" text API. It is convenient for short
@@ -963,20 +967,20 @@ safely be changed, without loosing the current state. Use
If text is drawn without a call to :meth:`.select_font_face`, (nor
:meth:`.set_font_face` nor :meth:`.set_scaled_font`), the default family
is platform-specific, but is essentially "sans-serif". Default slant is
- cairo.FONT_SLANT_NORMAL, and default weight is
- cairo.FONT_WEIGHT_NORMAL.
+ :attr:`cairo.FontSlant.NORMAL`, and default weight is
+ :attr:`cairo.FontWeight.NORMAL`.
This function is equivalent to a call to :class:`ToyFontFace`
followed by :meth:`.set_font_face`.
.. method:: set_antialias(antialias)
- :param antialias: the new :ref:`ANTIALIAS <constants_ANTIALIAS>` mode
+ :param cairo.Antialias antialias: the new antialias mode
Set the antialiasing mode of the rasterizer used for drawing shapes.
This value is a hint, and a particular backend may or may not support a
particular value. At the current time, no backend supports
- :data:`cairo.ANTIALIAS_SUBPIXEL` when drawing shapes.
+ :attr:`cairo.Antialias.SUBPIXEL` when drawing shapes.
Note that this option does not affect text rendering, instead see
:meth:`FontOptions.set_antialias`.
@@ -984,8 +988,7 @@ safely be changed, without loosing the current state. Use
.. method:: set_dash(dashes, [offset=0])
:param dashes: a sequence specifying alternate lengths of on and off
- stroke portions.
- :type dashes: sequence of float
+ stroke portions as float.
:param offset: an offset into the dash pattern at which the stroke
should start, defaults to 0.
:type offset: int
@@ -1000,7 +1003,7 @@ safely be changed, without loosing the current state. Use
Each "on" segment will have caps applied as if the segment were a
separate sub-path. In particular, it is valid to use an "on" length of
- 0.0 with :data:`cairo.LINE_CAP_ROUND` or :data:`cairo.LINE_CAP_SQUARE`
+ 0.0 with :attr:`cairo.LineCap.ROUND` or :attr:`cairo.LineCap.SQUARE`
in order to distributed dots or squares along a path.
Note: The length values are in user-space units as evaluated at the time
@@ -1015,13 +1018,13 @@ safely be changed, without loosing the current state. Use
.. method:: set_fill_rule(fill_rule)
- :param fill_rule: a :ref:`FILL RULE <constants_FILL_RULE>` to set the
+ :param cairo.FillRule fill_rule: a fill rule to set the
within the cairo context. The fill rule is used to determine which
regions are inside or outside a complex (potentially
self-intersecting) path. The current fill rule affects both
:meth:`.fill` and :meth:`.clip`.
- The default fill rule is :data:`cairo.FILL_RULE_WINDING`.
+ The default fill rule is :attr:`cairo.FillRule.WINDING`.
.. method:: set_font_face(font_face)
@@ -1049,7 +1052,7 @@ safely be changed, without loosing the current state. Use
Sets a set of custom font rendering options for the :class:`Context`.
Rendering options are derived by merging these options with the options
derived from underlying surface; if the value in *options* has a default
- value (like :data:`cairo.ANTIALIAS_DEFAULT`), then the value from the
+ value (like :attr:`cairo.Antialias.DEFAULT`), then the value from the
surface is used.
.. method:: set_font_size(size)
@@ -1069,7 +1072,7 @@ safely be changed, without loosing the current state. Use
.. method:: set_line_cap(line_cap)
- :param line_cap: a :ref:`LINE_CAP <constants_LINE_CAP>` style
+ :param cairo.LineCap line_cap: a line cap style
Sets the current line cap style within the :class:`Context`.
@@ -1078,11 +1081,11 @@ safely be changed, without loosing the current state. Use
:meth:`.stroke_to_path`, but does not have any effect during path
construction.
- The default line cap style is :data:`cairo.LINE_CAP_BUTT`.
+ The default line cap style is :attr:`cairo.LineCap.BUTT`.
.. method:: set_line_join(line_join)
- :param line_join: a :ref:`LINE_JOIN <constants_LINE_JOIN>` style
+ :param cairo.LineJoin line_join: a line join style
Sets the current line join style within the :class:`Context`.
@@ -1091,7 +1094,7 @@ safely be changed, without loosing the current state. Use
:meth:`.stroke_to_path`, but does not have any effect during path
construction.
- The default line join style is :data:`cairo.LINE_JOIN_MITER`.
+ The default line join style is :attr:`cairo.LineJoin.MITER`.
.. method:: set_line_width(width)
@@ -1134,7 +1137,7 @@ safely be changed, without loosing the current state. Use
Sets the current miter limit within the :class:`Context`.
- If the current line join style is set to :data:`cairo.LINE_JOIN_MITER`
+ If the current line join style is set to :attr:`cairo.LineJoin.MITER`
(see :meth:`.set_line_join`), the miter limit is used to determine
whether the lines should be joined with a bevel instead of a miter.
Cairo divides the length of the miter by the line width. If the result
@@ -1156,10 +1159,10 @@ safely be changed, without loosing the current state. Use
.. method:: set_operator(op)
- :param op: the compositing :ref:`OPERATOR <constants_OPERATOR>` to set
+ :param cairo.Operator op: the compositing operator to set
for use in all drawing operations.
- The default operator is :data:`cairo.OPERATOR_OVER`.
+ The default operator is :attr:`cairo.Operator.OVER`.
.. method:: set_scaled_font(scaled_font)
@@ -1274,8 +1277,7 @@ safely be changed, without loosing the current state. Use
.. method:: show_glyphs(glyphs[, num_glyphs])
- :param glyphs: glyphs to show
- :type glyphs: a sequence of (int, float, float)
+ :param glyphs: glyphs to show as a sequence of (int, float, float)
:param num_glyphs: number of glyphs to show, defaults to showing all
glyphs
:type num_glyphs: int
@@ -1330,27 +1332,27 @@ safely be changed, without loosing the current state. Use
provide a useful result. These can result in two different situations:
1. Zero-length "on" segments set in :meth:`.set_dash`. If the cap
- style is :data:`cairo.LINE_CAP_ROUND` or :data:`cairo.LINE_CAP_SQUARE`
+ style is :attr:`cairo.LineCap.ROUND` or :attr:`cairo.LineCap.SQUARE`
then these segments will be drawn as circular dots or squares
- respectively. In the case of :data:`cairo.LINE_CAP_SQUARE`, the
+ respectively. In the case of :attr:`cairo.LineCap.SQUARE`, the
orientation of the squares is determined by the direction of the
underlying path.
2. A sub-path created by :meth:`.move_to` followed by either a
:meth:`.close_path` or one or more calls to :meth:`.line_to` to the same
coordinate as the :meth:`.move_to`. If the cap style is
- :data:`cairo.LINE_CAP_ROUND` then these sub-paths will be drawn as
- circular dots. Note that in the case of :data:`cairo.LINE_CAP_SQUARE` a
+ :attr:`cairo.LineCap.ROUND` then these sub-paths will be drawn as
+ circular dots. Note that in the case of :attr:`cairo.LineCap.SQUARE` a
degenerate sub-path will not be drawn at all, (since the correct
orientation is indeterminate).
- In no case will a cap style of :data:`cairo.LINE_CAP_BUTT` cause anything
+ In no case will a cap style of :attr:`cairo.LineCap.BUTT` cause anything
to be drawn in the case of either degenerate segments or sub-paths.
.. method:: stroke_extents()
- :returns: (x1, y1, x2, y2)
- :rtype: (float, float, float, float)
+ :returns: (x1, y1, x2, y2), all float
+ :rtype: tuple
* *x1*: left of the resulting extents
* *y1*: top of the resulting extents
@@ -1390,8 +1392,9 @@ safely be changed, without loosing the current state. Use
:param text: text to get extents for
:type text: text
- :returns: x_bearing, y_bearing, width, height, x_advance, y_advance
- :rtype: 6-tuple of float
+ :returns: (x_bearing, y_bearing, width, height, x_advance, y_advance)
+ , 6-tuple of float
+ :rtype: tuple
Gets the extents for a string of text. The extents describe a user-space
rectangle that encloses the "inked" portion of the text, (as it would be
@@ -1458,8 +1461,8 @@ safely be changed, without loosing the current state. Use
:type x: float
:param y: Y value of coordinate
:type y: float
- :returns: (x, y)
- :rtype: (float, float)
+ :returns: (x, y), both float
+ :rtype: tuple
* *x*: X value of coordinate
* *y*: Y value of coordinate
@@ -1473,8 +1476,8 @@ safely be changed, without loosing the current state. Use
:type dx: float
:param dy: Y value of a distance vector
:type dy: float
- :returns: (dx, dy)
- :rtype: (float, float)
+ :returns: (dx, dy), both float
+ :rtype: tuple
* *dx*: X value of a distance vector
* *dy*: Y value of a distance vector
@@ -1498,3 +1501,12 @@ safely be changed, without loosing the current state. Use
See :meth:`clip`, and :meth:`clip_preserve`.
.. versionadded:: 1.12.0
+
+ .. method:: show_text_glyphs()
+
+ .. note:: This functions is not implemented in Pycairo yet
+
+ .. method:: stroke_to_path()
+
+ .. note:: This function is not implemented in cairo, but still
+ mentioned in the documentation.
diff --git a/docs/reference/enums.rst b/docs/reference/enums.rst
new file mode 100644
index 0000000..8855b9e
--- /dev/null
+++ b/docs/reference/enums.rst
@@ -0,0 +1,666 @@
+=====
+Enums
+=====
+
+Before Pycairo 1.13 most of the enum values defined here where only available
+as constants on the module level. See :ref:`legacy_constants`.
+
+.. currentmodule:: cairo
+
+.. class:: Antialias
+
+ Specifies the type of antialiasing to do when rendering text or shapes.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: DEFAULT
+
+ Use the default antialiasing for the subsystem and target device
+
+ .. attribute:: NONE
+
+ Use a bilevel alpha mask
+
+ .. attribute:: GRAY
+
+ Perform single-color antialiasing (using shades of gray for black text
+ on a white background, for example).
+
+ .. attribute:: SUBPIXEL
+
+ Perform antialiasing by taking advantage of the order of subpixel
+ elements on devices such as LCD panels.
+
+ .. attribute:: FAST
+
+ Hint that the backend should perform some antialiasing but prefer
+ speed over quality.
+
+ .. attribute:: GOOD
+
+ The backend should balance quality against performance.
+
+ .. attribute:: BEST
+
+ Hint that the backend should render at the highest quality,
+ sacrificing speed if necessary.
+
+
+.. class:: Content
+
+ These constants are used to describe the content that a :class:`Surface`
+ will contain, whether color information, alpha information (translucence
+ vs. opacity), or both.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: COLOR
+
+ The surface will hold color content only.
+
+ .. attribute:: ALPHA
+
+ The surface will hold alpha content only.
+
+ .. attribute:: COLOR_ALPHA
+
+ The surface will hold color and alpha content.
+
+
+.. class:: Extend
+
+ These constants are used to describe how :class:`Pattern` color/alpha will
+ be determined for areas "outside" the pattern's natural area, (for
+ example, outside the surface bounds or outside the gradient geometry).
+
+ The default extend mode is :attr:`NONE` for :class:`SurfacePattern` and
+ :attr:`PAD` for :class:`Gradient` patterns.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: NONE
+
+ pixels outside of the source pattern are fully transparent
+
+ .. attribute:: REPEAT
+
+ the pattern is tiled by repeating
+
+ .. attribute:: REFLECT
+
+ the pattern is tiled by reflecting at the edges (Implemented for
+ surface patterns since 1.6)
+
+ .. attribute:: PAD
+
+ pixels outside of the pattern copy the closest pixel from the source
+ (Since 1.2; but only implemented for surface patterns since 1.6)
+
+
+.. class:: FillRule
+
+ These constants are used to select how paths are filled. For both fill
+ rules, whether or not a point is included in the fill is determined by
+ taking a ray from that point to infinity and looking at intersections with
+ the path. The ray can be in any direction, as long as it doesn't pass
+ through the end point of a segment or have a tricky intersection such as
+ intersecting tangent to the path. (Note that filling is not actually
+ implemented in this way. This is just a description of the rule that is
+ applied.)
+
+ The default fill rule is :attr:`WINDING`.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: WINDING
+
+ If the path crosses the ray from left-to-right, counts +1. If the path
+ crosses the ray from right to left, counts -1. (Left and right are
+ determined from the perspective of looking along the ray from the
+ starting point.) If the total count is non-zero, the point will be
+ filled.
+
+ .. attribute:: EVEN_ODD
+
+ Counts the total number of intersections, without regard to the
+ orientation of the contour. If the total number of intersections is
+ odd, the point will be filled.
+
+
+.. class:: Filter
+
+ These constants are used to indicate what filtering should be applied when
+ reading pixel values from patterns. See :meth:`Pattern.set_filter` for
+ indicating the desired filter to be used with a particular pattern.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: FAST
+
+ A high-performance filter, with quality similar *FILTER_NEAREST*
+
+ .. attribute:: GOOD
+
+ A reasonable-performance filter, with quality similar to
+ *FILTER_BILINEAR*
+
+ .. attribute:: BEST
+
+ The highest-quality available, performance may not be suitable for
+ interactive use.
+
+ .. attribute:: NEAREST
+
+ Nearest-neighbor filtering
+
+ .. attribute:: BILINEAR
+
+ Linear interpolation in two dimensions
+
+ .. attribute:: GAUSSIAN
+
+ This filter value is currently unimplemented, and should not be used
+ in current code.
+
+
+.. class:: FontSlant
+
+ These constants specify variants of a :class:`FontFace` based on their
+ slant.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: NORMAL
+
+ Upright font style
+
+ .. attribute:: ITALIC
+
+ Italic font style
+
+ .. attribute:: OBLIQUE
+
+ Oblique font style
+
+
+.. class:: FontWeight
+
+ These constants specify variants of a :class:`FontFace` based on their
+ weight.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: NORMAL
+
+ Normal font weight
+
+ .. attribute:: BOLD
+
+ Bold font weight
+
+
+.. class:: Format
+
+ These constants are used to identify the memory format of
+ :class:`ImageSurface` data.
+
+ New entries may be added in future versions.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: INVALID
+
+ no such format exists or is supported.
+
+ .. attribute:: ARGB32
+
+ each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then
+ red, then green, then blue. The 32-bit quantities are stored
+ native-endian. Pre-multiplied alpha is used. (That is, 50% transparent
+ red is 0x80800000, not 0x80ff0000.)
+
+ .. attribute:: RGB24
+
+ each pixel is a 32-bit quantity, with the upper 8 bits unused. Red,
+ Green, and Blue are stored in the remaining 24 bits in that order.
+
+ .. attribute:: A8
+
+ each pixel is a 8-bit quantity holding an alpha value.
+
+ .. attribute:: A1
+
+ each pixel is a 1-bit quantity holding an alpha value. Pixels are
+ packed together into 32-bit quantities. The ordering of the bits
+ matches the endianess of the platform. On a big-endian machine, the
+ first pixel is in the uppermost bit, on a little-endian machine the
+ first pixel is in the least-significant bit.
+
+ .. attribute:: RGB16_565
+
+ each pixel is a 16-bit quantity with red in the upper 5 bits, then
+ green in the middle 6 bits, and blue in the lower 5 bits.
+
+ .. attribute:: RGB30
+
+ like :data:`RGB24` but with 10bpc.
+
+
+.. class:: HintMetrics
+
+ These constants specify whether to hint font metrics; hinting font metrics
+ means quantizing them so that they are integer values in device space.
+ Doing this improves the consistency of letter and line spacing, however it
+ also means that text will be laid out differently at different zoom
+ factors.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: DEFAULT
+
+ Hint metrics in the default manner for the font backend and target
+ device
+
+ .. attribute:: OFF
+
+ Do not hint font metrics
+
+ .. attribute:: ON
+
+ Hint font metrics
+
+
+.. class:: HintStyle
+
+ These constants specify the type of hinting to do on font outlines.
+ Hinting is the process of fitting outlines to the pixel grid in order to
+ improve the appearance of the result. Since hinting outlines involves
+ distorting them, it also reduces the faithfulness to the original outline
+ shapes. Not all of the outline hinting styles are supported by all font
+ backends.
+
+ New entries may be added in future versions.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: DEFAULT
+
+ Use the default hint style for font backend and target device
+
+ .. attribute:: NONE
+
+ Do not hint outlines
+
+ .. attribute:: SLIGHT
+
+ Hint outlines slightly to improve contrast while retaining good
+ fidelity to the original shapes.
+
+ .. attribute:: MEDIUM
+
+ Hint outlines with medium strength giving a compromise between fidelity
+ to the original shapes and contrast
+
+ .. attribute:: FULL
+
+ Hint outlines to maximize contrast
+
+
+.. class:: LineCap
+
+ These constants specify how to render the endpoints of the path when
+ stroking.
+
+ The default line cap style is :attr:`BUTT`
+
+ .. versionadded:: 1.13
+
+ .. attribute:: BUTT
+
+ start(stop) the line exactly at the start(end) point
+
+ .. attribute:: ROUND
+
+ use a round ending, the center of the circle is the end point
+
+ .. attribute:: SQUARE
+
+ use squared ending, the center of the square is the end point
+
+
+.. class:: LineJoin
+
+ These constants specify how to render the junction of two lines when
+ stroking.
+
+ The default line join style is :attr:`MITER`
+
+ .. versionadded:: 1.13
+
+ .. attribute:: MITER
+
+ use a sharp (angled) corner, see :meth:`Context.set_miter_limit`
+
+ .. attribute:: ROUND
+
+ use a rounded join, the center of the circle is the joint point
+
+ .. attribute:: BEVEL
+
+ use a cut-off join, the join is cut off at half the line width from
+ the joint point
+
+
+.. class:: Operator
+
+ These constants are used to set the compositing operator for all cairo
+ drawing operations.
+
+ The default operator is :attr:`OVER`.
+
+ The operators marked as *unbounded* modify their destination even outside
+ of the mask layer (that is, their effect is not bound by the mask layer).
+ However, their effect can still be limited by way of clipping.
+
+ To keep things simple, the operator descriptions here document the
+ behavior for when both source and destination are either fully transparent
+ or fully opaque. The actual implementation works for translucent layers
+ too.
+
+ For a more detailed explanation of the effects of each operator, including
+ the mathematical definitions, see https://cairographics.org/operators.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: CLEAR
+
+ clear destination layer (bounded)
+
+ .. attribute:: SOURCE
+
+ replace destination layer (bounded)
+
+ .. attribute:: OVER
+
+ draw source layer on top of destination layer (bounded)
+
+ .. attribute:: IN
+
+ draw source where there was destination content (unbounded)
+
+ .. attribute:: OUT
+
+ draw source where there was no destination content (unbounded)
+
+ .. attribute:: ATOP
+
+ draw source on top of destination content and only there
+
+ .. attribute:: DEST
+
+ ignore the source
+
+ .. attribute:: DEST_OVER
+
+ draw destination on top of source
+
+ .. attribute:: DEST_IN
+
+ leave destination only where there was source content (unbounded)
+
+ .. attribute:: DEST_OUT
+
+ leave destination only where there was no source content
+
+ .. attribute:: DEST_ATOP
+
+ leave destination on top of source content and only there (unbounded)
+
+ .. attribute:: XOR
+
+ source and destination are shown where there is only one of them
+
+ .. attribute:: ADD
+
+ source and destination layers are accumulated
+
+ .. attribute:: SATURATE
+
+ like over, but assuming source and dest are disjoint geometries
+
+ .. attribute:: MULTIPLY
+
+ source and destination layers are multiplied. This causes the result
+ to be at least as dark as the darker inputs.
+
+ .. attribute:: SCREEN
+
+ source and destination are complemented and multiplied. This causes
+ the result to be at least as light as the lighter inputs.
+
+ .. attribute:: OVERLAY
+
+ multiplies or screens, depending on the lightness of the destination
+ color.
+
+ .. attribute:: DARKEN
+
+ replaces the destination with the source if it is darker, otherwise
+ keeps the source.
+
+ .. attribute:: LIGHTEN
+
+ replaces the destination with the source if it is lighter, otherwise
+ keeps the source.
+
+ .. attribute:: COLOR_DODGE
+
+ brightens the destination color to reflect the source color.
+
+ .. attribute:: COLOR_BURN
+
+ darkens the destination color to reflect the source color.
+
+ .. attribute:: HARD_LIGHT
+
+ Multiplies or screens, dependent on source color.
+
+ .. attribute:: SOFT_LIGHT
+
+ Darkens or lightens, dependent on source color.
+
+ .. attribute:: DIFFERENCE
+
+ Takes the difference of the source and destination color.
+
+ .. attribute:: EXCLUSION
+
+ Produces an effect similar to difference, but with lower contrast.
+
+ .. attribute:: HSL_HUE
+
+ Creates a color with the hue of the source and the saturation and
+ luminosity of the target.
+
+ .. attribute:: HSL_SATURATION
+
+ Creates a color with the saturation of the source and the hue and
+ luminosity of the target. Painting with this mode onto a gray area
+ produces no change.
+
+ .. attribute:: HSL_COLOR
+
+ Creates a color with the hue and saturation of the source and the
+ luminosity of the target. This preserves the gray levels of the target
+ and is useful for coloring monochrome images or tinting color images.
+
+ .. attribute:: HSL_LUMINOSITY
+
+ Creates a color with the luminosity of the source and the hue and
+ saturation of the target. This produces an inverse effect to
+ :attr:`HSL_COLOR`
+
+
+.. class:: PathDataType
+
+ These constants are used to describe the type of one portion of a path
+ when represented as a :class:`Path`.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: MOVE_TO
+
+ A move-to operation
+
+ .. attribute:: LINE_TO
+
+ A line-to operation
+
+ .. attribute:: CURVE_TO
+
+ A curve-to operation
+
+ .. attribute:: CLOSE_PATH
+
+ A close-path operation
+
+
+.. class:: PSLevel
+
+ These constants are used to describe the language level of the PostScript
+ Language Reference that a generated PostScript file will conform to.
+ Note: the constants are only defined when cairo has been compiled with PS
+ support enabled.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: LEVEL_2
+
+ The language level 2 of the PostScript specification.
+
+ .. attribute:: LEVEL_3
+
+ The language level 3 of the PostScript specification.
+
+
+.. class:: PDFVersion
+
+ These constants are used to describe the version number of the PDF
+ specification that a generated PDF file will conform to.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: VERSION_1_4
+
+ The version 1.4 of the PDF specification.
+
+ .. attribute:: VERSION_1_5
+
+ The version 1.5 of the PDF specification.
+
+
+.. class:: SVGVersion
+
+ These constants are used to describe the version number of the SVG
+ specification that a generated SVG file will conform to.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: VERSION_1_1
+
+ The version 1.1 of the SVG specification.
+
+ .. attribute:: VERSION_1_2
+
+ The version 1.2 of the SVG specification.
+
+
+.. class:: SubpixelOrder
+
+ The subpixel order specifies the order of color elements within each pixel
+ on the display device when rendering with an antialiasing mode of
+ :attr:`Antialias.SUBPIXEL`.
+
+ .. versionadded:: 1.13
+
+ .. attribute:: DEFAULT
+
+ Use the default subpixel order for for the target device
+
+ .. attribute:: RGB
+
+ Subpixel elements are arranged horizontally with red at the left
+
+ .. attribute:: BGR
+
+ Subpixel elements are arranged horizontally with blue at the left
+
+ .. attribute:: VRGB
+
+ Subpixel elements are arranged vertically with red at the top
+
+ .. attribute:: VBGR
+
+ Subpixel elements are arranged vertically with blue at the top
+
+
+.. class:: RegionOverlap
+
+ .. versionadded:: 1.13
+
+ .. attribute:: IN
+
+ The contents are entirely inside the region.
+
+ .. attribute:: OUT
+
+ The contents are entirely outside the region.
+
+ .. attribute:: PART
+
+ The contents are partially inside and partially outside the region.
+
+
+.. class:: Status
+
+ .. versionadded:: 1.13
+
+ .. attribute:: SUCCESS
+ NO_MEMORY
+ INVALID_RESTORE
+ INVALID_POP_GROUP
+ NO_CURRENT_POINT
+ INVALID_MATRIX
+ INVALID_STATUS
+ NULL_POINTER
+ INVALID_STRING
+ INVALID_PATH_DATA
+ READ_ERROR
+ WRITE_ERROR
+ SURFACE_FINISHED
+ SURFACE_TYPE_MISMATCH
+ PATTERN_TYPE_MISMATCH
+ INVALID_CONTENT
+ INVALID_FORMAT
+ INVALID_VISUAL
+ FILE_NOT_FOUND
+ INVALID_DASH
+ INVALID_DSC_COMMENT
+ INVALID_INDEX
+ CLIP_NOT_REPRESENTABLE
+ TEMP_FILE_ERROR
+ INVALID_STRIDE
+ FONT_TYPE_MISMATCH
+ USER_FONT_IMMUTABLE
+ USER_FONT_ERROR
+ NEGATIVE_COUNT
+ INVALID_CLUSTERS
+ INVALID_SLANT
+ INVALID_WEIGHT
+ INVALID_SIZE
+ USER_FONT_NOT_IMPLEMENTED
+ DEVICE_TYPE_MISMATCH
+ DEVICE_ERROR
+ INVALID_MESH_CONSTRUCTION
+ DEVICE_FINISHED
+ LAST_STATUS
diff --git a/docs/reference/exceptions.rst b/docs/reference/exceptions.rst
index 42ac144..327cc3d 100644
--- a/docs/reference/exceptions.rst
+++ b/docs/reference/exceptions.rst
@@ -19,7 +19,7 @@ cairo.Error()
.. attribute:: status
- :type: :ref:`constants_STATUS`
+ :type: :class:`cairo.Status`
.. data:: CairoError
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
index 7876f6c..c256cbf 100644
--- a/docs/reference/index.rst
+++ b/docs/reference/index.rst
@@ -10,6 +10,7 @@ API Reference
:maxdepth: 2
constants
+ enums
context
exceptions
matrix
@@ -18,3 +19,4 @@ API Reference
region
surfaces
text
+ legacy_constants
diff --git a/docs/reference/legacy_constants.rst b/docs/reference/legacy_constants.rst
new file mode 100644
index 0000000..d2087e6
--- /dev/null
+++ b/docs/reference/legacy_constants.rst
@@ -0,0 +1,490 @@
+.. _legacy_constants:
+
+================
+Legacy Constants
+================
+
+These constants are aliases for enum attributes in newer versions of Pycairo.
+They might still be useful if you need to support Pycairo versions older than
+1.13.
+
+.. currentmodule:: cairo
+
+.. data:: ANTIALIAS_DEFAULT
+
+ See :attr:`Antialias.DEFAULT`
+
+.. data:: ANTIALIAS_NONE
+
+ See :attr:`Antialias.NONE`
+
+.. data:: ANTIALIAS_GRAY
+
+ See :attr:`Antialias.GRAY`
+
+.. data:: ANTIALIAS_SUBPIXEL
+
+ See :attr:`Antialias.SUBPIXEL`
+
+.. data:: ANTIALIAS_FAST
+
+ See :attr:`Antialias.FAST`
+
+ .. versionadded:: 1.12.0
+
+.. data:: ANTIALIAS_GOOD
+
+ See :attr:`Antialias.GOOD`
+
+ .. versionadded:: 1.12.0
+
+.. data:: ANTIALIAS_BEST
+
+ See :attr:`Antialias.BEST`
+
+ .. versionadded:: 1.12.0
+
+.. data:: CONTENT_COLOR
+
+ See :attr:`Content.COLOR`
+
+.. data:: CONTENT_ALPHA
+
+ See :attr:`Content.ALPHA`
+
+.. data:: CONTENT_COLOR_ALPHA
+
+ See :attr:`Content.COLOR_ALPHA`
+
+.. data:: EXTEND_NONE
+
+ See :attr:`Extend.NONE`
+
+.. data:: EXTEND_REPEAT
+
+ See :attr:`Extend.REPEAT`
+
+.. data:: EXTEND_REFLECT
+
+ See :attr:`Extend.REFLECT`
+
+.. data:: EXTEND_PAD
+
+ See :attr:`Extend.PAD`
+
+.. data:: FILL_RULE_WINDING
+
+ See :attr:`FillRule.WINDING`
+
+.. data:: FILL_RULE_EVEN_ODD
+
+ See :attr:`FillRule.EVEN_ODD`
+
+.. data:: FILTER_FAST
+
+ See :attr:`Filter.FAST`
+
+.. data:: FILTER_GOOD
+
+ See :attr:`Filter.GOOD`
+
+.. data:: FILTER_BEST
+
+ See :attr:`Filter.BEST`
+
+.. data:: FILTER_NEAREST
+
+ See :attr:`Filter.NEAREST`
+
+.. data:: FILTER_BILINEAR
+
+ See :attr:`Filter.BILINEAR`
+
+.. data:: FILTER_GAUSSIAN
+
+ See :attr:`Filter.GAUSSIAN`
+
+.. data:: FONT_SLANT_NORMAL
+
+ See :attr:`FontSlant.NORMAL`
+
+.. data:: FONT_SLANT_ITALIC
+
+ See :attr:`FontSlant.ITALIC`
+
+.. data:: FONT_SLANT_OBLIQUE
+
+ See :attr:`FontSlant.OBLIQUE`
+
+.. data:: FONT_WEIGHT_NORMAL
+
+ See :attr:`FontWeight.NORMAL`
+
+.. data:: FONT_WEIGHT_BOLD
+
+ See :attr:`FontWeight.BOLD`
+
+.. data:: FORMAT_INVALID
+
+ See :attr:`Format.INVALID`
+
+ .. versionadded:: 1.12.0
+
+.. data:: FORMAT_ARGB32
+
+ See :attr:`Format.ARGB32`
+
+.. data:: FORMAT_RGB24
+
+ See :attr:`Format.RGB24`
+
+.. data:: FORMAT_A8
+
+ See :attr:`Format.A8`
+
+.. data:: FORMAT_A1
+
+ See :attr:`Format.A1`
+
+.. data:: FORMAT_RGB16_565
+
+ See :attr:`Format.RGB16_565`
+
+.. data:: FORMAT_RGB30
+
+ See :attr:`Format.RGB30`
+
+ .. versionadded:: 1.12.0
+
+.. data:: HINT_METRICS_DEFAULT
+
+ See :attr:`HintMetrics.DEFAULT`
+
+.. data:: HINT_METRICS_OFF
+
+ See :attr:`HintMetrics.OFF`
+
+.. data:: HINT_METRICS_ON
+
+ See :attr:`HintMetrics.ON`
+
+
+.. data:: HINT_STYLE_DEFAULT
+
+ See :attr:`HintStyle.DEFAULT`
+
+.. data:: HINT_STYLE_NONE
+
+ See :attr:`HintStyle.NONE`
+
+.. data:: HINT_STYLE_SLIGHT
+
+ See :attr:`HintStyle.SLIGHT`
+
+.. data:: HINT_STYLE_MEDIUM
+
+ See :attr:`HintStyle.MEDIUM`
+
+.. data:: HINT_STYLE_FULL
+
+ See :attr:`HintStyle.FULL`
+
+.. data:: LINE_CAP_BUTT
+
+ See :attr:`LineCap.BUTT`
+
+.. data:: LINE_CAP_ROUND
+
+ See :attr:`LineCap.ROUND`
+
+.. data:: LINE_CAP_SQUARE
+
+ See :attr:`LineCap.SQUARE`
+
+.. data:: LINE_JOIN_MITER
+
+ See :attr:`LineJoin.MITER`
+
+.. data:: LINE_JOIN_ROUND
+
+ See :attr:`LineJoin.ROUND`
+
+.. data:: LINE_JOIN_BEVEL
+
+ See :attr:`LineJoin.BEVEL`
+
+.. data:: OPERATOR_CLEAR
+
+ See :attr:`Operator.CLEAR`
+
+.. data:: OPERATOR_SOURCE
+
+ See :attr:`Operator.SOURCE`
+
+.. data:: OPERATOR_OVER
+
+ See :attr:`Operator.OVER`
+
+.. data:: OPERATOR_IN
+
+ See :attr:`Operator.IN`
+
+.. data:: OPERATOR_OUT
+
+ See :attr:`Operator.OUT`
+
+.. data:: OPERATOR_ATOP
+
+ See :attr:`Operator.ATOP`
+
+.. data:: OPERATOR_DEST
+
+ See :attr:`Operator.DEST`
+
+.. data:: OPERATOR_DEST_OVER
+
+ See :attr:`Operator.DEST_OVER`
+
+.. data:: OPERATOR_DEST_IN
+
+ See :attr:`Operator.DEST_IN`
+
+.. data:: OPERATOR_DEST_OUT
+
+ See :attr:`Operator.DEST_OUT`
+
+.. data:: OPERATOR_DEST_ATOP
+
+ See :attr:`Operator.DEST_ATOP`
+
+.. data:: OPERATOR_XOR
+
+ See :attr:`Operator.XOR`
+
+.. data:: OPERATOR_ADD
+
+ See :attr:`Operator.ADD`
+
+.. data:: OPERATOR_SATURATE
+
+ See :attr:`Operator.SATURATE`
+
+.. data:: OPERATOR_MULTIPLY
+
+ See :attr:`Operator.MULTIPLY`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_SCREEN
+
+ See :attr:`Operator.SCREEN`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_OVERLAY
+
+ See :attr:`Operator.OVERLAY`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_DARKEN
+
+ See :attr:`Operator.DARKEN`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_LIGHTEN
+
+ See :attr:`Operator.LIGHTEN`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_COLOR_DODGE
+
+ See :attr:`Operator.COLOR_DODGE`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_COLOR_BURN
+
+ See :attr:`Operator.COLOR_BURN`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_HARD_LIGHT
+
+ See :attr:`Operator.HARD_LIGHT`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_SOFT_LIGHT
+
+ See :attr:`Operator.SOFT_LIGHT`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_DIFFERENCE
+
+ See :attr:`Operator.DIFFERENCE`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_EXCLUSION
+
+ See :attr:`Operator.EXCLUSION`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_HSL_HUE
+
+ See :attr:`Operator.HSL_HUE`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_HSL_SATURATION
+
+ See :attr:`Operator.HSL_SATURATION`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_HSL_COLOR
+
+ See :attr:`Operator.HSL_COLOR`
+
+ .. versionadded:: 1.12.0
+
+.. data:: OPERATOR_HSL_LUMINOSITY
+
+ See :attr:`Operator.HSL_LUMINOSITY`
+
+ .. versionadded:: 1.12.0
+
+.. data:: PATH_MOVE_TO
+
+ See :attr:`PathDataType.MOVE_TO`
+
+.. data:: PATH_LINE_TO
+
+ See :attr:`PathDataType.LINE_TO`
+
+.. data:: PATH_CURVE_TO
+
+ See :attr:`PathDataType.CURVE_TO`
+
+.. data:: PATH_CLOSE_PATH
+
+ See :attr:`PathDataType.CLOSE_PATH`
+
+.. data:: PS_LEVEL_2
+
+ See :attr:`PSLevel.LEVEL_2`
+
+.. data:: PS_LEVEL_3
+
+ See :attr:`PSLevel.LEVEL_3`
+
+.. data:: PDF_VERSION_1_4
+
+ See :attr:`PDFVersion.VERSION_1_4`
+
+ .. versionadded:: 1.12.0
+
+.. data:: PDF_VERSION_1_5
+
+ See :attr:`PDFVersion.VERSION_1_5`
+
+ .. versionadded:: 1.12.0
+
+.. data:: SVG_VERSION_1_1
+
+ See :attr:`SVGVersion.VERSION_1_1`
+
+ .. versionadded:: 1.12.0
+
+.. data:: SVG_VERSION_1_2
+
+ See :attr:`SVGVersion.VERSION_1_2`
+
+ .. versionadded:: 1.12.0
+
+.. data:: SUBPIXEL_ORDER_DEFAULT
+
+ See :attr:`SubpixelOrder.DEFAULT`
+
+.. data:: SUBPIXEL_ORDER_RGB
+
+ See :attr:`SubpixelOrder.RGB`
+
+.. data:: SUBPIXEL_ORDER_BGR
+
+ See :attr:`SubpixelOrder.BGR`
+
+.. data:: SUBPIXEL_ORDER_VRGB
+
+ See :attr:`SubpixelOrder.VRGB`
+
+.. data:: SUBPIXEL_ORDER_VBGR
+
+ See :attr:`SubpixelOrder.VBGR`
+
+.. data:: REGION_OVERLAP_IN
+
+ See :attr:`RegionOverlap.IN`
+
+ .. versionadded:: 1.11
+
+.. data:: REGION_OVERLAP_OUT
+
+ See :attr:`RegionOverlap.OUT`
+
+ .. versionadded:: 1.11
+
+.. data:: REGION_OVERLAP_PART
+
+ See :attr:`RegionOverlap.PART`
+
+ .. versionadded:: 1.11
+
+.. data:: STATUS_SUCCESS
+ STATUS_NO_MEMORY
+ STATUS_INVALID_RESTORE
+ STATUS_INVALID_POP_GROUP
+ STATUS_NO_CURRENT_POINT
+ STATUS_INVALID_MATRIX
+ STATUS_INVALID_STATUS
+ STATUS_NULL_POINTER
+ STATUS_INVALID_STRING
+ STATUS_INVALID_PATH_DATA
+ STATUS_READ_ERROR
+ STATUS_WRITE_ERROR
+ STATUS_SURFACE_FINISHED
+ STATUS_SURFACE_TYPE_MISMATCH
+ STATUS_PATTERN_TYPE_MISMATCH
+ STATUS_INVALID_CONTENT
+ STATUS_INVALID_FORMAT
+ STATUS_INVALID_VISUAL
+ STATUS_FILE_NOT_FOUND
+ STATUS_INVALID_DASH
+ STATUS_INVALID_DSC_COMMENT
+ STATUS_INVALID_INDEX
+ STATUS_CLIP_NOT_REPRESENTABLE
+ STATUS_TEMP_FILE_ERROR
+ STATUS_INVALID_STRIDE
+ STATUS_FONT_TYPE_MISMATCH
+ STATUS_USER_FONT_IMMUTABLE
+ STATUS_USER_FONT_ERROR
+ STATUS_NEGATIVE_COUNT
+ STATUS_INVALID_CLUSTERS
+ STATUS_INVALID_SLANT
+ STATUS_INVALID_WEIGHT
+ STATUS_INVALID_SIZE
+ STATUS_USER_FONT_NOT_IMPLEMENTED
+ STATUS_DEVICE_TYPE_MISMATCH
+ STATUS_DEVICE_ERROR
+ STATUS_INVALID_MESH_CONSTRUCTION
+ STATUS_DEVICE_FINISHED
+ STATUS_LAST_STATUS
+
+ See :class:`Status`
+
+ .. versionadded:: 1.12
diff --git a/docs/reference/matrix.rst b/docs/reference/matrix.rst
index c34e106..426521c 100644
--- a/docs/reference/matrix.rst
+++ b/docs/reference/matrix.rst
@@ -140,8 +140,8 @@ For more information on matrix transformation see https://www.cairographics.org/
:type dx: float
:param dy: Y component of a distance vector.
:type dy: float
- :returns: the transformed distance vector (dx,dy)
- :rtype: (float, float)
+ :returns: the transformed distance vector (dx,dy), both float
+ :rtype: tuple
Transforms the distance vector *(dx,dy)* by *Matrix*. This is similar to
:meth:`.transform_point` except that the translation components of
@@ -163,8 +163,8 @@ For more information on matrix transformation see https://www.cairographics.org/
:type x: float
:param y: Y position.
:type y: float
- :returns: the transformed point (x,y)
- :rtype: (float, float)
+ :returns: the transformed point (x,y), both float
+ :rtype: tuple
Transforms the point *(x, y)* by *Matrix*.
diff --git a/docs/reference/paths.rst b/docs/reference/paths.rst
index ebaac59..b003adb 100644
--- a/docs/reference/paths.rst
+++ b/docs/reference/paths.rst
@@ -16,7 +16,7 @@ class Path()
str(path) lists the path elements.
- See :ref:`PATH attributes <constants_PATH>`
+ See :class:`path attributes <cairo.PathDataType>`
Path is an iterator.
diff --git a/docs/reference/patterns.rst b/docs/reference/patterns.rst
index 85b7873..a83e536 100644
--- a/docs/reference/patterns.rst
+++ b/docs/reference/patterns.rst
@@ -26,11 +26,11 @@ derive. It cannot be instantiated directly.
.. method:: get_extend()
:returns: the current extend strategy used for drawing the *Pattern*.
- :rtype: int
+ :rtype: cairo.Extend
Gets the current extend mode for the *Pattern*. See
- :ref:`EXTEND attributes <constants_EXTEND>`
- for details on the semantics of each extend strategy.
+ :class:`cairo.Extend` attributes for details on the semantics of each
+ extend strategy.
.. method:: get_matrix()
@@ -38,8 +38,9 @@ derive. It cannot be instantiated directly.
.. method:: get_filter()
- :returns: the current :ref:`FILTER <constants_filter>` used for
+ :returns: the current filter used for
resizing the pattern.
+ :rtype: cairo.Filter
.. versionadded:: 1.12.0
@@ -47,7 +48,7 @@ derive. It cannot be instantiated directly.
.. method:: set_filter(filter)
- :param filter: a :ref:`FILTER <constants_filter>` describing the filter
+ :param cairo.Filter filter: a filter describing the filter
to use for resizing the pattern
Note that you might want to control filtering even when you do not have
@@ -65,13 +66,13 @@ derive. It cannot be instantiated directly.
.. method:: set_extend(extend)
- :param extend: an :ref:`EXTEND <constants_EXTEND>` describing how the
+ :param cairo.Extend extend: an extend describing how the
area outside of the *Pattern* will be drawn
Sets the mode to be used for drawing outside the area of a *Pattern*.
- The default extend mode is :data:`cairo.EXTEND_NONE` for
- :class:`SurfacePattern` and :data:`cairo.EXTEND_PAD` for
+ The default extend mode is :attr:`cairo.Extend.NONE` for
+ :class:`SurfacePattern` and :attr:`cairo.Extend.PAD` for
:class:`Gradient` Patterns.
.. method:: set_matrix(matrix)
diff --git a/docs/reference/region.rst b/docs/reference/region.rst
index 30030f0..99bfe03 100644
--- a/docs/reference/region.rst
+++ b/docs/reference/region.rst
@@ -63,7 +63,8 @@ areas of interest, such as change or clip areas.
.. method:: contains_rectangle(rectangle)
:param RectangleInt rectangle:
- :returns: :ref:`REGION_OVERLAP <constants_REGION_OVERLAP>`
+ :returns: region overlap
+ :rtype: cairo.RegionOverlap
Checks whether rectangle is inside, outside or partially contained in
region
diff --git a/docs/reference/surfaces.rst b/docs/reference/surfaces.rst
index 48bd548..cca9059 100644
--- a/docs/reference/surfaces.rst
+++ b/docs/reference/surfaces.rst
@@ -29,7 +29,6 @@ Surfaces
:exc:`cairo.Error`
:meth:`.copy_page`
:meth:`Context.copy_page`
- :ref:`LINE_CAP <constants_LINE_CAP>`
``ctx.rel_move_to(dx, dy)`` # code snippet
@@ -62,7 +61,7 @@ class Surface()
.. method:: create_similar(content, width, height)
- :param content: the :ref:`CONTENT <constants_CONTENT>` for the new
+ :param cairo.Content content: the content for the new
surface
:param width: width of the new surface, (in device-space units)
:type width: int
@@ -99,9 +98,10 @@ class Surface()
.. method:: get_content()
- :returns: The :ref:`CONTENT <constants_CONTENT>` type of *Surface*,
+ :returns: The content type of *Surface*,
which indicates whether the *Surface* contains color and/or alpha
information.
+ :rtype: cairo.Content
.. versionadded:: 1.2
@@ -317,7 +317,7 @@ class Surface()
.. method:: create_similar_image(format, width, height)
- :param format: the :ref:`FORMAT <constants_FORMAT>` for the new surface
+ :param cairo.Format format: the format for the new surface
:param int width: width of the new surface, (in device-space units)
:param int height: height of the new surface, (in device-space units)
:returns: a new image surface
@@ -357,11 +357,11 @@ class ImageSurface(:class:`Surface`)
A *cairo.ImageSurface* provides the ability to render to memory buffers either
allocated by cairo or by the calling code. The supported image formats are
-those defined in :ref:`FORMAT attributes <constants_FORMAT>`.
+those defined in :class:`cairo.Format`.
.. class:: ImageSurface(format, width, height)
- :param format: :ref:`FORMAT <constants_FORMAT>` of pixels in the surface to create
+ :param cairo.Format format: format of pixels in the surface to create
:param width: width of the surface, in pixels
:param height: height of the surface, in pixels
:returns: a new *ImageSurface*
@@ -375,7 +375,7 @@ those defined in :ref:`FORMAT attributes <constants_FORMAT>`.
.. classmethod:: create_for_data(data, format, width, height[, stride])
:param data: a writable Python buffer/memoryview object
- :param format: the :ref:`FORMAT <constants_FORMAT>` of pixels in the
+ :param cairo.Format format: the format of pixels in the
buffer
:param width: the width of the image to be stored in the buffer
:param height: the height of the image to be stored in the buffer
@@ -409,7 +409,7 @@ those defined in :ref:`FORMAT attributes <constants_FORMAT>`.
.. staticmethod:: format_stride_for_width(format, width)
- :param format: a cairo :ref:`FORMAT <constants_FORMAT>` value
+ :param cairo.Format format: a cairo format value
:param width: the desired width of an *ImageSurface* to be created.
:returns: the appropriate stride to use given the desired format and
width, or -1 if either the format is invalid or the width too large.
@@ -434,7 +434,8 @@ those defined in :ref:`FORMAT attributes <constants_FORMAT>`.
.. method:: get_format()
- :returns: the :ref:`FORMAT <constants_FORMAT>` of the *ImageSurface*.
+ :returns: the format of the *ImageSurface*.
+ :rtype: cairo.Format
.. versionadded:: 1.2
@@ -495,7 +496,7 @@ multi-page vector surface backend.
.. method:: restrict_to_version(version)
:param version: PDF version
- :type version: :ref:`constants_PDF_VERSION`
+ :type cairo.PDFVersion version: PDF version
Restricts the generated PDF file to version . See :meth:`get_versions`
for a list of available version values that can be used here.
@@ -519,7 +520,7 @@ multi-page vector surface backend.
.. staticmethod:: version_to_string(version)
:param version: PDF version
- :type version: :ref:`constants_PDF_VERSION`
+ :type cairo.PDFVersion version: PDF version
:returns: the string associated to the given version
:rtype: str
:raises ValueError: if version isn't valid
@@ -674,7 +675,7 @@ is a multi-page vector surface backend.
.. staticmethod:: level_to_string(level)
- :param level: a :ref:`PS_LEVEL <constants_PS_LEVEL>`
+ :param cairo.PSLevel level: a PS level
:returns: the string associated to given level.
:rtype: str
@@ -695,7 +696,7 @@ is a multi-page vector surface backend.
.. method:: restrict_to_level(level)
- :param level: a :ref:`PS_LEVEL <constants_PS_LEVEL>`
+ :param cairo.PSLevel level: a PS level
Restricts the generated PostSript file to *level*. See
:meth:`get_levels` for a list of available level values that
@@ -780,7 +781,7 @@ replay.
.. class:: RecordingSurface(content, rectangle)
- :param content: the :ref:`CONTENT <constants_CONTENT>` for the new surface
+ :param cairo.Content content: the content for the new surface
:param rectangle: a 4-tuple of float, or None to record unbounded operations.
:returns: a new *RecordingSurface*
@@ -842,7 +843,7 @@ multi-page vector surface backend
.. method:: restrict_to_version(version)
:param version: SVG version
- :type version: :ref:`constants_SVG_VERSION`
+ :type cairo.SVGVersion version: SVG version
Restricts the generated SVG file to version . See :meth:`get_versions`
for a list of available version values that can be used here.
@@ -866,7 +867,7 @@ multi-page vector surface backend
.. staticmethod:: version_to_string(version)
:param version: SVG version
- :type version: :ref:`constants_SVG_VERSION`
+ :type cairo.SVGVersion version: SVG version
:returns: the string associated to the given version
:rtype: str
:raises ValueError: if version isn't valid
@@ -893,7 +894,7 @@ Windows windows, bitmaps, and printing device contexts.
Creates a cairo surface that targets the given DC. The DC will be queried
for its initial clip extents, and this will be used as the size of the
cairo surface. The resulting surface will always be of format
- cairo.FORMAT_RGB24, see :ref:`FORMAT attributes <constants_FORMAT>`.
+ cairo.FORMAT_RGB24, see :class:`cairo.Format`.
diff --git a/docs/reference/text.rst b/docs/reference/text.rst
index 552f6cc..0b74f19 100644
--- a/docs/reference/text.rst
+++ b/docs/reference/text.rst
@@ -66,10 +66,10 @@ The *cairo.ToyFontFace* class can be used instead of :meth:`Context.select_font_
:param family: a font family name
:type family: text
- :param slant: the :ref:`FONT_SLANT <constants_FONT_SLANT>` of the font,
- defaults to :data:`cairo.FONT_SLANT_NORMAL`.
- :param weight: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` of the font,
- defaults to :data:`cairo.FONT_WEIGHT_NORMAL`.
+ :param cairo.FontSlant slant: the font slant of the font,
+ defaults to :attr:`cairo.FontSlant.NORMAL`.
+ :param cairo.FontWeight weight: the font weight of the font,
+ defaults to :attr:`cairo.FontWeight.NORMAL`.
:returns: a new *ToyFontFace*
Creates a *ToyFontFace* from a triplet of family, slant, and weight. These
@@ -93,13 +93,15 @@ The *cairo.ToyFontFace* class can be used instead of :meth:`Context.select_font_
.. method:: get_slant()
- :returns: the :ref:`FONT_SLANT <constants_FONT_SLANT>` value
+ :returns: the font slant value
+ :rtype: cairo.FontSlant
.. versionadded:: 1.8.4
.. method:: get_weight()
- :returns: the :ref:`FONT_WEIGHT <constants_FONT_WEIGHT>` value
+ :returns: the font weight value
+ :rtype: cairo.FontWeight
.. versionadded:: 1.8.4
@@ -205,8 +207,9 @@ use.
:param text: text
:type text: text
- :returns: (x_bearing, y_bearing, width, height, x_advance, y_advance)
- :rtype: 6-tuple of float
+ :returns: 6-tuple of float:
+ (x_bearing, y_bearing, width, height, x_advance, y_advance)
+ :rtype: tuple
Gets the extents for a string of text. The extents describe a user-space
rectangle that encloses the "inked" portion of the text drawn at the
@@ -256,47 +259,51 @@ objects.
.. method:: get_antialias()
- :returns: the :ref:`ANTIALIAS <constants_ANTIALIAS>` mode for the *FontOptions* object
+ :returns: the antialias mode for the *FontOptions* object
+ :rtype: cairo.Antialias
.. method:: get_hint_metrics()
- :returns: the :ref:`HINT METRICS <constants_HINT_METRICS>` mode for the *FontOptions* object
+ :returns: the hint metrics mode for the *FontOptions* object
+ :rtype: cairo.HintMetrics
.. method:: get_hint_style()
- :returns: the :ref:`HINT STYLE <constants_HINT_STYLE>` for the *FontOptions* object
+ :returns: the hint style for the *FontOptions* object
+ :rtype: cairo.HintStyle
.. method:: get_subpixel_order()
- :returns: the :ref:`SUBPIXEL_ORDER <constants_SUBPIXEL_ORDER>` for the *FontOptions* object
+ :returns: the subpixel order for the *FontOptions* object
+ :rtype: cairo.SubpixelOrder
.. method:: set_antialias(antialias)
- :param antialias: the :ref:`ANTIALIAS <constants_ANTIALIAS>` mode
+ :param cairo.Antialias antialias: the antialias mode
This specifies the type of antialiasing to do when rendering text.
.. method:: set_hint_metrics(hint_metrics)
- :param hint_metrics: the :ref:`HINT METRICS <constants_HINT_METRICS>` mode
+ :param cairo.HintMetrics hint_metrics: the hint metrics mode
This controls whether metrics are quantized to integer values in device
units.
.. method:: set_hint_style(hint_style)
- :param hint_style: the :ref:`HINT STYLE <constants_HINT_STYLE>`
+ :param cairo.HintStyle hint_style: the hint style
This controls whether to fit font outlines to the pixel grid, and if so,
whether to optimize for fidelity or contrast.
.. method:: set_subpixel_order(subpixel_order)
- :param subpixel_order: the :ref:`SUBPIXEL_ORDER <constants_SUBPIXEL_ORDER>`
+ :param cairo.SubpixelOrder subpixel_order: the subpixel order
The subpixel order specifies the order of color elements within each
pixel on the display device when rendering with an antialiasing mode of
- :data:`cairo.ANTIALIAS_SUBPIXEL`.
+ :attr:`cairo.Antialias.SUBPIXEL`.
.. method:: merge(other)
@@ -305,7 +312,7 @@ objects.
Merges non-default options from other into options , replacing existing
values. This operation can be thought of as somewhat similar to
compositing other onto options with the operation of
- :data:`OPERATOR_OVER`.
+ :attr:`Operator.OVER`.
.. versionadded:: 1.12.0
diff --git a/docs/resources.rst b/docs/resources.rst
new file mode 100644
index 0000000..cc3986e
--- /dev/null
+++ b/docs/resources.rst
@@ -0,0 +1,67 @@
+=========
+Resources
+=========
+
+This section is for listing various useful pycairo resources, feel free to
+contribute !
+
+Windows Binary Packages (unofficial)
+ Precompiled binaries for the Microsoft Windows platform can be obtained from
+ the following sources:
+
+ `Precompiled PyCairo for Python 2.x from Uri Shaked
+ <http://www.salsabeatmachine.org/python/pycairo-win32-packages.html>`_
+
+Some Libraries/Modules Using pycairo
+ * `Cairo Plot <https://launchpad.net/cairoplot>`_: a module to plot
+ graphics
+ * `hamster graphics library
+ <http://wiki.github.com/tbaugis/hamster_experiments/>`_ - a sprite styled
+ abstraction library for drawing and animation in PyGTK
+ * `matplotlib <http://matplotlib.sourceforge.net/>`_: a python 2D plotting
+ library which produces publication quality figures in a variety of
+ hardcopy formats and interactive environments across platforms.
+ * `PyCha <http://bitbucket.org/lgs/pycha/wiki/Home>`_: PYthon CHArts - a
+ Python package for drawing charts
+ * `PyGoocanvas <http://live.gnome.org/PyGoocanvas>`_: python bindings for
+ GooCanvas which is a canvas widget for GTK+
+ * `PyGTK <http://www.pygtk.org>`_: GTK+ for Python.
+ * rsvg: part of `gnome-python-desktop
+ <http://www.pygtk.org/downloads.html>`_, it provides Python bindings for
+ librsvg
+
+Some Applications Using pycairo
+ * `A Shogiban for Gnushogi
+ <http://ralph-glass.homepage.t-online.de/shogi/readme.html>`_.
+ * `gPodder <http://gpodder.berlios.de>`_: a podcatcher.
+ * `Miro <http://www.getmiro.com/>`_: Internet TV, HD video player.
+ * pycairo projects at `Google Code
+ <http://code.google.com/hosting/search?q=pycairo&btn=Search+projects>`_.
+ * `PyChess <http://pychess.googlepages.com>`_.
+ * `Pyroute - OpenStreetMap <http://wiki.openstreetmap.org/wiki/Pyroute>`_.
+ * `Shoebot <http://tinkerhouse.net/shoebot/>`_ - a pure Python graphics
+ robot.
+
+Tutorials
+ * `Cairo Tutorial for Python (and other) Programmers
+ <http://www.tortall.net/mu/wiki/CairoTutorial>`_: Generic introduction to
+ cairo concepts oriented to python.
+ * `Cairo Tutorial for PyGTK Programmers
+ <http://www.tortall.net/mu/wiki/PyGTKCairoTutorial>`_: Tutorial about how
+ to use cairo for drawing in `PyGTK <http://www.pygtk.org>`_.
+ * Writing a widget using cairo and PyGTK 2.8 `Part 1
+ <http://www.pygtk.org/articles/cairo-pygtk-widgets/cairo-pygtk-widgets.htm>`_,
+ `Part 2
+ <http://www.pygtk.org/articles/cairo-pygtk-widgets/cairo-pygtk-widgets2.htm>`_:
+ A translation of the GNOME Journal tutorial by Davyd Madeley from C to
+ Python.
+
+Demos
+ * `A Basic Cairo-clock in Python
+ <http://blog.eikke.com/index.php/ikke/2007/02/17/python_cairo_xshape_and_clocks>`_
+ using XShape.
+ * `A simple clock implemented in pygtk and cairo
+ <http://ralph-glass.homepage.t-online.de/clock/readme.html>`_.
+
+Recipies
+ See the main `Cairo Cookbook <https://www.cairographics.org/cookbook/>`_.
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
new file mode 100644
index 0000000..9b6f250
--- /dev/null
+++ b/docs/tutorial.rst
@@ -0,0 +1,114 @@
+.. title:: Tutorial
+
+====================================
+An Introduction to Cairo with Python
+====================================
+
+Cairo is a library for drawing vector graphics. Vector graphics are
+interesting because they don't lose clarity when resized or transformed.
+
+Pycairo is a set of bindings for cairo. It provides the cairo module which can
+be used to call cairo commands from Python.
+
+.. toctree::
+ :titlesonly:
+
+ integration
+ examples
+
+
+Understanding How to use Cairo
+------------------------------
+
+The best way to understand how to use cairo is to imagine that you are an
+artist using a paintbrush to draw out a shape on canvas.
+
+To begin, you can choose a few characteristics of your brush. You can choose
+the thickness of your brush and the colour you want to paint with. You can
+also choose the shape of your brush tip - You can choose either a circle or a
+square.
+
+Once you have chosen your brush, you are ready to start painting. You have to
+be quite precise when describing what you want to appear.
+
+Firstly, decide where you want to place your brush on the canvas. You do this
+by supplying an x & y coordinate. Next you define how you want your brush
+stroke to look - an arc, a straight line etc. Finally you define the point
+where you want your stoke to end, again by supplying an x & y coordinate.
+Triangles and squares are very easy to do!
+
+More complex graphics are generated using variations of the above theme with a
+few additions such as Fills (colouring in), transformations (zooming in,
+moving) etc. Using the Python interface to cairo
+
+Nearly all the work revolves around using the :class:`cairo.Context` (or
+``cairo_t`` in the cairo C API). This is the object that you send your drawing
+commands to. There are a few options available to initialize this object in
+different ways.
+
+Initializing the cairo.Context Object
+-------------------------------------
+
+* One Very Important thing to realize is there is a difference between the
+ coordinates you are describing your graphics on and the coordinates you will
+ be displaying your graphic on.
+
+ (Ex - When giving a presentation you draw on your transparent acetate before
+ hand, and then display it on your overhead projector - cairo calls the
+ transparent acetate the user space coordinates and the projected image the
+ device space coordinates)
+
+ On initializing the cairo context object, we tell it how to transform our
+ description to how it should be displayed. To do this we supply a
+ transformation matrix. Modifying the transformation matrix can lead to some
+ very interesting results.
+
+* One of cairo's most powerful features is that it can output graphics in many
+ different formats (it can use multiple back ends). For printing, we can have
+ cairo translate our graphics into Postscript to be sent off to the printer.
+ For on screen display, we can have cairo translate our graphics into
+ something glitz can understand for hardware accelerated rendering! It has
+ many more important and useful target back ends. On initializing the
+ :class:`cairo.Context`, we set its target back end, supplying a few details
+ (such as colour depth and size), as in the example below.
+
+Example
+-------
+
+.. code:: python
+
+ #!/usr/bin/env python
+
+ import math
+ import cairo
+
+ WIDTH, HEIGHT = 256, 256
+
+ surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
+ ctx = cairo.Context (surface)
+
+ ctx.scale (WIDTH, HEIGHT) # Normalizing the canvas
+
+ pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
+ pat.add_color_stop_rgba (1, 0.7, 0, 0, 0.5) # First stop, 50% opacity
+ pat.add_color_stop_rgba (0, 0.9, 0.7, 0.2, 1) # Last stop, 100% opacity
+
+ ctx.rectangle (0, 0, 1, 1) # Rectangle(x0, y0, x1, y1)
+ ctx.set_source (pat)
+ ctx.fill ()
+
+ ctx.translate (0.1, 0.1) # Changing the current transformation matrix
+
+ ctx.move_to (0, 0)
+ # Arc(cx, cy, radius, start_angle, stop_angle)
+ ctx.arc (0.2, 0.1, 0.1, -math.pi/2, 0)
+ ctx.line_to (0.5, 0.1) # Line to (x,y)
+ # Curve(x1, y1, x2, y2, x3, y3)
+ ctx.curve_to (0.5, 0.2, 0.5, 0.4, 0.2, 0.8)
+ ctx.close_path ()
+
+ ctx.set_source_rgb (0.3, 0.2, 0.5) # Solid color
+ ctx.set_line_width (0.02)
+ ctx.stroke ()
+
+ surface.write_to_png ("example.png") # Output to PNG
diff --git a/examples/cairo_snippets/c_to_python.py b/examples/cairo_snippets/c_to_python.py
deleted file mode 100644
index c01ebe5..0000000
--- a/examples/cairo_snippets/c_to_python.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env python
-"""
-translate C <snippet>.cairo to Python <snippet>.py
-
-; -> ''
-cairo_ -> cr.
-'(cr, ' -> ( but not snippet_normalize (cr, width, height)
-(cr) -> ()
-/* -> #/*
-CAIRO_ -> cairo.
-"""
-
-import sys
-
-
-if len(sys.argv) != 2 or not sys.argv[1].endswith('.cairo'):
- raise SystemExit('usage: c_to_python.py <file>.cairo')
-
-filename_in = sys.argv[1]
-filename_out = filename_in.replace('.cairo', '.py')
-
-file_in = file(filename_in)
-file_out = file(filename_out, 'w')
-
-for line in file_in:
- line = line.replace(';', '') # should be ';' and whitespace to EOL only -> \n
- if not line.startswith('snippet_'):
- line = line.replace('cairo_', 'cr.')
- line = line.replace('(cr, ', '(')
- line = line.replace('(cr)', '()')
- line = line.replace('/*', '#/*')
- line = line.replace(' ', '')
- line = line.replace('CAIRO_', 'cairo.')
-
- file_out.write (line)
diff --git a/examples/cairo_snippets/snippets/__init__.py b/examples/cairo_snippets/snippets/__init__.py
index 70b4813..33ea3ad 100644
--- a/examples/cairo_snippets/snippets/__init__.py
+++ b/examples/cairo_snippets/snippets/__init__.py
@@ -1,12 +1,36 @@
-# snippet list generation
import os
+import importlib
-# list of snippet files
-snip_list = [x[:-3] for x in os.listdir (os.path.dirname (__file__))
- if not x.startswith('_') and x.endswith('.py')]
-snip_list.sort()
-# function used by some or all snippets
-def snippet_normalize (ctx, width, height):
- ctx.scale (width, height)
- ctx.set_line_width (0.04)
+class Snippet(object):
+
+ name = ""
+ """name of the snippet"""
+
+ code = ""
+ """Snippet code as text"""
+
+ def draw_func(cr, width, height):
+ """Snippet entry point"""
+
+ raise NotImplementedError
+
+
+def get_snippets():
+ """Returns a name:snippet dict"""
+
+ # list of snippet files
+ snip_list = [x[:-3] for x in os.listdir(os.path.dirname(__file__))
+ if not x.startswith('_') and x.endswith('.py')]
+ snip_list.sort()
+
+ snippets = {}
+ for name in snip_list:
+ s = Snippet()
+ s.name = name
+ mod = importlib.import_module("." + name, __package__)
+ s.draw_func = getattr(mod, "draw")
+ with open(mod.__file__, "rb") as h:
+ s.code = h.read().decode("utf-8")
+ snippets[s.name] = s
+ return snippets
diff --git a/examples/cairo_snippets/snippets/arc.py b/examples/cairo_snippets/snippets/arc.py
index b4e6e5d..4857dfb 100644
--- a/examples/cairo_snippets/snippets/arc.py
+++ b/examples/cairo_snippets/snippets/arc.py
@@ -1,21 +1,26 @@
-xc = 0.5
-yc = 0.5
-radius = 0.4
-angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */
-angle2 = 180.0 * (M_PI/180.0) #/* in radians */
+from math import pi
-snippet_normalize (cr, width, height)
-cr.arc (xc, yc, radius, angle1, angle2)
-cr.stroke ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-#/* draw helping lines */
-cr.set_source_rgba (1,0.2,0.2,0.6)
-cr.arc (xc, yc, 0.05, 0, 2*M_PI)
-cr.fill ()
-cr.set_line_width (0.03)
-cr.arc (xc, yc, radius, angle1, angle1)
-cr.line_to (xc, yc)
-cr.arc (xc, yc, radius, angle2, angle2)
-cr.line_to (xc, yc)
-cr.stroke ()
+ xc = 0.5
+ yc = 0.5
+ radius = 0.4
+ angle1 = 45.0 * (pi / 180.0) # angles are specified
+ angle2 = 180.0 * (pi / 180.0) # in radians
+
+ cr.arc(xc, yc, radius, angle1, angle2)
+ cr.stroke()
+
+ # draw helping lines
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.arc(xc, yc, 0.05, 0, 2 * pi)
+ cr.fill()
+ cr.set_line_width(0.03)
+ cr.arc(xc, yc, radius, angle1, angle1)
+ cr.line_to(xc, yc)
+ cr.arc(xc, yc, radius, angle2, angle2)
+ cr.line_to(xc, yc)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/arc_negative.py b/examples/cairo_snippets/snippets/arc_negative.py
index ca6a85d..76a446d 100644
--- a/examples/cairo_snippets/snippets/arc_negative.py
+++ b/examples/cairo_snippets/snippets/arc_negative.py
@@ -1,22 +1,26 @@
-xc = 0.5
-yc = 0.5
-radius = 0.4
-angle1 = 45.0 * (M_PI/180.0) #/* angles are specified */
-angle2 = 180.0 * (M_PI/180.0) #/* in radians */
+from math import pi
-snippet_normalize (cr, width, height)
-cr.arc_negative (xc, yc, radius, angle1, angle2)
-cr.stroke ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-#/* draw helping lines */
-cr.set_source_rgba (1,0.2,0.2,0.6)
-cr.arc (xc, yc, 0.05, 0, 2*M_PI)
-cr.fill ()
-cr.set_line_width (0.03)
-cr.arc (xc, yc, radius, angle1, angle1)
-cr.line_to (xc, yc)
-cr.arc (xc, yc, radius, angle2, angle2)
-cr.line_to (xc, yc)
-cr.stroke ()
-#cr.stroke (10)
+ xc = 0.5
+ yc = 0.5
+ radius = 0.4
+ angle1 = 45.0 * (pi / 180.0) # angles are specified
+ angle2 = 180.0 * (pi / 180.0) # in radians
+
+ cr.arc_negative(xc, yc, radius, angle1, angle2)
+ cr.stroke()
+
+ # draw helping lines
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.arc(xc, yc, 0.05, 0, 2 * pi)
+ cr.fill()
+ cr.set_line_width(0.03)
+ cr.arc(xc, yc, radius, angle1, angle1)
+ cr.line_to(xc, yc)
+ cr.arc(xc, yc, radius, angle2, angle2)
+ cr.line_to(xc, yc)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/clip.py b/examples/cairo_snippets/snippets/clip.py
index 8456235..16c087b 100644
--- a/examples/cairo_snippets/snippets/clip.py
+++ b/examples/cairo_snippets/snippets/clip.py
@@ -1,13 +1,18 @@
-snippet_normalize (cr, width, height)
-
-cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI)
-cr.clip ()
-
-cr.rectangle (0, 0, 1, 1)
-cr.fill ()
-cr.set_source_rgb (0, 1, 0)
-cr.move_to (0, 0)
-cr.line_to (1, 1)
-cr.move_to (1, 0)
-cr.line_to (0, 1)
-cr.stroke ()
+from math import pi
+
+
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ cr.arc(0.5, 0.5, 0.3, 0, 2 * pi)
+ cr.clip()
+
+ cr.rectangle(0, 0, 1, 1)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 0)
+ cr.move_to(0, 0)
+ cr.line_to(1, 1)
+ cr.move_to(1, 0)
+ cr.line_to(0, 1)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/curve_rectangle.py b/examples/cairo_snippets/snippets/curve_rectangle.py
index 3fb3c4a..b1a05be 100644
--- a/examples/cairo_snippets/snippets/curve_rectangle.py
+++ b/examples/cairo_snippets/snippets/curve_rectangle.py
@@ -1,53 +1,54 @@
-#/* a custom shape, that could be wrapped in a function */
-x0 = 0.1 #/*< parameters like cairo_rectangle */
-y0 = 0.1
-rect_width = 0.8
-rect_height = 0.8
-radius = 0.4 #/*< and an approximate curvature radius */
-snippet_normalize (cr, width, height)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-x1=x0+rect_width
-y1=y0+rect_height
-#if (!rect_width || !rect_height)
-# return
-if rect_width/2<radius:
- if rect_height/2<radius:
- cr.move_to (x0, (y0 + y1)/2)
- cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
- cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
- cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
- cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
- else:
- cr.move_to (x0, y0 + radius)
- cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
- cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
- cr.line_to (x1 , y1 - radius)
- cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
- cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+ # a custom shape, that could be wrapped in a function
+ x0 = 0.1 # parameters like cairo_rectangle
+ y0 = 0.1
+ rect_width = 0.8
+ rect_height = 0.8
+ radius = 0.4 # and an approximate curvature radius
+
+ x1 = x0 + rect_width
+ y1 = y0 + rect_height
-else:
- if rect_height/2<radius:
- cr.move_to (x0, (y0 + y1)/2)
- cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
- cr.line_to (x1 - radius, y0)
- cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
- cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
- cr.line_to (x0 + radius, y1)
- cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
+ if rect_width / 2 < radius:
+ if rect_height / 2 < radius:
+ cr.move_to(x0, (y0 + y1) / 2)
+ cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)
+ cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)
+ else:
+ cr.move_to(x0, y0 + radius)
+ cr.curve_to(x0, y0, x0, y0, (x0 + x1) / 2, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0 + radius)
+ cr.line_to(x1, y1 - radius)
+ cr.curve_to(x1, y1, x1, y1, (x1 + x0) / 2, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1 - radius)
else:
- cr.move_to (x0, y0 + radius)
- cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
- cr.line_to (x1 - radius, y0)
- cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
- cr.line_to (x1 , y1 - radius)
- cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
- cr.line_to (x0 + radius, y1)
- cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+ if rect_height / 2 < radius:
+ cr.move_to(x0, (y0 + y1) / 2)
+ cr.curve_to(x0, y0, x0, y0, x0 + radius, y0)
+ cr.line_to(x1 - radius, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, (y0 + y1) / 2)
+ cr.curve_to(x1, y1, x1, y1, x1 - radius, y1)
+ cr.line_to(x0 + radius, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, (y0 + y1) / 2)
+ else:
+ cr.move_to(x0, y0 + radius)
+ cr.curve_to(x0, y0, x0, y0, x0 + radius, y0)
+ cr.line_to(x1 - radius, y0)
+ cr.curve_to(x1, y0, x1, y0, x1, y0 + radius)
+ cr.line_to(x1, y1 - radius)
+ cr.curve_to(x1, y1, x1, y1, x1 - radius, y1)
+ cr.line_to(x0 + radius, y1)
+ cr.curve_to(x0, y1, x0, y1, x0, y1 - radius)
-cr.close_path ()
+ cr.close_path()
-cr.set_source_rgb (0.5,0.5,1)
-cr.fill_preserve ()
-cr.set_source_rgba (0.5,0,0,0.5)
-cr.stroke ()
+ cr.set_source_rgb(0.5, 0.5, 1)
+ cr.fill_preserve()
+ cr.set_source_rgba(0.5, 0, 0, 0.5)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/curve_to.py b/examples/cairo_snippets/snippets/curve_to.py
index 59e3b00..4dd0ca1 100644
--- a/examples/cairo_snippets/snippets/curve_to.py
+++ b/examples/cairo_snippets/snippets/curve_to.py
@@ -1,17 +1,22 @@
-x, y = 0.1, 0.5
-x1, y1 = 0.4, 0.9
-x2, y2 = 0.6, 0.1
-x3, y3 = 0.9, 0.5
-snippet_normalize (cr, width, height)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.move_to (x, y)
-cr.curve_to (x1, y1, x2, y2, x3, y3)
+ x, y = 0.1, 0.5
+ x1, y1 = 0.4, 0.9
+ x2, y2 = 0.6, 0.1
+ x3, y3 = 0.9, 0.5
-cr.stroke ()
+ cr.move_to(x, y)
+ cr.curve_to(x1, y1, x2, y2, x3, y3)
-cr.set_source_rgba (1,0.2,0.2,0.6)
-cr.set_line_width (0.03)
-cr.move_to (x,y); cr.line_to (x1,y1)
-cr.move_to (x2,y2); cr.line_to (x3,y3)
-cr.stroke ()
+ cr.stroke()
+
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.set_line_width(0.03)
+ cr.move_to(x, y)
+ cr.line_to(x1, y1)
+ cr.move_to(x2, y2)
+ cr.line_to(x3, y3)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/ellipse.py b/examples/cairo_snippets/snippets/ellipse.py
index 9afd4f2..443bd30 100644
--- a/examples/cairo_snippets/snippets/ellipse.py
+++ b/examples/cairo_snippets/snippets/ellipse.py
@@ -1,4 +1,5 @@
-snippet_normalize(cr, width, height)
+from math import pi
+
def path_ellipse(cr, x, y, width, height, angle=0):
"""
@@ -12,22 +13,26 @@ def path_ellipse(cr, x, y, width, height, angle=0):
cr.translate(x, y)
cr.rotate(angle)
cr.scale(width / 2.0, height / 2.0)
- cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * M_PI)
+ cr.arc(0.0, 0.0, 1.0, 0.0, 2.0 * pi)
cr.restore()
-path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, M_PI/4.0)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ path_ellipse(cr, 0.5, 0.5, 1.0, 0.3, pi / 4.0)
-# fill
-cr.set_source_rgba(1,0,0,1)
-cr.fill_preserve()
+ # fill
+ cr.set_source_rgba(1, 0, 0, 1)
+ cr.fill_preserve()
-# stroke
-# reset identity matrix so line_width is a constant
-# width in device-space, not user-space
-cr.save()
-cr.identity_matrix()
-cr.set_source_rgba(0,0,0,1)
-cr.set_line_width(3)
-cr.stroke()
-cr.restore()
+ # stroke
+ # reset identity matrix so line_width is a constant
+ # width in device-space, not user-space
+ cr.save()
+ cr.identity_matrix()
+ cr.set_source_rgba(0, 0, 0, 1)
+ cr.set_line_width(3)
+ cr.stroke()
+ cr.restore()
diff --git a/examples/cairo_snippets/snippets/fill_and_stroke.py b/examples/cairo_snippets/snippets/fill_and_stroke.py
index 6d66192..7da85f9 100644
--- a/examples/cairo_snippets/snippets/fill_and_stroke.py
+++ b/examples/cairo_snippets/snippets/fill_and_stroke.py
@@ -1,12 +1,15 @@
-snippet_normalize (cr, width, height)
-cr.move_to (0.5, 0.1)
-cr.line_to (0.9, 0.9)
-cr.rel_line_to (-0.4, 0.0)
-cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
-cr.close_path()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.set_source_rgb (0, 0, 1)
-cr.fill_preserve ()
-cr.set_source_rgb (0, 0, 0)
-cr.stroke ()
+ cr.move_to(0.5, 0.1)
+ cr.line_to(0.9, 0.9)
+ cr.rel_line_to(-0.4, 0.0)
+ cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+ cr.close_path()
+
+ cr.set_source_rgb(0, 0, 1)
+ cr.fill_preserve()
+ cr.set_source_rgb(0, 0, 0)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/fill_and_stroke2.py b/examples/cairo_snippets/snippets/fill_and_stroke2.py
index c520630..4d8df67 100644
--- a/examples/cairo_snippets/snippets/fill_and_stroke2.py
+++ b/examples/cairo_snippets/snippets/fill_and_stroke2.py
@@ -1,18 +1,21 @@
-snippet_normalize (cr, width, height)
-cr.move_to (0.5, 0.1)
-cr.line_to (0.9, 0.9)
-cr.rel_line_to (-0.4, 0.0)
-cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
-cr.close_path ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.move_to (0.25, 0.1)
-cr.rel_line_to (0.2, 0.2)
-cr.rel_line_to (-0.2, 0.2)
-cr.rel_line_to (-0.2, -0.2)
-cr.close_path ()
+ cr.move_to(0.5, 0.1)
+ cr.line_to(0.9, 0.9)
+ cr.rel_line_to(-0.4, 0.0)
+ cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+ cr.close_path()
-cr.set_source_rgb (0, 0, 1)
-cr.fill_preserve ()
-cr.set_source_rgb (0, 0, 0)
-cr.stroke ()
+ cr.move_to(0.25, 0.1)
+ cr.rel_line_to(0.2, 0.2)
+ cr.rel_line_to(-0.2, 0.2)
+ cr.rel_line_to(-0.2, -0.2)
+ cr.close_path()
+
+ cr.set_source_rgb(0, 0, 1)
+ cr.fill_preserve()
+ cr.set_source_rgb(0, 0, 0)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/glyph_path.py b/examples/cairo_snippets/snippets/glyph_path.py
index 2b73193..bb887ce 100644
--- a/examples/cairo_snippets/snippets/glyph_path.py
+++ b/examples/cairo_snippets/snippets/glyph_path.py
@@ -1,21 +1,25 @@
-snippet_normalize (cr, width, height)
+import cairo
-cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_NORMAL)
-# draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner
-cr.set_font_size (0.16)
-glyphs = []
-index = 20
-for y in range(5):
- for x in range(5):
- glyphs.append ((index, x/5.0 + 0.02, y/5.0 + 0.16))
- index += 1
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.glyph_path (glyphs)
-cr.set_source_rgb (0.5,0.5,1.0)
-cr.fill_preserve ()
-cr.set_source_rgb (0,0,0)
-cr.set_line_width (0.005)
-cr.stroke ()
+ cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+ # draw 0.16 glyphs in 0.20 squares, at (0.02, 0.04) from left corner
+ cr.set_font_size(0.16)
+ glyphs = []
+ index = 20
+ for y in range(5):
+ for x in range(5):
+ glyphs.append((index, x / 5.0 + 0.02, y / 5.0 + 0.16))
+ index += 1
+
+ cr.glyph_path(glyphs)
+ cr.set_source_rgb(0.5, 0.5, 1.0)
+ cr.fill_preserve()
+ cr.set_source_rgb(0, 0, 0)
+ cr.set_line_width(0.005)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/gradient.py b/examples/cairo_snippets/snippets/gradient.py
index 22f0658..dd4a728 100644
--- a/examples/cairo_snippets/snippets/gradient.py
+++ b/examples/cairo_snippets/snippets/gradient.py
@@ -1,16 +1,22 @@
-snippet_normalize (cr, width, height)
+from math import pi
+import cairo
-pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
-pat.add_color_stop_rgba (1, 0, 0, 0, 1)
-pat.add_color_stop_rgba (0, 1, 1, 1, 1)
-cr.rectangle (0,0,1,1)
-cr.set_source (pat)
-cr.fill ()
-pat = cairo.RadialGradient (0.45, 0.4, 0.1,
- 0.4, 0.4, 0.5)
-pat.add_color_stop_rgba (0, 1, 1, 1, 1)
-pat.add_color_stop_rgba (1, 0, 0, 0, 1)
-cr.set_source (pat)
-cr.arc (0.5, 0.5, 0.3, 0, 2 * M_PI)
-cr.fill ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0)
+ pat.add_color_stop_rgba(1, 0, 0, 0, 1)
+ pat.add_color_stop_rgba(0, 1, 1, 1, 1)
+ cr.rectangle(0, 0, 1, 1)
+ cr.set_source(pat)
+ cr.fill()
+
+ pat = cairo.RadialGradient(0.45, 0.4, 0.1,
+ 0.4, 0.4, 0.5)
+ pat.add_color_stop_rgba(0, 1, 1, 1, 1)
+ pat.add_color_stop_rgba(1, 0, 0, 0, 1)
+ cr.set_source(pat)
+ cr.arc(0.5, 0.5, 0.3, 0, 2 * pi)
+ cr.fill()
diff --git a/examples/cairo_snippets/snippets/gradient_mask.py b/examples/cairo_snippets/snippets/gradient_mask.py
index 4a0eba4..410f93a 100644
--- a/examples/cairo_snippets/snippets/gradient_mask.py
+++ b/examples/cairo_snippets/snippets/gradient_mask.py
@@ -1,12 +1,17 @@
-snippet_normalize (cr, width, height)
+import cairo
-pattern = cairo.LinearGradient (0, 0, 1, 1)
-pattern.add_color_stop_rgb (0, 0, 0.3, 0.8)
-pattern.add_color_stop_rgb (1, 0, 0.8, 0.3)
-mask = cairo.RadialGradient (0.5, 0.5, 0.25, 0.5, 0.5, 0.5)
-mask.add_color_stop_rgba (0, 0, 0, 0, 1)
-mask.add_color_stop_rgba (0.5, 0, 0, 0, 0)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.set_source (pattern)
-cr.mask (mask)
+ pattern = cairo.LinearGradient(0, 0, 1, 1)
+ pattern.add_color_stop_rgb(0, 0, 0.3, 0.8)
+ pattern.add_color_stop_rgb(1, 0, 0.8, 0.3)
+
+ mask = cairo.RadialGradient(0.5, 0.5, 0.25, 0.5, 0.5, 0.5)
+ mask.add_color_stop_rgba(0, 0, 0, 0, 1)
+ mask.add_color_stop_rgba(0.5, 0, 0, 0, 0)
+
+ cr.set_source(pattern)
+ cr.mask(mask)
diff --git a/examples/cairo_snippets/snippets/group.py b/examples/cairo_snippets/snippets/group.py
index a787f4d..8b01b36 100644
--- a/examples/cairo_snippets/snippets/group.py
+++ b/examples/cairo_snippets/snippets/group.py
@@ -1,16 +1,20 @@
-# demo/test for group functions
-snippet_normalize (cr, width, height)
+import cairo
-cr.rectangle (0.1, 0.1, 0.6, 0.6)
-cr.set_line_width (0.03)
-cr.set_source_rgb (0.8, 0.8, 0.8)
-cr.fill()
-cr.push_group()
-cr.rectangle (0.3, 0.3, 0.6, 0.6)
-cr.set_source (cairo.SolidPattern (1, 0, 0))
-cr.fill_preserve()
-cr.set_source (cairo.SolidPattern (0, 0, 0))
-cr.stroke ()
-cr.pop_group_to_source()
-cr.paint_with_alpha (0.5)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ cr.rectangle(0.1, 0.1, 0.6, 0.6)
+ cr.set_line_width(0.03)
+ cr.set_source_rgb(0.8, 0.8, 0.8)
+ cr.fill()
+
+ cr.push_group()
+ cr.rectangle(0.3, 0.3, 0.6, 0.6)
+ cr.set_source(cairo.SolidPattern(1, 0, 0))
+ cr.fill_preserve()
+ cr.set_source(cairo.SolidPattern(0, 0, 0))
+ cr.stroke()
+ cr.pop_group_to_source()
+ cr.paint_with_alpha(0.5)
diff --git a/examples/cairo_snippets/snippets/hering.py b/examples/cairo_snippets/snippets/hering.py
new file mode 100644
index 0000000..faea18b
--- /dev/null
+++ b/examples/cairo_snippets/snippets/hering.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+"""cairo/cairo-demo/png/hering.c translated into Python"""
+
+import math
+
+
+def draw(ctx, width, height):
+ LINES = 32
+ MAX_THETA = .80 * math.pi * 2
+ THETA_INC = 2.0 * MAX_THETA / (LINES - 1)
+
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.set_line_width(2.0)
+
+ ctx.save()
+
+ ctx.translate(width / 2, height / 2)
+ ctx.rotate(MAX_THETA)
+
+ for i in range(LINES):
+ ctx.move_to(-2 * width, 0)
+ ctx.line_to(2 * width, 0)
+ ctx.stroke()
+
+ ctx.rotate(- THETA_INC)
+
+ ctx.restore()
+
+ ctx.set_line_width(6)
+ ctx.set_source_rgb(1, 0, 0)
+
+ ctx.move_to(width / 4.0, 0)
+ ctx.rel_line_to(0, height)
+ ctx.stroke()
+
+ ctx.move_to(3 * width / 4.0, 0)
+ ctx.rel_line_to(0, height)
+ ctx.stroke()
diff --git a/examples/cairo_snippets/snippets/path.py b/examples/cairo_snippets/snippets/path.py
index cce8aec..b8adb74 100644
--- a/examples/cairo_snippets/snippets/path.py
+++ b/examples/cairo_snippets/snippets/path.py
@@ -1,7 +1,11 @@
-snippet_normalize (cr, width, height)
-cr.move_to (0.5, 0.1)
-cr.line_to (0.9, 0.9)
-cr.rel_line_to (-0.4, 0.0)
-cr.curve_to (0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
-cr.stroke ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ cr.move_to(0.5, 0.1)
+ cr.line_to(0.9, 0.9)
+ cr.rel_line_to(-0.4, 0.0)
+ cr.curve_to(0.2, 0.9, 0.2, 0.5, 0.5, 0.5)
+
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/set_line_cap.py b/examples/cairo_snippets/snippets/set_line_cap.py
index 6de1fae..f6256df 100644
--- a/examples/cairo_snippets/snippets/set_line_cap.py
+++ b/examples/cairo_snippets/snippets/set_line_cap.py
@@ -1,19 +1,31 @@
-snippet_normalize (cr, width, height)
-cr.set_line_width (0.12)
-cr.set_line_cap (cairo.LINE_CAP_BUTT) #/* default */
-cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8)
-cr.stroke ()
-cr.set_line_cap (cairo.LINE_CAP_ROUND)
-cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8)
-cr.stroke ()
-cr.set_line_cap (cairo.LINE_CAP_SQUARE)
-cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8)
-cr.stroke ()
+import cairo
-#/* draw helping lines */
-cr.set_source_rgb (1,0.2,0.2)
-cr.set_line_width (0.01)
-cr.move_to (0.25, 0.2); cr.line_to (0.25, 0.8)
-cr.move_to (0.5, 0.2); cr.line_to (0.5, 0.8)
-cr.move_to (0.75, 0.2); cr.line_to (0.75, 0.8)
-cr.stroke ()
+
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+
+ cr.set_line_width(0.12)
+ cr.set_line_cap(cairo.LINE_CAP_BUTT) # default
+ cr.move_to(0.25, 0.2)
+ cr.line_to(0.25, 0.8)
+ cr.stroke()
+ cr.set_line_cap(cairo.LINE_CAP_ROUND)
+ cr.move_to(0.5, 0.2)
+ cr.line_to(0.5, 0.8)
+ cr.stroke()
+ cr.set_line_cap(cairo.LINE_CAP_SQUARE)
+ cr.move_to(0.75, 0.2)
+ cr.line_to(0.75, 0.8)
+ cr.stroke()
+
+ # draw helping lines
+ cr.set_source_rgb(1, 0.2, 0.2)
+ cr.set_line_width(0.01)
+ cr.move_to(0.25, 0.2)
+ cr.line_to(0.25, 0.8)
+ cr.move_to(0.5, 0.2)
+ cr.line_to(0.5, 0.8)
+ cr.move_to(0.75, 0.2)
+ cr.line_to(0.75, 0.8)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/set_line_join.py b/examples/cairo_snippets/snippets/set_line_join.py
index b2e1919..1a62723 100644
--- a/examples/cairo_snippets/snippets/set_line_join.py
+++ b/examples/cairo_snippets/snippets/set_line_join.py
@@ -1,21 +1,25 @@
-snippet_normalize (cr, width, height)
-cr.set_line_width (0.16)
-cr.move_to (0.3, 0.33)
-cr.rel_line_to (0.2, -0.2)
-cr.rel_line_to (0.2, 0.2)
-cr.set_line_join (cairo.LINE_JOIN_MITER) #/* default */
-cr.stroke ()
+import cairo
-cr.move_to (0.3, 0.63)
-cr.rel_line_to (0.2, -0.2)
-cr.rel_line_to (0.2, 0.2)
-cr.set_line_join (cairo.LINE_JOIN_BEVEL)
-cr.stroke ()
-cr.move_to (0.3, 0.93)
-cr.rel_line_to (0.2, -0.2)
-cr.rel_line_to (0.2, 0.2)
-cr.set_line_join (cairo.LINE_JOIN_ROUND)
-cr.stroke ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
+ cr.set_line_width(0.16)
+ cr.move_to(0.3, 0.33)
+ cr.rel_line_to(0.2, -0.2)
+ cr.rel_line_to(0.2, 0.2)
+ cr.set_line_join(cairo.LINE_JOIN_MITER) # default
+ cr.stroke()
+ cr.move_to(0.3, 0.63)
+ cr.rel_line_to(0.2, -0.2)
+ cr.rel_line_to(0.2, 0.2)
+ cr.set_line_join(cairo.LINE_JOIN_BEVEL)
+ cr.stroke()
+
+ cr.move_to(0.3, 0.93)
+ cr.rel_line_to(0.2, -0.2)
+ cr.rel_line_to(0.2, 0.2)
+ cr.set_line_join(cairo.LINE_JOIN_ROUND)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/show_glyphs.py b/examples/cairo_snippets/snippets/show_glyphs.py
index a41cf61..c6f02c7 100644
--- a/examples/cairo_snippets/snippets/show_glyphs.py
+++ b/examples/cairo_snippets/snippets/show_glyphs.py
@@ -1,15 +1,20 @@
-snippet_normalize (cr, width, height)
+import cairo
-cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_NORMAL)
-# draw 0.08 glyphs in 0.10 squares, at (0.01, 0.02) from left corner
-cr.set_font_size (0.08)
-glyphs = []
-index = 0
-for y in range(10):
- for x in range(10):
- glyphs.append ((index, x/10.0 + 0.01, y/10.0 + 0.08))
- index += 1
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.show_glyphs (glyphs)
+ cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+ # draw 0.08 glyphs in 0.10 squares, at(0.01, 0.02) from left corner
+ cr.set_font_size(0.08)
+
+ glyphs = []
+ index = 0
+ for y in range(10):
+ for x in range(10):
+ glyphs.append((index, x / 10.0 + 0.01, y / 10.0 + 0.08))
+ index += 1
+
+ cr.show_glyphs(glyphs)
diff --git a/examples/cairo_snippets/snippets/spiral.py b/examples/cairo_snippets/snippets/spiral.py
new file mode 100644
index 0000000..4a3e8c4
--- /dev/null
+++ b/examples/cairo_snippets/snippets/spiral.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+"""cairo/cairo-demo/png/spiral.c translated into Python"""
+
+
+def draw(ctx, width, height):
+ wd = .02 * width
+ hd = .02 * height
+
+ width -= 2
+ height -= 2
+
+ ctx.move_to(width + 1, 1 - hd)
+ for i in range(9):
+ ctx.rel_line_to(0, height - hd * (2 * i - 1))
+ ctx.rel_line_to(-(width - wd * (2 * i)), 0)
+ ctx.rel_line_to(0, -(height - hd * (2 * i)))
+ ctx.rel_line_to(width - wd * (2 * i + 1), 0)
+
+ ctx.set_source_rgb(0, 0, 1)
+ ctx.stroke()
diff --git a/examples/cairo_snippets/snippets/text.py b/examples/cairo_snippets/snippets/text.py
index 1ba80e6..efa55e8 100644
--- a/examples/cairo_snippets/snippets/text.py
+++ b/examples/cairo_snippets/snippets/text.py
@@ -1,22 +1,28 @@
-snippet_normalize (cr, width, height)
-cr.select_font_face ("Sans", cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_BOLD)
-cr.set_font_size (0.35)
+from math import pi
+import cairo
-cr.move_to (0.04, 0.53)
-cr.show_text ("Hello")
-cr.move_to (0.27, 0.65)
-cr.text_path ("void")
-cr.set_source_rgb (0.5,0.5,1)
-cr.fill_preserve ()
-cr.set_source_rgb (0,0,0)
-cr.set_line_width (0.01)
-cr.stroke ()
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-#/* draw helping lines */
-cr.set_source_rgba (1,0.2,0.2, 0.6)
-cr.arc (0.04, 0.53, 0.02, 0, 2*M_PI)
-cr.arc (0.27, 0.65, 0.02, 0, 2*M_PI)
-cr.fill ()
+ cr.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_BOLD)
+ cr.set_font_size(0.35)
+ cr.move_to(0.04, 0.53)
+ cr.show_text("Hello")
+
+ cr.move_to(0.27, 0.65)
+ cr.text_path("void")
+ cr.set_source_rgb(0.5, 0.5, 1)
+ cr.fill_preserve()
+ cr.set_source_rgb(0, 0, 0)
+ cr.set_line_width(0.01)
+ cr.stroke()
+
+ # draw helping lines
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.arc(0.04, 0.53, 0.02, 0, 2 * pi)
+ cr.arc(0.27, 0.65, 0.02, 0, 2 * pi)
+ cr.fill()
diff --git a/examples/cairo_snippets/snippets/text_align_center.py b/examples/cairo_snippets/snippets/text_align_center.py
index 4bc3124..cda9905 100644
--- a/examples/cairo_snippets/snippets/text_align_center.py
+++ b/examples/cairo_snippets/snippets/text_align_center.py
@@ -1,26 +1,32 @@
-utf8 = "cairo"
+from math import pi
+import cairo
-snippet_normalize (cr, width, height)
-cr.select_font_face ("Sans",
- cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_NORMAL)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.set_font_size (0.2)
-x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8)
-x = 0.5-(width/2 + x_bearing)
-y = 0.5-(height/2 + y_bearing)
+ utf8 = "cairo"
-cr.move_to (x, y)
-cr.show_text (utf8)
+ cr.select_font_face("Sans",
+ cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
-#/* draw helping lines */
-cr.set_source_rgba (1,0.2,0.2,0.6)
-cr.arc (x, y, 0.05, 0, 2*M_PI)
-cr.fill ()
-cr.move_to (0.5, 0)
-cr.rel_line_to (0, 1)
-cr.move_to (0, 0.5)
-cr.rel_line_to (1, 0)
-cr.stroke ()
+ cr.set_font_size(0.2)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = \
+ cr.text_extents(utf8)
+ x = 0.5 - (width / 2 + x_bearing)
+ y = 0.5 - (height / 2 + y_bearing)
+ cr.move_to(x, y)
+ cr.show_text(utf8)
+
+ # draw helping lines
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.arc(x, y, 0.05, 0, 2 * pi)
+ cr.fill()
+ cr.move_to(0.5, 0)
+ cr.rel_line_to(0, 1)
+ cr.move_to(0, 0.5)
+ cr.rel_line_to(1, 0)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/text_extents.py b/examples/cairo_snippets/snippets/text_extents.py
index 890fb88..7b584fe 100644
--- a/examples/cairo_snippets/snippets/text_extents.py
+++ b/examples/cairo_snippets/snippets/text_extents.py
@@ -1,27 +1,33 @@
-utf8 = "cairo"
+from math import pi
+import cairo
-snippet_normalize (cr, width, height)
-cr.select_font_face ("Sans",
- cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_NORMAL)
+def draw(cr, width, height):
+ cr.scale(width, height)
+ cr.set_line_width(0.04)
-cr.set_font_size (0.4)
-x_bearing, y_bearing, width, height, x_advance, y_advance = cr.text_extents (utf8)
+ utf8 = "cairo"
-x=0.1
-y=0.6
+ cr.select_font_face("Sans",
+ cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
-cr.move_to (x,y)
-cr.show_text (utf8)
+ cr.set_font_size(0.4)
+ x_bearing, y_bearing, width, height, x_advance, y_advance = \
+ cr.text_extents(utf8)
-#/* draw helping lines */
-cr.set_source_rgba (1,0.2,0.2,0.6)
-cr.arc (x, y, 0.05, 0, 2*M_PI)
-cr.fill ()
-cr.move_to (x,y)
-cr.rel_line_to (0, -height)
-cr.rel_line_to (width, 0)
-cr.rel_line_to (x_bearing, -y_bearing)
-cr.stroke ()
+ x = 0.1
+ y = 0.6
+ cr.move_to(x, y)
+ cr.show_text(utf8)
+
+ # draw helping lines
+ cr.set_source_rgba(1, 0.2, 0.2, 0.6)
+ cr.arc(x, y, 0.05, 0, 2 * pi)
+ cr.fill()
+ cr.move_to(x, y)
+ cr.rel_line_to(0, -height)
+ cr.rel_line_to(width, 0)
+ cr.rel_line_to(x_bearing, -y_bearing)
+ cr.stroke()
diff --git a/examples/cairo_snippets/snippets/warpedtext.py b/examples/cairo_snippets/snippets/warpedtext.py
new file mode 100644
index 0000000..14eac56
--- /dev/null
+++ b/examples/cairo_snippets/snippets/warpedtext.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+
+import cairo
+import math
+
+
+all_width = all_height = text_width = 0
+
+
+def warpPath(ctx, function):
+ first = True
+
+ for type, points in ctx.copy_path():
+ if type == cairo.PATH_MOVE_TO:
+ if first:
+ ctx.new_path()
+ first = False
+ x, y = function(*points)
+ ctx.move_to(x, y)
+
+ elif type == cairo.PATH_LINE_TO:
+ x, y = function(*points)
+ ctx.line_to(x, y)
+
+ elif type == cairo.PATH_CURVE_TO:
+ x1, y1, x2, y2, x3, y3 = points
+ x1, y1 = function(x1, y1)
+ x2, y2 = function(x2, y2)
+ x3, y3 = function(x3, y3)
+ ctx.curve_to(x1, y1, x2, y2, x3, y3)
+
+ elif type == cairo.PATH_CLOSE_PATH:
+ ctx.close_path()
+
+
+def spiral(x, y):
+ theta0 = -math.pi * 3 / 4
+ theta = x / all_width * math.pi * 2 + theta0
+ radius = y + 200 - x / 7
+ xnew = radius * math.cos(theta)
+ ynew = radius * math.sin(-theta)
+ return xnew + all_width / 2, ynew + all_height / 2
+
+
+def curl(x, y):
+ xn = x - text_width / 2
+ xnew = xn
+ ynew = y + xn ** 3 / ((text_width / 2) ** 3) * 70
+ return xnew + all_width / 2, ynew + all_height * 2 / 5
+
+
+def draw(ctx, width, height):
+ global text_width, all_width, all_height
+
+ all_width, all_height = width, height
+
+ solidpattern = ctx.get_source()
+
+ # background
+ pat = cairo.LinearGradient(0.0, 0.0, 0, height)
+ pat.add_color_stop_rgba(1, 0, 0, 0, 1)
+ pat.add_color_stop_rgba(0, 1, 1, 1, 1)
+
+ ctx.rectangle(0, 0, width, height)
+ ctx.set_source(pat)
+ ctx.fill()
+
+ # foreground
+ ctx.set_source(solidpattern)
+ ctx.set_source_rgb(1, 1, 1)
+
+ ctx.select_font_face("Sans")
+ ctx.set_font_size(80)
+
+ # spiral text
+ ctx.new_path()
+ ctx.move_to(0, 0)
+ ctx.text_path("pycairo - " + "spam " * 5)
+ warpPath(ctx, spiral)
+ ctx.fill()
+
+ # curly text
+ ctx.new_path()
+ ctx.move_to(0, 0)
+ ctx.set_source_rgb(0.3, 0.3, 0.3)
+ text = "I am curly :)"
+ ctx.text_path(text)
+ text_width = ctx.text_extents(text)[2]
+ warpPath(ctx, curl)
+ ctx.fill()
diff --git a/examples/cairo_snippets/snippets_gtk.py b/examples/cairo_snippets/snippets_gtk.py
index c7796ea..8982897 100644
--- a/examples/cairo_snippets/snippets_gtk.py
+++ b/examples/cairo_snippets/snippets_gtk.py
@@ -1,140 +1,116 @@
#!/usr/bin/env python
-"""Python version of cairo-demo/cairo_snippets/cairo_snippets_gtk.c
-"""
-from __future__ import division
-from math import pi as M_PI # used by many snippets
-import os.path
-import sys
-import cairo
-import gtk
-import pango
+import gi
+gi.require_version("Gtk", "3.0")
+gi.require_foreign("cairo")
+from gi.repository import Gtk, Pango
-from snippets import snip_list, snippet_normalize
+from snippets import get_snippets
-Width, Height = 400, 400
-
-snippets_path = os.path.join(os.path.dirname(__file__), 'snippets')
+class Window(Gtk.Window):
+ """Composite widget"""
-def gdkcolor_to_rgb (gdkcolor):
- return gdkcolor.red/65535, gdkcolor.green/65535, gdkcolor.blue/65535
+ WIDTH, HEIGHT = 400, 400
+ def __init__(self, title=None):
+ super(Window, self).__init__()
+ self.set_default_size(self.WIDTH, self.HEIGHT)
-class Window (gtk.Window):
- """Composite widget"""
- def __init__ (self, title=None, type=gtk.WINDOW_TOPLEVEL):
- gtk.Window.__init__ (self, type)
- self.set_default_size (Width, Height)
+ self.da = Gtk.DrawingArea()
+ self.da.connect('draw', self.da_draw_event)
- self.da = gtk.DrawingArea()
- self.da.connect('expose-event', self.da_expose_event)
-
- def put_in_frame (widget):
- frame = gtk.Frame (label=None)
- frame.set_property ('shadow_type', gtk.SHADOW_IN)
- frame.add (widget)
+ def put_in_frame(widget):
+ frame = Gtk.Frame(label=None)
+ frame.set_property('shadow_type', Gtk.ShadowType.IN)
+ frame.add(widget)
return frame
- vpaned = gtk.VPaned()
- self.add (vpaned)
+ self.current_snippet = None
+
+ vpaned = Gtk.VPaned()
+ self.add(vpaned)
sv = self.create_text_view()
- vpaned.pack1 (put_in_frame (sv), True, True)
- sv.set_size_request (Width, int(Height/2))
+ vpaned.pack1(put_in_frame(sv), True, True)
+ sv.set_size_request(self.WIDTH, int(self.HEIGHT / 2))
- hpaned = gtk.HPaned()
- vpaned.pack2 (hpaned, True, False)
+ hpaned = Gtk.HPaned()
+ vpaned.pack2(hpaned, True, False)
sl = self.create_snippet_list()
- hpaned.pack1 (put_in_frame (sl), True, True)
+ hpaned.pack1(put_in_frame(sl), True, True)
- hpaned.pack2 (put_in_frame (self.da), True, True)
- self.da.set_size_request (int(Width/2), int(Height/2))
+ hpaned.pack2(put_in_frame(self.da), True, True)
+ self.da.set_size_request(int(self.WIDTH / 2), int(self.HEIGHT / 2))
# set focus to snippet list
sl.get_child().grab_focus()
+ def da_draw_event(self, da, cr):
+ if self.current_snippet is None:
+ return False
- def da_expose_event (self, da, event, data=None):
- x, y, width, height = da.allocation
-
- cr = da.window.cairo_create()
-
- try:
- exec (self.snippet_str, globals(), locals())
- except:
- exc_type, exc_value = sys.exc_info()[:2]
- print >> sys.stderr, exc_type, exc_value
+ alloc = da.get_allocation()
+ self.current_snippet.draw_func(cr, alloc.width, alloc.height)
return True
+ def create_text_view(self):
+ sw = Gtk.ScrolledWindow()
+ sw.set_property('shadow-type', Gtk.ShadowType.IN)
+ sw.set_policy(hscrollbar_policy=Gtk.PolicyType.AUTOMATIC,
+ vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
- def create_text_view (self):
- sw = gtk.ScrolledWindow()
- sw.set_property ('shadow-type', gtk.SHADOW_IN)
- sw.set_policy (hscrollbar_policy=gtk.POLICY_AUTOMATIC,
- vscrollbar_policy=gtk.POLICY_AUTOMATIC)
-
- text_view = gtk.TextView()
- sw.add (text_view)
+ text_view = Gtk.TextView()
+ sw.add(text_view)
# set a fixed width font, so any tabs line up
- text_view.modify_font(pango.FontDescription ("Fixed"))
+ text_view.override_font(Pango.FontDescription.from_string("Fixed"))
self.text_buffer = text_view.get_buffer()
return sw
-
- def cb_selection_changed (self, tselection, data=None):
+ def cb_selection_changed(self, tselection, data=None):
model, iter = tselection.get_selected()
if iter:
- filename = model[iter][0] + '.py'
- try:
- path = os.path.join(snippets_path, filename)
- file_obj = open(path, 'r')
- self.snippet_str = file_obj.read()
- file_obj.close()
- self.text_buffer.set_text(self.snippet_str)
- except IOError, exc:
- print "%s: %s" % (exc.filename, exc.strerror)
-
- self._draw_pixmap = True
+ self.current_snippet = model[iter][1]
+ self.text_buffer.set_text(self.current_snippet.code)
self.da.queue_draw()
+ def create_snippet_list(self):
+ sw = Gtk.ScrolledWindow()
+ sw.set_property('shadow-type', Gtk.ShadowType.IN)
+ sw.set_policy(hscrollbar_policy=Gtk.PolicyType.NEVER,
+ vscrollbar_policy=Gtk.PolicyType.AUTOMATIC)
- def create_snippet_list (self):
- sw = gtk.ScrolledWindow()
- sw.set_property ('shadow-type', gtk.SHADOW_IN)
- sw.set_policy (hscrollbar_policy=gtk.POLICY_NEVER,
- vscrollbar_policy=gtk.POLICY_AUTOMATIC)
-
- model = gtk.ListStore (str,)
- for row in snip_list:
- model.append (row=(row,))
+ snippets = get_snippets()
+ model = Gtk.ListStore(str, object)
+ for name, s in snippets.items():
+ model.append(row=(name, s))
- tree_view = gtk.TreeView (model)
- sw.add (tree_view)
- tree_view.set_property ('headers-visible', False)
- tree_view.set_property ('search-column', 0)
- tree_view.set_property ('rules-hint', False)
+ tree_view = Gtk.TreeView(model)
+ sw.add(tree_view)
+ tree_view.set_property('headers-visible', False)
+ tree_view.set_property('search-column', 0)
+ tree_view.set_property('rules-hint', False)
tselection = tree_view.get_selection()
- tselection.connect ("changed", self.cb_selection_changed)
- tselection.set_mode (gtk.SELECTION_BROWSE)
+ tselection.connect("changed", self.cb_selection_changed)
+ tselection.set_mode(Gtk.SelectionMode.BROWSE)
- cr = gtk.CellRendererText()
- tvc = gtk.TreeViewColumn (None, cr, text=0)
- tree_view.append_column (tvc)
+ cr = Gtk.CellRendererText()
+ tvc = Gtk.TreeViewColumn(None, cr, text=0)
+ tree_view.append_column(tvc)
- tselection.select_path(0,) # select first item
+ tselection.select_path(0,) # select first item
return sw
if __name__ == '__main__':
- app = Window ()
- app.connect('destroy', gtk.main_quit)
+ app = Window()
+ app.connect('destroy', Gtk.main_quit)
app.show_all()
- gtk.main()
+ Gtk.main()
diff --git a/examples/cairo_snippets/snippets_pdf.py b/examples/cairo_snippets/snippets_pdf.py
index 0606804..b690de9 100644
--- a/examples/cairo_snippets/snippets_pdf.py
+++ b/examples/cairo_snippets/snippets_pdf.py
@@ -1,56 +1,59 @@
#!/usr/bin/env python
-"""Python version of cairo-demo/cairo_snippets/cairo_snippets_pdf.c
-create a file for each example rather than one large file for all examples
-"""
-from __future__ import division
-from math import pi as M_PI # used by many snippets
-import sys
+"""Create a PDF file for each example"""
+
+from __future__ import print_function
+import os
+import sys
import cairo
-if not cairo.HAS_PDF_SURFACE:
- raise SystemExit ('cairo was not compiled with PDF support')
-from snippets import snip_list, snippet_normalize
+from snippets import get_snippets
-width_in_inches, height_in_inches = 2, 2
-width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
-width, height = width_in_points, height_in_points # used by snippet_normalize()
+def do_snippet(snippet):
+ if verbose_mode:
+ print('processing %s' % snippet.name)
+ width_in_inches, height_in_inches = 2, 2
+ width_in_points, height_in_points = \
+ width_in_inches * 72, height_in_inches * 72
+ width, height = width_in_points, height_in_points
-def do_snippet (snippet):
- if verbose_mode:
- print 'processing %s' % snippet,
+ try:
+ os.makedirs(os.path.join("_build", "pdf"))
+ except EnvironmentError:
+ pass
+ filename = os.path.join("_build", "pdf", "%s.pdf" % snippet.name)
- filename = 'snippets/%s.pdf' % snippet
- surface = cairo.PDFSurface (filename, width_in_points, height_in_points)
- cr = cairo.Context (surface)
+ surface = cairo.PDFSurface(filename, width_in_points, height_in_points)
+ cr = cairo.Context(surface)
cr.save()
- try:
- execfile ('snippets/%s.py' % snippet, globals(), locals())
- except:
- exc_type, exc_value = sys.exc_info()[:2]
- print >> sys.stderr, exc_type, exc_value
- else:
- cr.restore()
- cr.show_page()
- surface.finish()
+ snippet.draw_func(cr, width, height)
+ cr.restore()
+ cr.show_page()
+ surface.finish()
- if verbose_mode:
- print
if __name__ == '__main__':
+
+ if not cairo.HAS_PDF_SURFACE:
+ raise SystemExit('cairo was not compiled with PDF support')
+
verbose_mode = True
if len(sys.argv) > 1 and sys.argv[1] == '-s':
verbose_mode = False
del sys.argv[1]
- if len(sys.argv) > 1: # do specified snippets
- snippet_list = sys.argv[1:]
- else: # do all snippets
- snippet_list = snip_list
+ snippets = get_snippets()
+
+ if len(sys.argv) > 1:
+ # do specified snippets
+ selected = [snippets[n] for n in sys.argv[1:]]
+ else:
+ # do all snippets
+ selected = snippets.values()
- for s in snippet_list:
- do_snippet (s)
+ for s in selected:
+ do_snippet(s)
diff --git a/examples/cairo_snippets/snippets_png.py b/examples/cairo_snippets/snippets_png.py
index 5341979..36f59ab 100644
--- a/examples/cairo_snippets/snippets_png.py
+++ b/examples/cairo_snippets/snippets_png.py
@@ -1,52 +1,57 @@
#!/usr/bin/env python
-"""Python version of cairo-demo/cairo_snippets/cairo_snippets_png.c
-"""
-from __future__ import division
-from math import pi as M_PI # used by many snippets
-import sys
+"""Create a PNG file for each example"""
+
+from __future__ import print_function
+import os
+import sys
import cairo
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-from snippets import snip_list, snippet_normalize
+from snippets import get_snippets
-width, height = 256, 256 # used by snippet_normalize()
+def do_snippet(snippet):
+ if verbose_mode:
+ print('processing %s' % snippet.name)
+ width, height = 256, 256
-def do_snippet (snippet):
- if verbose_mode:
- print 'processing %s' % snippet,
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ cr = cairo.Context(surface)
- surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height)
- cr = cairo.Context (surface)
+ cr.save()
+ snippet.draw_func(cr, width, height)
- cr.save()
- try:
- execfile ('snippets/%s.py' % snippet, globals(), locals())
- except:
-# exc_type, exc_value = sys.exc_info()[:2]
-# print >> sys.stderr, exc_type, exc_value
- raise
- else:
cr.restore()
- surface.write_to_png ('snippets/%s.png' % snippet)
- if verbose_mode:
- print
+ try:
+ os.makedirs(os.path.join("_build", "png"))
+ except EnvironmentError:
+ pass
+ filename = os.path.join("_build", "png", "%s.png" % snippet.name)
+
+ surface.write_to_png(filename)
+
if __name__ == '__main__':
- verbose_mode = True
- if len(sys.argv) > 1 and sys.argv[1] == '-s':
- verbose_mode = False
- del sys.argv[1]
-
- if len(sys.argv) > 1: # do specified snippets
- snippet_list = sys.argv[1:]
- else: # do all snippets
- snippet_list = snip_list
-
- for s in snippet_list:
- do_snippet (s)
+ if not(cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
+ raise SystemExit(
+ 'cairo was not compiled with ImageSurface and PNG support')
+
+ verbose_mode = True
+ if len(sys.argv) > 1 and sys.argv[1] == '-s':
+ verbose_mode = False
+ del sys.argv[1]
+
+ snippets = get_snippets()
+
+ if len(sys.argv) > 1:
+ # do specified snippets
+ selected = [snippets[n] for n in sys.argv[1:]]
+ else:
+ # do all snippets
+ selected = snippets.values()
+
+ for s in selected:
+ do_snippet(s)
diff --git a/examples/cairo_snippets/snippets_ps.py b/examples/cairo_snippets/snippets_ps.py
index 364402a..265145a 100644
--- a/examples/cairo_snippets/snippets_ps.py
+++ b/examples/cairo_snippets/snippets_ps.py
@@ -1,56 +1,58 @@
#!/usr/bin/env python
-"""Python version of cairo-demo/cairo_snippets/cairo_snippets_ps.c
-create a file for each example rather than one large file for all examples
-"""
-from __future__ import division
-from math import pi as M_PI # used by many snippets
-import sys
+"""Create a PS file for each example"""
+
+from __future__ import print_function
+import os
+import sys
import cairo
-if not cairo.HAS_PS_SURFACE:
- raise SystemExit ('cairo was not compiled with PS support')
-from snippets import snip_list, snippet_normalize
+from snippets import get_snippets
-width_in_inches, height_in_inches = 2, 2
-width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
-width, height = width_in_points, height_in_points # used by snippet_normalize()
+def do_snippet(snippet):
+ if verbose_mode:
+ print('processing %s' % snippet.name)
+ width_in_inches, height_in_inches = 2, 2
+ width_in_points, height_in_points = \
+ width_in_inches * 72, height_in_inches * 72
+ width, height = width_in_points, height_in_points
-def do_snippet (snippet):
- if verbose_mode:
- print 'processing %s' % snippet,
+ try:
+ os.makedirs(os.path.join("_build", "ps"))
+ except EnvironmentError:
+ pass
+ filename = os.path.join("_build", "ps", "%s.ps" % snippet.name)
- filename = 'snippets/%s.ps' % snippet
- surface = cairo.PSSurface (filename, width_in_points, height_in_points)
- cr = cairo.Context (surface)
+ surface = cairo.PSSurface(filename, width_in_points, height_in_points)
+ cr = cairo.Context(surface)
cr.save()
- try:
- execfile ('snippets/%s.py' % snippet, globals(), locals())
- except:
- exc_type, exc_value = sys.exc_info()[:2]
- print >> sys.stderr, exc_type, exc_value
- else:
- cr.restore()
- cr.show_page()
- surface.finish()
+ snippet.draw_func(cr, width, height)
+ cr.restore()
+ cr.show_page()
+ surface.finish()
- if verbose_mode:
- print
if __name__ == '__main__':
+ if not cairo.HAS_PS_SURFACE:
+ raise SystemExit('cairo was not compiled with PS support')
+
verbose_mode = True
if len(sys.argv) > 1 and sys.argv[1] == '-s':
verbose_mode = False
del sys.argv[1]
- if len(sys.argv) > 1: # do specified snippets
- snippet_list = sys.argv[1:]
- else: # do all snippets
- snippet_list = snip_list
+ snippets = get_snippets()
+
+ if len(sys.argv) > 1:
+ # do specified snippets
+ selected = [snippets[n] for n in sys.argv[1:]]
+ else:
+ # do all snippets
+ selected = snippets.values()
- for s in snippet_list:
- do_snippet (s)
+ for s in selected:
+ do_snippet(s)
diff --git a/examples/cairo_snippets/snippets_svg.py b/examples/cairo_snippets/snippets_svg.py
index 3620ee7..e67f45d 100644
--- a/examples/cairo_snippets/snippets_svg.py
+++ b/examples/cairo_snippets/snippets_svg.py
@@ -1,53 +1,58 @@
#!/usr/bin/env python
-from __future__ import division
-from math import pi as M_PI # used by many snippets
-import sys
+"""Create a SVG file for each example"""
+
+from __future__ import print_function
+import os
+import sys
import cairo
-if not cairo.HAS_SVG_SURFACE:
- raise SystemExit ('cairo was not compiled with SVG support')
-from snippets import snip_list, snippet_normalize
+from snippets import get_snippets
-width_in_inches, height_in_inches = 2, 2
-width_in_points, height_in_points = width_in_inches * 72, height_in_inches * 72
-width, height = width_in_points, height_in_points # used by snippet_normalize()
+def do_snippet(snippet):
+ if verbose_mode:
+ print('processing %s' % snippet.name)
+ width_in_inches, height_in_inches = 2, 2
+ width_in_points, height_in_points = \
+ width_in_inches * 72, height_in_inches * 72
+ width, height = width_in_points, height_in_points
-def do_snippet (snippet):
- if verbose_mode:
- print 'processing %s' % snippet,
+ try:
+ os.makedirs(os.path.join("_build", "svg"))
+ except EnvironmentError:
+ pass
+ filename = os.path.join("_build", "svg", "%s.svg" % snippet.name)
- filename = 'snippets/%s.svg' % snippet
- surface = cairo.SVGSurface (filename, width_in_points, height_in_points)
- cr = cairo.Context (surface)
+ surface = cairo.SVGSurface(filename, width_in_points, height_in_points)
+ cr = cairo.Context(surface)
cr.save()
- try:
- execfile ('snippets/%s.py' % snippet, globals(), locals())
- except:
- exc_type, exc_value = sys.exc_info()[:2]
- print >> sys.stderr, exc_type, exc_value
- else:
- cr.restore()
- cr.show_page()
- surface.finish()
+ snippet.draw_func(cr, width, height)
+ cr.restore()
+ cr.show_page()
+ surface.finish()
- if verbose_mode:
- print
if __name__ == '__main__':
+ if not cairo.HAS_SVG_SURFACE:
+ raise SystemExit('cairo was not compiled with SVG support')
+
verbose_mode = True
if len(sys.argv) > 1 and sys.argv[1] == '-s':
verbose_mode = False
del sys.argv[1]
- if len(sys.argv) > 1: # do specified snippets
- snippet_list = sys.argv[1:]
- else: # do all snippets
- snippet_list = snip_list
+ snippets = get_snippets()
+
+ if len(sys.argv) > 1:
+ # do specified snippets
+ selected = [snippets[n] for n in sys.argv[1:]]
+ else:
+ # do all snippets
+ selected = snippets.values()
- for s in snippet_list:
- do_snippet (s)
+ for s in selected:
+ do_snippet(s)
diff --git a/examples/gradient.py b/examples/gradient.py
deleted file mode 100644
index 9ebbf76..0000000
--- a/examples/gradient.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-"""/cairo-demo/cairo_snippets/gradient.cairo translated to Python
-"""
-
-import math
-import cairo
-
-WIDTH, HEIGHT = 256, 256
-
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
-ctx = cairo.Context(surface)
-
-ctx.scale (WIDTH/1.0, HEIGHT/1.0)
-
-pat = cairo.LinearGradient (0.0, 0.0, 0.0, 1.0)
-pat.add_color_stop_rgba (1, 0, 0, 0, 1)
-pat.add_color_stop_rgba (0, 1, 1, 1, 1)
-
-ctx.rectangle (0,0,1,1)
-ctx.set_source (pat)
-ctx.fill ()
-
-pat = cairo.RadialGradient (0.45, 0.4, 0.1,
- 0.4, 0.4, 0.5)
-pat.add_color_stop_rgba (0, 1, 1, 1, 1)
-pat.add_color_stop_rgba (1, 0, 0, 0, 1)
-
-ctx.set_source (pat)
-ctx.arc (0.5, 0.5, 0.3, 0, 2 * math.pi)
-ctx.fill ()
-
-surface.write_to_png('gradient.png')
-#surface.write_to_png(10)
diff --git a/examples/gtk/cairo-demo.py b/examples/gtk/cairo-demo.py
index 76795ce..babc4cd 100644
--- a/examples/gtk/cairo-demo.py
+++ b/examples/gtk/cairo-demo.py
@@ -1,44 +1,52 @@
#!/usr/bin/env python
-"""Based on cairo-demo/X11/cairo-demo.c
-"""
+"""Based on cairo-demo/X11/cairo-demo.c"""
+
import cairo
-import gtk
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
SIZE = 30
+
def triangle(ctx):
ctx.move_to(SIZE, 0)
- ctx.rel_line_to(SIZE, 2*SIZE)
- ctx.rel_line_to(-2*SIZE, 0)
+ ctx.rel_line_to(SIZE, 2 * SIZE)
+ ctx.rel_line_to(-2 * SIZE, 0)
ctx.close_path()
+
def square(ctx):
ctx.move_to(0, 0)
- ctx.rel_line_to(2*SIZE, 0)
- ctx.rel_line_to(0, 2*SIZE)
- ctx.rel_line_to(-2*SIZE, 0)
+ ctx.rel_line_to(2 * SIZE, 0)
+ ctx.rel_line_to(0, 2 * SIZE)
+ ctx.rel_line_to(-2 * SIZE, 0)
ctx.close_path()
+
def bowtie(ctx):
ctx.move_to(0, 0)
- ctx.rel_line_to(2*SIZE, 2*SIZE)
- ctx.rel_line_to(-2*SIZE, 0)
- ctx.rel_line_to(2*SIZE, -2*SIZE)
+ ctx.rel_line_to(2 * SIZE, 2 * SIZE)
+ ctx.rel_line_to(-2 * SIZE, 0)
+ ctx.rel_line_to(2 * SIZE, -2 * SIZE)
ctx.close_path()
+
def inf(ctx):
ctx.move_to(0, SIZE)
- ctx.rel_curve_to(0,SIZE, SIZE,SIZE, 2*SIZE,0)
- ctx.rel_curve_to(SIZE,-SIZE, 2*SIZE,-SIZE, 2*SIZE,0)
- ctx.rel_curve_to(0,SIZE, -SIZE,SIZE, -2*SIZE,0)
- ctx.rel_curve_to(-SIZE,-SIZE, -2*SIZE,-SIZE, -2*SIZE,0)
+ ctx.rel_curve_to(0, SIZE, SIZE, SIZE, 2 * SIZE, 0)
+ ctx.rel_curve_to(SIZE, -SIZE, 2 * SIZE, -SIZE, 2 * SIZE, 0)
+ ctx.rel_curve_to(0, SIZE, -SIZE, SIZE, -2 * SIZE, 0)
+ ctx.rel_curve_to(-SIZE, -SIZE, -2 * SIZE, -SIZE, -2 * SIZE, 0)
ctx.close_path()
+
def draw_shapes(ctx, x, y, fill):
ctx.save()
ctx.new_path()
- ctx.translate(x+SIZE, y+SIZE)
+ ctx.translate(x + SIZE, y + SIZE)
bowtie(ctx)
if fill:
ctx.fill()
@@ -46,7 +54,7 @@ def draw_shapes(ctx, x, y, fill):
ctx.stroke()
ctx.new_path()
- ctx.translate(3*SIZE, 0)
+ ctx.translate(3 * SIZE, 0)
square(ctx)
if fill:
ctx.fill()
@@ -54,7 +62,7 @@ def draw_shapes(ctx, x, y, fill):
ctx.stroke()
ctx.new_path()
- ctx.translate(3*SIZE, 0)
+ ctx.translate(3 * SIZE, 0)
triangle(ctx)
if fill:
ctx.fill()
@@ -62,7 +70,7 @@ def draw_shapes(ctx, x, y, fill):
ctx.stroke()
ctx.new_path()
- ctx.translate(3*SIZE, 0)
+ ctx.translate(3 * SIZE, 0)
inf(ctx)
if fill:
ctx.fill()
@@ -71,51 +79,54 @@ def draw_shapes(ctx, x, y, fill):
ctx.restore()
+
def fill_shapes(ctx, x, y):
draw_shapes(ctx, x, y, True)
+
def stroke_shapes(ctx, x, y):
draw_shapes(ctx, x, y, False)
-def expose (da, event):
- ctx = da.window.cairo_create()
+def draw(da, ctx):
ctx.set_source_rgb(0, 0, 0)
ctx.set_line_width(SIZE / 4)
ctx.set_tolerance(0.1)
ctx.set_line_join(cairo.LINE_JOIN_ROUND)
- ctx.set_dash([SIZE/4.0, SIZE/4.0], 0)
+ ctx.set_dash([SIZE / 4.0, SIZE / 4.0], 0)
stroke_shapes(ctx, 0, 0)
ctx.set_dash([], 0)
- stroke_shapes(ctx, 0, 3*SIZE)
+ stroke_shapes(ctx, 0, 3 * SIZE)
ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
- stroke_shapes(ctx, 0, 6*SIZE)
+ stroke_shapes(ctx, 0, 6 * SIZE)
ctx.set_line_join(cairo.LINE_JOIN_MITER)
- stroke_shapes(ctx, 0, 9*SIZE)
+ stroke_shapes(ctx, 0, 9 * SIZE)
- fill_shapes(ctx, 0, 12*SIZE)
+ fill_shapes(ctx, 0, 12 * SIZE)
ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
- fill_shapes(ctx, 0, 15*SIZE)
- ctx.set_source_rgb(1,0,0)
- stroke_shapes(ctx, 0, 15*SIZE)
+ fill_shapes(ctx, 0, 15 * SIZE)
+ ctx.set_source_rgb(1, 0, 0)
+ stroke_shapes(ctx, 0, 15 * SIZE)
+
def main():
- win = gtk.Window()
- win.connect('destroy', gtk.main_quit)
+ win = Gtk.Window()
+ win.connect('destroy', Gtk.main_quit)
win.set_default_size(450, 550)
- drawingarea = gtk.DrawingArea()
+ drawingarea = Gtk.DrawingArea()
win.add(drawingarea)
- drawingarea.connect('expose_event', expose)
+ drawingarea.connect('draw', draw)
win.show_all()
- gtk.main()
+ Gtk.main()
+
if __name__ == '__main__':
main()
diff --git a/examples/gtk/cairo-knockout.py b/examples/gtk/cairo-knockout.py
index e8c2c90..16f21cd 100644
--- a/examples/gtk/cairo-knockout.py
+++ b/examples/gtk/cairo-knockout.py
@@ -4,38 +4,41 @@
from __future__ import division
import math
-import sys
import cairo
-import gtk
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
def oval_path(ctx, xc, yc, xr, yr):
ctx.save()
- ctx.translate (xc, yc)
- ctx.scale (1.0, yr / xr)
- ctx.move_to (xr, 0.0)
- ctx.arc (0, 0, xr, 0, 2 * math.pi)
- ctx.close_path ()
+ ctx.translate(xc, yc)
+ ctx.scale(1.0, yr / xr)
+ ctx.move_to(xr, 0.0)
+ ctx.arc(0, 0, xr, 0, 2 * math.pi)
+ ctx.close_path()
ctx.restore()
+
def fill_checks(ctx, x, y, width, height):
CHECK_SIZE = 32
- ctx.rectangle (x, y, width, height)
- ctx.set_source_rgb (0.4, 0.4, 0.4)
- ctx.fill ()
+ ctx.rectangle(x, y, width, height)
+ ctx.set_source_rgb(0.4, 0.4, 0.4)
+ ctx.fill()
# Only works for CHECK_SIZE a power of 2
- for j in range (x & -CHECK_SIZE, height, CHECK_SIZE):
- for i in range (y & -CHECK_SIZE, width, CHECK_SIZE):
- if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0):
- ctx.rectangle (i, j, CHECK_SIZE, CHECK_SIZE)
+ for j in range(x & -CHECK_SIZE, height, CHECK_SIZE):
+ for i in range(y & -CHECK_SIZE, width, CHECK_SIZE):
+ if((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0):
+ ctx.rectangle(i, j, CHECK_SIZE, CHECK_SIZE)
+
+ ctx.set_source_rgb(0.7, 0.7, 0.7)
+ ctx.fill()
- ctx.set_source_rgb (0.7, 0.7, 0.7)
- ctx.fill ()
def draw_3circles(ctx, xc, yc, radius, alpha):
subradius = radius * (2 / 3. - 0.1)
@@ -49,80 +52,81 @@ def draw_3circles(ctx, xc, yc, radius, alpha):
ctx.set_source_rgba(0, 1, 0, alpha)
oval_path(ctx,
- xc + radius / 3. * math.cos(math.pi * (0.5 + 2/.3)),
- yc - radius / 3. * math.sin(math.pi * (0.5 + 2/.3)),
+ xc + radius / 3. * math.cos(math.pi * (0.5 + 2 / .3)),
+ yc - radius / 3. * math.sin(math.pi * (0.5 + 2 / .3)),
subradius, subradius)
ctx.fill()
ctx.set_source_rgba(0, 0, 1, alpha)
oval_path(ctx,
- xc + radius / 3. * math.cos(math.pi * (0.5 + 4/.3)),
- yc - radius / 3. * math.sin(math.pi * (0.5 + 4/.3)),
+ xc + radius / 3. * math.cos(math.pi * (0.5 + 4 / .3)),
+ yc - radius / 3. * math.sin(math.pi * (0.5 + 4 / .3)),
subradius, subradius)
ctx.fill()
-def draw (ctx, width, height):
+
+def draw(ctx, width, height):
radius = 0.5 * min(width, height) - 10
xc = width / 2.
yc = height / 2.
- target = ctx.get_target()
+ target = ctx.get_target()
overlay = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height)
- punch = target.create_similar(cairo.CONTENT_ALPHA, width, height)
+ punch = target.create_similar(cairo.CONTENT_ALPHA, width, height)
circles = target.create_similar(cairo.CONTENT_COLOR_ALPHA, width, height)
fill_checks(ctx, 0, 0, width, height)
# Draw a black circle on the overlay
- overlay_cr = cairo.Context (overlay)
- overlay_cr.set_source_rgb (0, 0, 0)
- oval_path (overlay_cr, xc, yc, radius, radius)
+ overlay_cr = cairo.Context(overlay)
+ overlay_cr.set_source_rgb(0, 0, 0)
+ oval_path(overlay_cr, xc, yc, radius, radius)
overlay_cr.fill()
# Draw 3 circles to the punch surface, then cut
# that out of the main circle in the overlay
- punch_cr = cairo.Context (punch)
- draw_3circles (punch_cr, xc, yc, radius, 1.0)
+ punch_cr = cairo.Context(punch)
+ draw_3circles(punch_cr, xc, yc, radius, 1.0)
- overlay_cr.set_operator (cairo.OPERATOR_DEST_OUT)
- overlay_cr.set_source_surface (punch, 0, 0)
+ overlay_cr.set_operator(cairo.OPERATOR_DEST_OUT)
+ overlay_cr.set_source_surface(punch, 0, 0)
overlay_cr.paint()
# Now draw the 3 circles in a subgroup again
# at half intensity, and use OperatorAdd to join up
# without seams.
- circles_cr = cairo.Context (circles)
+ circles_cr = cairo.Context(circles)
- circles_cr.set_operator (cairo.OPERATOR_OVER)
- draw_3circles (circles_cr, xc, yc, radius, 0.5)
+ circles_cr.set_operator(cairo.OPERATOR_OVER)
+ draw_3circles(circles_cr, xc, yc, radius, 0.5)
- overlay_cr.set_operator (cairo.OPERATOR_ADD)
- overlay_cr.set_source_surface (circles, 0, 0)
+ overlay_cr.set_operator(cairo.OPERATOR_ADD)
+ overlay_cr.set_source_surface(circles, 0, 0)
overlay_cr.paint()
- ctx.set_source_surface (overlay, 0, 0)
+ ctx.set_source_surface(overlay, 0, 0)
ctx.paint()
-def expose(drawingarea, event):
- ctx = drawingarea.window.cairo_create()
-
- _, _, width, height = drawingarea.allocation
- draw (ctx, width, height)
+def draw_event(drawingarea, ctx):
+ alloc = drawingarea.get_allocation()
+ draw(ctx, alloc.width, alloc.height)
return False
+
def main():
- win = gtk.Window()
- win.connect('destroy', gtk.main_quit)
+ win = Gtk.Window()
+ win.connect('destroy', Gtk.main_quit)
win.set_title('Knockout Groups')
win.set_default_size(400, 400)
- drawingarea = gtk.DrawingArea()
+ drawingarea = Gtk.DrawingArea()
win.add(drawingarea)
- drawingarea.connect('expose_event', expose)
+ drawingarea.connect('draw', draw_event)
win.show_all()
- gtk.main()
+ Gtk.main()
+
if __name__ == '__main__':
main()
diff --git a/examples/gtk/hangman.py b/examples/gtk/hangman.py
deleted file mode 100644
index 8aa16ce..0000000
--- a/examples/gtk/hangman.py
+++ /dev/null
@@ -1,257 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: iso8859-1 -*-
-#
-# Copyright 2004 Kevin Worth
-#
-# Permission to use, copy, modify, distribute, and sell this software
-# and its documentation for any purpose is hereby granted without fee,
-# provided that the above copyright notice appear in all copies and
-# that both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of the Kevin Worth not
-# be used in advertising or publicity pertaining to distribution of
-# the software without specific, written prior permission. Kevin Worth
-# California makes no representations about the suitability of this
-# software for any purpose. It is provided "as is" without express or
-# implied warranty.
-#
-# KEVIN WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
-# NO EVENT SHALL KEVIN WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# Author: Kevin Worth <kevin@theworths.org>
-
-from math import pi
-from random import randint
-
-import cairo
-import gtk
-
-letters_guessed = ""
-letters_guessed_right = ""
-letters_guessed_wrong = ""
-
-body_parts = 6
-words = ['cairo', 'graphics', 'pencil', 'keyboard', 'science', 'ricochet', 'flood', 'president', 'sanity']
-
-idxRandom = randint(0, len(words) -1)
-word_chosen = words[idxRandom]
-
-#print "The secret word is " + word_chosen
-
-def guess_letter(widget, event):
- global letters_guessed, letters_guessed_right, letters_guessed_wrong
- if event.string in letters_guessed:
- print "What?!?! You already guessed '" + event.string + "'!"
- else:
- letters_guessed += event.string
- if word_chosen.lower().find(event.string) != -1:
- letters_guessed_right += event.string
- else:
- letters_guessed_wrong += event.string
- widget.queue_draw()
-
-def expose_event(widget, event):
- _, _, width, height = widget.allocation
-
- if width < height:
- size = width
- else:
- size = height
-
- pixmap = gtk.gdk.Pixmap (widget.window, width, height)
- ctx = pixmap.cairo_create()
-
- # set the background
- ctx.set_source_rgb(0.7,0.7,0.7)
- ctx.set_operator (cairo.OPERATOR_SOURCE)
- ctx.paint()
-
- ctx.translate ((width - size) / 2, (height - size) / 2)
- ctx.scale(size / 150.0, size / 160.0)
-
- def man_hung():
- return len(letters_guessed_wrong) == body_parts
-
- ctx.set_font_size(10)
- ctx.set_source_rgb(0,0,0)
- for idxLetter in range(len(word_chosen)):
- #print "Examining letter: " + word_chosen[idxLetter]
- if word_chosen[idxLetter].lower() in letters_guessed_right or man_hung():
- if idxLetter == 0:
- ctx.move_to(0, 150)
- ctx.show_text(word_chosen[idxLetter].upper())
- else:
- ctx.move_to(idxLetter * 15, 150)
- ctx.show_text(word_chosen[idxLetter].lower())
- else:
- ctx.move_to(idxLetter * 15, 150)
- ctx.show_text('_')
-
- # Draw Letters Guessed
-
- ctx.move_to(0, 160)
- ctx.set_source_rgb(0, 0, 0)
- ctx.show_text(letters_guessed)
-
- # Draw noose
-
- ctx.move_to(100, 12.5)
- ctx.line_to(100, 5)
- ctx.line_to(130, 5)
- ctx.line_to(130, 100)
- ctx.set_source_rgb(0, 0, 0)
- ctx.stroke()
-
- # Draw base fill color
-
- ctx.move_to(130, 100)
- ctx.line_to(130, 140)
- ctx.line_to(40, 140)
- ctx.line_to(40, 130)
- ctx.line_to(50, 130)
- ctx.line_to(50, 122)
- ctx.line_to(60, 122)
- ctx.line_to(60, 114)
- ctx.line_to(70, 114)
- ctx.line_to(70, 106)
- ctx.line_to(130, 106)
- ctx.set_source_rgb(.4, .2, .1)
- ctx.fill()
-
- # Draw base outline color
-
- ctx.move_to(130, 100)
- ctx.line_to(130, 140)
- ctx.line_to(40, 140)
-
- # Draw 1st(lowest) stair
-
- ctx.line_to(40, 130)
- ctx.line_to(50, 130)
- ctx.line_to(130, 130)
- ctx.set_source_rgb(0, 0, 0)
- ctx.stroke()
-
- # Draw 2nd stair
-
- ctx.move_to(50, 130)
- ctx.line_to(50, 121)
- ctx.line_to(60, 121)
- ctx.line_to(130, 121)
- ctx.stroke()
-
- # Draw 3rd stair
-
- ctx.move_to(60, 121)
- ctx.line_to(60, 113)
- ctx.line_to(70, 113)
- ctx.line_to(130, 113)
- ctx.stroke()
-
- # Draw 4th(top) stair
-
- ctx.move_to(70, 113)
- ctx.line_to(70, 105)
- ctx.line_to(130, 105)
- ctx.stroke()
-
- # Draw Head
-
- if len(letters_guessed_wrong) > 0:
- ctx.move_to(107.5, 20)
- ctx.arc(100, 20, 7.5, 0, 2*pi)
- ctx.set_line_width(1)
- ctx.stroke()
-
- # Draw Eye 1
-
- ctx.move_to(104, 17)
- ctx.arc(103, 17, 1, 0, 2*pi)
- ctx.move_to(103.1, 17)
- ctx.arc(103, 17, .1, 0, 2*pi)
-
- # Draw Eye 2
-
- ctx.move_to(98, 17)
- ctx.arc(97, 17, 1, 0, 2*pi)
- ctx.move_to(97.1, 17)
- ctx.arc(97, 17, .1, 0, 2*pi)
-
- # Draw Nose
-
- ctx.move_to(100.5, 19)
- ctx.line_to(99.5, 21)
- ctx.line_to(100.5, 21)
-
- # Draw Mouth
-
- if len(letters_guessed_wrong) < 6:
- ctx.move_to(97, 23)
- ctx.curve_to(97, 23, 100, 27.5, 103, 23)
- ctx.set_line_width(.5)
- ctx.stroke()
- else:
- ctx.move_to(100.5, 24)
- ctx.arc(100, 24, .5, 0, 2*pi)
- ctx.set_line_width(.5)
- ctx.stroke()
-
- ctx.set_source_rgb(0, 0, 0)
- ctx.set_line_width(1)
-
- # Draw Body
-
- if len(letters_guessed_wrong) > 1:
- ctx.move_to(100, 27.5)
- ctx.line_to(100, 70)
- ctx.stroke()
-
- # Draw Arm 1
-
- if len(letters_guessed_wrong) > 2:
- ctx.move_to(100, 35)
- ctx.line_to(110, 50)
- ctx.stroke()
-
- # Draw Arm 2
-
- if len(letters_guessed_wrong) > 3:
- ctx.move_to(100, 35)
- ctx.line_to(90, 50)
- ctx.stroke()
-
- # Draw Leg 1
-
- if len(letters_guessed_wrong) > 4:
- ctx.move_to(100, 70)
- ctx.line_to(112, 95)
- ctx.stroke()
-
- # Draw Leg 2
-
- if len(letters_guessed_wrong) > 5:
- ctx.move_to(100, 70)
- ctx.line_to(88, 95)
- ctx.stroke()
-
- # draw pixmap to gdk.window
- gc = gtk.gdk.GC(widget.window)
- widget.window.draw_drawable(gc, pixmap, 0,0, 0,0, -1,-1)
-
-
-win = gtk.Window()
-win.connect('destroy', gtk.main_quit)
-win.connect('key_press_event', guess_letter)
-win.set_title('Kevin\'s cairo demo')
-
-drawingarea = gtk.DrawingArea()
-win.add(drawingarea)
-drawingarea.connect('expose_event', expose_event)
-drawingarea.set_size_request(300,320)
-
-win.show_all()
-gtk.main()
diff --git a/examples/gtk/lsystem.py b/examples/gtk/lsystem.py
deleted file mode 100644
index e08c8dc..0000000
--- a/examples/gtk/lsystem.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python
-
-import cairo
-import gtk
-
-# Copyright 2003 Jesse Andrews (jdandr2@uky.edu) under GPL
-
-
-class lindenmayer:
- def __init__( self ):
- self.str = ''
- self.prod = {'[':'[','f':'f',']':']','+':'+','-':'-'}
- self.SIZE = 10
- self.THETA = 90
-
- def addProd( self, let, pro ):
- self.prod[let]=pro
-
- def iterate( self, qty=1 ):
- for i in xrange(qty):
- self.str = ''.join([ self.prod[l] for l in self.str])
- print 'Done iterating'
-
- def expose( self, drawingarea, event ):
- drawable = drawingarea.window
- x, y, width, height = drawingarea.allocation
-
- ctx = drawable.cairo_create()
- ctx.set_source_rgb(0, 0, 0)
-
- ctx.set_line_width(self.SIZE / 4)
- ctx.set_tolerance(0.1)
- ctx.set_line_join(cairo.LINE_JOIN_BEVEL)
-
- ctx.new_path()
- ctx.move_to(100,100)
-
- for c in self.str:
- if c == 'f': line(ctx, self.SIZE )
- if c == '+': rotate( ctx, +self.THETA )
- if c == '-': rotate( ctx, -self.THETA )
- if c == '[': ctx.save()
- if c == ']': ctx.restore()
-
- ctx.stroke()
-
-def line(ctx, len):
- ctx.rel_line_to( 0, len )
-
-def rotate(ctx, deg):
- ctx.rotate( 2*3.141592653589793*deg/360.0 )
-
-def lin_setup():
- cls = lindenmayer()
- ################# SETUP LSYSTEM HERE ################
-
- ### Generic stuff ###
-
- cls.str = 'f' # the starting string
-
- cls.SIZE = 5 # length of a line
-
- ##############################################
- ##############################################
- #### Uncomment the one you want to use... ####
- #### only one at a time right now! ####
- ##############################################
- ##############################################
-
- ###### Kock Square Curve #######
- cls.addProd('f','f-f+f+f-f')
- cls.THETA = 90
-
- ###### Kock Snowflake ######
-
-# cls.addProd('f','f-f++f-f')
-# cls.THETA = 60
-
- ######## Peano Curve ########
-# cls.addProd('x', 'xfyfx+f+yfxfy-f-xfyfx')
-# cls.addProd('y', 'yfxfy-f-xfyfx+f+yfxfy')
-# cls.addProd('f', 'f')
-# cls.THETA = 90
-# cls.str = 'y'
-
- ###### the plant ######
- ## doesn't seem to work ... .save & .restore messed up ##
-
-# cls.addProd( 'f','f[+f]f[-f]f' )
-# cls.THETA = 25
-
- ####### the tree #########
- ## doesn't seem to work ... .save & .restore messed up ##
-
-# cls.addProd( 'f', 'ff+[+f-f-f]-[-f+f+f]' )
-# cls.THETA = 22
-
-
- ### times to iterate string rewriting ###
- #this grows QUICKLY, so start only inc by 1 each run!
- cls.iterate(4)
-
- ################ DONE SETUP ###############
- return cls
-
-def main():
- win = gtk.Window()
- win.connect('destroy', lambda x: gtk.main_quit())
- win.set_title('cairo Lindenmayer System')
- win.set_default_size(600, 600)
-
- cls = lin_setup()
-
- drawingarea = gtk.DrawingArea()
- win.add(drawingarea)
- drawingarea.connect('expose_event', cls.expose)
-
- win.show_all()
- gtk.main()
-
-if __name__ == '__main__':
- main()
-
diff --git a/examples/gtk/png_view.py b/examples/gtk/png_view.py
index 1100c75..1c567f7 100644
--- a/examples/gtk/png_view.py
+++ b/examples/gtk/png_view.py
@@ -5,12 +5,13 @@
import sys
import cairo
-import gtk
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
-def expose_event(widget, event, surface):
- ctx = widget.window.cairo_create()
- ctx.set_source_surface(surface, 0,0)
+def draw_event(widget, ctx, surface):
+ ctx.set_source_surface(surface, 0, 0)
ctx.paint()
@@ -20,16 +21,16 @@ if len(sys.argv) != 2:
filename = sys.argv[1]
surface = cairo.ImageSurface.create_from_png(filename)
-Width = surface.get_width()
-Height = surface.get_height()
+width = surface.get_width()
+height = surface.get_height()
-win = gtk.Window()
-win.connect('destroy', gtk.main_quit)
+win = Gtk.Window()
+win.connect('destroy', Gtk.main_quit)
-drawingarea = gtk.DrawingArea()
+drawingarea = Gtk.DrawingArea()
win.add(drawingarea)
-drawingarea.connect('expose_event', expose_event, surface)
-drawingarea.set_size_request(Width,Height)
+drawingarea.connect('draw', draw_event, surface)
+drawingarea.set_size_request(width, height)
win.show_all()
-gtk.main()
+Gtk.main()
diff --git a/examples/gtk/text.py b/examples/gtk/text.py
index 2bef98b..79efc4f 100644
--- a/examples/gtk/text.py
+++ b/examples/gtk/text.py
@@ -1,12 +1,11 @@
#!/usr/bin/env python
-import cairo
-import gtk
+import gi
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
-def expose_event(widget, event):
- ctx = widget.window.cairo_create()
-
+def draw_event(widget, ctx):
ctx.set_line_width(6)
ctx.set_tolerance(.1)
@@ -14,28 +13,29 @@ def expose_event(widget, event):
ctx.set_font_size(48)
(x, y, width, height, dx, dy) = ctx.text_extents('Hello World')
- ctx.translate (100, 100)
+ ctx.translate(100, 100)
ctx.new_path()
- ctx.move_to(x-10,y-10)
+ ctx.move_to(x - 10, y - 10)
ctx.rel_line_to(width + 20, 0)
ctx.rel_line_to(0, height + 20)
ctx.rel_line_to(-(width + 20), 0)
ctx.close_path()
- ctx.set_source_rgb(0,0,1)
+ ctx.set_source_rgb(0, 0, 1)
ctx.stroke()
ctx.move_to(0, 0)
- ctx.set_source_rgb(0,0,0)
+ ctx.set_source_rgb(0, 0, 0)
ctx.show_text('Hello World')
-win = gtk.Window()
-win.connect('destroy', gtk.main_quit)
-drawingarea = gtk.DrawingArea()
+win = Gtk.Window()
+win.connect('destroy', Gtk.main_quit)
+
+drawingarea = Gtk.DrawingArea()
win.add(drawingarea)
-drawingarea.connect('expose_event', expose_event)
-drawingarea.set_size_request(400,150)
+drawingarea.connect('draw', draw_event)
+drawingarea.set_size_request(400, 150)
win.show_all()
-gtk.main()
+Gtk.main()
diff --git a/examples/hering.py b/examples/hering.py
deleted file mode 100644
index e400e15..0000000
--- a/examples/hering.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python
-"""cairo/cairo-demo/png/hering.c translated into Python
-"""
-
-import math
-
-import cairo
-
-WIDTH = 300
-HEIGHT = 600
-
-def draw_hering (ctx, width, height):
- LINES= 32
- MAX_THETA = .80 * math.pi * 2
- THETA_INC = 2.0 * MAX_THETA / (LINES-1)
-
- ctx.set_source_rgb (0, 0, 0)
- ctx.set_line_width (2.0)
-
- ctx.save()
-
- ctx.translate (width / 2, height / 2)
- ctx.rotate (MAX_THETA)
-
- for i in range (LINES):
- ctx.move_to (-2 * width, 0)
- ctx.line_to (2 * width, 0)
- ctx.stroke()
-
- ctx.rotate (- THETA_INC)
-
- ctx.restore()
-
- ctx.set_line_width (6)
- ctx.set_source_rgb (1, 0, 0)
-
- ctx.move_to (width / 4.0, 0)
- ctx.rel_line_to (0, height)
- ctx.stroke()
-
- ctx.move_to (3 * width / 4.0, 0)
- ctx.rel_line_to (0, height)
- ctx.stroke()
-
-
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
-ctx = cairo.Context(surface)
-
-ctx.set_source_rgb (1, 1, 1)
-ctx.set_operator (cairo.OPERATOR_SOURCE)
-ctx.paint()
-
-draw_hering (ctx, WIDTH, HEIGHT)
-
-surface.write_to_png('hering.png')
diff --git a/examples/manual_tests/isurface_create_for_data1.py b/examples/manual_tests/isurface_create_for_data1.py
deleted file mode 100644
index 867fde4..0000000
--- a/examples/manual_tests/isurface_create_for_data1.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-"""test cairo.ImageSurface.create_for_data() with a Python array
-"""
-
-import array
-import tempfile
-
-import cairo
-
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-
-h, fileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-width, height = 255, 255
-data = array.array('B', [0] * width * height * 4)
-
-for y in range(height):
- for x in range(width):
- offset = (x + (y * width)) * 4
- alpha = y
-
- # cairo.FORMAT_ARGB32 uses pre-multiplied alpha
- data[offset+0] = int(x * alpha/255.0) # B
- data[offset+1] = int(y * alpha/255.0) # G
- data[offset+2] = 0 # R
- data[offset+3] = alpha # A
-
-surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32,
- width, height)
-ctx = cairo.Context(surface)
-surface.write_to_png(fileName)
-print "see %s output file" % fileName
diff --git a/examples/manual_tests/isurface_create_for_data2.py b/examples/manual_tests/isurface_create_for_data2.py
deleted file mode 100644
index c4f290b..0000000
--- a/examples/manual_tests/isurface_create_for_data2.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-"""test cairo.ImageSurface.create_for_data() with a numpy array
-"""
-import tempfile
-
-import cairo
-import numpy
-
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-
-h, fileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-width, height = 255, 255
-data = numpy.ndarray (shape=(height,width,4), dtype=numpy.uint8)
-
-for x in range(width):
- for y in range(height):
- alpha = y
-
- # cairo.FORMAT_ARGB32 uses pre-multiplied alpha
- data[y][x][0] = int(x * alpha/255.0) # B
- data[y][x][1] = int(y * alpha/255.0) # G
- data[y][x][2] = 0 # R
- data[y][x][3] = alpha # A
-
-surface = cairo.ImageSurface.create_for_data (data, cairo.FORMAT_ARGB32,
- width, height)
-ctx = cairo.Context(surface)
-surface.write_to_png(fileName)
-print "see %s output file" % fileName
diff --git a/examples/manual_tests/isurface_create_from_png.py b/examples/manual_tests/isurface_create_from_png.py
deleted file mode 100644
index 8d1ce5d..0000000
--- a/examples/manual_tests/isurface_create_from_png.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-'''test cairo.ImageSurface.create_from_png() and
- cairo.Surface.write_to_png()
-'''
-
-import os
-import tempfile
-
-import cairo
-
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-
-inFileName = os.path.join(os.path.dirname(__file__), '..', 'examples',
- 'cairo_snippets', 'data', 'romedalen.png')
-surface = cairo.ImageSurface.create_from_png(inFileName)
-
-# write to filename
-_, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-surface.write_to_png(outFileName)
-print "see %s output file" % outFileName
-
-# write to file object
-h, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-os.close(h)
-f=file(outFileName, "wb")
-surface.write_to_png(f)
-f.close()
-print "see %s output file" % outFileName
-
-# write to object that has a "write" method
-import StringIO
-_, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-buf = StringIO.StringIO()
-surface.write_to_png(buf)
-png_string = buf.getvalue()
-buf.close()
-f=file(outFileName, "wb")
-f.write(png_string)
-f.close()
-print "see %s output file" % outFileName
-
-# write to object that has a "write" method
-_, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-import cStringIO
-buf = cStringIO.StringIO()
-surface.write_to_png(buf)
-png_string = buf.getvalue()
-buf.close()
-f=file(outFileName, "wb")
-f.write(png_string)
-f.close()
-print "see %s output file" % outFileName
-
-# error test - to check the error message, should raise TypeError
-#surface.write_to_png(101)
diff --git a/examples/manual_tests/isurface_get_data.py b/examples/manual_tests/isurface_get_data.py
deleted file mode 100644
index f2662d4..0000000
--- a/examples/manual_tests/isurface_get_data.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-"""
-Test ImageSurface.get_data()
-"""
-import tempfile
-
-import cairo
-import numpy
-
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-
-w, h = 128, 128
-
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
-ctx = cairo.Context(surface)
-
-ctx.set_source_rgb(1, 1, 1) # white
-ctx.set_operator(cairo.OPERATOR_SOURCE)
-ctx.paint()
-
-# Draw out the triangle using absolute coordinates
-ctx.move_to(w/2, h/3)
-ctx.line_to(2*w/3, 2*h/3)
-ctx.rel_line_to(-1*w/3, 0)
-ctx.close_path()
-
-ctx.set_source_rgb(0, 0, 0) # black
-ctx.set_line_width(15)
-ctx.stroke()
-_, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-surface.write_to_png(outFileName)
-print "see %s output file" % outFileName
-
-# modify surface using numpy
-buf = surface.get_data()
-# alternative which should work (?) but reports
-# TypeError: buffer is read-only
-# - is a Python bug?
-#buf = buffer (surface1)
-
-a = numpy.ndarray(shape=(w,h,4), dtype=numpy.uint8, buffer=buf)
-
-# draw a vertical line
-a[:,40,0] = 255 # byte 0 is blue on little-endian systems
-a[:,40,1] = 0
-a[:,40,2] = 0
-_, outFileName = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
-surface.write_to_png(outFileName)
-print "see %s output file" % outFileName
diff --git a/examples/manual_tests/pygame-test1.py b/examples/manual_tests/pygame-test1.py
deleted file mode 100644
index bd96b88..0000000
--- a/examples/manual_tests/pygame-test1.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env python
-"""demonstrate pycairo and pygame
-method1: use pycairo and pygame directly
-"""
-
-import array
-import math
-import sys
-
-import cairo
-import pygame
-
-def draw(surface):
- x,y, radius = (250,250, 200)
- ctx = cairo.Context(surface)
- ctx.set_line_width(15)
- ctx.arc(x, y, radius, 0, 2.0 * math.pi)
- ctx.set_source_rgb(0.8, 0.8, 0.8)
- ctx.fill_preserve()
- ctx.set_source_rgb(1, 1, 1)
- ctx.stroke()
-
-def input(events):
- for event in events:
- if event.type == pygame.QUIT:
- sys.exit(0)
- else:
- print event
-
-
-Width, Height = 512, 512
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height)
-
-pygame.init()
-window = pygame.display.set_mode( (Width,Height) )
-screen = pygame.display.get_surface()
-
-draw(surface)
-
-#Create PyGame surface from Cairo Surface
-buf = surface.get_data()
-image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
-#Tranfer to Screen
-screen.blit(image, (0,0))
-pygame.display.flip()
-
-while True:
- input(pygame.event.get())
-
-
-"""
-with pycairo 1.4.12 and pygame 1.7.1 you get the error message:
-
-Traceback (most recent call last):
- File "./pygame-test1.py", line 42, in <module>
- image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
-TypeError: char buffer type not available
-
-This is because with
- buf = surface.get_data()
-pycairo provides a binary image buffer,
-whereas with
- image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",)
-pygame is expecting a text-based character buffer!
-"""
diff --git a/examples/manual_tests/pygame-test2.py b/examples/manual_tests/pygame-test2.py
deleted file mode 100644
index bec32de..0000000
--- a/examples/manual_tests/pygame-test2.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-"""demonstrate pycairo and pygame
-method1: use an intermediate Python array object
-"""
-
-import array
-import math
-import sys
-
-import cairo
-import pygame
-
-def draw(surface):
- x,y, radius = (250,250, 200)
- ctx = cairo.Context(surface)
- ctx.set_line_width(15)
- ctx.arc(x, y, radius, 0, 2.0 * math.pi)
- ctx.set_source_rgb(0.8, 0.8, 0.8)
- ctx.fill_preserve()
- ctx.set_source_rgb(1, 1, 1)
- ctx.stroke()
-
-def input(events):
- for event in events:
- if event.type == pygame.QUIT:
- sys.exit(0)
- else:
- print event
-
-
-Width, Height = 512, 512
-data = array.array('c', chr(0) * Width * Height * 4)
-stride = Width * 4
-surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32,Width, Height, stride)
-
-pygame.init()
-window = pygame.display.set_mode( (Width,Height) )
-screen = pygame.display.get_surface()
-
-draw(surface)
-
-#Create PyGame surface from Cairo Surface
-image = pygame.image.frombuffer(data.tostring(),(Width,Height),"ARGB",)
-#Tranfer to Screen
-screen.blit(image, (0,0))
-pygame.display.flip()
-
-while True:
- input(pygame.event.get())
diff --git a/examples/manual_tests/surface_create_for_stream.py b/examples/manual_tests/surface_create_for_stream.py
deleted file mode 100644
index da543f2..0000000
--- a/examples/manual_tests/surface_create_for_stream.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python
-"""
-Test PDF/PS/SVG constructors (using streams)
-"""
-
-import cStringIO
-import gc
-import math
-import sys
-import StringIO
-
-import cairo
-
-
-class C(object):
- """a file-like object (for testing), it simulates sys.stdout
- """
- def __init__ (self):
- self.closed = False
-
- def write(self, s):
- """just echo to stdout, without newlines"""
- if self.closed:
- raise ValueError ("I/O operation on closed file")
- sys.stdout.write(s)
-
- def close(self):
- self.closed = True
-
-
-# a selection of possible args to surface.write_to_png()
-#fo = '/tmp/f.ps'
-fo = file('/tmp/f.svg', 'wb')
-#fo = StringIO.StringIO()
-#fo = cStringIO.StringIO()
-#fo = sys.stdout
-#fo = C()
-
-#fo.close() # this should cause: ValueError: I/O operation on closed file
-
-WIDTH, HEIGHT = 256, 256
-
-#surface = cairo.PDFSurface(fo, WIDTH, HEIGHT)
-#surface = cairo.PSSurface(fo, WIDTH, HEIGHT)
-surface = cairo.SVGSurface(fo, WIDTH, HEIGHT)
-
-#sys.stdout.write ('1\n'); sys.stdout.flush()
-ctx = cairo.Context(surface)
-
-#del fo # test that 'fo' is referenced to keep it alive
-#gc.collect()
-
-#fo.close() # this should cause: ValueError: I/O operation on closed file
-
-ctx.scale(WIDTH/1.0, HEIGHT/1.0)
-
-pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0)
-pat.add_color_stop_rgba(1, 0, 0, 0, 1)
-pat.add_color_stop_rgba(0, 1, 1, 1, 1)
-
-ctx.rectangle(0,0,1,1)
-ctx.set_source(pat)
-ctx.fill()
-
-pat = cairo.RadialGradient(0.45, 0.4, 0.1,
- 0.4, 0.4, 0.5)
-pat.add_color_stop_rgba(0, 1, 1, 1, 1)
-pat.add_color_stop_rgba(1, 0, 0, 0, 1)
-
-ctx.set_source(pat)
-ctx.arc(0.5, 0.5, 0.3, 0, 2 * math.pi)
-ctx.fill()
-
-ctx.show_page()
-surface.finish()
-
-# for testing StringIO: get data and write to file
-#string = fo.getvalue()
-#f2 = file('/tmp/f.ps', 'wb')
-#f2.write(string)
-#f2.close()
diff --git a/examples/manual_tests/surface_write_to_png.py b/examples/manual_tests/surface_write_to_png.py
deleted file mode 100644
index eb2ddef..0000000
--- a/examples/manual_tests/surface_write_to_png.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-"""
-Test Surface.write_to_png()
-"""
-
-import cStringIO
-import math
-import sys
-import StringIO
-
-import cairo
-
-
-if not (cairo.HAS_IMAGE_SURFACE and cairo.HAS_PNG_FUNCTIONS):
- raise SystemExit ('cairo was not compiled with ImageSurface and PNG support')
-
-
-class C(object):
- """a file-like object (for testing), it simulates sys.stdout
- """
- def __init__(self):
- self.closed = False
-
- def write(self, s):
- """just echo to stdout, without newlines"""
- if self.closed:
- raise ValueError("I/O operation on closed file")
- sys.stdout.write(s)
-
- def close(self):
- self.closed = True
-
-
-WIDTH, HEIGHT = 256, 256
-
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
-ctx = cairo.Context(surface)
-
-ctx.scale(WIDTH/1.0, HEIGHT/1.0)
-
-pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0)
-pat.add_color_stop_rgba(1, 0, 0, 0, 1)
-pat.add_color_stop_rgba(0, 1, 1, 1, 1)
-
-ctx.rectangle(0,0,1,1)
-ctx.set_source(pat)
-ctx.fill()
-
-pat = cairo.RadialGradient(0.45, 0.4, 0.1,
- 0.4, 0.4, 0.5)
-pat.add_color_stop_rgba(0, 1, 1, 1, 1)
-pat.add_color_stop_rgba(1, 0, 0, 0, 1)
-
-ctx.set_source(pat)
-ctx.arc(0.5, 0.5, 0.3, 0, 2 * math.pi)
-ctx.fill()
-
-# a selection of possible args to surface.write_to_png()
-#fo = '/tmp/f.png'
-fo = file('/tmp/f.png', 'wb')
-#fo = StringIO.StringIO()
-#fo = cStringIO.StringIO()
-#fo = sys.stdout
-#fo = C()
-
-#fo.close() # this should cause: ValueError: I/O operation on closed file
-surface.write_to_png(fo)
-
-# for testing StringIO: get data and write to file
-#string = fo.getvalue()
-#f2 = file('/tmp/f.png', 'wb')
-#f2.write(string)
-#f2.close()
diff --git a/examples/manual_tests/unicodeFilenames.py b/examples/manual_tests/unicodeFilenames.py
deleted file mode 100755
index 40d5b7d..0000000
--- a/examples/manual_tests/unicodeFilenames.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Test unicode filenames
-
-Functions/methods using unicode filenames:
- cairo.PDFSurface()
- cairo.PSSurface()
- cairo.SVGSurface()
- surface.write_to_png()
- surface.create_from_png()
-"""
-
-import cairo
-
-WIDTH, HEIGHT = 256, 256
-
-#f = open(u"a1ēxāmple.pdf","wb")
-#surface = cairo.PDFSurface (f, WIDTH, HEIGHT)
-
-surface = cairo.PDFSurface(u"a1ēxāmple.pdf", WIDTH, HEIGHT)
-
-ctx = cairo.Context(surface)
-ctx.set_source_rgb(1,0,0)
-ctx.set_operator(cairo.OPERATOR_SOURCE)
-ctx.paint()
-
-surface.write_to_png(u"a2ēxāmple.png")
-surface.show_page()
-surface.flush()
-surface.finish()
diff --git a/examples/manual_tests/unicodeText.py b/examples/manual_tests/unicodeText.py
deleted file mode 100755
index 5ad50c7..0000000
--- a/examples/manual_tests/unicodeText.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Test unicode text
-
-Functions/methods which accept unicode text:
- Context.select_font_face()
- Context.show_text()
- Context.text_extents()
- Context.text_path()
- ToyFontFace()
- ScaledFont.text_extents()
-"""
-
-import cairo
-
-width, height = 300,300
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
-ctx = cairo.Context(surface)
-
-ctx.scale(width, height)
-ctx.set_line_width(0.04)
-
-ctx.select_font_face("Sans",
- cairo.FONT_SLANT_NORMAL,
- cairo.FONT_WEIGHT_NORMAL)
-ctx.set_font_size(0.20)
-ctx.move_to(0.05, 0.5)
-ctx.show_text("ēxāmple.")
-
-surface.write_to_png("test-out.png")
diff --git a/examples/pygame-demo.py b/examples/pygame-demo.py
new file mode 100644
index 0000000..4335d78
--- /dev/null
+++ b/examples/pygame-demo.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+"""demonstrate pycairo and pygame"""
+
+from __future__ import print_function
+
+import math
+import sys
+
+import cairo
+import pygame
+
+
+def draw(surface):
+ x, y, radius = (250, 250, 200)
+ ctx = cairo.Context(surface)
+ ctx.set_line_width(15)
+ ctx.arc(x, y, radius, 0, 2.0 * math.pi)
+ ctx.set_source_rgb(0.8, 0.8, 0.8)
+ ctx.fill_preserve()
+ ctx.set_source_rgb(1, 1, 1)
+ ctx.stroke()
+
+
+def input(events):
+ for event in events:
+ if event.type == pygame.QUIT:
+ sys.exit(0)
+ else:
+ print(event)
+
+
+def main():
+ width, height = 512, 512
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+
+ pygame.init()
+ pygame.display.set_mode((width, height))
+ screen = pygame.display.get_surface()
+
+ draw(surface)
+
+ # Create PyGame surface from Cairo Surface
+ buf = surface.get_data()
+ image = pygame.image.frombuffer(buf, (width, height), "ARGB")
+ # Tranfer to Screen
+ screen.blit(image, (0, 0))
+ pygame.display.flip()
+
+ while True:
+ input(pygame.event.get())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/spiral.py b/examples/spiral.py
deleted file mode 100644
index 7be9af2..0000000
--- a/examples/spiral.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-"""cairo/cairo-demo/png/spiral.c translated into Python
-"""
-
-import cairo
-
-WIDTH, HEIGHT = 600, 600
-
-def draw_spiral (ctx, width, height):
- wd = .02 * width
- hd = .02 * height
-
- width -= 2
- height -= 2
-
- ctx.move_to (width + 1, 1-hd)
- for i in range(9):
- ctx.rel_line_to (0, height - hd * (2 * i - 1))
- ctx.rel_line_to (- (width - wd * (2 *i)), 0)
- ctx.rel_line_to (0, - (height - hd * (2*i)))
- ctx.rel_line_to (width - wd * (2 * i + 1), 0)
-
- ctx.set_source_rgb (0, 0, 1)
- ctx.stroke()
-
-
-surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
-ctx = cairo.Context(surface)
-
-ctx.set_source_rgb (1, 1, 1)
-ctx.set_operator (cairo.OPERATOR_SOURCE)
-ctx.paint()
-
-draw_spiral (ctx, WIDTH, HEIGHT)
-
-surface.write_to_png('spiral.png')
diff --git a/examples/warpedtext.py b/examples/warpedtext.py
deleted file mode 100644
index cd83ee7..0000000
--- a/examples/warpedtext.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-
-import cairo
-import math
-
-def warpPath(ctx, function):
- first = True
-
- for type, points in ctx.copy_path():
- if type == cairo.PATH_MOVE_TO:
- if first:
- ctx.new_path()
- first = False
- x, y = function(*points)
- ctx.move_to(x, y)
-
- elif type == cairo.PATH_LINE_TO:
- x, y = function(*points)
- ctx.line_to(x, y)
-
- elif type == cairo.PATH_CURVE_TO:
- x1, y1, x2, y2, x3, y3 = points
- x1, y1 = function(x1, y1)
- x2, y2 = function(x2, y2)
- x3, y3 = function(x3, y3)
- ctx.curve_to(x1, y1, x2, y2, x3, y3)
-
- elif type == cairo.PATH_CLOSE_PATH:
- ctx.close_path()
-
-def spiral(x, y):
- theta0 = -math.pi * 3 / 4
- theta = x / Width * math.pi * 2 + theta0
- radius = y + 200 - x/7
- xnew = radius*math.cos(theta)
- ynew = radius*math.sin(-theta)
- return xnew + Width/2, ynew + Height/2
-
-def curl(x, y):
- xn = x - Textwidth/2
- #yn = y - Textheight/2
- xnew = xn
- ynew = y + xn ** 3 / ((Textwidth/2)**3) * 70
- return xnew + Width/2, ynew + Height*2/5
-
-
-Width, Height = 512, 512
-surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height)
-ctx = cairo.Context(surface)
-solidpattern = ctx.get_source()
-
-# background
-pat = cairo.LinearGradient (0.0, 0.0, 0, Height)
-pat.add_color_stop_rgba (1, 0, 0, 0, 1)
-pat.add_color_stop_rgba (0, 1, 1, 1, 1)
-
-ctx.rectangle (0,0,Width,Height)
-ctx.set_source (pat)
-ctx.fill ()
-
-# foreground
-ctx.set_source (solidpattern)
-ctx.set_source_rgb (1,1,1)
-
-ctx.select_font_face("Sans")
-ctx.set_font_size(80)
-
-# spiral text
-ctx.new_path()
-ctx.move_to(0, 0)
-ctx.text_path("pycairo - " + "spam " * 5)
-warpPath(ctx, spiral)
-ctx.fill()
-
-# curly text
-ctx.new_path()
-ctx.move_to(0, 0)
-ctx.set_source_rgb(0.3, 0.3, 0.3)
-text = "I am curly :)"
-ctx.text_path(text)
-Textwidth, Textheight = ctx.text_extents(text)[2:4]
-warpPath(ctx, curl)
-ctx.fill()
-
-surface.write_to_png("warpedtext.png")
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..a4b23e5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,3 @@
+[flake8]
+ignore=E402
+builtins=buffer
diff --git a/setup.py b/setup.py
index 7bf9507..c6676c4 100755
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ from distutils.command.install_data import install_data as du_install_data
from distutils.command.build import build as du_build
-PYCAIRO_VERSION = '1.12.0'
+PYCAIRO_VERSION = '1.13.0'
CAIRO_VERSION_REQUIRED = '1.12.0'
XPYB_VERSION_REQUIRED = '1.3'
@@ -207,6 +207,12 @@ class install_data(du_install_data):
def main():
+ extra_compile_args = []
+ if sys.version_info[0] == 2:
+ # Some python setups don't pass -fno-strict-aliasing, while MACROS like
+ # Py_RETURN_TRUE require it.
+ extra_compile_args.append("-fno-strict-aliasing")
+
cairo_ext = Extension(
name='cairo._cairo',
sources=[
@@ -219,10 +225,12 @@ def main():
'cairo/pattern.c',
'cairo/region.c',
'cairo/surface.c',
+ 'cairo/enums.c',
],
include_dirs=pkg_config_parse('--cflags-only-I', 'cairo'),
library_dirs=pkg_config_parse('--libs-only-L', 'cairo'),
libraries=pkg_config_parse('--libs-only-l', 'cairo'),
+ extra_compile_args=extra_compile_args,
)
setup(
diff --git a/tests/test_api.py b/tests/test_api.py
index 7a94837..3c8a65e 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -4,11 +4,13 @@ from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
+import os
import io
import sys
import tempfile as tfi
import base64
import zlib
+import shutil
import cairo
import pytest
@@ -20,6 +22,38 @@ except NameError:
long = int
+def test_show_unicode_text():
+ width, height = 300, 300
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ ctx = cairo.Context(surface)
+
+ ctx.scale(width, height)
+ ctx.set_line_width(0.04)
+
+ ctx.select_font_face(
+ "Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
+ ctx.set_font_size(0.20)
+ ctx.move_to(0.05, 0.5)
+ ctx.show_text(u"ēxāmple.")
+
+
+def test_unicode_filenames():
+ # FIXME: cairo does not support wchar on Windows and byte support is
+ # missing under Python 3
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ dirname = tfi.mkdtemp()
+ old_dir = os.getcwd()
+ try:
+ os.chdir(dirname)
+ surface.write_to_png("foobar")
+ new = cairo.ImageSurface.create_from_png(u"foobar")
+ assert surface.get_data() == new.get_data()
+ finally:
+ os.chdir(old_dir)
+ shutil.rmtree(dirname)
+
+
def test_scaled_font_get_ctm():
surface = cairo.ImageSurface(0, 10, 10)
ctx = cairo.Context(surface)
@@ -44,12 +78,6 @@ def test_scaled_font_get_font_options():
assert isinstance(font_options, cairo.FontOptions)
-def test_ps_surface_get_levels():
- levels = cairo.PSSurface.get_levels()
- assert isinstance(levels, list)
- assert all(isinstance(v, int) for v in levels)
-
-
def test_ps_surface_level_to_string():
level_id = cairo.PSSurface.level_to_string(cairo.PS_LEVEL_2)
assert isinstance(level_id, str)
@@ -60,7 +88,7 @@ def test_surface_has_show_text_glyphs():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
assert not surface.has_show_text_glyphs()
surface.finish()
- with pytest.raises(cairo.Error) as excinfo:
+ with pytest.raises(cairo.Error):
surface.has_show_text_glyphs()
@@ -95,12 +123,6 @@ def test_surface_create_similar_image():
assert image.get_height() == 42
-def test_pdf_get_versions():
- versions = cairo.PDFSurface.get_versions()
- assert isinstance(versions, list)
- assert all(isinstance(v, int) for v in versions)
-
-
def test_pdf_surface_restrict_to_version():
surface = cairo.PDFSurface(None, 10, 10)
surface.restrict_to_version(cairo.PDF_VERSION_1_4)
@@ -123,6 +145,8 @@ def test_error_context():
ctx.restore()
error = excinfo.value
assert error.status == cairo.STATUS_INVALID_RESTORE
+ assert error.status == cairo.Status.INVALID_RESTORE
+ assert isinstance(error.status, cairo.Status)
assert str(error)
@@ -549,12 +573,6 @@ def test_surface_mime_data_for_pdf():
assert jpeg_bytes in file_like.getvalue()
-def test_svg_surface_get_versions():
- versions = cairo.SVGSurface.get_versions()
- assert isinstance(versions, list)
- assert all(isinstance(v, int) for v in versions)
-
-
def test_svg_version_to_string():
ver = cairo.SVGSurface.version_to_string(cairo.SVG_VERSION_1_1)
assert ver and isinstance(ver, str)
diff --git a/tests/test_context.py b/tests/test_context.py
new file mode 100644
index 0000000..16efeb1
--- /dev/null
+++ b/tests/test_context.py
@@ -0,0 +1,33 @@
+import cairo
+import pytest
+
+
+@pytest.fixture
+def context():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 42, 42)
+ return cairo.Context(surface)
+
+
+def test_get_antialias(context):
+ assert context.get_antialias() == cairo.Antialias.DEFAULT
+ assert isinstance(context.get_antialias(), cairo.Antialias)
+
+
+def test_get_fill_rule(context):
+ assert context.get_fill_rule() == cairo.FillRule.WINDING
+ assert isinstance(context.get_fill_rule(), cairo.FillRule)
+
+
+def test_get_line_cap(context):
+ assert context.get_line_cap() == cairo.LineCap.BUTT
+ assert isinstance(context.get_line_cap(), cairo.LineCap)
+
+
+def test_get_line_join(context):
+ assert context.get_line_join() == cairo.LineJoin.MITER
+ assert isinstance(context.get_line_join(), cairo.LineJoin)
+
+
+def test_get_operator(context):
+ assert context.get_operator() == cairo.Operator.OVER
+ assert isinstance(context.get_operator(), cairo.Operator)
diff --git a/tests/test_enums.py b/tests/test_enums.py
new file mode 100644
index 0000000..4d5851d
--- /dev/null
+++ b/tests/test_enums.py
@@ -0,0 +1,107 @@
+import pickle
+import re
+
+import pytest
+import cairo
+
+
+def test_type():
+ t = cairo.Antialias
+ assert int in t.__mro__
+ assert isinstance(t(42), int)
+ assert isinstance(t(0), int)
+ assert issubclass(t, int)
+
+ with pytest.raises(TypeError):
+ t()
+
+ with pytest.raises(TypeError):
+ type("foo", (t,), {})
+
+ assert hasattr(t, "DEFAULT")
+ assert t.DEFAULT == 0
+ assert t.__name__ == "Antialias"
+ assert t.__module__ == "cairo"
+
+ assert repr(t.DEFAULT) == "cairo.Antialias.DEFAULT"
+ assert repr(t(123456)) == "123456"
+ assert repr(t(0)) == "cairo.Antialias.DEFAULT"
+ assert str(t(0)) == "0"
+
+ assert isinstance(cairo.ANTIALIAS_DEFAULT, t)
+
+
+def test_aliases():
+ types_ = [
+ cairo.Antialias,
+ cairo.Content,
+ cairo.Extend,
+ cairo.FillRule,
+ cairo.Filter,
+ cairo.FontWeight,
+ cairo.FontSlant,
+ cairo.Format,
+ cairo.HintMetrics,
+ cairo.HintStyle,
+ cairo.LineCap,
+ cairo.LineJoin,
+ cairo.Operator,
+ cairo.PathDataType,
+ cairo.RegionOverlap,
+ cairo.SubpixelOrder,
+ ]
+
+ def get_prefix(t):
+ name = t.__name__
+ # special case..
+ if name == "PathDataType":
+ name = "Path"
+ return"_".join([s.upper() for s in re.findall('[A-Z][^A-Z]*', name)])
+
+ for t in types_:
+ for name in dir(t):
+ if name.upper() != name:
+ continue
+ value = getattr(t, name)
+ assert isinstance(value, t)
+ prefix = get_prefix(t)
+ assert getattr(cairo, prefix + "_" + name) == value
+
+ for name in dir(cairo):
+ for t in types_:
+ prefix = get_prefix(t)
+ if name.startswith(prefix + "_"):
+ postfix = name[len(prefix) + 1:]
+ value = getattr(cairo, name)
+ assert getattr(t, postfix) == value
+
+ # some enums are different, check manually
+ assert cairo.SVG_VERSION_1_1 == cairo.SVGVersion.VERSION_1_1
+ assert isinstance(cairo.SVG_VERSION_1_1, cairo.SVGVersion)
+ assert isinstance(cairo.SVGVersion.VERSION_1_1, cairo.SVGVersion)
+ assert cairo.SVG_VERSION_1_2 == cairo.SVGVersion.VERSION_1_2
+ assert isinstance(cairo.SVG_VERSION_1_2, cairo.SVGVersion)
+ assert isinstance(cairo.SVGVersion.VERSION_1_2, cairo.SVGVersion)
+
+ assert cairo.PDF_VERSION_1_4 == cairo.PDFVersion.VERSION_1_4
+ assert isinstance(cairo.PDF_VERSION_1_4, cairo.PDFVersion)
+ assert isinstance(cairo.PDFVersion.VERSION_1_4, cairo.PDFVersion)
+ assert cairo.PDF_VERSION_1_5 == cairo.PDFVersion.VERSION_1_5
+ assert isinstance(cairo.PDF_VERSION_1_5, cairo.PDFVersion)
+ assert isinstance(cairo.PDFVersion.VERSION_1_5, cairo.PDFVersion)
+
+ assert cairo.PS_LEVEL_2 == cairo.PSLevel.LEVEL_2
+ assert isinstance(cairo.PS_LEVEL_2, cairo.PSLevel)
+ assert isinstance(cairo.PSLevel.LEVEL_2, cairo.PSLevel)
+ assert cairo.PS_LEVEL_3 == cairo.PSLevel.LEVEL_3
+ assert isinstance(cairo.PS_LEVEL_3, cairo.PSLevel)
+ assert isinstance(cairo.PSLevel.LEVEL_3, cairo.PSLevel)
+
+
+def test_pickle():
+ # These constants used to be plain int. Try to pickle to int so that
+ # there is no dependency on pycairo when unpickling.
+
+ value = cairo.Antialias(42)
+ new_value = pickle.loads(pickle.dumps(value))
+ assert type(new_value) == int
diff --git a/tests/test_font.py b/tests/test_font.py
new file mode 100644
index 0000000..e6a5613
--- /dev/null
+++ b/tests/test_font.py
@@ -0,0 +1,40 @@
+import cairo
+import pytest
+
+
+def test_toy_font_get_slant():
+ font_face = cairo.ToyFontFace("")
+ assert font_face.get_slant() == cairo.FontSlant.NORMAL
+ assert isinstance(font_face.get_slant(), cairo.FontSlant)
+
+
+def test_toy_font_get_weight():
+ font_face = cairo.ToyFontFace("")
+ assert font_face.get_weight() == cairo.FontWeight.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)
+
+
+def test_font_options_get_hint_metrics(font_options):
+ assert font_options.get_hint_metrics() == cairo.HintMetrics.ON
+ assert isinstance(font_options.get_hint_metrics(), cairo.HintMetrics)
+
+
+def test_font_options_get_hint_style(font_options):
+ assert font_options.get_hint_style() == cairo.HintStyle.DEFAULT
+ assert isinstance(font_options.get_hint_style(), cairo.HintStyle)
+
+
+def test_font_options_get_subpixel_order(font_options):
+ assert font_options.get_subpixel_order() == cairo.SubpixelOrder.DEFAULT
+ assert isinstance(font_options.get_subpixel_order(), cairo.SubpixelOrder)
diff --git a/tests/test_pattern.py b/tests/test_pattern.py
new file mode 100644
index 0000000..10900cf
--- /dev/null
+++ b/tests/test_pattern.py
@@ -0,0 +1,12 @@
+import cairo
+
+
+def test_get_extend():
+ pattern = cairo.SolidPattern(1, 2, 4)
+ assert pattern.get_extend() == cairo.Extend.PAD
+ assert isinstance(pattern.get_extend(), cairo.Extend)
+
+
+def test_get_filter():
+ pattern = cairo.SolidPattern(1, 2, 4)
+ assert pattern.get_filter() == cairo.Filter.GOOD
diff --git a/tests/test_region.py b/tests/test_region.py
new file mode 100644
index 0000000..4988367
--- /dev/null
+++ b/tests/test_region.py
@@ -0,0 +1,8 @@
+import cairo
+
+
+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)
diff --git a/tests/test_surface.py b/tests/test_surface.py
new file mode 100644
index 0000000..8aec540
--- /dev/null
+++ b/tests/test_surface.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+
+import io
+import os
+import array
+import tempfile
+import struct
+
+import cairo
+import pytest
+
+
+def test_surface_get_content():
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
+ assert surface.get_content() == cairo.Content.COLOR_ALPHA
+ assert isinstance(surface.get_content(), cairo.Content)
+
+
+def test_surface_get_format():
+ surface = cairo.ImageSurface(cairo.Format.ARGB32, 10, 10)
+ assert surface.get_format() == cairo.Format.ARGB32
+ assert isinstance(surface.get_format(), cairo.Format)
+
+
+def test_pdf_get_versions():
+ versions = cairo.PDFSurface.get_versions()
+ assert isinstance(versions, list)
+ assert all(isinstance(v, cairo.PDFVersion) for v in versions)
+
+
+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_svg_surface_get_versions():
+ versions = cairo.SVGSurface.get_versions()
+ assert isinstance(versions, list)
+ assert all(isinstance(v, cairo.SVGVersion) for v in versions)
+
+
+@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)
+
+ for y in range(height):
+ for x in range(width):
+ offset = (x + (y * width)) * 4
+ alpha = y
+
+ b = int(x * alpha / 255.0)
+ g = int(y * alpha / 255.0)
+ # cairo.FORMAT_ARGB32 uses pre-multiplied alpha
+ data[offset:offset + 3] = array.array(
+ "B", struct.pack("=I", b | g << 8 | alpha << 24))
+
+ surface = cairo.ImageSurface.create_for_data(
+ data, cairo.FORMAT_ARGB32, width, height)
+
+ # for debugging
+ fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
+ os.close(fd)
+ surface.write_to_png(filename)
+ 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.close(fd)
+ surface.write_to_png(filename)
+
+ fileobj = io.BytesIO()
+ surface.write_to_png(fileobj)
+
+ with open(filename, "rb") as h:
+ assert h.read() == fileobj.getvalue()
+
+ 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)
+ surface.write_to_png(fileobj)
+ fileobj.seek(0)
+ new_surface = cairo.ImageSurface.create_from_png(fileobj)
+ assert surface.get_data() == new_surface.get_data()
+
+
+@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)
+
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128)
+ surface.write_to_png(filename)
+
+ new_surface = cairo.ImageSurface.create_from_png(filename)
+ assert surface.get_data() == new_surface.get_data()
+ 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)
+
+
+def test_surface_from_stream_closed_before_finished():
+ for Kind in [cairo.PDFSurface, cairo.PSSurface, cairo.SVGSurface]:
+ fileobj = io.BytesIO()
+ surface = cairo.PDFSurface(fileobj, 128, 128)
+ fileobj.close()
+ with pytest.raises(IOError):
+ surface.finish()
diff --git a/tests/test_surface_numpy.py b/tests/test_surface_numpy.py
new file mode 100644
index 0000000..cd67d22
--- /dev/null
+++ b/tests/test_surface_numpy.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+
+import os
+import tempfile
+
+import cairo
+import pytest
+
+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)
+
+ for y in range(height):
+ for x in range(width):
+ alpha = y
+ b = int(x * alpha / 255.0)
+ g = int(y * alpha / 255.0)
+ data[y][x] = (b | g << 8 | alpha << 24)
+
+ surface = cairo.ImageSurface.create_for_data(
+ data, cairo.FORMAT_ARGB32, width, height)
+
+ # for debugging
+ fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
+ os.close(fd)
+ surface.write_to_png(filename)
+ 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)
+ ctx = cairo.Context(surface)
+
+ ctx.set_source_rgb(1, 1, 1) # white
+ ctx.set_operator(cairo.OPERATOR_SOURCE)
+ ctx.paint()
+
+ # Draw out the triangle using absolute coordinates
+ ctx.move_to(w / 2, h / 3)
+ ctx.line_to(2 * w / 3, 2 * h / 3)
+ ctx.rel_line_to(-1 * w / 3, 0)
+ ctx.close_path()
+
+ ctx.set_source_rgb(0, 0, 0) # black
+ ctx.set_line_width(15)
+ ctx.stroke()
+
+ buf = surface.get_data()
+
+ a = numpy.ndarray(shape=(w, h), dtype=numpy.uint32, buffer=buf)
+
+ # draw a vertical blue line
+ a[:, 40] = 0xff | 0xff << 24
+
+ # for debugging
+ fd, filename = tempfile.mkstemp(prefix='pycairo_', suffix='.png')
+ os.close(fd)
+ surface.write_to_png(filename)
+ os.unlink(filename)
diff --git a/tests/test_surface_pygame.py b/tests/test_surface_pygame.py
new file mode 100644
index 0000000..4d36fe2
--- /dev/null
+++ b/tests/test_surface_pygame.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+import cairo
+import pytest
+
+pygame = pytest.importorskip("pygame")
+
+
+def test_image_surface_to_pygame_image():
+ width, height = 100, 100
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
+ buf = surface.get_data()
+ image = pygame.image.frombuffer(buf, (width, height), "ARGB")
+ assert image