From 3c11fe61c32325c89d76ed5164649d8de3c95592 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 7 May 2022 14:36:52 +0200 Subject: [PATCH] WIP: enabling PixelBuffer and BitmapBuffer for RBA::LayoutView --- src/lay/lay/layNavigator.cc | 2 +- src/laybasic/laybasic/gsiDeclLayLayoutView.cc | 68 +++++- .../laybasic/gsiDeclLayPixelBuffer.cc | 4 +- src/laybasic/laybasic/layColor.h | 8 + src/laybasic/laybasic/layLayoutCanvas.cc | 6 +- src/laybasic/laybasic/layLayoutCanvas.h | 2 +- src/laybasic/laybasic/layLayoutViewBase.cc | 212 +++++++++++++----- src/laybasic/laybasic/layLayoutViewBase.h | 48 +++- .../laybasic/layNetlistBrowserPage.cc | 2 +- src/laybasic/laybasic/laybasic.pro | 8 +- .../lay_plugin/layNetTracerDialog.cc | 2 +- .../view_25d/lay_plugin/layD25ViewWidget.cc | 8 +- 12 files changed, 296 insertions(+), 74 deletions(-) diff --git a/src/lay/lay/layNavigator.cc b/src/lay/lay/layNavigator.cc index 5855b403d..77b19d25a 100644 --- a/src/lay/lay/layNavigator.cc +++ b/src/lay/lay/layNavigator.cc @@ -80,7 +80,7 @@ public: } lay::Color contrast; - if (c.green () > 128) { + if (c.to_mono ()) { contrast = lay::Color (0, 0, 0); } else { contrast = lay::Color (255, 255, 255); diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc index f76bc9c99..73a8e0350 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc @@ -327,18 +327,26 @@ static void save_as2 (lay::LayoutView *view, unsigned int index, const std::stri view->save_as (index, filename, tl::OutputStream::OM_Auto, options, true, 0); } -#if defined(HAVE_QTBINDINGS) // @@@ +#if defined(HAVE_QT) && defined(HAVE_QTBINDINGS) static QImage get_image_with_options (lay::LayoutView *view, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, const db::DBox &target_box, bool monochrome) { return view->get_image_with_options (width, height, linewidth, oversampling, resolution, lay::Color (), lay::Color (), lay::Color (), target_box, monochrome); } #endif +static lay::PixelBuffer get_pixels_with_options (lay::LayoutView *view, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, const db::DBox &target_box) +{ + return view->get_pixels_with_options (width, height, linewidth, oversampling, resolution, lay::Color (), lay::Color (), lay::Color (), target_box); +} + +static lay::BitmapBuffer get_pixels_with_options_mono (lay::LayoutView *view, unsigned int width, unsigned int height, int linewidth, const db::DBox &target_box) +{ + return view->get_pixels_with_options_mono (width, height, linewidth, lay::Color (), lay::Color (), lay::Color (), target_box); +} + static void save_image_with_options (lay::LayoutView *view, const std::string &fn, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, const db::DBox &target_box, bool monochrome) { -#if defined(HAVE_QT) // @@@ view->save_image_with_options (fn, width, height, linewidth, oversampling, resolution, lay::Color (), lay::Color (), lay::Color (), target_box, monochrome); -#endif } static std::vector @@ -1128,7 +1136,7 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou "Show the layout in full depth down to the deepest level of hierarchy. " "This method may cause a redraw." ) + -#if defined(HAVE_QTBINDINGS) +#if defined(HAVE_QT) && defined(HAVE_QTBINDINGS) gsi::method ("get_screenshot", &lay::LayoutView::get_screenshot, "@brief Gets a screenshot as a \\QImage\n" "\n" @@ -1157,12 +1165,61 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou "@param monochrome If true, monochrome images will be produced.\n" "\n" "The image contains the current scene (layout, annotations etc.).\n" - "The image is written as a PNG file to the given file. " "The image is drawn synchronously with the given width and height. Drawing may take some time. " "Monochrome images don't have background or annotation objects currently.\n" "\n" "This method has been introduced in 0.23.10.\n" ) + +#endif + gsi::method ("get_screenshot_pixels", &lay::LayoutView::get_screenshot_pb, + "@brief Gets a screenshot as a \\PixelBuffer\n" + "\n" + "Getting the image requires the drawing to be complete. Ideally, synchronous mode is switched on " + "for the application to guarantee this condition. The image will have the size of the viewport " + "showing the current layout." + "\n" + "This method has been introduced in 0.28.\n" + ) + + gsi::method ("get_pixels", &lay::LayoutView::get_pixels, gsi::arg ("width"), gsi::arg ("height"), + "@brief Gets the layout image as a \\PixelBuffer\n" + "\n" + "@param width The width of the image to render in pixel.\n" + "@param height The height of the image to render in pixel.\n" + "\n" + "The image contains the current scene (layout, annotations etc.).\n" + "The image is drawn synchronously with the given width and height. Drawing may take some time. " + "\n" + "This method has been introduced in 0.28.\n" + ) + + gsi::method_ext ("get_pixels_with_options", &get_pixels_with_options, gsi::arg ("width"), gsi::arg ("height"), gsi::arg ("linewidth"), gsi::arg ("oversampling"), gsi::arg ("resolution"), gsi::arg ("target"), + "@brief Gets the layout image as a \\PixelBuffer (with options)\n" + "\n" + "@param width The width of the image to render in pixel.\n" + "@param height The height of the image to render in pixel.\n" + "@param linewidth The width of a line in pixels (usually 1) or 0 for default.\n" + "@param oversampling The oversampling factor (1..3) or 0 for default.\n" + "@param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default.\n" + "@param target_box The box to draw or an empty box for default.\n" + "\n" + "The image contains the current scene (layout, annotations etc.).\n" + "The image is drawn synchronously with the given width and height. Drawing may take some time. " + "\n" + "This method has been introduced in 0.28.\n" + ) + + gsi::method_ext ("get_pixels_with_options_mono", &get_pixels_with_options_mono, gsi::arg ("width"), gsi::arg ("height"), gsi::arg ("linewidth"), gsi::arg ("target"), + "@brief Gets the layout image as a \\PixelBuffer (with options)\n" + "\n" + "@param width The width of the image to render in pixel.\n" + "@param height The height of the image to render in pixel.\n" + "@param linewidth The width of a line in pixels (usually 1) or 0 for default.\n" + "@param target_box The box to draw or an empty box for default.\n" + "\n" + "The image contains the current scene (layout, annotations etc.).\n" + "The image is drawn synchronously with the given width and height. Drawing may take some time. " + "Monochrome images don't have background or annotation objects currently.\n" + "\n" + "This method has been introduced in 0.28.\n" + ) + gsi::method ("save_screenshot", &lay::LayoutView::save_screenshot, gsi::arg ("filename"), "@brief Saves a screenshot to the given file\n" "\n" @@ -1184,7 +1241,6 @@ Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou "The image is written as a PNG file to the given file. " "The image is drawn synchronously with the given width and height. Drawing may take some time. " ) + -#endif gsi::method_ext ("save_image_with_options", &save_image_with_options, gsi::arg ("filename"), gsi::arg ("width"), gsi::arg ("height"), gsi::arg ("linewidth"), gsi::arg ("oversampling"), gsi::arg ("resolution"), gsi::arg ("target"), gsi::arg ("monochrome"), "@brief Saves the layout as an image to the given file (with options)\n" "\n" diff --git a/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc b/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc index 81305e225..7ee615853 100644 --- a/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc +++ b/src/laybasic/laybasic/gsiDeclLayPixelBuffer.cc @@ -23,7 +23,9 @@ #include "gsiDecl.h" #include "layPixelBuffer.h" -#include +#if defined(HAVE_QT) +# include +#endif namespace gsi { diff --git a/src/laybasic/laybasic/layColor.h b/src/laybasic/laybasic/layColor.h index 79725ecfb..1be4ae0b1 100644 --- a/src/laybasic/laybasic/layColor.h +++ b/src/laybasic/laybasic/layColor.h @@ -142,6 +142,14 @@ public: return (m_color & 0xff); } + /** + * @brief Converts the color into monochrome "on" value + */ + bool to_mono () const + { + return (m_color & 0x8000) != 0; + } + /** * @brief Gets the HSV color components * hue: 0..359 diff --git a/src/laybasic/laybasic/layLayoutCanvas.cc b/src/laybasic/laybasic/layLayoutCanvas.cc index 56eefe300..49ec4eb0d 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.cc +++ b/src/laybasic/laybasic/layLayoutCanvas.cc @@ -933,12 +933,16 @@ LayoutCanvas::image_with_options (unsigned int width, unsigned int height, int l } lay::BitmapBuffer -LayoutCanvas::image_with_options_mono (unsigned int width, unsigned int height, int linewidth, bool background, bool foreground, bool active, const db::DBox &target_box) +LayoutCanvas::image_with_options_mono (unsigned int width, unsigned int height, int linewidth, lay::Color background_c, lay::Color foreground_c, lay::Color active_c, const db::DBox &target_box) { if (linewidth <= 0) { linewidth = 1; } + bool background = background_c.is_valid () ? background_c.to_mono () : background_color ().to_mono (); + bool foreground = foreground_c.is_valid () ? foreground_c.to_mono () : foreground_color ().to_mono (); + bool active = active_c.is_valid () ? active_c.to_mono () : active_color ().to_mono (); + // provide canvas objects for the layout bitmaps and the foreground/background objects BitmapRedrawThreadCanvas rd_canvas; DetachedViewObjectCanvasMono vo_canvas (background, foreground, active, width, height); diff --git a/src/laybasic/laybasic/layLayoutCanvas.h b/src/laybasic/laybasic/layLayoutCanvas.h index 2ce31f095..8e254a1fb 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.h +++ b/src/laybasic/laybasic/layLayoutCanvas.h @@ -173,7 +173,7 @@ public: lay::PixelBuffer screenshot (); lay::PixelBuffer image (unsigned int width, unsigned int height); lay::PixelBuffer image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box); - lay::BitmapBuffer image_with_options_mono (unsigned int width, unsigned int height, int linewidth, bool background, bool foreground, bool active_color, const db::DBox &target_box); + lay::BitmapBuffer image_with_options_mono (unsigned int width, unsigned int height, int linewidth, lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box); void update_image (); diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index 2e84b2b25..a8d8eed03 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -2468,7 +2468,7 @@ LayoutViewBase::init_layer_properties (LayerProperties &p, const LayerProperties p.set_marked (false); } -#if defined(HAVE_QT) // @@@ add methods without QImage!!!! +#if defined(HAVE_QT) QImage LayoutViewBase::get_screenshot () { @@ -2479,31 +2479,52 @@ LayoutViewBase::get_screenshot () return mp_canvas->screenshot ().to_image_copy (); } +#endif -void +lay::PixelBuffer +LayoutViewBase::get_screenshot_pb () +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save screenshot"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->screenshot (); +} + +static std::vector > +png_texts (const lay::LayoutViewBase *view, const db::DBox &box) +{ + std::vector > texts; + + // Unfortunately the PNG writer does not allow writing of long strings. + // We separate the description into a set of keys: + + for (unsigned int i = 0; i < view->cellviews (); ++i) { + if (view->cellview (i).is_valid ()) { + std::string name = view->cellview (i)->layout ().cell_name (view->cellview (i).cell_index ()); + texts.push_back (std::make_pair (std::string ("Cell") + tl::to_string (int (i) + 1), name)); + } + } + + texts.push_back (std::make_pair (std::string ("Rect"), box.to_string ())); + + return texts; +} + +#if defined(HAVE_QT) +void LayoutViewBase::save_screenshot (const std::string &fn) { tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save screenshot"))); QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); - // Unfortunately the PNG writer does not allow writing of long strings. - // We separate the description into a set of keys: - - for (unsigned int i = 0; i < cellviews (); ++i) { - if (cellview (i).is_valid ()) { - std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); - writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); - } + std::vector > texts = png_texts (this, box ()); + for (auto i = texts.begin (); i != texts.end (); ++i) { + writer.setText (tl::to_qstring (i->first), tl::to_qstring (i->second)); } - db::DBox b (box ()); - std::string desc; - desc += tl::micron_to_string (b.left ()) + "," + tl::micron_to_string (b.bottom ()); - desc += "/"; - desc += tl::micron_to_string (b.right ()) + "," + tl::micron_to_string (b.top ()); - writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (desc)); - // Execute all deferred methods - ensure there are no pending tasks tl::DeferredMethodScheduler::execute (); @@ -2513,54 +2534,104 @@ LayoutViewBase::save_screenshot (const std::string &fn) tl::log << "Saved screen shot to " << fn; } +#else +void +LayoutViewBase::save_screenshot (const std::string &fn) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save screenshot"))); -QImage + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + tl::OutputStream stream (fn); + // @@@ TODO: add texts + // @@@ mp_canvas->screenshot ().write_png (stream, png_texts (this, box ())); + mp_canvas->screenshot ().write_png (stream); + + tl::log << "Saved screen shot to " << fn; +} +#endif + +#if defined(HAVE_QT) +QImage LayoutViewBase::get_image (unsigned int width, unsigned int height) { - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Get image"))); // Execute all deferred methods - ensure there are no pending tasks tl::DeferredMethodScheduler::execute (); return mp_canvas->image (width, height).to_image_copy (); } +#endif -QImage +lay::PixelBuffer +LayoutViewBase::get_pixels (unsigned int width, unsigned int height) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Get image"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->image (width, height); +} + +#if defined(HAVE_QT) +QImage LayoutViewBase::get_image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) { - tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Get image"))); // Execute all deferred methods - ensure there are no pending tasks tl::DeferredMethodScheduler::execute (); if (monochrome) { - return mp_canvas->image_with_options_mono (width, height, linewidth, background.green () >= 128, foreground.green () >= 128, active.green () >= 128, target_box).to_image_copy (); + return mp_canvas->image_with_options_mono (width, height, linewidth, background, foreground, active, target_box).to_image_copy (); } else { return mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box).to_image_copy (); } } +#endif -void +lay::PixelBuffer +LayoutViewBase::get_pixels_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Get image"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box); +} + +lay::BitmapBuffer +LayoutViewBase::get_pixels_with_options_mono (unsigned int width, unsigned int height, int linewidth, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Get image"))); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + return mp_canvas->image_with_options_mono (width, height, linewidth, background, foreground, active, target_box); +} + +#if defined(HAVE_QT) +void LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned int height) { tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); - // Unfortunately the PNG writer does not allow writing of long strings. - // We separate the description into a set of keys: - - for (unsigned int i = 0; i < cellviews (); ++i) { - if (cellview (i).is_valid ()) { - std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); - writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); - } + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + std::vector > texts = png_texts (this, vp.box ()); + for (auto i = texts.begin (); i != texts.end (); ++i) { + writer.setText (tl::to_qstring (i->first), tl::to_qstring (i->second)); } - lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); - writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (vp.box ().to_string ())); - // Execute all deferred methods - ensure there are no pending tasks tl::DeferredMethodScheduler::execute (); @@ -2568,36 +2639,48 @@ LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ())); } - tl::log << "Saved screen shot to " << fn; + tl::log << "Saved image to " << fn; } +#else +void +LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned int height) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); -void + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + std::vector > texts = png_texts (this, vp.box ()); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + tl::OutputStream stream (fn); + mp_canvas->image (width, height).write_png (stream); + + tl::log << "Saved image to " << fn; +} +#endif + +#if defined(HAVE_QT) +void LayoutViewBase::save_image_with_options (const std::string &fn, - unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, - lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) + unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) { tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); QImageWriter writer (tl::to_qstring (fn), QByteArray ("PNG")); - // Unfortunately the PNG writer does not allow writing of long strings. - // We separate the description into a set of keys: - - for (unsigned int i = 0; i < cellviews (); ++i) { - if (cellview (i).is_valid ()) { - std::string name = cellview (i)->layout ().cell_name (cellview (i).cell_index ()); - writer.setText (tl::to_qstring ("Cell" + tl::to_string (int (i) + 1)), tl::to_qstring (name)); - } + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + std::vector > texts = png_texts (this, vp.box ()); + for (auto i = texts.begin (); i != texts.end (); ++i) { + writer.setText (tl::to_qstring (i->first), tl::to_qstring (i->second)); } - lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); - writer.setText (QString::fromUtf8 ("Rect"), tl::to_qstring (vp.box ().to_string ())); - // Execute all deferred methods - ensure there are no pending tasks tl::DeferredMethodScheduler::execute (); if (monochrome) { - if (! writer.write (mp_canvas->image_with_options_mono (width, height, linewidth, background.green () >= 128, foreground.green () >= 128, active.green () >= 128, target_box).to_image ())) { + if (! writer.write (mp_canvas->image_with_options_mono (width, height, linewidth, background.to_mono (), foreground.to_mono (), active.to_mono (), target_box).to_image ())) { throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ())); } } else { @@ -2606,7 +2689,30 @@ LayoutViewBase::save_image_with_options (const std::string &fn, } } - tl::log << "Saved screen shot to " << fn; + tl::log << "Saved image to " << fn; +} +#else +void +LayoutViewBase::save_image_with_options (const std::string &fn, + unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, + lay::Color background, lay::Color foreground, lay::Color active, const db::DBox &target_box, bool monochrome) +{ + tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Save image"))); + + lay::Viewport vp (width, height, mp_canvas->viewport ().target_box ()); + std::vector > texts = png_texts (this, vp.box ()); + + // Execute all deferred methods - ensure there are no pending tasks + tl::DeferredMethodScheduler::execute (); + + tl::OutputStream stream (fn); + if (monochrome) { + mp_canvas->image_with_options_mono (width, height, linewidth, background.to_mono (), foreground.to_mono (), active.to_mono (), target_box).write_png (stream); + } else { + mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box).write_png (stream); + } + + tl::log << "Saved image to " << fn; } #endif @@ -3591,7 +3697,7 @@ LayoutViewBase::do_prop_changed () void LayoutViewBase::set_view_ops () { - bool bright_background = (mp_canvas->background_color ().green () > 128); + bool bright_background = (mp_canvas->background_color ().to_mono ()); int brightness_for_context = ((bright_background ? m_ctx_dimming : -m_ctx_dimming) * 256) / 100; int brightness_for_child_context = ((bright_background ? m_child_ctx_dimming : -m_child_ctx_dimming) * 256) / 100; @@ -4185,7 +4291,7 @@ LayoutViewBase::background_color (lay::Color c) } lay::Color contrast; - if (c.green () > 128) { + if (c.to_mono ()) { contrast = lay::Color (0, 0, 0); } else { contrast = lay::Color (255, 255, 255); diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index d1bcaa412..d2a91e26f 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -798,16 +798,22 @@ public: */ void load_layer_props (const std::string &fn, int cv_index, bool add_default); -#if defined(HAVE_QT) // @@@ /** * @brief Save the screen content to a file */ void save_screenshot (const std::string &fn); +#if defined(HAVE_QT) /** * @brief Get the screen content as a QImage object */ QImage get_screenshot (); +#endif + + /** + * @brief Gets the screen content as a lay::PixelBuffer object + */ + lay::PixelBuffer get_screenshot_pb (); /** * @brief Save an image file with the given width and height @@ -831,11 +837,19 @@ public: */ void save_image_with_options (const std::string &fn, unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, Color background, Color foreground, Color active_color, const db::DBox &target_box, bool monochrome); +#if defined(HAVE_QT) /** * @brief Get the screen content as a QImage object with the given width and height */ QImage get_image (unsigned int width, unsigned int height); +#endif + /** + * @brief Gets the screen content as a lay::PixelBuffer object + */ + lay::PixelBuffer get_pixels (unsigned int width, unsigned int height); + +#if defined(HAVE_QT) /** * @brief Get the screen content as a QImage object with the given width and height * @@ -853,6 +867,38 @@ public: QImage get_image_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box, bool monochrome); #endif + /** + * @brief Get the screen content as a lay::PixelBuffer object with the given width and height + * + * @param width The width of the image in pixels + * @param height The height of the image + * @param linewidth The width of a line in pixels (usually 1) or 0 for default + * @param oversampling The oversampling factor (1..3) or 0 for default + * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default + * @param background The background color or lay::Color() for default + * @param foreground The foreground color or lay::Color() for default + * @param active The active color or lay::Color() for default + * @param target_box The box to draw or db::DBox() for default + */ + lay::PixelBuffer get_pixels_with_options (unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box); + + /** + * @brief Get the screen content as a monochrome lay::BitmapBuffer object with the given options + * + * @param width The width of the image in pixels + * @param height The height of the image + * @param linewidth The width of a line in pixels (usually 1) or 0 for default + * @param oversampling The oversampling factor (1..3) or 0 for default + * @param resolution The resolution (pixel size compared to a screen pixel size, i.e 1/oversampling) or 0 for default + * @param background The background color or lay::Color() for default + * @param foreground The foreground color or lay::Color() for default + * @param active The active color or lay::Color() for default + * @param target_box The box to draw or db::DBox() for default + * + * The colors will are converted to "on" pixels with a green channel value >= 50%. + */ + lay::BitmapBuffer get_pixels_with_options_mono (unsigned int width, unsigned int height, int linewidth, lay::Color background, lay::Color foreground, lay::Color active_color, const db::DBox &target_box); + /** * @brief Hierarchy level selection setter */ diff --git a/src/laybasic/laybasic/layNetlistBrowserPage.cc b/src/laybasic/laybasic/layNetlistBrowserPage.cc index ef1fdc4f0..1909956f9 100644 --- a/src/laybasic/laybasic/layNetlistBrowserPage.cc +++ b/src/laybasic/laybasic/layNetlistBrowserPage.cc @@ -1099,7 +1099,7 @@ lay::Color NetlistBrowserPage::make_valid_color (const lay::Color &color) { if (! color.is_valid () && mp_view) { - return mp_view->background_color ().green () < 128 ? lay::Color (255, 255, 255) : lay::Color (0, 0, 0); + return mp_view->background_color ().to_mono () ? lay::Color (0, 0, 0) : lay::Color (255, 255, 255); } else { return color; } diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index f5a3c3334..1702e9fac 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -138,8 +138,6 @@ DEFINES += MAKE_LAYBASIC_LIBRARY layNetlistBrowserPage.cc \ layNetlistBrowserTreeModel.cc \ layNetlistCrossReferenceModel.cc \ - layPixelBuffer.cc \ - layPixelBufferPainter.cc \ layPluginConfigPage.cc \ layProperties.cc \ layPropertiesDialog.cc \ @@ -213,8 +211,6 @@ DEFINES += MAKE_LAYBASIC_LIBRARY layNetlistBrowserPage.h \ layNetlistBrowserTreeModel.h \ layNetlistCrossReferenceModel.h \ - layPixelBuffer.h \ - layPixelBufferPainter.h \ layPluginConfigPage.h \ layProperties.h \ layPropertiesDialog.h \ @@ -267,6 +263,8 @@ SOURCES += \ layNetColorizer.cc \ layObjectInstPath.cc \ layParsedLayerSource.cc \ + layPixelBuffer.cc \ + layPixelBufferPainter.cc \ layPlugin.cc \ layRedrawLayerInfo.cc \ layRedrawThread.cc \ @@ -308,6 +306,8 @@ HEADERS += \ layNetColorizer.h \ layObjectInstPath.h \ layParsedLayerSource.h \ + layPixelBuffer.h \ + layPixelBufferPainter.h \ layPlugin.h \ layRedrawLayerInfo.h \ layRedrawThread.h \ diff --git a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc index 7bda1dbb2..d9b50d85a 100644 --- a/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc +++ b/src/plugins/tools/net_tracer/lay_plugin/layNetTracerDialog.cc @@ -1640,7 +1640,7 @@ NetTracerDialog::update_highlights () mp_markers.back ()->set_line_width (original->width (true)); mp_markers.back ()->set_vertex_size (1); mp_markers.back ()->set_dither_pattern (original->dither_pattern (true)); - if (view ()->background_color ().green () < 128) { + if (! view ()->background_color ().to_mono ()) { mp_markers.back ()->set_color (original->eff_fill_color_brighter (true, (m_marker_intensity * 255) / 100)); mp_markers.back ()->set_frame_color (original->eff_frame_color_brighter (true, (m_marker_intensity * 255) / 100)); } else { diff --git a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc index 9fa1f77d6..45194bca0 100644 --- a/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc +++ b/src/plugins/tools/view_25d/lay_plugin/layD25ViewWidget.cc @@ -1090,10 +1090,10 @@ D25ViewWidget::paintGL () glViewport (0, 0, width () * retina_scale, height () * retina_scale); lay::Color c = mp_view->background_color (); - float foreground_rgb = (c.green () > 128 ? 0.0f : 1.0f); - float ambient = (c.green () > 128 ? 0.8f : 0.25f); - float mist_factor = (c.green () > 128 ? 0.2f : 0.4f); - float mist_add = (c.green () > 128 ? 0.8f : 0.2f); + float foreground_rgb = (c.to_mono () ? 0.0f : 1.0f); + float ambient = (c.to_mono () ? 0.8f : 0.25f); + float mist_factor = (c.to_mono () ? 0.2f : 0.4f); + float mist_add = (c.to_mono () ? 0.8f : 0.2f); glClearColor (float (c.red ()) / 255.0f, float (c.green ()) / 255.0f, float (c.blue ()) / 255.0f, 1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);