/*! * \brief Draw object * * Optional on the PyDia side. If not implemented the base class method * will be called. * * Intercepting this method on the Python side allows to create per * object information in the drawing. It is also necessary if the PyDia * renderer should support transformations. * * If implementing a drawing export filter and overwriting draw_object() * the following code shall be used. Otherwise no draw/fill method will * be called at all. * * \code # don't forget to render the object object.draw (self) * \endcode * * Not calling the object draw method is only useful when a non-drawing * export - e.g. code generation \sa codegen.py - is implemented. * * @param renderer Self * @param object The object to draw * @param matrix The transformation matrix to use or NULL for no transformation * * \memberof _DiaPyRenderer */ static void draw_object (DiaRenderer *renderer, DiaObject *object, DiaMatrix *matrix) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_object"); if (func && PyCallable_Check(func)) { PyObject *oobj = PyDiaObject_New (object); PyObject *mat = NULL; Py_INCREF(self); Py_INCREF(func); if (matrix) mat = PyDiaMatrix_New (matrix); else { Py_INCREF(Py_None); mat = Py_None; } arg = Py_BuildValue ("(OO)", oobj, mat); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (oobj); Py_XDECREF (mat); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* but should still call the base class */ DIA_RENDERER_CLASS (parent_class)->draw_object (renderer, object, matrix); } }
/*! * \brief Set fillstyle for later use * * Optional on the PyDia side. * * \memberof _DiaPyRenderer */ static void set_fillstyle(DiaRenderer *renderer, FillStyle mode) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); switch(mode) { case FILLSTYLE_SOLID: break; default: PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n"); } func = PyObject_GetAttrString (self, "set_fillstyle"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(i)", mode); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF(func); Py_DECREF(self); } else /* member optional */ PyErr_Clear(); }
/*! * \brief Draw line * * Not optional on the PyDia side. If not implemented a runtime warning * will be generated when called. * * \memberof _DiaPyRenderer */ static void draw_line(DiaRenderer *renderer, Point *start, Point *end, Color *line_colour) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_line"); if (func && PyCallable_Check(func)) { PyObject *ostart = PyDiaPoint_New (start); PyObject *oend = PyDiaPoint_New (end); PyObject *ocolor = PyDiaColor_New (line_colour); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OOO)", ostart, oend, ocolor); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (ostart); Py_XDECREF (oend); Py_XDECREF (ocolor); Py_DECREF(func); Py_DECREF(self); } else { /* member not optional */ gchar *msg = g_strdup_printf ("%s.draw_line() implmentation missing.", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer))); PyErr_Clear(); PyErr_Warn (PyExc_RuntimeWarning, msg); g_free (msg); } }
/*! * \brief Set linejoin for later use * * Optional on the PyDia side. * * \memberof _DiaPyRenderer */ static void set_linejoin(DiaRenderer *renderer, LineJoin mode) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); switch(mode) { case LINEJOIN_MITER: break; case LINEJOIN_ROUND: break; case LINEJOIN_BEVEL: break; case LINEJOIN_DEFAULT: default: PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n"); } func = PyObject_GetAttrString (self, "set_linejoin"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(i)", mode); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF(func); Py_DECREF(self); } else /* member optional */ PyErr_Clear(); }
/*! * \brief Draw polyline * * Optional on the PyDia side. If not implemented fallback to base class member. * * \memberof _DiaPyRenderer */ static void draw_polyline(DiaRenderer *renderer, Point *points, int num_points, Color *line_colour) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_polyline"); if (func && PyCallable_Check(func)) { PyObject *optt = PyDiaPointTuple_New (points, num_points); PyObject *ocolor = PyDiaColor_New (line_colour); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OO)", optt, ocolor); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (optt); Py_XDECREF (ocolor); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* XXX: implementing the same fallback as DiaRenderer */ DIA_RENDERER_CLASS (parent_class)->draw_polyline (renderer, points, num_points, line_colour); } }
/* kept for backward compatibility, not any longer in the renderer interface */ static void fill_bezier(DiaRenderer *renderer, BezPoint *points, /* Last point must be same as first point */ int num_points, Color *colour) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "fill_bezier"); if (func && PyCallable_Check(func)) { PyObject *obt = PyDiaBezPointTuple_New (points, num_points); PyObject *ocolor = PyDiaColor_New (colour); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OO)", obt, ocolor); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (obt); Py_XDECREF (ocolor); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* XXX: implementing the same fallback as DiaRenderer would do */ DIA_RENDERER_CLASS (parent_class)->draw_beziergon (renderer, points, num_points, colour, NULL); } }
/*! * \brief Draw image * * Not optional on the PyDia side. If not implemented a runtime warning * will be generated when called. * * \memberof _DiaPyRenderer */ static void draw_image(DiaRenderer *renderer, Point *point, real width, real height, DiaImage *image) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_image"); if (func && PyCallable_Check(func)) { PyObject *opoint = PyDiaPoint_New (point); PyObject *oimage = PyDiaImage_New (image); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OddO)", opoint, width, height, oimage); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (opoint); Py_XDECREF (oimage); Py_DECREF(func); Py_DECREF(self); } else { /* member not optional */ gchar *msg = g_strdup_printf ("%s.draw_image() implmentation missing.", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer))); PyErr_Clear(); PyErr_Warn (PyExc_RuntimeWarning, msg); g_free (msg); } }
/*! * \brief Advertise the renderer's capabilities * \memberof _DiaTransformRenderer */ static gboolean is_capable_to (DiaRenderer *renderer, RenderCapability cap) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); gboolean bRet = FALSE; func = PyObject_GetAttrString (self, "is_capable_to"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(i)", cap); if (arg) { res = PyEval_CallObject (func, arg); if (res && PyInt_Check(res)) { bRet = (PyInt_AsLong(res) != 0); Py_DECREF (res); } else { ON_RES(res, FALSE); } } Py_XDECREF(arg); Py_DECREF(func); Py_DECREF(self); } else { PyErr_Clear(); /* member optional */ return DIA_RENDERER_CLASS (parent_class)->is_capable_to (renderer, cap); } return bRet; }
/* * Callback for "removed" signal, used by the connect_after method, * it's a proxy for the python function, creating the values it needs. * Params are those of the "removed" signal on the Diagram object. * @param Diagram The Diagram that emitted the signal * @param user_data The python function to be called by the callback. */ static void PyDiaDiagram_CallbackRemoved(Diagram *dia,void *user_data) { /* Check that we got a function */ PyObject *diaobj,*res,*arg; PyObject *func = user_data; if (!func || !PyCallable_Check (func)) { g_warning ("Callback called without valid callback function."); return; } /* Create a new PyDiaDiagram object. This really should reuse the object that we connected to. * We'll do that later. */ if (dia) diaobj = PyDiaDiagram_New (dia); else { diaobj = Py_None; Py_INCREF (diaobj); } Py_INCREF(func); /* Call the callback. */ arg = Py_BuildValue ("(O)", diaobj); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF(func); Py_XDECREF(diaobj); }
/*! * Callback for "object_add" and "object_remove "signal, used by the connect_after method, * it's a proxy for the python function, creating the values it needs. * Params are those of the signals on the Diagram object. * @param dia The DiagramData that emitted the signal * @param layer The Layer that the object is removed or added to. * @param obj The DiaObject that the signal is about. * @param user_data The python function to be called by the callback. */ static void PyDiaDiagramData_CallbackObject(DiagramData *dia,Layer *layer,DiaObject *obj,void *user_data) { PyObject *pydata,*pylayer,*pyobj,*res,*arg; PyObject *func = user_data; /* Check that we got a function */ if (!func || !PyCallable_Check (func)) { g_warning ("Callback called without valid callback function."); return; } /* Create a new PyDiaDiagramData object. */ if (dia) pydata = PyDiaDiagramData_New (dia); else { pydata = Py_None; Py_INCREF (pydata); } /* * Create PyDiaLayer */ if (layer) pylayer = PyDiaLayer_New (layer); else { pylayer = Py_None; Py_INCREF (pylayer); } /* * Create PyDiaObject */ if (layer) pyobj = PyDiaObject_New (obj); else { pyobj = Py_None; Py_INCREF (pyobj); } Py_INCREF(func); /* Call the callback. */ arg = Py_BuildValue ("(OOO)", pydata,pylayer,pyobj); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } /* Cleanup */ Py_XDECREF (arg); Py_DECREF(func); Py_XDECREF(pydata); Py_XDECREF(pylayer); Py_XDECREF(pyobj); }
/*! * \brief Fill and/or stroke a closed path * \memberof _DiaPyRenderer */ static void draw_beziergon (DiaRenderer *renderer, BezPoint *points, int num_points, Color *fill, Color *stroke) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_beziergon"); if (func && PyCallable_Check(func)) { PyObject *obt = PyDiaBezPointTuple_New (points, num_points); PyObject *fill_po; PyObject *stroke_po; Py_INCREF(self); Py_INCREF(func); /* we have to provide a Python object even if there is no color */ if (fill) fill_po = PyDiaColor_New (fill); else Py_INCREF(Py_None), fill_po = Py_None; if (stroke) stroke_po = PyDiaColor_New (stroke); else Py_INCREF(Py_None), stroke_po = Py_None; arg = Py_BuildValue ("(OOO)", obt, fill_po, stroke_po); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (obt); Py_XDECREF (fill_po); Py_XDECREF (stroke_po); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* PyDia only backward compatibility */ if (fill) fill_bezier (renderer, points, num_points, fill); if (stroke) /* XXX: still not closing */ draw_bezier (renderer, points, num_points, stroke); } }
/*! * \brief Draw ellipse * * Not optional on the PyDia side. If not implemented a runtime warning * will be generated when called. * * \memberof _DiaPyRenderer */ static void draw_ellipse(DiaRenderer *renderer, Point *center, real width, real height, Color *fill, Color *stroke) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_ellipse"); if (func && PyCallable_Check(func)) { PyObject *opoint = PyDiaPoint_New (center); PyObject *fill_po; PyObject *stroke_po; Py_INCREF(self); Py_INCREF(func); /* we have to provide a Python object even if there is no color */ if (fill) fill_po = PyDiaColor_New (fill); else Py_INCREF(Py_None), fill_po = Py_None; if (stroke) stroke_po = PyDiaColor_New (stroke); else Py_INCREF(Py_None), stroke_po = Py_None; arg = Py_BuildValue ("(OddOO)", opoint, width, height, fill_po, stroke_po); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (opoint); Py_XDECREF (fill_po); Py_XDECREF (stroke_po); Py_DECREF(func); Py_DECREF(self); } else { /* member not optional */ gchar *msg = g_strdup_printf ("%s.draw_ellipse() implementation missing.", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer))); PyErr_Clear(); PyErr_Warn (PyExc_RuntimeWarning, msg); g_free (msg); } }
/*! * \brief Draw string * * Not optional on the PyDia side. If not implemented a runtime warning * will be generated when called. * * \memberof _DiaPyRenderer */ static void draw_string(DiaRenderer *renderer, const char *text, Point *pos, Alignment alignment, Color *colour) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); switch (alignment) { case ALIGN_LEFT: break; case ALIGN_CENTER: break; case ALIGN_RIGHT: break; } func = PyObject_GetAttrString (self, "draw_string"); if (func && PyCallable_Check(func)) { PyObject *opoint = PyDiaPoint_New (pos); PyObject *ocolor = PyDiaColor_New (colour); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(sOiO)", text, opoint, alignment, ocolor); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (opoint); Py_XDECREF (ocolor); Py_DECREF(func); Py_DECREF(self); } else { /* member not optional */ gchar *msg = g_strdup_printf ("%s.draw_string() implmentation missing.", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer))); PyErr_Clear(); PyErr_Warn (PyExc_RuntimeWarning, msg); g_free (msg); } }
static void draw_rounded_rect(DiaRenderer *renderer, Point *ul_corner, Point *lr_corner, Color *fill, Color *stroke, real rounding) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_rounded_rect"); if (func && PyCallable_Check(func)) { PyObject *orect = PyDiaRectangle_New_FromPoints (ul_corner, lr_corner); PyObject *fill_po, *stroke_po; Py_INCREF(self); Py_INCREF(func); if (fill) fill_po = PyDiaColor_New (fill); else Py_INCREF(Py_None), fill_po = Py_None; if (stroke) stroke_po = PyDiaColor_New (stroke); else Py_INCREF(Py_None), stroke_po = Py_None; arg = Py_BuildValue ("(OOOd)", orect, fill_po, stroke_po, rounding); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (fill_po); Py_XDECREF (stroke_po); Py_XDECREF (orect); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* implementing the same fallback as DiaRenderer would do */ DIA_RENDERER_CLASS (parent_class)->draw_rounded_rect (renderer, ul_corner, lr_corner, fill, stroke, rounding); } }
/*! * \brief Finalize drawing/exporting * * \memberof _DiaPyRenderer */ static void end_render(DiaRenderer *renderer) { PyObject *func, *res, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "end_render"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); res = PyEval_CallObject (func, (PyObject *)NULL); ON_RES(res, FALSE); Py_DECREF(func); Py_DECREF(self); } Py_DECREF (DIA_PY_RENDERER(renderer)->diagram_data); g_free (DIA_PY_RENDERER(renderer)->filename); DIA_PY_RENDERER(renderer)->filename = NULL; setlocale(LC_NUMERIC, DIA_PY_RENDERER(renderer)->old_locale); }
/*! * \brief Set linewidth for later use * * Optional on the PyDia side. * * \memberof _DiaPyRenderer */ static void set_linewidth(DiaRenderer *renderer, real linewidth) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "set_linewidth"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(d)", linewidth); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF(func); Py_DECREF(self); } else /* member optional */ PyErr_Clear(); }
/*! * \brief Draw polygon * * Optional on the PyDia side. If not implemented fallback to base class member. * * \memberof _DiaPyRenderer */ static void draw_polygon(DiaRenderer *renderer, Point *points, int num_points, Color *fill, Color *stroke) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_polygon"); if (func && PyCallable_Check(func)) { PyObject *optt = PyDiaPointTuple_New (points, num_points); PyObject *fill_po, *stroke_po; if (fill) fill_po = PyDiaColor_New (fill); else Py_INCREF(Py_None), fill_po = Py_None; if (stroke) stroke_po = PyDiaColor_New (stroke); else Py_INCREF(Py_None), stroke_po = Py_None; Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OOO)", optt, fill_po, stroke_po); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (optt); Py_XDECREF (fill_po); Py_XDECREF (stroke_po); Py_DECREF(func); Py_DECREF(self); } else { /* fill_polygon was not an optional member */ PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : draw_polygon() method missing!\n"); } }
/*! * \brief Set linestyle for later use * * Optional on the PyDia side. * * \memberof _DiaPyRenderer */ static void set_linestyle(DiaRenderer *renderer, LineStyle mode, real dash_length) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); /* line type */ switch (mode) { case LINESTYLE_SOLID: break; case LINESTYLE_DASHED: break; case LINESTYLE_DASH_DOT: break; case LINESTYLE_DASH_DOT_DOT: break; case LINESTYLE_DOTTED: break; case LINESTYLE_DEFAULT: default: PyErr_Warn (PyExc_RuntimeWarning, "DiaPyRenderer : Unsupported fill mode specified!\n"); } func = PyObject_GetAttrString (self, "set_linestyle"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(id)", mode, dash_length); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF(func); Py_DECREF(self); } else /* member optional */ PyErr_Clear(); }
/*! * \brief Begin rendering with Python * * @param renderer Explicit this pointer * @param update The rectangle to update or NULL for everything * * The Python side of the begin_render() method has a different signature. * It gets passed in a PyDia wrapped _DiagramData object and a filename * to store to. * * \memberof _DiaPyRenderer */ static void begin_render(DiaRenderer *renderer, const Rectangle *update) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); DIA_PY_RENDERER(renderer)->old_locale = setlocale(LC_NUMERIC, "C"); func = PyObject_GetAttrString (self, "begin_render"); if (func && PyCallable_Check(func)) { Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(Os)", DIA_PY_RENDERER(renderer)->diagram_data, DIA_PY_RENDERER(renderer)->filename); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_DECREF (func); Py_DECREF (self); } }
/*! * \brief Fill arc * * Not optional on the PyDia side. If not implemented a runtime warning * will be generated when called. * * \memberof _DiaPyRenderer */ static void fill_arc(DiaRenderer *renderer, Point *center, real width, real height, real angle1, real angle2, Color *colour) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "fill_arc"); if (func && PyCallable_Check(func)) { PyObject *opoint = PyDiaPoint_New (center); PyObject *ocolor = PyDiaColor_New (colour); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(OddddO)", opoint, width, height, angle1, angle2, ocolor); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (opoint); Py_XDECREF (ocolor); Py_DECREF(func); Py_DECREF(self); } else { /* member not optional */ gchar *msg = g_strdup_printf ("%s.fill_arc() implmentation missing.", G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (renderer))); PyErr_Clear(); PyErr_Warn (PyExc_RuntimeWarning, msg); g_free (msg); } }
/*! * \brief Render all the visible object in the layer * @param renderer explicit this pointer * @param layer layer to draw * @param active TRUE if it is the currently active layer * @param update the update rectangle, NULL for unlimited * * \memberof _DiaPyRenderer */ static void draw_layer (DiaRenderer *renderer, Layer *layer, gboolean active, Rectangle *update) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "draw_layer"); if (func && PyCallable_Check(func)) { PyObject *olayer = PyDiaLayer_New (layer); PyObject *orect; Py_INCREF (self); Py_INCREF (func); if (update) { orect = PyDiaRectangle_New (update, NULL); } else { Py_INCREF(Py_None); orect = Py_None; } arg = Py_BuildValue ("(OiO)", olayer, active, orect); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (olayer); Py_XDECREF (orect); Py_DECREF(func); Py_DECREF(self); } else { /* member optional */ PyErr_Clear(); /* have to call the base class */ DIA_RENDERER_CLASS (parent_class)->draw_layer (renderer, layer, active, update); } }
/*! * \brief Set font for later use * * Optional on the PyDia side. * * \memberof _DiaPyRenderer */ static void set_font(DiaRenderer *renderer, DiaFont *font, real height) { PyObject *func, *res, *arg, *self = PYDIA_RENDERER (renderer); func = PyObject_GetAttrString (self, "set_font"); if (func && PyCallable_Check(func)) { PyObject *ofont = PyDiaFont_New (font); Py_INCREF(self); Py_INCREF(func); arg = Py_BuildValue ("(Od)", ofont, height); if (arg) { res = PyEval_CallObject (func, arg); ON_RES(res, FALSE); } Py_XDECREF (arg); Py_XDECREF (ofont); Py_DECREF(func); Py_DECREF(self); } else /* member optional */ PyErr_Clear(); }