diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index f2a91af17..0f97e0166 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -30,6 +30,7 @@ #include "laySelector.h" #include "layFinder.h" #include "layLayerProperties.h" +#include "laybasicConfig.h" #include "tlProgress.h" #include "edtPlugin.h" #include "edtMainService.h" diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index cef7e30bf..db6c1c5d5 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -1603,6 +1603,17 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "Returns an array of \\LayerPropertiesIterator objects pointing to the currently selected layers. " "If no layer view is selected currently, an empty array is returned.\n" ) + + gsi::method ("icon_for_layer", &lay::LayoutViewBase::icon_for_layer, gsi::arg ("iter"), gsi::arg ("w"), gsi::arg ("h"), gsi::arg ("dpr"), gsi::arg ("di_off", 0), gsi::arg ("no_state", false), + "@brief Creates an icon pixmap for the given layer.\n" + "\n" + "The icon will have size w times h pixels multiplied by the device pixel ratio (dpr). The dpr is " + "The number of physical pixels per logical pixels on high-DPI displays.\n" + "\n" + "'di_off' will shift the dither pattern by the given number of (physical) pixels. " + "If 'no_state' is true, the icon will not reflect visibility or validity states but rather the display style.\n" + "\n" + "This method has been introduced in version 0.28." + ) + gsi::event ("on_active_cellview_changed", static_cast (&lay::LayoutViewBase::active_cellview_changed_event), "@brief An event indicating that the active cellview has changed\n" "\n" diff --git a/src/laybasic/laybasic/layLayoutCanvas.cc b/src/laybasic/laybasic/layLayoutCanvas.cc index ad89580fa..4ae778d95 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.cc +++ b/src/laybasic/laybasic/layLayoutCanvas.cc @@ -131,137 +131,6 @@ std::string ImageCacheEntry::to_string () const // ---------------------------------------------------------------------------- -static void -blowup (const tl::PixelBuffer &src, tl::PixelBuffer &dest, unsigned int os) -{ - unsigned int ymax = src.height (); - unsigned int xmax = src.width (); - - for (unsigned int y = 0; y < ymax; ++y) { - for (unsigned int i = 0; i < os; ++i) { - const uint32_t *psrc = (const uint32_t *) src.scan_line (y); - uint32_t *pdest = (uint32_t *) dest.scan_line (y * os + i); - for (unsigned int x = 0; x < xmax; ++x) { - for (unsigned int j = 0; j < os; ++j) { - *pdest++ = *psrc; - } - ++psrc; - } - } - } -} - -static void -subsample (const tl::PixelBuffer &src, tl::PixelBuffer &dest, unsigned int os, double g) -{ - // TODO: this is probably not compatible with the endianess of SPARC .. - - // LUT's for combining the RGB channels - - // forward transformation table - unsigned short lut1[256]; - for (unsigned int i = 0; i < 256; ++i) { - double f = (65536 / (os * os)) - 1; - lut1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + pow (i / 255.0, g) * f))); - } - - // backward transformation table - unsigned char lut2[65536]; - for (unsigned int i = 0; i < 65536; ++i) { - double f = os * os * ((65536 / (os * os)) - 1); - lut2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + pow (i / f, 1.0 / g) * 255.0))); - } - - // LUT's for alpha channel - - // forward transformation table - unsigned short luta1[256]; - for (unsigned int i = 0; i < 256; ++i) { - double f = (65536 / (os * os)) - 1; - luta1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + (i / 255.0) * f))); - } - - // backward transformation table - unsigned char luta2[65536]; - for (unsigned int i = 0; i < 65536; ++i) { - double f = os * os * ((65536 / (os * os)) - 1); - luta2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + (i / f) * 255.0))); - } - - unsigned int ymax = dest.height (); - unsigned int xmax = dest.width (); - - unsigned short *buffer = new unsigned short[xmax * 4]; - - for (unsigned int y = 0; y < ymax; ++y) { - - { - - const unsigned char *psrc = (const unsigned char *) src.scan_line (y * os); - unsigned short *pdest = buffer; - - for (unsigned int x = 0; x < xmax; ++x) { - - pdest[0] = lut1[psrc[0]]; - pdest[1] = lut1[psrc[1]]; - pdest[2] = lut1[psrc[2]]; - pdest[3] = luta1[psrc[3]]; - psrc += 4; - - for (unsigned int j = os; j > 1; j--) { - pdest[0] += lut1[psrc[0]]; - pdest[1] += lut1[psrc[1]]; - pdest[2] += lut1[psrc[2]]; - pdest[3] += luta1[psrc[3]]; - psrc += 4; - } - - pdest += 4; - - } - - } - - for (unsigned int i = 1; i < os; ++i) { - - const unsigned char *psrc = (const unsigned char *) src.scan_line (y * os + i); - unsigned short *pdest = buffer; - - for (unsigned int x = 0; x < xmax; ++x) { - - for (unsigned int j = os; j > 0; j--) { - pdest[0] += lut1[psrc[0]]; - pdest[1] += lut1[psrc[1]]; - pdest[2] += lut1[psrc[2]]; - pdest[3] += luta1[psrc[3]]; - psrc += 4; - } - - pdest += 4; - - } - - } - - { - - unsigned char *pdest = (unsigned char *) dest.scan_line (y); - const unsigned short *psrc = buffer; - - for (unsigned int x = 0; x < xmax; ++x) { - *pdest++ = lut2[*psrc++]; - *pdest++ = lut2[*psrc++]; - *pdest++ = lut2[*psrc++]; - *pdest++ = luta2[*psrc++]; - } - - } - - } - - delete[] buffer; -} - void invert (unsigned char *data, unsigned int width, unsigned int height) { @@ -693,7 +562,7 @@ LayoutCanvas::paint_event () } else { tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ()); subsampled_image.set_transparent (mp_image->transparent ()); - subsample (full_image, subsampled_image, m_oversampling, m_gamma); + full_image.subsample (subsampled_image, m_oversampling, m_gamma); *mp_image_fg = subsampled_image; } @@ -705,7 +574,7 @@ LayoutCanvas::paint_event () tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ()); subsampled_image.set_transparent (mp_image->transparent ()); - subsample (*mp_image, subsampled_image, m_oversampling, m_gamma); + mp_image->subsample (subsampled_image, m_oversampling, m_gamma); *mp_image_fg = subsampled_image; } @@ -744,7 +613,7 @@ LayoutCanvas::paint_event () } else { tl::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ()); subsampled_image.set_transparent (true); - subsample (full_image, subsampled_image, m_oversampling, m_gamma); + full_image.subsample (subsampled_image, m_oversampling, m_gamma); QImage img = subsampled_image.to_image (); #if QT_VERSION >= 0x050000 img.setDevicePixelRatio (dpr ()); @@ -820,9 +689,9 @@ public: { if (mp_image_l) { unsigned int os = mp_image_l->width () / width; - blowup (*mp_image, *mp_image_l, os); + mp_image->blowup (*mp_image_l, os); bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dp, ls, 1.0 / resolution (), mp_image_l, mp_image_l->width (), mp_image_l->height (), false, 0); - subsample (*mp_image_l, *mp_image, os, m_gamma); + mp_image_l->subsample (*mp_image, os, m_gamma); } else { bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dp, ls, 1.0 / resolution (), mp_image, width, height, false, 0); } @@ -833,7 +702,7 @@ public: { if (mp_image_l && mp_image->width () > 0) { unsigned int os = mp_image_l->width () / mp_image->width (); - subsample (*mp_image_l, *mp_image, os, m_gamma); + mp_image_l->subsample (*mp_image, os, m_gamma); } } diff --git a/src/laybasic/laybasic/layLayoutCanvas.h b/src/laybasic/laybasic/layLayoutCanvas.h index 32100c05d..d73f614b2 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.h +++ b/src/laybasic/laybasic/layLayoutCanvas.h @@ -257,10 +257,26 @@ public: void set_oversampling (unsigned int os); /** - * @brief Set high-resolution mode (utilize full DPI on high-DPI displays) + * @brief Gets the oversampling factor + */ + unsigned int oversampling () const + { + return m_oversampling; + } + + /** + * @brief Set high resolution mode (utilize full DPI on high-DPI displays) */ void set_highres_mode (bool hrm); + /** + * @brief Gets the high resolution mode flag + */ + bool highres_mode () const + { + return m_hrm; + } + /** * @brief Sets the depth of the image cache */ diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index 4852504d7..dc176a9e5 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -36,6 +36,7 @@ #include "tlExceptions.h" #include "tlDeferredExecution.h" #include "layLayoutViewBase.h" +#include "layBitmapsToImage.h" #include "layViewOp.h" #include "layViewObject.h" #include "layConverters.h" @@ -1527,6 +1528,181 @@ LayoutViewBase::set_selected_layers (const std::vector view_ops; + view_ops.push_back (view_op); + + std::vector pbitmaps; + pbitmaps.push_back (&bitmap); + + lay::bitmaps_to_image (view_ops, pbitmaps, dither_pattern, line_styles, dpr, pimage, width, height, false, 0); +} + +tl::PixelBuffer +LayoutViewBase::icon_for_layer (const LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state) +{ + int oversampling = canvas () ? canvas ()->oversampling () : 1; + double gamma = 2.0; + + bool hrm = canvas () ? canvas ()->highres_mode () : false; + double dpr_drawing = oversampling * (hrm ? 1.0 : dpr); + + h = std::max ((unsigned int) 16, h) * oversampling * dpr + 0.5; + w = std::max ((unsigned int) 16, w) * oversampling * dpr + 0.5; + + tl::color_t def_color = 0x808080; + tl::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color; + tl::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color; + + tl::PixelBuffer image (w, h); + image.set_transparent (true); + image.fill (background_color ().rgb ()); + + // upper scanline is a dummy one + tl::color_t *sl0 = (uint32_t *) image.scan_line (0); + for (size_t i = 0; i < w; ++i) { + *sl0++ = 0; + } + + lay::Bitmap fill (w, h, 1.0); + lay::Bitmap frame (w, h, 1.0); + lay::Bitmap text (w, h, 1.0); + lay::Bitmap vertex (w, h, 1.0); + + unsigned int wp = w - 1; + + if (! no_state && ! iter->visible (true)) { + + wp = w / 4; + + // Show the arrow if it is invisible also locally. + if (! iter->visible (false)) { + + unsigned int aw = h / 4; + unsigned int ap = w / 2 - 1; + for (unsigned int i = 0; i <= aw; ++i) { + text.fill (h / 2 - 1 - i, ap, ap + aw - i + 1); + text.fill (h / 2 - 1 + i, ap, ap + aw - i + 1); + } + + } + + } + + if (! no_state && no_stipples ()) { + // Show a partial stipple pattern only for "no stipple" mode + for (unsigned int i = 1; i < h - 2; ++i) { + fill.fill (i, w - 1 - w / 4, w); + } + } else { + for (unsigned int i = 1; i < h - 2; ++i) { + fill.fill (i, w - 1 - wp, w); + } + } + + int lw = iter->width (true); + if (lw < 0) { + // default line width is 0 for parents and 1 for leafs + lw = iter->has_children () ? 0 : 1; + } + lw = lw * dpr_drawing + 0.5; + + int p0 = lw / 2; + p0 = std::max (0, std::min (int (w / 4 - 1), p0)); + + int p1 = (lw - 1) / 2; + p1 = std::max (0, std::min (int (w / 4 - 1), p1)); + + int p0x = p0, p1x = p1; + unsigned int ddx = 0; + unsigned int ddy = h - 2 - p1 - p0; + if (iter->xfill (true)) { + ddx = wp - p0 - p1 - 1; + } + unsigned int d = ddx / 2; + + frame.fill (p0, w - 1 - (wp - p1), w); + frame.fill (h - 2 - p1, w - 1 - (wp - p1), w); + + for (unsigned int i = p0; i < h - 2; ++i) { + + frame.fill (i, w - 1 - p0, w - p0); + frame.fill (i, w - 1 - (wp - p1), w - (wp - p1)); + frame.fill (i, w - 1 - p0x, w - p0x); + frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x)); + + while (d < ddx) { + d += ddy; + frame.fill (i, w - 1 - p0x, w - p0x); + frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x)); + ++p0x; + ++p1x; + } + + if (d >= ddx) { + d -= ddx; + } + + } + + if (! no_state && ! iter->valid (true)) { + + unsigned int bp = w - 1 - ((w * 7) / 8 - 1); + unsigned int be = bp + h / 2; + unsigned int bw = h / 4 - 1; + unsigned int by = h / 2 - 1; + + for (unsigned int i = 0; i < bw + 2; ++i) { + fill.clear (by - i, bp - 1, be); + fill.clear (by + i, bp - 1, be); + } + + for (unsigned int i = 0; i < bw; ++i) { + text.fill (by - i, bp + bw - i - 1, bp + bw - i + 1); + text.fill (by - i - 1, bp + bw - i - 1, bp + bw - i + 1); + text.fill (by - i, bp + bw + i, bp + bw + i + 2); + text.fill (by - i - 1, bp + bw + i, bp + bw + i + 2); + text.fill (by + i, bp + bw - i - 1, bp + bw - i + 1); + text.fill (by + i + 1, bp + bw - i - 1, bp + bw - i + 1); + text.fill (by + i, bp + bw + i, bp + bw + i + 2); + text.fill (by + i + 1, bp + bw + i, bp + bw + i + 2); + } + + } + + vertex.fill (h / 2 - 1, w - 1 - wp / 2, w - wp / 2); + + lay::ViewOp::Mode mode = lay::ViewOp::Copy; + + // create fill + single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, dither_pattern (), line_styles (), dpr_drawing, w, h); + // create frame + if (lw == 0) { + single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, dither_pattern (), line_styles (), dpr_drawing, w, h); + } else { + single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, dither_pattern (), line_styles (), dpr_drawing, w, h); + } + // create text + single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, dither_pattern (), line_styles (), dpr_drawing, w, h); + // create vertex + single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? 9/*mark size*/ : 0), vertex, &image, dither_pattern (), line_styles (), dpr_drawing, w, h); + + if (oversampling > 1) { + tl::PixelBuffer subsampled (image.width () / oversampling, image.height () / oversampling); + image.subsample (subsampled, oversampling, gamma); + return subsampled; + } else { + return image; + } +} + void LayoutViewBase::merge_dither_pattern (lay::LayerPropertiesList &props) { diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index d34426ce8..9f7b188d5 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -581,6 +581,18 @@ public: */ virtual std::vector selected_layers () const; + /** + * @brief Gets a pixmap representing the given layer + * + * @param iter indicates the layer + * @param w The width in logical pixels of the generated pixmap (will be multiplied by dpr) + * @param h The height in logical pixels of the generated pixmap (will be multiplied by dpr) + * @param dpr The device pixel ratio (number of image pixes per logical pixel) + * @param di_off The dither pattern offset (used for animation) + * @param no_state If true, the state will not be indicated + */ + tl::PixelBuffer icon_for_layer (const lay::LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state); + /** * @brief Sets the layers that are selected in the layer browser */ diff --git a/src/layui/layui/layLayerControlPanel.cc b/src/layui/layui/layLayerControlPanel.cc index 5b1ff584c..1ff0370c8 100644 --- a/src/layui/layui/layLayerControlPanel.cc +++ b/src/layui/layui/layLayerControlPanel.cc @@ -208,6 +208,8 @@ LayerControlPanel::LayerControlPanel (lay::LayoutViewBase *view, db::Manager *ma m_hidden_flags_need_update (true), m_in_update (false), m_phase (0), + m_oversampling (1), + m_hrm (false), m_do_update_content_dm (this, &LayerControlPanel::do_update_content), m_no_stipples (false) { @@ -1712,6 +1714,24 @@ LayerControlPanel::set_phase (int phase) } } +void +LayerControlPanel::set_highres_mode (bool hrm) +{ + if (m_hrm != hrm) { + m_hrm = hrm; + m_do_update_content_dm (); + } +} + +void +LayerControlPanel::set_oversampling (int os) +{ + if (m_oversampling != os) { + m_oversampling = os; + m_do_update_content_dm (); + } +} + static void set_hidden_flags_rec (LayerTreeModel *model, QTreeView *tree_view, const QModelIndex &parent) { diff --git a/src/layui/layui/layLayerControlPanel.h b/src/layui/layui/layLayerControlPanel.h index 93aad12b6..87920ff57 100644 --- a/src/layui/layui/layLayerControlPanel.h +++ b/src/layui/layui/layLayerControlPanel.h @@ -208,6 +208,16 @@ public: */ void set_phase (int phase); + /** + * @brief Sets highres mode + */ + void set_highres_mode (bool hrm); + + /** + * @brief Sets oversampling mode + */ + void set_oversampling (int os); + /** * @brief Tell, if the model has been updated already (true) or if it is still under construction (false) */ @@ -347,6 +357,8 @@ private: bool m_in_update; std::vector m_new_sel; int m_phase; + int m_oversampling; + bool m_hrm; tl::DeferredMethod m_do_update_content_dm; std::set m_expanded; bool m_no_stipples; diff --git a/src/layui/layui/layLayerTreeModel.cc b/src/layui/layui/layLayerTreeModel.cc index fe3f1a97f..b2a284a11 100644 --- a/src/layui/layui/layLayerTreeModel.cc +++ b/src/layui/layui/layLayerTreeModel.cc @@ -24,7 +24,6 @@ #include "layLayerTreeModel.h" #include "layLayoutViewBase.h" -#include "layBitmapsToImage.h" #include "dbLayoutUtils.h" #include "tlLog.h" #include "tlTimer.h" @@ -182,7 +181,8 @@ EmptyWithinViewCache::determine_empty_layers (const db::Layout *layout, unsigned LayerTreeModel::LayerTreeModel (QWidget *parent, lay::LayoutViewBase *view) : QAbstractItemModel (parent), mp_parent (parent), mp_view (view), m_filter_mode (false), m_id_start (0), m_id_end (0), - m_phase ((unsigned int) -1), m_test_shapes_in_view (false), m_hide_empty_layers (false) + m_phase ((unsigned int) -1), + m_test_shapes_in_view (false), m_hide_empty_layers (false) { // .. nothing yet .. } @@ -620,170 +620,11 @@ LayerTreeModel::empty_within_view_predicate (const QModelIndex &index) const } } -/** - * @brief A helper function to create an image from a single bitmap - */ -static void -single_bitmap_to_image (const lay::ViewOp &view_op, lay::Bitmap &bitmap, - tl::PixelBuffer *pimage, const lay::DitherPattern &dither_pattern, const lay::LineStyles &line_styles, - double dpr, unsigned int width, unsigned int height) -{ - std::vector view_ops; - view_ops.push_back (view_op); - - std::vector pbitmaps; - pbitmaps.push_back (&bitmap); - - lay::bitmaps_to_image (view_ops, pbitmaps, dither_pattern, line_styles, dpr, pimage, width, height, false, 0); -} - -LAYUI_PUBLIC QIcon LayerTreeModel::icon_for_layer (const lay::LayerPropertiesConstIterator &iter, lay::LayoutViewBase *view, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state) { - h = std::max ((unsigned int) 16, h) * dpr + 0.5; - w = std::max ((unsigned int) 16, w) * dpr + 0.5; - - tl::color_t def_color = 0x808080; - tl::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color; - tl::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color; - - tl::PixelBuffer image (w, h); - image.set_transparent (true); - image.fill (view->background_color ().rgb ()); - - // upper scanline is a dummy one - uint32_t *sl0 = (uint32_t *) image.scan_line (0); - uint32_t transparent = QColor (Qt::transparent).rgba (); - for (size_t i = 0; i < w; ++i) { - *sl0++ = transparent; - } - - // TODO: adjust the resolution according to the oversampling mode - lay::Bitmap fill (w, h, 1.0); - lay::Bitmap frame (w, h, 1.0); - lay::Bitmap text (w, h, 1.0); - lay::Bitmap vertex (w, h, 1.0); - - unsigned int wp = w - 1; - - if (! no_state && ! iter->visible (true)) { - - wp = w / 4; - - // Show the arrow if it is invisible also locally. - if (! iter->visible (false)) { - - unsigned int aw = h / 4; - unsigned int ap = w / 2 - 1; - for (unsigned int i = 0; i <= aw; ++i) { - text.fill (h / 2 - 1 - i, ap, ap + aw - i + 1); - text.fill (h / 2 - 1 + i, ap, ap + aw - i + 1); - } - - } - - } - - if (! no_state && view->no_stipples ()) { - // Show a partial stipple pattern only for "no stipple" mode - for (unsigned int i = 1; i < h - 2; ++i) { - fill.fill (i, w - 1 - w / 4, w); - } - } else { - for (unsigned int i = 1; i < h - 2; ++i) { - fill.fill (i, w - 1 - wp, w); - } - } - - int lw = iter->width (true); - if (lw < 0) { - // default line width is 0 for parents and 1 for leafs - lw = iter->has_children () ? 0 : 1; - } - lw = lw * dpr + 0.5; - - int p0 = lw / 2; - p0 = std::max (0, std::min (int (w / 4 - 1), p0)); - - int p1 = (lw - 1) / 2; - p1 = std::max (0, std::min (int (w / 4 - 1), p1)); - - int p0x = p0, p1x = p1; - unsigned int ddx = 0; - unsigned int ddy = h - 2 - p1 - p0; - if (iter->xfill (true)) { - ddx = wp - p0 - p1 - 1; - } - unsigned int d = ddx / 2; - - frame.fill (p0, w - 1 - (wp - p1), w); - frame.fill (h - 2 - p1, w - 1 - (wp - p1), w); - - for (unsigned int i = p0; i < h - 2; ++i) { - - frame.fill (i, w - 1 - p0, w - p0); - frame.fill (i, w - 1 - (wp - p1), w - (wp - p1)); - frame.fill (i, w - 1 - p0x, w - p0x); - frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x)); - - while (d < ddx) { - d += ddy; - frame.fill (i, w - 1 - p0x, w - p0x); - frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x)); - ++p0x; - ++p1x; - } - - if (d >= ddx) { - d -= ddx; - } - - } - - if (! no_state && ! iter->valid (true)) { - - unsigned int bp = w - 1 - ((w * 7) / 8 - 1); - unsigned int be = bp + h / 2; - unsigned int bw = h / 4 - 1; - unsigned int by = h / 2 - 1; - - for (unsigned int i = 0; i < bw + 2; ++i) { - fill.clear (by - i, bp - 1, be); - fill.clear (by + i, bp - 1, be); - } - - for (unsigned int i = 0; i < bw; ++i) { - text.fill (by - i, bp + bw - i - 1, bp + bw - i + 1); - text.fill (by - i - 1, bp + bw - i - 1, bp + bw - i + 1); - text.fill (by - i, bp + bw + i, bp + bw + i + 2); - text.fill (by - i - 1, bp + bw + i, bp + bw + i + 2); - text.fill (by + i, bp + bw - i - 1, bp + bw - i + 1); - text.fill (by + i + 1, bp + bw - i - 1, bp + bw - i + 1); - text.fill (by + i, bp + bw + i, bp + bw + i + 2); - text.fill (by + i + 1, bp + bw + i, bp + bw + i + 2); - } - - } - - vertex.fill (h / 2 - 1, w - 1 - wp / 2, w - wp / 2); - - lay::ViewOp::Mode mode = lay::ViewOp::Copy; - - // create fill - single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, view->dither_pattern (), view->line_styles (), dpr, w, h); - // create frame - if (lw == 0) { - single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, view->dither_pattern (), view->line_styles (), dpr, w, h); - } else { - single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, view->dither_pattern (), view->line_styles (), dpr, w, h); - } - // create text - single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, view->dither_pattern (), view->line_styles (), dpr, w, h); - // create vertex - single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? 9/*mark size*/ : 0), vertex, &image, view->dither_pattern (), view->line_styles (), dpr, w, h); - - QPixmap pixmap = QPixmap::fromImage (image.to_image ()); + tl::PixelBuffer px = view->icon_for_layer (iter, w, h, dpr, di_off, no_state); + QPixmap pixmap = QPixmap::fromImage (px.to_image ()); #if QT_VERSION >= 0x050000 pixmap.setDevicePixelRatio (dpr); #endif diff --git a/src/layui/layui/layLayerTreeModel.h b/src/layui/layui/layLayerTreeModel.h index 902166bdd..fbd548814 100644 --- a/src/layui/layui/layLayerTreeModel.h +++ b/src/layui/layui/layLayerTreeModel.h @@ -123,17 +123,17 @@ public: QModelIndex index (lay::LayerPropertiesConstIterator iter, int column) const; /** - * @brief Convert a QModelIndex to an iterator + * @brief Converts a QModelIndex to an iterator */ lay::LayerPropertiesConstIterator iterator (const QModelIndex &index) const; /** - * @brief Get a flag indicating that an entry is hidden + * @brief Gets a flag indicating that an entry is hidden */ bool is_hidden (const QModelIndex &index) const; /** - * @brief Set the animation phase + * @brief Sets the animation phase */ void set_phase (unsigned int ph); diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index e25e42ebb..f99154707 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -731,6 +731,20 @@ LayoutView::update_menu (lay::LayoutView *view, lay::AbstractMenu &menu) bool LayoutView::configure (const std::string &name, const std::string &value) { + if (name == cfg_bitmap_oversampling) { + + int os = 1; + tl::from_string (value, os); + mp_control_panel->set_oversampling (os); + + } else if (name == cfg_highres_mode) { + + bool hrm = false; + tl::from_string (value, hrm); + mp_control_panel->set_highres_mode (hrm); + + } + if (LayoutViewBase::configure (name, value)) { return true; } diff --git a/src/tl/tl/tlPixelBuffer.cc b/src/tl/tl/tlPixelBuffer.cc index 0c8566ad8..4accba4df 100644 --- a/src/tl/tl/tlPixelBuffer.cc +++ b/src/tl/tl/tlPixelBuffer.cc @@ -29,6 +29,7 @@ #endif #include +#include namespace tl { @@ -358,6 +359,141 @@ PixelBuffer::diff (const PixelBuffer &other) const return res; } +void +PixelBuffer::blowup (tl::PixelBuffer &dest, unsigned int os) +{ + tl_assert (dest.width () == width () * os); + tl_assert (dest.height () == height () * os); + + unsigned int ymax = height (); + unsigned int xmax = width (); + + for (unsigned int y = 0; y < ymax; ++y) { + for (unsigned int i = 0; i < os; ++i) { + const uint32_t *psrc = (const uint32_t *) scan_line (y); + uint32_t *pdest = (uint32_t *) dest.scan_line (y * os + i); + for (unsigned int x = 0; x < xmax; ++x) { + for (unsigned int j = 0; j < os; ++j) { + *pdest++ = *psrc; + } + ++psrc; + } + } + } +} + +void +PixelBuffer::subsample (tl::PixelBuffer &dest, unsigned int os, double g) +{ + // TODO: this is probably not compatible with the endianess of SPARC .. + + // LUT's for combining the RGB channels + + // forward transformation table + unsigned short lut1[256]; + for (unsigned int i = 0; i < 256; ++i) { + double f = (65536 / (os * os)) - 1; + lut1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + pow (i / 255.0, g) * f))); + } + + // backward transformation table + unsigned char lut2[65536]; + for (unsigned int i = 0; i < 65536; ++i) { + double f = os * os * ((65536 / (os * os)) - 1); + lut2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + pow (i / f, 1.0 / g) * 255.0))); + } + + // LUT's for alpha channel + + // forward transformation table + unsigned short luta1[256]; + for (unsigned int i = 0; i < 256; ++i) { + double f = (65536 / (os * os)) - 1; + luta1[i] = (unsigned short)std::min (f, std::max (0.0, floor (0.5 + (i / 255.0) * f))); + } + + // backward transformation table + unsigned char luta2[65536]; + for (unsigned int i = 0; i < 65536; ++i) { + double f = os * os * ((65536 / (os * os)) - 1); + luta2[i] = (unsigned char)std::min (255.0, std::max (0.0, floor (0.5 + (i / f) * 255.0))); + } + + unsigned int ymax = dest.height (); + unsigned int xmax = dest.width (); + + unsigned short *buffer = new unsigned short[xmax * 4]; + + for (unsigned int y = 0; y < ymax; ++y) { + + { + + const unsigned char *psrc = (const unsigned char *) scan_line (y * os); + unsigned short *pdest = buffer; + + for (unsigned int x = 0; x < xmax; ++x) { + + pdest[0] = lut1[psrc[0]]; + pdest[1] = lut1[psrc[1]]; + pdest[2] = lut1[psrc[2]]; + pdest[3] = luta1[psrc[3]]; + psrc += 4; + + for (unsigned int j = os; j > 1; j--) { + pdest[0] += lut1[psrc[0]]; + pdest[1] += lut1[psrc[1]]; + pdest[2] += lut1[psrc[2]]; + pdest[3] += luta1[psrc[3]]; + psrc += 4; + } + + pdest += 4; + + } + + } + + for (unsigned int i = 1; i < os; ++i) { + + const unsigned char *psrc = (const unsigned char *) scan_line (y * os + i); + unsigned short *pdest = buffer; + + for (unsigned int x = 0; x < xmax; ++x) { + + for (unsigned int j = os; j > 0; j--) { + pdest[0] += lut1[psrc[0]]; + pdest[1] += lut1[psrc[1]]; + pdest[2] += lut1[psrc[2]]; + pdest[3] += luta1[psrc[3]]; + psrc += 4; + } + + pdest += 4; + + } + + } + + { + + unsigned char *pdest = (unsigned char *) dest.scan_line (y); + const unsigned short *psrc = buffer; + + for (unsigned int x = 0; x < xmax; ++x) { + *pdest++ = lut2[*psrc++]; + *pdest++ = lut2[*psrc++]; + *pdest++ = lut2[*psrc++]; + *pdest++ = luta2[*psrc++]; + } + + } + + } + + delete[] buffer; +} + + #if defined(HAVE_PNG) PixelBuffer diff --git a/src/tl/tl/tlPixelBuffer.h b/src/tl/tl/tlPixelBuffer.h index 62b6206f3..0f48d91fb 100644 --- a/src/tl/tl/tlPixelBuffer.h +++ b/src/tl/tl/tlPixelBuffer.h @@ -257,6 +257,28 @@ public: */ PixelBuffer diff (const PixelBuffer &other) const; + /** + * @brief Subsamples the image and puts the subsampled image into the destination image + * + * @param dest Where the subsampled image goes to + * @param os The subsampling factor + * @param g The gamma value for color interpolation + * + * The dimension of the destination image must be set to the corresponding fraction of + * self's dimension. + */ + void subsample (tl::PixelBuffer &dest, unsigned int os, double g); + + /** + * @brief Scales the image into the given destination image + * + * @param dest Where the scaled image goes to + * @param os The scaling factor + * + * The destination images dimension must have been set of self's dimension times os. + */ + void blowup (tl::PixelBuffer &dest, unsigned int os); + /** * @brief Gets the texts *