X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fluainstance.cc;h=5893c15fd942d7e31be0dfccc366d310a2bb698b;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=0519aec1ecd51eadaf064b55aa6917b9d1692134;hpb=d21f20290515817cd7664301912184edb43c1845;p=ardour.git diff --git a/gtk2_ardour/luainstance.cc b/gtk2_ardour/luainstance.cc index 0519aec1ec..5893c15fd9 100644 --- a/gtk2_ardour/luainstance.cc +++ b/gtk2_ardour/luainstance.cc @@ -17,6 +17,8 @@ */ #include +#include +#include #include "gtkmm2ext/gui_thread.h" @@ -38,7 +40,277 @@ #include "selection.h" #include "script_selector.h" -#include "i18n.h" +#include "pbd/i18n.h" + +namespace LuaCairo { +/** wrap RefPtr< Cairo::ImageSurface > + * + * Image surfaces provide the ability to render to memory buffers either + * allocated by cairo or by the calling code. The supported image formats are + * those defined in Cairo::Format. + */ +class ImageSurface { + public: + /** + * Creates an image surface of the specified format and dimensions. Initially + * the surface contents are all 0. (Specifically, within each pixel, each + * color or alpha channel belonging to format will be 0. The contents of bits + * within a pixel, but not belonging to the given format are undefined). + * + * @param 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 + */ + ImageSurface (Cairo::Format format, int width, int height) + : _surface (Cairo::ImageSurface::create (format, width, height)) + , _ctx (Cairo::Context::create (_surface)) + , ctx (_ctx->cobj ()) {} + + ~ImageSurface () {} + + /** + * Set this surface as source for another context. + * This allows to draw this surface + */ + void set_as_source (Cairo::Context* c, int x, int y) { + _surface->flush (); + c->set_source (_surface, x, y); + } + + /** + * Returns a context object to perform operations on the surface + */ + Cairo::Context* context () { + return (Cairo::Context *)&ctx; + } + + /** + * Returns the stride of the image surface in bytes (or 0 if surface is not + * an image surface). The stride is the distance in bytes from the beginning + * of one row of the image data to the beginning of the next row. + */ + int get_stride () const { + return _surface->get_stride (); + } + + /** Gets the width of the ImageSurface in pixels */ + int get_width () const { + return _surface->get_width (); + } + + /** Gets the height of the ImageSurface in pixels */ + int get_height () const { + return _surface->get_height (); + } + + /** + * Get a pointer to the data of the image surface, for direct + * inspection or modification. + * + * Return value: a pointer to the image data of this surface or NULL + * if @surface is not an image surface. + * + */ + unsigned char* get_data () { + return _surface->get_data (); + } + + /** Tells cairo to consider the data buffer dirty. + * + * In particular, if you've created an ImageSurface with a data buffer that + * you've allocated yourself and you draw to that data buffer using means + * other than cairo, you must call mark_dirty() before doing any additional + * drawing to that surface with cairo. + * + * Note that if you do draw to the Surface outside of cairo, you must call + * flush() before doing the drawing. + */ + void mark_dirty () { + _surface->mark_dirty (); + } + + /** Marks a rectangular area of the given surface dirty. + * + * @param x X coordinate of dirty rectangle + * @param y Y coordinate of dirty rectangle + * @param width width of dirty rectangle + * @param height height of dirty rectangle + */ + void mark_dirty (int x, int y, int width, int height) { + _surface->mark_dirty (x, y, width, height); + } + + private: + Cairo::RefPtr _surface; + Cairo::RefPtr _ctx; + Cairo::Context ctx; +}; + +class PangoLayout { + public: + /** Create a new PangoLayout Text Display + * @param c CairoContext for the layout + * @param font_name a font-description e.g. "Mono 8px" + */ + PangoLayout (Cairo::Context* c, std::string font_name) { + ::PangoLayout* pl = pango_cairo_create_layout (c->cobj ()); + _layout = Glib::wrap (pl); + Pango::FontDescription fd (font_name); + _layout->set_font_description (fd); + } + + ~PangoLayout () {} + + /** Gets the text in the layout. The returned text should not + * be freed or modified. + * + * @return The text in the @a layout. + */ + std::string get_text () const { + return _layout->get_text (); + } + /** Set the text of the layout. + * @param text The text for the layout. + */ + void set_text (const std::string& text) { + _layout->set_text (text); + } + + /** Sets the layout text and attribute list from marked-up text (see markup format). + * Replaces the current text and attribute list. + * @param markup Some marked-up text. + */ + void set_markup (const std::string& markup) { + _layout->set_markup (markup); + } + + /** Sets the width to which the lines of the Pango::Layout should wrap or + * ellipsized. The default value is -1: no width set. + * + * @param width The desired width in Pango units, or -1 to indicate that no + * wrapping or ellipsization should be performed. + */ + void set_width (int width) { + _layout->set_width (width * PANGO_SCALE); + } + + /** Gets the width to which the lines of the Pango::Layout should wrap. + * + * @return The width in Pango units, or -1 if no width set. + */ + int get_width () const { + return _layout->get_width () / PANGO_SCALE; + } + + /** Sets the type of ellipsization being performed for @a layout. + * Depending on the ellipsization mode @a ellipsize text is + * removed from the start, middle, or end of text so they + * fit within the width and height of layout set with + * set_width() and set_height(). + * + * If the layout contains characters such as newlines that + * force it to be layed out in multiple paragraphs, then whether + * each paragraph is ellipsized separately or the entire layout + * is ellipsized as a whole depends on the set height of the layout. + * See set_height() for details. + * + * @param ellipsize The new ellipsization mode for @a layout. + */ + void set_ellipsize (Pango::EllipsizeMode ellipsize) { + _layout->set_ellipsize (ellipsize); + } + + /** Gets the type of ellipsization being performed for @a layout. + * See set_ellipsize() + * + * @return The current ellipsization mode for @a layout. + * + * Use is_ellipsized() to query whether any paragraphs + * were actually ellipsized. + */ + Pango::EllipsizeMode get_ellipsize () const { + return _layout->get_ellipsize (); + } + + /** Queries whether the layout had to ellipsize any paragraphs. + * + * This returns true if the ellipsization mode for @a layout + * is not Pango::ELLIPSIZE_NONE, a positive width is set on @a layout, + * and there are paragraphs exceeding that width that have to be + * ellipsized. + * + * @return true if any paragraphs had to be ellipsized, false + * otherwise. + */ + bool is_ellipsized () const { + return _layout->is_ellipsized (); + } + + /** Sets the wrap mode; the wrap mode only has effect if a width + * is set on the layout with set_width(). + * To turn off wrapping, set the width to -1. + * + * @param wrap The wrap mode. + */ + void set_wrap (Pango::WrapMode wrap) { + _layout->set_width (wrap); + } + + /** Gets the wrap mode for the layout. + * + * Use is_wrapped() to query whether any paragraphs + * were actually wrapped. + * + * @return Active wrap mode. + */ + Pango::WrapMode get_wrap () const { + return _layout->get_wrap (); + } + + /** Queries whether the layout had to wrap any paragraphs. + * + * This returns true if a positive width is set on @a layout, + * ellipsization mode of @a layout is set to Pango::ELLIPSIZE_NONE, + * and there are paragraphs exceeding the layout width that have + * to be wrapped. + * + * @return true if any paragraphs had to be wrapped, false + * otherwise. + */ + bool is_wrapped () const { + return _layout->is_wrapped (); + } + + /** Determines the logical width and height of a Pango::Layout + * in device units. + */ + int get_pixel_size (lua_State *L) { + int width, height; + _layout->get_pixel_size (width, height); + luabridge::Stack::push (L, width); + luabridge::Stack::push (L, height); + return 2; + } + + + /** Draws a Layout in the specified Cairo @a context. The top-left + * corner of the Layout will be drawn at the current point of the + * cairo context. + * + * @param context A Cairo context. + */ + void show_in_cairo_context (Cairo::Context* c) { + pango_cairo_update_layout (c->cobj (), _layout->gobj()); + pango_cairo_show_layout (c->cobj (), _layout->gobj()); + } + + private: + Glib::RefPtr _layout; +}; + +}; // namespace + +//////////////////////////////////////////////////////////////////////////////// namespace LuaSignal { @@ -181,6 +453,51 @@ LuaInstance::bind_cairo (lua_State* L) .addConst ("Add", CAIRO_OPERATOR_ADD) .endNamespace () + .beginNamespace ("Format") + .addConst ("ARGB32", CAIRO_FORMAT_ARGB32) + .addConst ("RGB24", CAIRO_FORMAT_RGB24) + .endNamespace () + + .beginClass ("ImageSurface") + .addConstructor () + .addFunction ("set_as_source", &LuaCairo::ImageSurface::set_as_source) + .addFunction ("context", &LuaCairo::ImageSurface::context) + .addFunction ("get_stride", &LuaCairo::ImageSurface::get_stride) + .addFunction ("get_width", &LuaCairo::ImageSurface::get_width) + .addFunction ("get_height", &LuaCairo::ImageSurface::get_height) + //.addFunction ("get_data", &LuaCairo::ImageSurface::get_data) // uint8_t* array is n/a + .endClass () + + .beginClass ("PangoLayout") + .addConstructor () + .addCFunction ("get_pixel_size", &LuaCairo::PangoLayout::get_pixel_size) + .addFunction ("get_text", &LuaCairo::PangoLayout::get_text) + .addFunction ("set_text", &LuaCairo::PangoLayout::set_text) + .addFunction ("show_in_cairo_context", &LuaCairo::PangoLayout::show_in_cairo_context) + .addFunction ("set_markup", &LuaCairo::PangoLayout::set_markup) + .addFunction ("set_width", &LuaCairo::PangoLayout::set_width) + .addFunction ("set_ellipsize", &LuaCairo::PangoLayout::set_ellipsize) + .addFunction ("get_ellipsize", &LuaCairo::PangoLayout::get_ellipsize) + .addFunction ("is_ellipsized", &LuaCairo::PangoLayout::is_ellipsized) + .addFunction ("set_wrap", &LuaCairo::PangoLayout::set_wrap) + .addFunction ("get_wrap", &LuaCairo::PangoLayout::get_wrap) + .addFunction ("is_wrapped", &LuaCairo::PangoLayout::is_wrapped) + .endClass () + + /* enums */ + .beginNamespace ("EllipsizeMode") + .addConst ("None", Pango::ELLIPSIZE_NONE) + .addConst ("Start", Pango::ELLIPSIZE_START) + .addConst ("Middle", Pango::ELLIPSIZE_MIDDLE) + .addConst ("End", Pango::ELLIPSIZE_END) + .endNamespace () + + .beginNamespace ("WrapMode") + .addConst ("Word", Pango::WRAP_WORD) + .addConst ("Char", Pango::WRAP_CHAR) + .addConst ("WordChar", Pango::WRAP_WORD_CHAR) + .endNamespace () + .endNamespace (); /* Lua/cairo bindings operate on Cairo::Context, there is no Cairo::RefPtr wrapper [yet]. @@ -685,7 +1002,7 @@ LuaInstance::session_going_away () int LuaInstance::set_state (const XMLNode& node) { - LocaleGuard lg (X_("C")); + LocaleGuard lg; XMLNode* child; if ((child = find_named_node (node, "ActionScript"))) { @@ -791,7 +1108,7 @@ LuaInstance::interactive_add (LuaScriptInfo::ScriptType type, int id) XMLNode& LuaInstance::get_action_state () { - LocaleGuard lg (X_("C")); + LocaleGuard lg; std::string saved; { luabridge::LuaRef savedstate ((*_lua_save)());