/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HDR_layViewObject #define HDR_layViewObject #include "laybasicCommon.h" #include #include #include #include #include #include #include #include #include "tlObjectCollection.h" #include "tlVariant.h" #include "dbTrans.h" #include "dbBox.h" #include "layViewOp.h" #include "layCursor.h" #include "layBitmapRenderer.h" class QMouseEvent; class QImage; class QDragEnterEvent; class QDragMoveEvent; class QDragLeaveEvent; class QDropEvent; class QMimeData; namespace lay { class Viewport; class ViewObjectWidget; class ViewObjectCanvas; class CanvasPlane; class Bitmap; LAYBASIC_PUBLIC const char *drag_drop_mime_type (); /** * @brief A helper class required to store the drag/drop data * * Drag/drop data is basically a collection of key/value pairs. * A category string is provided to identify the kind of data. */ class LAYBASIC_PUBLIC DragDropDataBase { public: /** * @brief Default constructor */ DragDropDataBase () { } /** * @brief Dtor */ virtual ~DragDropDataBase () { } /** * @brief Serializes itself to an QByteArray */ virtual QByteArray serialized () const = 0; /** * @brief Try deserialization from an QByteArray * * Returns false, if deserialization failed. */ virtual bool deserialize (const QByteArray &ba) = 0; /** * @brief Create a QMimeData object from the object */ QMimeData *to_mime_data () const; }; /** * @brief Drag/drop data for a cell */ class LAYBASIC_PUBLIC CellDragDropData : public DragDropDataBase { public: /** * @brief Default ctor */ CellDragDropData () : mp_layout (0), m_cell_index (0) { // .. nothing yet .. } /** * @brief Specifies drag & drop of a cell * * @param layout the layout where the cell lives in * @param cell_index The index of the cell */ CellDragDropData (const db::Layout *layout, db::cell_index_type cell_index) : mp_layout (layout), m_cell_index (cell_index) { // .. nothing yet .. } /** * @brief Gets the layout object where the cell lives in */ const db::Layout *layout () const { return mp_layout; } /** * @brief Gets the index of the cell */ db::cell_index_type cell_index () const { return m_cell_index; } /** * @brief Serializes itself to an QByteArray */ virtual QByteArray serialized () const; /** * @brief Try deserialization from an QByteArray * * Returns false, if deserialization failed. */ bool deserialize (const QByteArray &ba); private: const db::Layout *mp_layout; db::cell_index_type m_cell_index; }; /** * @brief A view service * * A view service is providing editing or informational services * on the canvas. * A service can be "active" by requesting mouse * events through a trigger by "select" or "activate" after * which a "grab_mouse" redirects all mouse events to the * view service. * This is an interface that should/must be implemented * by the super class. */ class LAYBASIC_PUBLIC ViewService { public: /** * @brief Constructor */ ViewService (ViewObjectWidget *widget = 0); /** * @brief Destructor */ virtual ~ViewService (); /** * @brief Key press event handler * * This method will be called by the ViewObjectWidget object to * dispatch key press events. * * The active service will receive that call and should return true * if the event is taken. Otherwise the event will be passed further. */ virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/) { return false; } /** * @brief The drag enter event * * If something is dragged into the view, this event is triggered. * p will be the position of the event. * * The implementation should return true, if the drop is accepted. */ virtual bool drag_enter_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief The drag move event */ virtual bool drag_move_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief The drag leave event */ virtual void drag_leave_event () { } /** * @brief The drop event */ virtual bool drop_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief Mouse press event handler * * This method will be called by the ViewObjectWidget object to * dispatch mouse press events. First, the objects that grabbed * the mouse will receive the events with prio "true" in the reverse order they * grabbed the mouse (last one first). This loop will terminate * if one of the objects has returned "true". * If no service has grabbed the mouse or none of them was taking the * event, the active service receives the event with prio set to "true". * If this is not the case, then all objects will receive * the event with "prio" set to "false", unless one of the objects * returns "true". * This event is not sent immediately when the mouse button is pressed * but when a signification movement for the mouse cursor away from the * original position is detected. If the mouse button is released before * that, a mouse_clicked_event is sent rather than a press-move-release * sequence. * * @param p The point at which the button was pressed * @param buttons A ored combination of ShiftButton etc. * @return True to terminate dispatcher */ virtual bool mouse_press_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Mouse single-click event handler * * Analogeous to mouse_press_event (see above), but sent if the mouse was not moved. * The click event is coincident with the release of the mouse button. */ virtual bool mouse_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Mouse double-click event handler * * Analogeous to mouse_press_event (see above), but sent if a double-click was detected. */ virtual bool mouse_double_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Mouse leave event handler */ virtual bool leave_event (bool /*prio*/) { return false; } /** * @brief Mouse enter event handler */ virtual bool enter_event (bool /*prio*/) { return false; } /** * @brief Mouse move event handler * * Analogeous to mouse_press_event (see above). */ virtual bool mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Mouse release event handler * * Analogeous to mouse_press_event (see above). */ virtual bool mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Wheel event handler * * Analogeous to mouse_press_event (see above). * * @param delta The rotation angle in eigths of a degree * @param horizonal True, if the horizontal wheel was turned * @param p The position where the mouse currently is at (in micron units) */ virtual bool wheel_event (int /*delta*/, bool /*horizontal*/, const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/) { return false; } /** * @brief Set the mouse cursor * * This method can be called from a mouse event handler to set the cursor for the view. * It is only effective if called from a mouse event handler. */ void set_cursor (lay::Cursor::cursor_shape cursor); /** * @brief Do an update * * This method is supposed to update the internals, * specifically upon changing of the coordinate system */ virtual void update () { // The default implementation does nothing } /** * @brief Accessor to the widget pointer */ ViewObjectWidget *widget () const { return mp_widget; } /** * @brief This method is called on the service that got activated */ virtual void activated () { } /** * @brief This method is called on the service that got deactivated */ virtual void deactivated () { } /** * @brief This method is called to set the background and text (foreground) color */ virtual void set_colors (QColor /*background*/, QColor /*text*/) { } /** * @brief This method is called when a drag operation should be cancelled */ virtual void drag_cancel () { } /** * @brief Enable or disable a sevice * * If a service is disabled, it will not receive mouse events */ void enable (bool en); /** * @brief Returns true, if the service is enabled */ bool enabled () const { return m_enabled; } private: friend class ViewObjectWidget; ViewObjectWidget *mp_widget; bool m_abs_grab; bool m_enabled; }; /** * @brief The background view object * * A background view object is an object that is painted onto the * canvas background and is contained by the view object widget. * This is an interface that should/must be implemented * by the super class. */ class LAYBASIC_PUBLIC BackgroundViewObject : virtual public tl::Object { public: /** * @brief The constructor * * @param widget The widget object that the object is shown on. * @param _static True, if the object is in frozen mode initially */ BackgroundViewObject (ViewObjectWidget *widget = 0); /** * @brief The destructor */ virtual ~BackgroundViewObject (); /** * @brief Render the object on the background * * This method is supposed to repaint the background part of the object * on the QImage provided in the canvas. */ virtual void render_bg (const Viewport &vp, ViewObjectCanvas &canvas) = 0; /** * @brief Accessor to the widget object pointer */ ViewObjectWidget *widget () const { return const_cast (mp_widget.get()); } /** * @brief Set the visibility state of the view object * * Invisible objects are not drawn */ void visible (bool vis); /** * @brief Tell the visibility state of the view object */ bool is_visible () const { return m_visible; } /** * @brief This method tells the widget to update the object on next repaint * * If the object is static, a "touch" is issued on the widget. Otherwise * just a update is issued, resulting in a repaint * This is the preferred method to tell that an object needs repainting. * It can be called multiple times without performance penalty. */ void redraw (); /** * @brief Z-Order property * * This property controls in which order the background objects are drawn: * those with a lower z-order value are drawn first. Thus, ones with the * higher value overwrite them. */ int z_order () const { return m_z_order; } /** * @brief Z-Order write accessor */ void z_order (int z); private: friend class ViewObjectWidget; BackgroundViewObject (const BackgroundViewObject &d); BackgroundViewObject &operator= (const BackgroundViewObject &d); tl::weak_ptr mp_widget; bool m_visible; int m_z_order; }; /** * @brief The view object * * A view object is an object that is painted onto the * canvas and is contained by the view object widget. * View objects can be static or non-static. Changing a * view object in the non-static case is somewhat more * efficient and is recommended for dynamic objects. * Static mode is entered with "freeze", non-static mode * with "thaw". * This is an interface that should/must be implemented * by the super class. */ class LAYBASIC_PUBLIC ViewObject : public tl::Object { public: /** * @brief The constructor * * @param widget The widget object that the object is shown on. * @param _static True, if the object is in frozen mode initially */ ViewObject (ViewObjectWidget *widget = 0, bool _static = true); /** * @brief The destructor */ virtual ~ViewObject (); /** * @brief Render the object on the planes provided by the canvas. * * This method is supposed to repaint the object on the plane * objects that the canvas can provide upon request with the plane * method. */ virtual void render (const Viewport &vp, ViewObjectCanvas &canvas) = 0; /** * @brief Accessor to the widget object pointer */ ViewObjectWidget *widget () const { return const_cast (mp_widget.get()); } /** * @brief Set the visibility state of the view object * * Invisible objects are not drawn */ void visible (bool vis); /** * @brief Tell the visibility state of the view object */ bool is_visible () const { return m_visible; } /** * @brief This method tells the widget to update the object on next repaint * * If the object is static, a "touch" is issued on the widget. Otherwise * just a update is issued, resulting in a repaint * This is the preferred method to tell that an object needs repainting. * It can be called multiple times without performance penalty. */ void redraw (); /** * @brief thaw this object * * This is a convenience function that avoids having to store a widget pointer */ void thaw (); /** * @brief freeze this object * * This is a convenience function that avoids having to store a widget pointer */ void freeze (); private: friend class ViewObjectWidget; ViewObject (const ViewObject &d); ViewObject &operator= (const ViewObject &d); tl::weak_ptr mp_widget; bool m_static; bool m_visible; }; /** * @brief Describes the button state (supposed to be ored) */ enum ButtonState { ShiftButton = 1, ControlButton = 2, AltButton = 4, LeftButton = 8, MidButton = 16, RightButton = 32 }; /** * @brief The view object container * * The container holds the view objects and * manages the the mouse event distribution and * painting. */ class LAYBASIC_PUBLIC ViewObjectWidget : public QWidget, public tl::Object { public: typedef tl::weak_collection::iterator object_iterator; typedef tl::weak_collection::iterator background_object_iterator; typedef std::list::const_iterator service_iterator; typedef std::list::const_iterator mouse_receivers_iterator; /** * @brief ctor */ ViewObjectWidget (QWidget *view, const char *name); /** * @brief dtor */ ~ViewObjectWidget (); /** * @brief Cancel all drag operations */ void drag_cancel (); /** * @brief CanvasPlane rendering * * This method is supposed to render the object on the planes provided * by the planes() method. * * @param vp The viewport * @param st True, if only static (frozen) objects are to be redrawn */ void do_render (const Viewport &vp, ViewObjectCanvas &canvas, bool st); /** * @brief Background rendering * * Objects on the background must provide a paint method that paints * them on the canvas directly. * * @param vp The viewport * @param canvas The canvas where to paint on */ void do_render_bg (const Viewport &vp, ViewObjectCanvas &canvas); /** * @brief Query if any "static" object needs to be redrawn * * To reset this flag, call do_render with "st" set to true. */ bool needs_update_static () const { return m_needs_update_static; } /** * @brief Query if the background needs to be redrawn * * To reset this flag, call do_render_bg */ bool needs_update_bg () const { return m_needs_update_bg; } /** * @brief Puts the object into "static" mode */ void freeze (ViewObject *obj); /** * @brief Puts the object into "non-static" mode */ void thaw (ViewObject *obj); /** * @brief Marks the widget for update * * Beside issuing an "update" request, the widget is also * marked for "static-update", which shall redraw all static * objects also. */ void touch (); /** * @brief Marks the widget background for update * * Beside issuing an "update" request, the widget is also * marked for "bg-update", which shall redraw including the background. */ void touch_bg (); /** * @brief Grab the mouse for the object * * This will put the object into the list of objects interested * into mouse events with high priority (prio = true on mouse_* events). * Objects with dragging semantics (press-drag-release) may request * "absolute" mouse grab. This way, all mouse events are passed to the * object. The grab should then in any case be released on mouse button * release. */ void grab_mouse (ViewService *obj, bool abs); /** * @brief Remove the object from the list of objects that grabbed the mouse * * This will also remove any absolute grabs if there is no other object * that needs this. */ void ungrab_mouse (ViewService *obj); /** * @brief Set the mouse cursor * * This method can be called from a mouse event handler to set the cursor for the view. * It is only effective if called from a mouse event handler. */ void set_cursor (lay::Cursor::cursor_shape cursor); /** * @brief Determine the active service */ lay::ViewService *active_service () const { return const_cast (mp_active_service); } /** * @brief Activate a service * * The active service will be the first to receive mouse events * with prio==true, unless the mouse is grabbed and the event is * taken by the grabber. * Passing 0 deactivates all services. The service currently active * will get a "deactivated" signal. */ void activate (lay::ViewService *service); /** * @brief Services iterator: begin */ service_iterator begin_services () { return m_services.begin (); } /** * @brief Services iterator: end */ service_iterator end_services () { return m_services.end (); } /** * @brief Background objects iterator: begin */ background_object_iterator begin_background_objects () { return m_background_objects.begin (); } /** * @brief Background objects iterator: end */ background_object_iterator end_background_objects () { return m_background_objects.end (); } /** * @brief Objects iterator: begin */ object_iterator begin_objects () { return m_objects.begin (); } /** * @brief Objects iterator: end */ object_iterator end_objects () { return m_objects.end (); } /** * @brief Remaining leave event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void leave_event () { } /** * @brief Remaining enter event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void enter_event () { } /** * @brief Remaining key event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void key_event (unsigned int /*key*/, unsigned int /*buttons*/) { } /** * @brief The drag enter event * * If something is dragged into the view, this event is triggered. * p will be the position of the event. * * The implementation should return true, if the drop is accepted. */ virtual bool drag_enter_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief The drag move event */ virtual bool drag_move_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief The drag leave event */ virtual void drag_leave_event () { } /** * @brief The drop event */ virtual bool drop_event (const db::DPoint & /*p*/, const DragDropDataBase * /*data*/) { return false; } /** * @brief Remaining mouse double click event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void mouse_double_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Remaining single mouse click event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void mouse_click_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Remaining mouse press event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void mouse_press_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Remaining mouse release event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Remaining mouse move event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void mouse_move_event (const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Remaining wheel event handler * * This event handler is called if no ViewObject requested handling * of this event. */ virtual void wheel_event (int /*delta*/, bool /*horizontal*/, const db::DPoint & /*p*/, unsigned int /*buttons*/) { } /** * @brief Get the transformation for mouse events */ const db::DCplxTrans &mouse_event_trans () const { return m_trans; } /** * @brief Deliver an iterator for the mouse receivers (begin) */ mouse_receivers_iterator begin_mouse_receivers () const { return m_grabbed.begin (); } /** * @brief Deliver an iterator for the mouse receivers (end) */ mouse_receivers_iterator end_mouse_receivers () const { return m_grabbed.end (); } /** * @brief Get the viewport for mouse events */ db::DBox mouse_event_viewport () const; /** * @brief Set the default cursor * * The default cursor is shown when no mouse event sets the cursor. */ void set_default_cursor (lay::Cursor::cursor_shape cursor); protected: /** * @brief Qt focus event handler */ bool focusNextPrevChild (bool next); /** * @brief Qt keyboard event handler */ void keyPressEvent (QKeyEvent *e); /** * @brief Qt mouse move event handler */ void mouseMoveEvent (QMouseEvent *e); /** * @brief Qt mouse leave event handler */ void leaveEvent (QEvent *e); /** * @brief Qt mouse enter event handler */ void enterEvent (QEvent *e); /** * @brief Qt mouse button press event handler */ void mousePressEvent (QMouseEvent *e); /** * @brief Qt mouse button double-click event handler */ void mouseDoubleClickEvent (QMouseEvent *e); /** * @brief Qt mouse button release event handler */ void mouseReleaseEvent (QMouseEvent *e); /** * @brief Qt drag enter event handler */ void dragEnterEvent (QDragEnterEvent *event); /** * @brief Qt drag leave event handler */ void dragLeaveEvent (QDragLeaveEvent *event); /** * @brief Qt drag enter event handler */ void dragMoveEvent (QDragMoveEvent *event); /** * @brief Qt drop event handler */ void dropEvent (QDropEvent *event); /** * @brief Qt mouse wheel event handler */ void wheelEvent (QWheelEvent *e); /** * @brief Set the transformation for mouse events */ void mouse_event_trans (const db::DCplxTrans &trans); private: friend class lay::ViewObject; friend class lay::ViewService; friend class lay::BackgroundViewObject; tl::weak_collection m_objects; tl::weak_collection m_background_objects; std::list m_services; std::list m_grabbed; bool m_needs_update_static; bool m_needs_update_bg; lay::ViewService *mp_active_service; db::DCplxTrans m_trans; QPoint m_mouse_pos; QPoint m_mouse_pressed; bool m_mouse_pressed_state; unsigned int m_mouse_buttons; bool m_in_mouse_move; lay::Cursor::cursor_shape m_cursor, m_default_cursor; void do_mouse_move (); void begin_mouse_event (lay::Cursor::cursor_shape cursor = lay::Cursor::keep); void end_mouse_event (); void objects_changed (); /** * @brief Register a service * * This method is called by the service constructor and registers the service in the widget. */ void register_service (lay::ViewService *); /** * @brief Register a service * * This method is called by the service destructor and unregisters the service in the widget. */ void unregister_service (lay::ViewService *svc); }; /** * @brief The canvas interface * * The canvas provides ways and attributes that allow the view objects to render * themselves. The basic functionality of this interface is to provide planes * for painting. */ class LAYBASIC_PUBLIC ViewObjectCanvas { public: /** * The destructor */ virtual ~ViewObjectCanvas () { } /** * @brief Background color property: background color of the canvas */ virtual QColor background_color () const = 0; /** * @brief Foreground color property: foreground color of the canvas (some "contrast" color to background) */ virtual QColor foreground_color () const = 0; /** * @brief Active color property: color of active elements on the canvas (some "contrast" color to background and different from foreground) */ virtual QColor active_color () const = 0; /** * @brief Get the resolution * * The resolution describes the size of one pixel in relation to "one line width". "One line width" is the unit * of the drawing and describes the width of a "one unit" wide line. In that sense, the resolution is the reciprocal * of a "one unit" line's width in pixels. */ virtual double resolution () const = 0; /** * @brief CanvasPlane provider * * This method is used by the view objects to obtain the planes * they should paint themselves on. * A style can be specified that determines how the plane will * be displayed. CanvasPlanes may be shared if the style is identical. * The plane index of the ViewOp is not used. */ virtual lay::CanvasPlane *plane (const lay::ViewOp &style) = 0; /** * @brief CanvasPlane provider for a sequence of operations on the same plane * * This method is used by the view objects to obtain the planes * they should paint themselves on. * A operator vector can be specified that determines how the plane will * be displayed. The operators are executed in the order given on the same plane. * CanvasPlanes may be shared if the styles are identical. * The plane index of the ViewOp is not used. */ virtual lay::CanvasPlane *plane (const std::vector &style) = 0; /** * @brief Provide the renderer */ virtual lay::Renderer &renderer () = 0; /** * @brief Sort the planes in the painting order */ virtual void sort_planes () = 0; }; /** * @brief The canvas interface * * The canvas provides ways and attributes that allow the view objects to render * themselves. The basic functionality of this interface is to provide planes * for painting. */ class LAYBASIC_PUBLIC BitmapViewObjectCanvas : public ViewObjectCanvas { public: /** * @brief Constructor */ BitmapViewObjectCanvas (); /** * @brief Constructor */ BitmapViewObjectCanvas (unsigned int width, unsigned int height, double resolution); /** * @brief The destructor */ virtual ~BitmapViewObjectCanvas (); /** * @brief CanvasPlane provider * * This method is used by the view objects to obtain the planes * they should paint themselves on. * A style can be specified that determines how the plane will * be displayed. CanvasPlanes may be shared if the style is identical. * The plane index of the ViewOp is not used. */ virtual lay::CanvasPlane *plane (const lay::ViewOp &style); /** * @brief CanvasPlane provider for a sequence of operations on the same plane * * This method is used by the view objects to obtain the planes * they should paint themselves on. * A operator vector can be specified that determines how the plane will * be displayed. The operators are executed in the order given on the same plane. * CanvasPlanes may be shared if the styles are identical. * The plane index of the ViewOp is not used. */ virtual lay::CanvasPlane *plane (const std::vector &style); /** * @brief Sort the planes in the painting order */ virtual void sort_planes (); /** * @brief Provide the renderer */ virtual lay::Renderer &renderer () { return m_renderer; } /** * @brief Get the resolution */ virtual double resolution () const { return m_resolution; } /** * @brief Return the number of bitmaps stored so far */ size_t fg_bitmaps () const { return mp_fg_bitmaps.size (); } /** * @brief Return the foreground bitmap with the given index * * The returned pointer may be 0. The index must be less than the one returned * by fg_bitmaps (). */ const lay::Bitmap *fg_bitmap (unsigned int i) const { return mp_fg_bitmaps [i]; } /** * @brief Direct access to the bitmap pointers */ const std::vector &fg_bitmap_vector () const { return mp_fg_bitmaps; } /** * @brief Return the foreground plane style with the given index * * The index must be less than the one returned by fg_planes (). */ const lay::ViewOp &fg_style (unsigned int i) const { return m_fg_view_ops [i]; } /** * @brief Direct access to the styles vector */ const std::vector &fg_view_op_vector () const { return m_fg_view_ops; } /** * @brief Clear the foreground bitmaps and all associated information */ void clear_fg_bitmaps (); /** * @brief Return the background image */ virtual QImage &bg_image () = 0; /** * @brief Set the width and height and resolution */ void set_size (unsigned int width, unsigned int height, double resolution); /** * @brief Set the width and height */ void set_size (unsigned int width, unsigned int height); /** * @brief Set the resolution */ void set_size (double resolution); /** * @brief Get the width */ unsigned int canvas_width () const { return m_width; } /** * @brief Get the height */ unsigned int canvas_height () const { return m_height; } private: std::map m_fg_bitmap_table; std::map , unsigned int> m_fgv_bitmap_table; std::vector mp_fg_bitmaps; std::vector mp_alloc_bitmaps; std::vector m_fg_view_ops; lay::BitmapRenderer m_renderer; unsigned int m_width, m_height; double m_resolution; }; } // namespace lay #endif