klayout/src/laybasic/layViewObject.cc

1095 lines
26 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2016 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
*/
#include <QMouseEvent>
#include <QWheelEvent>
#include <QKeyEvent>
#include <QMimeData>
#include "layViewObject.h"
#include "layCanvasPlane.h"
#include "layBitmap.h"
#include "tlException.h"
#include "tlAlgorithm.h"
#include "tlExceptions.h"
#include <memory>
namespace lay
{
// The distance by which the mouse must move in order to create a press/move/release
// event rather than a single click event:
const int click_tolerance = 5;
// ---------------------------------------------------------------
// Implementation of DragDropDataBase
const char *drag_drop_mime_type ()
{
return "application/klayout-ddd";
}
QMimeData *
DragDropDataBase::to_mime_data () const
{
QMimeData *mimeData = new QMimeData();
mimeData->setData (QString::fromUtf8 (drag_drop_mime_type ()), serialized ());
return mimeData;
}
// ---------------------------------------------------------------
// Implementation of CellDragDropData
QByteArray
CellDragDropData::serialized () const
{
QByteArray data;
QDataStream stream (&data, QIODevice::WriteOnly);
stream << QString::fromUtf8 ("CellDragDropData");
stream << (quintptr) mp_layout;
stream << m_cell_index;
return data;
}
bool
CellDragDropData::deserialize (const QByteArray &ba)
{
QDataStream stream (const_cast<QByteArray *> (&ba), QIODevice::ReadOnly);
QString tag;
stream >> tag;
if (tag == QString::fromUtf8 ("CellDragDropData")) {
quintptr p = 0;
stream >> p;
mp_layout = reinterpret_cast <const db::Layout *> (p);
stream >> m_cell_index;
return true;
} else {
return false;
}
}
// ---------------------------------------------------------------
// A helper function to convert a Qt modifier/buttons to klayout buttons
static unsigned int
qt_to_buttons (Qt::MouseButtons b, Qt::KeyboardModifiers m)
{
// this is a straightforward conversion with the excepton that
// MetaModifyer+LeftButton is taken as a RightButton
// This is useful on MAC OX for people wizh a one-button mouse.
// They can do a right click by doing a ctrl-leftclick.
// BTW: On a MAC's keyboard, the cmd-key is received here as a ControlModifier
// while the ctrl-key is received as a MetaModifier
return ((b & Qt::LeftButton) ? ((m & Qt::MetaModifier) ? RightButton : LeftButton) : 0) |
((b & Qt::MidButton) ? MidButton : 0) |
((b & Qt::RightButton) ? RightButton : 0) |
((m & Qt::ShiftModifier) != 0 ? ShiftButton : 0) |
((m & Qt::ControlModifier) != 0 ? ControlButton : 0) |
((m & Qt::AltModifier) != 0 ? AltButton : 0);
}
// ---------------------------------------------------------------
// BackgroundViewObject implementation
BackgroundViewObject::BackgroundViewObject (ViewObjectWidget *widget)
: mp_widget (widget), m_visible (true), m_z_order (0)
{
if (widget) {
widget->m_background_objects.push_back (this);
redraw ();
}
}
BackgroundViewObject::~BackgroundViewObject ()
{
redraw ();
}
void
BackgroundViewObject::visible (bool vis)
{
if (vis != m_visible) {
m_visible = vis;
redraw ();
}
}
void
BackgroundViewObject::redraw ()
{
if (widget ()) {
widget ()->touch_bg ();
}
}
void
BackgroundViewObject::z_order (int z)
{
if (z != m_z_order) {
m_z_order = z;
redraw ();
}
}
// ---------------------------------------------------------------
// ViewObject implementation
ViewObject::ViewObject (ViewObjectWidget *widget, bool _static)
: mp_widget (widget), m_static (_static), m_visible (true)
{
if (widget) {
widget->m_objects.push_back (this);
redraw ();
}
}
ViewObject::~ViewObject ()
{
redraw ();
}
void
ViewObject::visible (bool vis)
{
if (vis != m_visible) {
m_visible = vis;
redraw ();
}
}
void
ViewObject::redraw ()
{
if (widget ()) {
if (m_static) {
widget ()->touch ();
} else {
widget ()->update ();
}
}
}
void
ViewObject::thaw ()
{
if (widget ()) {
widget ()->thaw (this);
}
}
void
ViewObject::freeze ()
{
if (widget ()) {
widget ()->freeze (this);
}
}
// ---------------------------------------------------------------
// ViewService implementation
ViewService::ViewService (ViewObjectWidget *widget)
: mp_widget (widget), m_abs_grab (false), m_enabled (true)
{
if (widget) {
widget->register_service (this);
}
}
ViewService::~ViewService ()
{
if (mp_widget) {
mp_widget->unregister_service (this);
}
mp_widget = 0;
}
void
ViewService::enable (bool en)
{
m_enabled = en;
}
void
ViewService::set_cursor (lay::Cursor::cursor_shape cursor)
{
mp_widget->set_cursor (cursor);
}
// ---------------------------------------------------------------
// ViewObject implementation
ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
: QWidget (parent),
m_needs_update_static (false),
m_needs_update_bg (false),
mp_active_service (0),
m_mouse_pressed_state (false),
m_mouse_buttons (0),
m_in_mouse_move (false),
m_cursor (lay::Cursor::none),
m_default_cursor (lay::Cursor::none)
{
setMouseTracking (true);
setObjectName (QString::fromUtf8 (name));
setAcceptDrops (true);
m_objects.changed ().add (this, &ViewObjectWidget::objects_changed);
}
ViewObjectWidget::~ViewObjectWidget ()
{
// release any mouse grabs now
while (m_grabbed.begin () != m_grabbed.end ()) {
ungrab_mouse (*m_grabbed.begin ());
}
while (! m_services.empty ()) {
delete m_services.front ();
}
}
void
ViewObjectWidget::register_service (lay::ViewService *svc)
{
m_services.push_back (svc);
}
void
ViewObjectWidget::unregister_service (lay::ViewService *svc)
{
if (mp_active_service == svc) {
mp_active_service = 0;
}
// make sure the service no longer has the mouse
ungrab_mouse (svc);
for (std::list<lay::ViewService *>::iterator s = m_services.begin(); s != m_services.end (); ++s) {
if (*s == svc) {
m_services.erase (s);
break;
}
}
}
void
ViewObjectWidget::activate (lay::ViewService *service)
{
if (mp_active_service != service) {
if (mp_active_service) {
BEGIN_PROTECTED
mp_active_service->deactivated ();
END_PROTECTED
}
mp_active_service = 0;
for (std::list<lay::ViewService *>::iterator s = m_services.begin(); s != m_services.end (); ++s) {
if (*s == service) {
mp_active_service = service;
break;
}
}
if (mp_active_service) {
BEGIN_PROTECTED
mp_active_service->activated ();
END_PROTECTED
}
}
}
void
ViewObjectWidget::set_cursor (lay::Cursor::cursor_shape cursor)
{
m_cursor = cursor;
}
void
ViewObjectWidget::set_default_cursor (lay::Cursor::cursor_shape cursor)
{
if (cursor != m_default_cursor) {
m_default_cursor = cursor;
if (m_cursor == lay::Cursor::none) {
if (m_default_cursor == lay::Cursor::none) {
unsetCursor ();
} else {
setCursor (lay::Cursor::qcursor (m_default_cursor));
}
}
}
}
void
ViewObjectWidget::begin_mouse_event (lay::Cursor::cursor_shape cursor)
{
m_cursor = cursor;
}
void
ViewObjectWidget::end_mouse_event ()
{
if (m_cursor == lay::Cursor::none) {
if (m_default_cursor == lay::Cursor::none) {
unsetCursor ();
} else {
setCursor (lay::Cursor::qcursor (m_default_cursor));
}
} else if (m_cursor != lay::Cursor::keep) {
setCursor (lay::Cursor::qcursor (m_cursor));
}
}
void
ViewObjectWidget::keyPressEvent (QKeyEvent *e)
{
BEGIN_PROTECTED
unsigned int buttons = qt_to_buttons (Qt::MouseButtons (), e->modifiers ());
bool done = false;
if (mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->key_event ((unsigned int) e->key(), buttons));
}
if (! done) {
key_event ((unsigned int) e->key (), buttons);
}
END_PROTECTED
}
DragDropDataBase *get_drag_drop_data (const QMimeData *data)
{
if (! data || ! data->hasFormat (QString::fromUtf8 (drag_drop_mime_type ()))) {
return 0;
}
QByteArray ba = data->data (QString::fromUtf8 (drag_drop_mime_type ()));
// TODO: provide some global mechanism to register drag & drop classes
std::auto_ptr<DragDropDataBase> cd (new CellDragDropData ());
if (cd->deserialize (ba)) {
return cd.release ();
}
// TODO: more ...
return 0;
}
void
ViewObjectWidget::dragEnterEvent (QDragEnterEvent *event)
{
BEGIN_PROTECTED
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
if (dd) {
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
bool done = drag_enter_event (p, dd);
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = (*svc)->drag_enter_event (p, dd);
svc = next;
}
if (done) {
event->acceptProposedAction ();
}
}
END_PROTECTED
}
void
ViewObjectWidget::dragLeaveEvent (QDragLeaveEvent * /*event*/)
{
BEGIN_PROTECTED
drag_leave_event ();
service_iterator svc = begin_services ();
while (svc != end_services ()) {
service_iterator next = svc;
++next;
(*svc)->drag_leave_event ();
svc = next;
}
END_PROTECTED
}
void
ViewObjectWidget::dragMoveEvent (QDragMoveEvent *event)
{
BEGIN_PROTECTED
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
if (dd) {
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
bool done = drag_move_event (p, dd);
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = (*svc)->drag_move_event (p, dd);
svc = next;
}
}
END_PROTECTED
}
void
ViewObjectWidget::dropEvent (QDropEvent *event)
{
BEGIN_PROTECTED
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
if (dd) {
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
bool done = drop_event (p, dd);
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = (*svc)->drop_event (p, dd);
svc = next;
}
}
END_PROTECTED
}
void
ViewObjectWidget::mouseMoveEvent (QMouseEvent *e)
{
BEGIN_PROTECTED
m_mouse_pos = e->pos ();
m_mouse_buttons = qt_to_buttons (e->buttons (), e->modifiers ());
do_mouse_move ();
END_PROTECTED
}
void
ViewObjectWidget::do_mouse_move ()
{
m_in_mouse_move = true;
if (m_mouse_pressed_state &&
(abs (m_mouse_pos.x () - m_mouse_pressed.x ()) > click_tolerance || abs (m_mouse_pos.y () - m_mouse_pressed.y ()) > click_tolerance)) {
begin_mouse_event (lay::Cursor::none);
m_mouse_pressed_state = false;
bool done = false;
db::DPoint p = m_trans.inverted () * db::DPoint (m_mouse_pressed.x (), height () - 1 - m_mouse_pressed.y ());
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->enabled () && (*g)->mouse_press_event (p, m_mouse_buttons, true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->mouse_press_event (p, m_mouse_buttons, true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->mouse_press_event (p, m_mouse_buttons, false));
svc = next;
}
if (! done) {
mouse_press_event (p, m_mouse_buttons);
}
end_mouse_event ();
}
if (! m_mouse_pressed_state) {
begin_mouse_event (lay::Cursor::none);
bool done = false;
db::DPoint p = m_trans.inverted () * db::DPoint (m_mouse_pos.x (), height () - 1 - m_mouse_pos.y ());
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->enabled () && (*g)->mouse_move_event (p, m_mouse_buttons, true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->mouse_move_event (p, m_mouse_buttons, true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->mouse_move_event (p, m_mouse_buttons, false));
svc = next;
}
if (! done) {
mouse_move_event (p, m_mouse_buttons);
}
end_mouse_event ();
}
m_in_mouse_move = false;
}
void
ViewObjectWidget::mouseDoubleClickEvent (QMouseEvent *e)
{
BEGIN_PROTECTED
begin_mouse_event (lay::Cursor::none);
setFocus ();
bool done = false;
m_mouse_pos = e->pos ();
m_mouse_pressed = e->pos ();
m_mouse_pressed_state = false;
unsigned int buttons = qt_to_buttons (e->buttons (), e->modifiers ());
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->m_enabled && (*g)->mouse_double_click_event (p, buttons, true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->mouse_double_click_event (p, buttons, true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->mouse_double_click_event (p, buttons, false));
svc = next;
}
if (! done) {
mouse_double_click_event (p, buttons);
}
end_mouse_event ();
END_PROTECTED
}
void
ViewObjectWidget::enterEvent (QEvent * /*event*/)
{
BEGIN_PROTECTED
begin_mouse_event ();
bool done = false;
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->enabled () && (*g)->enter_event (true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->enter_event (true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->enter_event (false));
svc = next;
}
if (! done) {
enter_event ();
}
end_mouse_event ();
END_PROTECTED
}
void
ViewObjectWidget::leaveEvent (QEvent * /*event*/)
{
BEGIN_PROTECTED
begin_mouse_event ();
bool done = false;
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->enabled () && (*g)->leave_event (true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->leave_event (true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->leave_event (false));
svc = next;
}
if (! done) {
leave_event ();
}
end_mouse_event ();
END_PROTECTED
}
void
ViewObjectWidget::wheelEvent (QWheelEvent *e)
{
BEGIN_PROTECTED
begin_mouse_event ();
e->ignore ();
bool done = false;
unsigned int buttons = qt_to_buttons (e->buttons (), e->modifiers ());
bool horizonal = (e->orientation () == Qt::Horizontal);
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
done = ((*g)->enabled () && (*g)->wheel_event (e->delta (), horizonal, p, buttons, true));
g = gg;
}
if (! done && mp_active_service) {
done = (mp_active_service->enabled () && mp_active_service->wheel_event (e->delta (), horizonal, p, buttons, true));
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
done = ((*svc)->enabled () && (*svc)->wheel_event (e->delta (), horizonal, p, buttons, false));
svc = next;
}
if (! done) {
wheel_event (e->delta (), horizonal, p, buttons);
}
end_mouse_event ();
END_PROTECTED
}
void
ViewObjectWidget::mousePressEvent (QMouseEvent *e)
{
setFocus ();
m_mouse_pos = e->pos ();
m_mouse_pressed = e->pos ();
m_mouse_buttons = qt_to_buttons (e->buttons (), e->modifiers ());
m_mouse_pressed_state = true;
}
void
ViewObjectWidget::mouseReleaseEvent (QMouseEvent *e)
{
BEGIN_PROTECTED
begin_mouse_event ();
bool done = false;
m_mouse_pos = e->pos ();
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
std::list<ViewService *>::iterator gg = g;
++gg;
if (m_mouse_pressed_state) {
done = (*g)->enabled () && (*g)->mouse_click_event (p, m_mouse_buttons, true);
} else {
done = (*g)->enabled () && (*g)->mouse_release_event (p, m_mouse_buttons, true);
}
g = gg;
}
if (! done && mp_active_service && mp_active_service->enabled ()) {
if (m_mouse_pressed_state) {
done = mp_active_service->mouse_click_event (p, m_mouse_buttons, true);
} else {
done = mp_active_service->mouse_release_event (p, m_mouse_buttons, true);
}
}
service_iterator svc = begin_services ();
while (svc != end_services () && !done) {
service_iterator next = svc;
++next;
if ((*svc)->enabled ()) {
if (m_mouse_pressed_state) {
done = (*svc)->mouse_click_event (p, m_mouse_buttons, false);
} else {
done = (*svc)->mouse_release_event (p, m_mouse_buttons, false);
}
}
svc = next;
}
if (! done) {
if (m_mouse_pressed_state) {
mouse_click_event (p, m_mouse_buttons);
} else {
mouse_release_event (p, m_mouse_buttons);
}
}
end_mouse_event ();
END_PROTECTED
m_mouse_pressed_state = false;
}
void
ViewObjectWidget::mouse_event_trans (const db::DCplxTrans &trans)
{
if (trans != m_trans) {
m_trans = trans;
// issue a move event in order to reposition the mouse in the new coordinate system
// since this may be called from within a mouse move event handler we need the recursion sentinel
if (! m_in_mouse_move) {
do_mouse_move ();
}
}
}
void
ViewObjectWidget::drag_cancel ()
{
for (service_iterator svc = begin_services (); svc != end_services (); ++svc) {
(*svc)->drag_cancel ();
}
}
namespace
{
struct z_order_compare_f
{
bool operator() (lay::BackgroundViewObject *a, lay::BackgroundViewObject *b) const
{
int za = a->z_order ();
int zb = b->z_order ();
return za < zb;
}
};
}
void
ViewObjectWidget::do_render_bg (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
{
m_needs_update_bg = false;
std::vector<lay::BackgroundViewObject *> bg_objects;
for (background_object_iterator obj = begin_background_objects (); obj != end_background_objects (); ++obj) {
if (obj->is_visible ()) {
bg_objects.push_back (&*obj);
}
}
// Sort objects by z-order
tl::sort (bg_objects.begin (), bg_objects.end (), z_order_compare_f ());
for (std::vector<lay::BackgroundViewObject *>::const_iterator obj = bg_objects.begin (); obj != bg_objects.end (); ++obj) {
BEGIN_PROTECTED_SILENT
(*obj)->render_bg (vp, canvas);
END_PROTECTED_SILENT
}
}
void
ViewObjectWidget::do_render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas, bool st)
{
if (st) {
m_needs_update_static = false;
}
for (object_iterator obj = begin_objects (); obj != end_objects (); ++obj) {
if (obj->m_static == st && obj->is_visible ()) {
BEGIN_PROTECTED_SILENT
obj->render (vp, canvas);
END_PROTECTED_SILENT
}
}
canvas.sort_planes ();
}
void
ViewObjectWidget::grab_mouse (ViewService *obj, bool a)
{
obj->m_abs_grab = a; // not used currently
// only add to m_grabbed if not grabbed already
std::list<ViewService *>::iterator g;
for (g = m_grabbed.begin (); g != m_grabbed.end () && *g != obj; ++g) {
;
}
if (g == m_grabbed.end ()) {
m_grabbed.push_front (obj);
}
}
void
ViewObjectWidget::ungrab_mouse (ViewService *obj)
{
std::list<ViewService *>::iterator g;
for (g = m_grabbed.begin (); g != m_grabbed.end () && *g != obj; ++g) {
;
}
if (g != m_grabbed.end ()) {
m_grabbed.erase (g);
}
}
void
ViewObjectWidget::freeze (ViewObject *obj)
{
if (! obj->m_static) {
obj->m_static = true;
m_needs_update_static = true;
// no update needed since the display will not change through this.
}
}
void
ViewObjectWidget::thaw (ViewObject *obj)
{
if (obj->m_static) {
obj->m_static = false;
m_needs_update_static = true;
// no update needed since the display will not change through this.
}
}
void
ViewObjectWidget::touch ()
{
if (! m_needs_update_static) {
m_needs_update_static = true;
update ();
}
}
void
ViewObjectWidget::touch_bg ()
{
if (! m_needs_update_bg) {
m_needs_update_bg = true;
update ();
}
}
void
ViewObjectWidget::objects_changed ()
{
touch ();
update ();
}
db::DBox
ViewObjectWidget::mouse_event_viewport () const
{
db::DPoint p1 = m_trans.inverted () * db::DPoint (0, 0);
db::DPoint p2 = m_trans.inverted () * db::DPoint (width (), height ());
return db::DBox (p1, p2);
}
// ---------------------------------------------------------------
// BitmapViewObjectCanvas implementation
BitmapViewObjectCanvas::BitmapViewObjectCanvas ()
: ViewObjectCanvas (), m_renderer (1, 1, 1.0), m_width (1), m_height (1), m_resolution (1.0)
{
// .. nothing yet ..
}
BitmapViewObjectCanvas::BitmapViewObjectCanvas (unsigned int width, unsigned int height, double resolution)
: ViewObjectCanvas (), m_renderer (width, height, resolution),
m_width (width), m_height (height), m_resolution (resolution)
{
// .. nothing yet ..
}
BitmapViewObjectCanvas::~BitmapViewObjectCanvas ()
{
clear_fg_bitmaps ();
}
lay::CanvasPlane *
BitmapViewObjectCanvas::plane (const lay::ViewOp &style)
{
std::map <lay::ViewOp, unsigned int>::iterator b = m_fg_bitmap_table.find (style);
if (b == m_fg_bitmap_table.end ()) {
// we need to create a new plane
m_fg_bitmap_table.insert (std::make_pair (style, mp_alloc_bitmaps.size ()));
lay::Bitmap *bm = new lay::Bitmap (m_width, m_height, m_resolution);
mp_fg_bitmaps.push_back (bm);
mp_alloc_bitmaps.push_back (bm);
m_fg_view_ops.push_back (style);
return bm;
} else {
// we can recycle a current one
return mp_alloc_bitmaps [b->second];
}
}
lay::CanvasPlane *
BitmapViewObjectCanvas::plane (const std::vector<lay::ViewOp> &style)
{
std::map <std::vector<lay::ViewOp>, unsigned int>::iterator b = m_fgv_bitmap_table.find (style);
if (b == m_fgv_bitmap_table.end ()) {
// we need to create a new bitmap
m_fgv_bitmap_table.insert (std::make_pair (style, mp_alloc_bitmaps.size ()));
lay::Bitmap *bm = new lay::Bitmap (m_width, m_height, m_resolution);
mp_alloc_bitmaps.push_back (bm);
for (std::vector<lay::ViewOp>::const_iterator s = style.begin (); s != style.end (); ++s) {
mp_fg_bitmaps.push_back (bm);
m_fg_view_ops.push_back (*s);
}
return bm;
} else {
// we can recycle a current one
return mp_alloc_bitmaps [b->second];
}
}
void
BitmapViewObjectCanvas::clear_fg_bitmaps ()
{
for (std::vector <lay::Bitmap *>::iterator i = mp_alloc_bitmaps.begin (); i != mp_alloc_bitmaps.end (); ++i) {
if (*i) {
delete *i;
}
}
mp_alloc_bitmaps.clear ();
mp_fg_bitmaps.clear ();
m_fg_view_ops.clear ();
m_fg_bitmap_table.clear ();
m_fgv_bitmap_table.clear ();
}
void
BitmapViewObjectCanvas::sort_planes ()
{
// sort the planes by view operator - this ensures a certain plane order as implied by
// the plane index of the plane operators.
std::vector <std::pair <lay::ViewOp, lay::Bitmap *> > bitmaps;
bitmaps.reserve (mp_fg_bitmaps.size ());
for (unsigned int i = 0; i < mp_fg_bitmaps.size (); ++i) {
bitmaps.push_back (std::make_pair (m_fg_view_ops [i], mp_fg_bitmaps [i]));
}
tl::sort (bitmaps.begin (), bitmaps.end ());
for (unsigned int i = 0; i < mp_fg_bitmaps.size (); ++i) {
m_fg_view_ops [i] = bitmaps [i].first;
mp_fg_bitmaps [i] = bitmaps [i].second;
}
}
void
BitmapViewObjectCanvas::set_size (unsigned int width, unsigned int height, double resolution)
{
m_renderer = lay::BitmapRenderer (width, height, resolution);
m_width = width;
m_height = height;
m_resolution = resolution;
}
void
BitmapViewObjectCanvas::set_size (unsigned int width, unsigned int height)
{
m_renderer = lay::BitmapRenderer (width, height, m_resolution);
m_width = width;
m_height = height;
}
void
BitmapViewObjectCanvas::set_size (double resolution)
{
m_renderer = lay::BitmapRenderer (m_width, m_height, resolution);
m_resolution = resolution;
}
}