mirror of https://github.com/KLayout/klayout.git
WIP: layer icons now follow oversampling and high-resolution mode, new GSI method to fetch layer icon: LayoutView#icon_for_layer
This commit is contained in:
parent
00e78eb76c
commit
1bff5c1ac3
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1603,6 +1603,17 @@ LAYBASIC_PUBLIC Class<lay::LayoutViewBase> 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<tl::Event (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::active_cellview_changed_event),
|
||||
"@brief An event indicating that the active cellview has changed\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<lay::LayerPropertiesConst
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 <lay::ViewOp> view_ops;
|
||||
view_ops.push_back (view_op);
|
||||
|
||||
std::vector <lay::Bitmap *> 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -581,6 +581,18 @@ public:
|
|||
*/
|
||||
virtual std::vector<lay::LayerPropertiesConstIterator> 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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<size_t> m_new_sel;
|
||||
int m_phase;
|
||||
int m_oversampling;
|
||||
bool m_hrm;
|
||||
tl::DeferredMethod<LayerControlPanel> m_do_update_content_dm;
|
||||
std::set<unsigned int> m_expanded;
|
||||
bool m_no_stipples;
|
||||
|
|
|
|||
|
|
@ -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 <lay::ViewOp> view_ops;
|
||||
view_ops.push_back (view_op);
|
||||
|
||||
std::vector <lay::Bitmap *> 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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue