mirror of https://github.com/KLayout/klayout.git
WIP
This commit is contained in:
parent
41cbef1e5a
commit
0198c7cd69
|
|
@ -566,7 +566,7 @@ LayoutCanvas::update_image ()
|
|||
void
|
||||
LayoutCanvas::free_resources ()
|
||||
{
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#if defined(HAVE_QT)
|
||||
if (mp_pixmap) {
|
||||
delete mp_pixmap;
|
||||
mp_pixmap = 0;
|
||||
|
|
@ -574,7 +574,7 @@ LayoutCanvas::free_resources ()
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#if defined(HAVE_QT)
|
||||
void
|
||||
LayoutCanvas::paintEvent (QPaintEvent *)
|
||||
{
|
||||
|
|
@ -1006,7 +1006,7 @@ LayoutCanvas::screenshot ()
|
|||
return img;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#if defined(HAVE_QT) // @@@
|
||||
void
|
||||
LayoutCanvas::resizeEvent (QResizeEvent *)
|
||||
{
|
||||
|
|
@ -1090,7 +1090,7 @@ LayoutCanvas::do_update_image ()
|
|||
update_image ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#if defined(HAVE_QT)
|
||||
bool
|
||||
LayoutCanvas::event (QEvent *e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@
|
|||
# include <QImageWriter>
|
||||
#endif
|
||||
|
||||
// Enable this if you have both Qt and libpng and want to use libpng for saving images:
|
||||
// #define PREFER_LIBPNG_FOR_SAVE 1
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace lay
|
||||
|
|
@ -2512,7 +2515,7 @@ png_texts (const lay::LayoutViewBase *view, const db::DBox &box)
|
|||
return texts;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#if defined(HAVE_QT) && !defined(PREFER_LIBPNG_FOR_SAVE)
|
||||
void
|
||||
LayoutViewBase::save_screenshot (const std::string &fn)
|
||||
{
|
||||
|
|
@ -2544,9 +2547,9 @@ LayoutViewBase::save_screenshot (const std::string &fn)
|
|||
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);
|
||||
lay::PixelBuffer img = mp_canvas->screenshot ();
|
||||
img.set_texts (png_texts (this, box ()));
|
||||
img.write_png (stream);
|
||||
|
||||
tl::log << "Saved screen shot to " << fn;
|
||||
}
|
||||
|
|
@ -2596,7 +2599,7 @@ LayoutViewBase::get_image_with_options (unsigned int width, unsigned int height,
|
|||
|
||||
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)
|
||||
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")));
|
||||
|
||||
|
|
@ -2608,7 +2611,7 @@ LayoutViewBase::get_pixels_with_options (unsigned int width, unsigned int height
|
|||
|
||||
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)
|
||||
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")));
|
||||
|
||||
|
|
@ -2618,7 +2621,7 @@ LayoutViewBase::get_pixels_with_options_mono (unsigned int width, unsigned int h
|
|||
return mp_canvas->image_with_options_mono (width, height, linewidth, background, foreground, active, target_box);
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#if defined(HAVE_QT) && !defined(PREFER_LIBPNG_FOR_SAVE)
|
||||
void
|
||||
LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned int height)
|
||||
{
|
||||
|
|
@ -2648,19 +2651,21 @@ LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned
|
|||
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<std::pair<std::string, std::string> > 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);
|
||||
lay::PixelBuffer img = mp_canvas->image (width, height);
|
||||
std::vector<std::pair<std::string, std::string> > texts = png_texts (this, vp.box ());
|
||||
img.set_texts (texts);
|
||||
img.write_png (stream);
|
||||
|
||||
tl::log << "Saved image to " << fn;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#if defined(HAVE_QT) && !defined(PREFER_LIBPNG_FOR_SAVE)
|
||||
void
|
||||
LayoutViewBase::save_image_with_options (const std::string &fn,
|
||||
unsigned int width, unsigned int height, int linewidth, int oversampling, double resolution,
|
||||
|
|
@ -2680,7 +2685,7 @@ LayoutViewBase::save_image_with_options (const std::string &fn,
|
|||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
if (monochrome) {
|
||||
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 ())) {
|
||||
if (! writer.write (mp_canvas->image_with_options_mono (width, height, linewidth, background, foreground, active, 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 {
|
||||
|
|
@ -2707,9 +2712,17 @@ LayoutViewBase::save_image_with_options (const std::string &fn,
|
|||
|
||||
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);
|
||||
|
||||
lay::BitmapBuffer img = mp_canvas->image_with_options_mono (width, height, linewidth, background, foreground, active, target_box);
|
||||
img.set_texts (texts);
|
||||
img.write_png (stream);
|
||||
|
||||
} else {
|
||||
mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box).write_png (stream);
|
||||
|
||||
lay::PixelBuffer img = mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box);
|
||||
img.set_texts (texts);
|
||||
img.write_png (stream);
|
||||
|
||||
}
|
||||
|
||||
tl::log << "Saved image to " << fn;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ PixelBuffer::operator= (const PixelBuffer &other)
|
|||
m_height = other.m_height;
|
||||
m_data = other.m_data;
|
||||
m_transparent = other.m_transparent;
|
||||
m_texts = other.m_texts;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -232,6 +233,7 @@ PixelBuffer::swap (PixelBuffer &other)
|
|||
std::swap (m_height, other.m_height);
|
||||
std::swap (m_transparent, other.m_transparent);
|
||||
m_data.swap (other.m_data);
|
||||
m_texts.swap (other.m_texts);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -435,6 +437,15 @@ PixelBuffer::write_png (tl::OutputStream &output) const
|
|||
|
||||
png_set_IHDR (png_ptr, info_ptr, width (), height (), bd, fmt, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
std::vector<png_text> tptrs;
|
||||
for (auto i = m_texts.begin (); i != m_texts.end (); ++i) {
|
||||
tptrs.push_back (png_text ());
|
||||
tptrs.back ().compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
tptrs.back ().key = const_cast<char *> (i->first.c_str ());
|
||||
tptrs.back ().text = const_cast<char *> (i->second.c_str ());
|
||||
}
|
||||
png_set_text (png_ptr, info_ptr, tptrs.begin ().operator-> (), m_texts.size ());
|
||||
|
||||
png_write_info (png_ptr, info_ptr);
|
||||
|
||||
for (unsigned int i = 0; i < height (); ++i) {
|
||||
|
|
@ -546,6 +557,7 @@ BitmapBuffer::operator= (const BitmapBuffer &other)
|
|||
m_height = other.m_height;
|
||||
m_stride = other.m_stride;
|
||||
m_data = other.m_data;
|
||||
m_texts = other.m_texts;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -570,6 +582,7 @@ BitmapBuffer::swap (BitmapBuffer &other)
|
|||
std::swap (m_height, other.m_height);
|
||||
std::swap (m_stride, other.m_stride);
|
||||
m_data.swap (other.m_data);
|
||||
m_texts.swap (other.m_texts);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -708,6 +721,15 @@ BitmapBuffer::write_png (tl::OutputStream &output) const
|
|||
|
||||
png_set_IHDR (png_ptr, info_ptr, width (), height (), bd, fmt, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
std::vector<png_text> tptrs;
|
||||
for (auto i = m_texts.begin (); i != m_texts.end (); ++i) {
|
||||
tptrs.push_back (png_text ());
|
||||
tptrs.back ().compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
tptrs.back ().key = const_cast<char *> (i->first.c_str ());
|
||||
tptrs.back ().text = const_cast<char *> (i->second.c_str ());
|
||||
}
|
||||
png_set_text (png_ptr, info_ptr, tptrs.begin ().operator-> (), m_texts.size ());
|
||||
|
||||
png_write_info (png_ptr, info_ptr);
|
||||
|
||||
for (unsigned int i = 0; i < height (); ++i) {
|
||||
|
|
|
|||
|
|
@ -258,6 +258,26 @@ public:
|
|||
*/
|
||||
PixelBuffer diff (const PixelBuffer &other) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the texts
|
||||
*
|
||||
* Texts are annotations which can be stored to PNG and back.
|
||||
*/
|
||||
const std::vector<std::pair<std::string, std::string> > &texts () const
|
||||
{
|
||||
return m_texts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the texts
|
||||
*
|
||||
* Texts are annotations which can be stored to PNG and back.
|
||||
*/
|
||||
void set_texts (const std::vector<std::pair<std::string, std::string> > &texts)
|
||||
{
|
||||
m_texts = texts;
|
||||
}
|
||||
|
||||
private:
|
||||
class ImageData
|
||||
{
|
||||
|
|
@ -301,6 +321,7 @@ private:
|
|||
unsigned int m_width, m_height;
|
||||
bool m_transparent;
|
||||
tl::copy_on_write_ptr<ImageData> m_data;
|
||||
std::vector<std::pair<std::string, std::string> > m_texts;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -466,6 +487,26 @@ public:
|
|||
void write_png (tl::OutputStream &output) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Gets the texts
|
||||
*
|
||||
* Texts are annotations which can be stored to PNG and back.
|
||||
*/
|
||||
const std::vector<std::pair<std::string, std::string> > &texts () const
|
||||
{
|
||||
return m_texts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the texts
|
||||
*
|
||||
* Texts are annotations which can be stored to PNG and back.
|
||||
*/
|
||||
void set_texts (const std::vector<std::pair<std::string, std::string> > &texts)
|
||||
{
|
||||
m_texts = texts;
|
||||
}
|
||||
|
||||
private:
|
||||
class MonoImageData
|
||||
{
|
||||
|
|
@ -509,6 +550,7 @@ private:
|
|||
unsigned int m_width, m_height;
|
||||
unsigned int m_stride;
|
||||
tl::copy_on_write_ptr<MonoImageData> m_data;
|
||||
std::vector<std::pair<std::string, std::string> > m_texts;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,3 +236,90 @@ TEST(13)
|
|||
EXPECT_EQ (compare_images (img, au_img), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PNG) || defined(HAVE_QT)
|
||||
TEST(21)
|
||||
{
|
||||
lay::LayoutView lv (0, false, 0);
|
||||
lv.cell_box_color (lay::Color (0, 0, 0));
|
||||
|
||||
lv.load_layout (tl::testsrc () + "/testdata/gds/t10.gds", true);
|
||||
|
||||
std::string tmp = tmp_file ("test.png");
|
||||
lv.save_image_with_options (tmp, 500, 500, 1, 1, 1.0, lay::Color (255, 255, 255), lay::Color (0, 0, 0), lay::Color (128, 128, 128), db::DBox (), false);
|
||||
|
||||
lay::PixelBuffer img;
|
||||
{
|
||||
tl::InputStream stream (tmp);
|
||||
img = lay::PixelBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << tmp;
|
||||
|
||||
std::string au = tl::testsrc () + "/testdata/lay/au_lv1.png";
|
||||
lay::PixelBuffer au_img;
|
||||
{
|
||||
tl::InputStream stream (au);
|
||||
au_img = lay::PixelBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << au;
|
||||
|
||||
EXPECT_EQ (compare_images (img, au_img), true);
|
||||
}
|
||||
|
||||
TEST(22)
|
||||
{
|
||||
lay::LayoutView lv (0, false, 0);
|
||||
lv.full_hier_new_cell (true);
|
||||
|
||||
lv.load_layout (tl::testsrc () + "/testdata/gds/t10.gds", true);
|
||||
|
||||
std::string tmp = tmp_file ("test.png");
|
||||
lv.save_image_with_options (tmp, 500, 500, 1, 1, 1.0, lay::Color (255, 255, 255), lay::Color (0, 0, 0), lay::Color (128, 128, 128), db::DBox (), false);
|
||||
|
||||
lay::PixelBuffer img;
|
||||
{
|
||||
tl::InputStream stream (tmp);
|
||||
img = lay::PixelBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << tmp;
|
||||
|
||||
std::string au = tl::testsrc () + "/testdata/lay/au_lv2.png";
|
||||
lay::PixelBuffer au_img;
|
||||
{
|
||||
tl::InputStream stream (au);
|
||||
au_img = lay::PixelBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << au;
|
||||
|
||||
EXPECT_EQ (compare_images (img, au_img), true);
|
||||
}
|
||||
|
||||
// monochrome
|
||||
TEST(23)
|
||||
{
|
||||
lay::LayoutView lv (0, false, 0);
|
||||
lv.full_hier_new_cell (true);
|
||||
|
||||
lv.load_layout (tl::testsrc () + "/testdata/gds/t10.gds", true);
|
||||
|
||||
std::string tmp = tmp_file ("test.png");
|
||||
lv.save_image_with_options (tmp, 500, 500, 1, 1, 1.0, lay::Color (255, 255, 255), lay::Color (0, 0, 0), lay::Color (128, 128, 128), db::DBox (), true);
|
||||
|
||||
lay::BitmapBuffer img;
|
||||
{
|
||||
tl::InputStream stream (tmp);
|
||||
img = lay::BitmapBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << tmp;
|
||||
|
||||
std::string au = tl::testsrc () + "/testdata/lay/au_lv3.png";
|
||||
lay::BitmapBuffer au_img;
|
||||
{
|
||||
tl::InputStream stream (au);
|
||||
au_img = lay::BitmapBuffer::read_png (stream);
|
||||
}
|
||||
tl::info << "PNG file read from " << au;
|
||||
|
||||
EXPECT_EQ (compare_images (img, au_img), true);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue