mirror of https://github.com/KLayout/klayout.git
Refactoring: substitute QImage by lay::PixelBuffer
This commit is contained in:
parent
5fa984324e
commit
0877de73d4
|
|
@ -83,7 +83,7 @@ private:
|
|||
// -------------------------------------------------------------
|
||||
|
||||
static void
|
||||
draw_scanline (unsigned int level, const img::Object &image_object, QImage &qimage, int y, const db::Matrix3d &t, const db::Matrix3d &it, const db::DPoint &q1, const db::DPoint &q2)
|
||||
draw_scanline (unsigned int level, const img::Object &image_object, lay::PixelBuffer &pxbuffer, int y, const db::Matrix3d &t, const db::Matrix3d &it, const db::DPoint &q1, const db::DPoint &q2)
|
||||
{
|
||||
double source_width = image_object.width ();
|
||||
double source_height = image_object.height ();
|
||||
|
|
@ -95,8 +95,8 @@ draw_scanline (unsigned int level, const img::Object &image_object, QImage &qima
|
|||
std::swap (x1, x2);
|
||||
}
|
||||
|
||||
int xstart = int (std::max (0.0, std::min (floor (x1), double (qimage.width ()))));
|
||||
int xstop = int (std::max (0.0, std::min (ceil (x2) + 1.0, double (qimage.width ()))));
|
||||
int xstart = int (std::max (0.0, std::min (floor (x1), double (pxbuffer.width ()))));
|
||||
int xstop = int (std::max (0.0, std::min (ceil (x2) + 1.0, double (pxbuffer.width ()))));
|
||||
|
||||
db::DPoint p1 = it.trans (db::DPoint (xstart, y));
|
||||
db::DPoint p2 = it.trans (db::DPoint (xstop, y));
|
||||
|
|
@ -106,8 +106,8 @@ draw_scanline (unsigned int level, const img::Object &image_object, QImage &qima
|
|||
|
||||
if (level < 7 && xstop > xstart + 1 && fabs (xm - (xstart + xstop) / 2) > 1.0 && xm > xstart + 1 && xm < xstop - 1) {
|
||||
|
||||
draw_scanline (level + 1, image_object, qimage, y, t, it, q1, qm);
|
||||
draw_scanline (level + 1, image_object, qimage, y, t, it, qm, q2);
|
||||
draw_scanline (level + 1, image_object, pxbuffer, y, t, it, q1, qm);
|
||||
draw_scanline (level + 1, image_object, pxbuffer, y, t, it, qm, q2);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -115,8 +115,8 @@ draw_scanline (unsigned int level, const img::Object &image_object, QImage &qima
|
|||
double dpx = (p2.x () - p1.x ()) / double (xstop - xstart);
|
||||
double dpy = (p2.y () - p1.y ()) / double (xstop - xstart);
|
||||
|
||||
QRgb *scanline_data = (QRgb *) qimage.scanLine (qimage.height () - y - 1) + xstart;
|
||||
QRgb *pixel_data = (QRgb *) image_object.pixel_data ();
|
||||
lay::color_t *scanline_data = pxbuffer.scan_line (pxbuffer.height () - y - 1) + xstart;
|
||||
lay::color_t *pixel_data = (lay::color_t *) image_object.pixel_data ();
|
||||
const unsigned char *mask_data = image_object.mask ();
|
||||
|
||||
for (int x = xstart; x < xstop; ++x) {
|
||||
|
|
@ -144,15 +144,15 @@ draw_image (const img::Object &image_object, const lay::Viewport &vp, lay::ViewO
|
|||
{
|
||||
// TODO: currently, the images can only be rendered to a bitmap canvas ..
|
||||
lay::BitmapViewObjectCanvas *bmp_canvas = dynamic_cast<lay::BitmapViewObjectCanvas *> (&canvas);
|
||||
if (! bmp_canvas) {
|
||||
if (! bmp_canvas || ! bmp_canvas->bg_image ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QImage &qimage = bmp_canvas->bg_image ();
|
||||
lay::PixelBuffer &image = *bmp_canvas->bg_image ();
|
||||
db::DBox source_image_box (0.0, 0.0, image_object.width (), image_object.height ());
|
||||
|
||||
// safety measure to avoid division by zero.
|
||||
if (qimage.width () < 1 || qimage.height () < 1) {
|
||||
if (image.width () < 1 || image.height () < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ draw_image (const img::Object &image_object, const lay::Viewport &vp, lay::ViewO
|
|||
db::DBox image_box = source_image_box.transformed (t);
|
||||
|
||||
int y1 = int (floor (std::max (0.0, image_box.bottom ())));
|
||||
int y2 = int (floor (std::min (double (qimage.height ()) - 1, image_box.top ())));
|
||||
int y2 = int (floor (std::min (double (image.height ()) - 1, image_box.top ())));
|
||||
|
||||
for (int y = y1; y <= y2; ++y) {
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ draw_image (const img::Object &image_object, const lay::Viewport &vp, lay::ViewO
|
|||
// clip the transformed scanline to the original image
|
||||
std::pair<bool, db::DEdge> clipped = scanline.clipped_line (source_image_box);
|
||||
if (clipped.first) {
|
||||
draw_scanline (0, image_object, qimage, y, t, it, clipped.second.p1 (), clipped.second.p2 ());
|
||||
draw_scanline (0, image_object, image, y, t, it, clipped.second.p1 (), clipped.second.p2 ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,10 @@
|
|||
#include "layBitmap.h"
|
||||
#include "layDitherPattern.h"
|
||||
#include "layLineStyles.h"
|
||||
#include "layPixelBuffer.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlAssert.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QImage>
|
||||
#include "tlThreads.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
|
@ -422,16 +421,17 @@ static void create_precursor_bitmaps (const std::vector<lay::ViewOp> &view_ops_i
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bitmaps_to_image_rgb (const std::vector<lay::ViewOp> &view_ops_in,
|
||||
const std::vector<lay::Bitmap *> &pbitmaps_in,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
QImage *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
bool transparent,
|
||||
tl::Mutex *mutex)
|
||||
void
|
||||
bitmaps_to_image (const std::vector<lay::ViewOp> &view_ops_in,
|
||||
const std::vector<lay::Bitmap *> &pbitmaps_in,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
PixelBuffer *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex)
|
||||
{
|
||||
bool transparent = pimage->transparent ();
|
||||
|
||||
std::vector<unsigned int> bm_map;
|
||||
std::vector<unsigned int> vo_map;
|
||||
|
||||
|
|
@ -588,7 +588,7 @@ bitmaps_to_image_rgb (const std::vector<lay::ViewOp> &view_ops_in,
|
|||
|
||||
if (masks.size () > 0) {
|
||||
|
||||
lay::color_t *pt = (lay::color_t *) pimage->scanLine (height - 1 - y);
|
||||
lay::color_t *pt = (lay::color_t *) pimage->scan_line (height - 1 - y);
|
||||
uint32_t *dptr_end = dptr;
|
||||
|
||||
unsigned int i = 0;
|
||||
|
|
@ -661,14 +661,14 @@ bitmaps_to_image_rgb (const std::vector<lay::ViewOp> &view_ops_in,
|
|||
delete [] buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmaps_to_image_mono (const std::vector<lay::ViewOp> &view_ops_in,
|
||||
const std::vector<lay::Bitmap *> &pbitmaps_in,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
QImage *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex)
|
||||
void
|
||||
bitmaps_to_image (const std::vector<lay::ViewOp> &view_ops_in,
|
||||
const std::vector<lay::Bitmap *> &pbitmaps_in,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
lay::BitmapBuffer *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex)
|
||||
{
|
||||
std::vector<unsigned int> bm_map;
|
||||
std::vector<unsigned int> vo_map;
|
||||
|
|
@ -825,7 +825,7 @@ bitmaps_to_image_mono (const std::vector<lay::ViewOp> &view_ops_in,
|
|||
|
||||
if (masks.size () > 0) {
|
||||
|
||||
lay::color_t *pt = (lay::color_t *) pimage->scanLine (height - 1 - y);
|
||||
lay::color_t *pt = (lay::color_t *) pimage->scan_line (height - 1 - y);
|
||||
uint32_t *dptr_end = dptr;
|
||||
|
||||
unsigned int i = 0;
|
||||
|
|
@ -866,23 +866,6 @@ bitmaps_to_image_mono (const std::vector<lay::ViewOp> &view_ops_in,
|
|||
delete [] buffer;
|
||||
}
|
||||
|
||||
void
|
||||
bitmaps_to_image (const std::vector<lay::ViewOp> &view_ops_in,
|
||||
const std::vector<lay::Bitmap *> &pbitmaps_in,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
QImage *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex)
|
||||
{
|
||||
if (pimage->depth () <= 1) {
|
||||
bitmaps_to_image_mono (view_ops_in, pbitmaps_in, dp, ls, pimage, width, height, use_bitmap_index, mutex);
|
||||
} else {
|
||||
bool transparent = (pimage->format () == QImage::Format_ARGB32);
|
||||
bitmaps_to_image_rgb (view_ops_in, pbitmaps_in, dp, ls, pimage, width, height, use_bitmap_index, transparent, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitmap_to_bitmap (const lay::ViewOp &view_op, const lay::Bitmap &bitmap,
|
||||
unsigned char *data,
|
||||
|
|
|
|||
|
|
@ -29,17 +29,17 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
class QImage;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class DitherPattern;
|
||||
class LineStyles;
|
||||
class Bitmap;
|
||||
class PixelBuffer;
|
||||
class BitmapBuffer;
|
||||
|
||||
/**
|
||||
* @brief This function converts the given set of bitmaps to a QImage
|
||||
* @brief This function converts the given set of bitmaps to a PixelBuffer
|
||||
*
|
||||
* This function uses the set of bitmaps in "pbitmaps" with the given set
|
||||
* of view operands in "view_ops" and converts these into the QImage
|
||||
|
|
@ -58,12 +58,26 @@ bitmaps_to_image (const std::vector <lay::ViewOp> &view_ops,
|
|||
const std::vector <lay::Bitmap *> &pbitmaps,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
QImage *pimage, unsigned int width, unsigned int height,
|
||||
lay::PixelBuffer *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex);
|
||||
|
||||
/**
|
||||
* @brief Convert a lay::Bitmap to a unsigned char * data field to be passed to QBitmap
|
||||
* @brief This function converts the given set of bitmaps to a BitmapBuffer
|
||||
*
|
||||
* This is the monochrome version of the previous bitmaps_to_image function.
|
||||
*/
|
||||
LAYBASIC_PUBLIC void
|
||||
bitmaps_to_image (const std::vector <lay::ViewOp> &view_ops,
|
||||
const std::vector <lay::Bitmap *> &pbitmaps,
|
||||
const lay::DitherPattern &dp,
|
||||
const lay::LineStyles &ls,
|
||||
lay::BitmapBuffer *pimage, unsigned int width, unsigned int height,
|
||||
bool use_bitmap_index,
|
||||
tl::Mutex *mutex);
|
||||
|
||||
/**
|
||||
* @brief Convert a lay::Bitmap to a unsigned char * data field to be passed to lay::BitmapBuffer
|
||||
*
|
||||
* This function converts the bitmap given the view_op into a raw byte data
|
||||
* field that can be passed to a QBitmap constructor. The data field is not
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "layConverters.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layFixedFont.h"
|
||||
#include "layPixelBufferPainter.h"
|
||||
#include "laySnap.h"
|
||||
#include "dbTrans.h"
|
||||
|
||||
|
|
@ -206,153 +207,7 @@ GridNet::configure (const std::string &name, const std::string &value)
|
|||
return taken;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
class ImagePainter
|
||||
{
|
||||
public:
|
||||
ImagePainter (lay::BitmapViewObjectCanvas &canvas)
|
||||
: mp_img (&canvas.bg_image ()),
|
||||
m_resolution (canvas.resolution ()), m_width (canvas.canvas_width ()), m_height (canvas.canvas_height ())
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void set (const db::Point &p, lay::Color c)
|
||||
{
|
||||
if (p.x () >= 0 && p.x () < m_width && p.y () >= 0 && p.y () < m_height) {
|
||||
((unsigned int *) mp_img->scanLine (p.y ())) [p.x ()] = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_line (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
if (p1.x () == p2.x ()) {
|
||||
|
||||
int x = p1.x ();
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
if ((y2 >= 0 || y1 < m_height) && x >= 0 && x < m_width) {
|
||||
y1 = std::max (y1, 0);
|
||||
y2 = std::min (y2, m_height - 1);
|
||||
for (int y = y1; y <= y2; ++y) {
|
||||
((unsigned int *) mp_img->scanLine (y)) [x] = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (p1.y () == p2.y ()) {
|
||||
|
||||
int y = p1.y ();
|
||||
int x1 = std::min (p1.x (), p2.x ());
|
||||
int x2 = std::max (p1.x (), p2.x ());
|
||||
if ((x2 >= 0 || x1 < m_width) && y >= 0 && y < m_height) {
|
||||
x1 = std::max (x1, 0);
|
||||
x2 = std::min (x2, m_width - 1);
|
||||
unsigned int *sl = (unsigned int *) mp_img->scanLine (y) + x1;
|
||||
for (int x = x1; x <= x2; ++x) {
|
||||
*sl++ = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// TODO: not implemented yet.
|
||||
}
|
||||
}
|
||||
|
||||
void fill_rect (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
for (int y = y1; y <= y2; ++y) {
|
||||
draw_line (db::Point (p1.x (), y), db::Point (p2.x (), y), c);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_rect (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
int x1 = std::min (p1.x (), p2.x ());
|
||||
int x2 = std::max (p1.x (), p2.x ());
|
||||
draw_line (db::Point (x1, y1), db::Point (x2, y1), c);
|
||||
draw_line (db::Point (x1, y2), db::Point (x2, y2), c);
|
||||
draw_line (db::Point (x1, y1), db::Point (x1, y2), c);
|
||||
draw_line (db::Point (x2, y1), db::Point (x2, y2), c);
|
||||
}
|
||||
|
||||
void draw_text (const char *t, const db::Point &p, lay::Color c, int halign, int valign)
|
||||
{
|
||||
const lay::FixedFont &ff = lay::FixedFont::get_font (m_resolution);
|
||||
int x = p.x (), y = p.y ();
|
||||
|
||||
if (halign < 0) {
|
||||
x -= ff.width () * int (strlen (t));
|
||||
} else if (halign == 0) {
|
||||
x -= ff.width () * int (strlen (t)) / 2;
|
||||
}
|
||||
|
||||
if (valign < 0) {
|
||||
y += ff.height ();
|
||||
} else if (valign == 0) {
|
||||
y += ff.height () / 2;
|
||||
}
|
||||
|
||||
// TODO: simple implementation
|
||||
for (; *t; ++t) {
|
||||
|
||||
unsigned char ch = *t;
|
||||
|
||||
if (x < -int (ff.width ()) || x >= int (mp_img->width ()) || y < 0 || y >= int (mp_img->height () + ff.height ())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch < ff.first_char () || (ch - ff.first_char ()) >= ff.n_chars ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t *dc = ff.data () + size_t (ch - ff.first_char ()) * ff.height () * ff.stride ();
|
||||
for (unsigned int i = 0; i < ff.height (); ++i, dc += ff.stride ()) {
|
||||
|
||||
int iy = y - ff.height () + i + 1;
|
||||
if (iy >= 0 || iy < mp_img->height ()) {
|
||||
|
||||
uint32_t *d = (uint32_t *) mp_img->scanLine (y - ff.height () + i);
|
||||
uint32_t m = 1;
|
||||
int ix = x;
|
||||
const uint32_t *ds = dc;
|
||||
|
||||
for (unsigned int j = 0; j < ff.width (); ++j, ++ix) {
|
||||
|
||||
if ((*ds & m) && ix >= 0 && ix < mp_img->width ()) {
|
||||
d[ix] = c.rgb ();
|
||||
}
|
||||
|
||||
m <<= 1;
|
||||
// word wrap
|
||||
if (m == 0) {
|
||||
++ds;
|
||||
m = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
x += ff.width ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
QImage *mp_img;
|
||||
double m_resolution;
|
||||
int m_width, m_height;
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
void
|
||||
GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
|
||||
{
|
||||
if (m_visible) {
|
||||
|
|
@ -377,12 +232,11 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
|
|||
|
||||
// TODO: currently, the grid net can only be rendered to a bitmap canvas ..
|
||||
BitmapViewObjectCanvas *bmp_canvas = dynamic_cast<BitmapViewObjectCanvas *> (&canvas);
|
||||
if (! bmp_canvas) {
|
||||
if (! bmp_canvas || ! bmp_canvas->bg_image ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
ImagePainter painter (*bmp_canvas);
|
||||
PixelBufferPainter painter (*bmp_canvas->bg_image (), bmp_canvas->canvas_width (), bmp_canvas->canvas_height (), bmp_canvas->resolution ());
|
||||
|
||||
db::DCplxTrans trans = vp.trans ();
|
||||
db::DCplxTrans::inverse_trans trans_inv (trans.inverted ());
|
||||
|
|
@ -694,7 +548,6 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
|
|||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ LayerTreeModel::parent (const QModelIndex &index) const
|
|||
*/
|
||||
static void
|
||||
single_bitmap_to_image (const lay::ViewOp &view_op, lay::Bitmap &bitmap,
|
||||
QImage *pimage, const lay::DitherPattern &dither_pattern, const lay::LineStyles &line_styles,
|
||||
lay::PixelBuffer *pimage, const lay::DitherPattern &dither_pattern, const lay::LineStyles &line_styles,
|
||||
unsigned int width, unsigned int height)
|
||||
{
|
||||
std::vector <lay::ViewOp> view_ops;
|
||||
|
|
@ -640,11 +640,12 @@ LayerTreeModel::icon_for_layer (const lay::LayerPropertiesConstIterator &iter, l
|
|||
lay::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color;
|
||||
lay::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color;
|
||||
|
||||
QImage image (w, h, QImage::Format_ARGB32);
|
||||
lay::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.scanLine (0);
|
||||
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;
|
||||
|
|
@ -773,7 +774,7 @@ LayerTreeModel::icon_for_layer (const lay::LayerPropertiesConstIterator &iter, l
|
|||
// 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 (), w, h);
|
||||
|
||||
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
|
||||
QPixmap pixmap = QPixmap::fromImage (image.to_image ()); // Qt 4.6.0 workaround
|
||||
return QIcon (pixmap);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,17 +136,16 @@ std::string ImageCacheEntry::to_string () const
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
static void
|
||||
blowup (const QImage &src, QImage &dest, unsigned int os)
|
||||
blowup (const lay::PixelBuffer &src, lay::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.scanLine (y);
|
||||
uint32_t *pdest = (uint32_t *) dest.scanLine (y * 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;
|
||||
|
|
@ -158,7 +157,7 @@ blowup (const QImage &src, QImage &dest, unsigned int os)
|
|||
}
|
||||
|
||||
static void
|
||||
subsample (const QImage &src, QImage &dest, unsigned int os, double g)
|
||||
subsample (const lay::PixelBuffer &src, lay::PixelBuffer &dest, unsigned int os, double g)
|
||||
{
|
||||
// TODO: this is probably not compatible with the endianess of SPARC ..
|
||||
|
||||
|
|
@ -203,7 +202,7 @@ subsample (const QImage &src, QImage &dest, unsigned int os, double g)
|
|||
|
||||
{
|
||||
|
||||
const unsigned char *psrc = src.scanLine (y * os);
|
||||
const unsigned char *psrc = (const unsigned char *) src.scan_line (y * os);
|
||||
unsigned short *pdest = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
|
@ -230,7 +229,7 @@ subsample (const QImage &src, QImage &dest, unsigned int os, double g)
|
|||
|
||||
for (unsigned int i = 1; i < os; ++i) {
|
||||
|
||||
const unsigned char *psrc = src.scanLine (y * 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) {
|
||||
|
|
@ -251,7 +250,7 @@ subsample (const QImage &src, QImage &dest, unsigned int os, double g)
|
|||
|
||||
{
|
||||
|
||||
unsigned char *pdest = dest.scanLine (y);
|
||||
unsigned char *pdest = (unsigned char *) dest.scan_line (y);
|
||||
const unsigned short *psrc = buffer;
|
||||
|
||||
for (unsigned int x = 0; x < xmax; ++x) {
|
||||
|
|
@ -279,9 +278,7 @@ invert (unsigned char *data, unsigned int width, unsigned int height)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
LayoutCanvas::LayoutCanvas (QWidget *parent, lay::LayoutViewBase *view, const char *name)
|
||||
: lay::ViewObjectWidget (parent, name),
|
||||
mp_view (view),
|
||||
|
|
@ -296,25 +293,11 @@ LayoutCanvas::LayoutCanvas (QWidget *parent, lay::LayoutViewBase *view, const ch
|
|||
m_do_update_image_dm (this, &LayoutCanvas::do_update_image),
|
||||
m_do_end_of_drawing_dm (this, &LayoutCanvas::do_end_of_drawing),
|
||||
m_image_cache_size (1)
|
||||
#else
|
||||
LayoutCanvas::LayoutCanvas (lay::LayoutViewBase *view)
|
||||
: lay::ViewObjectWidget (),
|
||||
mp_view (view),
|
||||
// @@@ mp_image (0), mp_image_bg (0), mp_pixmap (0),
|
||||
m_background (0), m_foreground (0), m_active (0),
|
||||
m_oversampling (1),
|
||||
m_dpr (1),
|
||||
m_need_redraw (false),
|
||||
m_redraw_clearing (false),
|
||||
m_redraw_force_update (true),
|
||||
m_update_image (true),
|
||||
m_do_update_image_dm (this, &LayoutCanvas::do_update_image),
|
||||
m_do_end_of_drawing_dm (this, &LayoutCanvas::do_end_of_drawing),
|
||||
m_image_cache_size (1)
|
||||
#endif
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
#if QT_VERSION > 0x050000
|
||||
m_dpr = devicePixelRatio ();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The gamma value used for subsampling: something between 1.8 and 2.2.
|
||||
|
|
@ -326,12 +309,14 @@ LayoutCanvas::LayoutCanvas (lay::LayoutViewBase *view)
|
|||
|
||||
mp_redraw_thread = new lay::RedrawThread (this, view);
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#if defined(HAVE_QT)
|
||||
setBackgroundRole (QPalette::NoRole);
|
||||
set_colors (lay::Color (palette ().color (QPalette::Normal, QPalette::Window).rgb ()),
|
||||
lay::Color (palette ().color (QPalette::Normal, QPalette::Text).rgb ()),
|
||||
lay::Color (palette ().color (QPalette::Normal, QPalette::Mid).rgb ()));
|
||||
setAttribute (Qt::WA_NoSystemBackground);
|
||||
#else
|
||||
set_colors (0xffffffff, 0xff000000, 0xffc0c0c0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +325,6 @@ LayoutCanvas::~LayoutCanvas ()
|
|||
// Detach all listeners so we don't trigger events in the destructor
|
||||
viewport_changed_event.clear ();
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
if (mp_image) {
|
||||
delete mp_image;
|
||||
mp_image = 0;
|
||||
|
|
@ -349,6 +333,7 @@ LayoutCanvas::~LayoutCanvas ()
|
|||
delete mp_image_bg;
|
||||
mp_image_bg = 0;
|
||||
}
|
||||
#if defined(HAVE_QT)
|
||||
if (mp_pixmap) {
|
||||
delete mp_pixmap;
|
||||
mp_pixmap = 0;
|
||||
|
|
@ -415,12 +400,10 @@ LayoutCanvas::set_colors (lay::Color background, lay::Color foreground, lay::Col
|
|||
m_active = active.rgb ();
|
||||
|
||||
// force regeneration of background image ..
|
||||
#if defined(HAVE_QT) // @@@
|
||||
if (mp_image_bg) {
|
||||
delete mp_image_bg;
|
||||
}
|
||||
mp_image_bg = 0;
|
||||
#endif
|
||||
|
||||
update_image ();
|
||||
}
|
||||
|
|
@ -459,17 +442,13 @@ LayoutCanvas::prepare_drawing ()
|
|||
|
||||
BitmapViewObjectCanvas::set_size (m_viewport_l.width (), m_viewport_l.height (), 1.0 / double (m_oversampling * m_dpr));
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
if (! mp_image ||
|
||||
(unsigned int) mp_image->width () != m_viewport_l.width () ||
|
||||
(unsigned int) mp_image->height () != m_viewport_l.height ()) {
|
||||
if (mp_image) {
|
||||
delete mp_image;
|
||||
}
|
||||
mp_image = new QImage (m_viewport_l.width (), m_viewport_l.height (), QImage::Format_RGB32);
|
||||
#if QT_VERSION > 0x050000
|
||||
mp_image->setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
mp_image = new lay::PixelBuffer (m_viewport_l.width (), m_viewport_l.height ());
|
||||
if (mp_pixmap) {
|
||||
delete mp_pixmap;
|
||||
mp_pixmap = 0;
|
||||
|
|
@ -477,7 +456,6 @@ LayoutCanvas::prepare_drawing ()
|
|||
}
|
||||
|
||||
mp_image->fill (m_background);
|
||||
#endif
|
||||
|
||||
// Cancel any pending "finish" event so there is no race between finish and restart (important for caching)
|
||||
m_do_end_of_drawing_dm.cancel ();
|
||||
|
|
@ -613,7 +591,7 @@ LayoutCanvas::paintEvent (QPaintEvent *)
|
|||
if (mp_image_bg) {
|
||||
delete mp_image_bg;
|
||||
}
|
||||
mp_image_bg = new QImage (*mp_image);
|
||||
mp_image_bg = new lay::PixelBuffer (*mp_image);
|
||||
|
||||
} else {
|
||||
// else reuse the saved image
|
||||
|
|
@ -636,8 +614,8 @@ LayoutCanvas::paintEvent (QPaintEvent *)
|
|||
// and static foreground objects
|
||||
|
||||
if (! mp_pixmap || needs_update_static () ||
|
||||
mp_image->size ().width () != mp_pixmap->size ().width () * int (m_oversampling) ||
|
||||
mp_image->size ().height () != mp_pixmap->size ().height () * int (m_oversampling)) {
|
||||
int (mp_image->width ()) != mp_pixmap->size ().width () * int (m_oversampling) ||
|
||||
int (mp_image->height ()) != mp_pixmap->size ().height () * int (m_oversampling)) {
|
||||
|
||||
if (mp_pixmap) {
|
||||
delete mp_pixmap;
|
||||
|
|
@ -650,36 +628,45 @@ LayoutCanvas::paintEvent (QPaintEvent *)
|
|||
|
||||
if (fg_bitmaps () > 0) {
|
||||
|
||||
QImage full_image (*mp_image);
|
||||
#if QT_VERSION > 0x050000
|
||||
full_image.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
lay::PixelBuffer full_image (*mp_image);
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
|
||||
// render the foreground parts ..
|
||||
if (m_oversampling == 1) {
|
||||
*mp_pixmap = QPixmap::fromImage (full_image); // Qt 4.6.0 workaround
|
||||
} else {
|
||||
QImage subsampled_image (m_viewport.width (), m_viewport.height (), mp_image->format ());
|
||||
QImage img = full_image.to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
subsampled_image.setDevicePixelRatio (double (m_dpr));
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
*mp_pixmap = QPixmap::fromImage (img); // Qt 4.6.0 workaround
|
||||
} else {
|
||||
lay::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);
|
||||
*mp_pixmap = QPixmap::fromImage (subsampled_image); // Qt 4.6.0 workaround
|
||||
QImage img = subsampled_image.to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
*mp_pixmap = QPixmap::fromImage (img); // Qt 4.6.0 workaround
|
||||
}
|
||||
|
||||
} else if (m_oversampling == 1) {
|
||||
|
||||
*mp_pixmap = QPixmap::fromImage (*mp_image);
|
||||
QImage img = mp_image->to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
*mp_pixmap = QPixmap::fromImage (img);
|
||||
|
||||
} else {
|
||||
|
||||
QImage subsampled_image (m_viewport.width (), m_viewport.height (), mp_image->format ());
|
||||
#if QT_VERSION > 0x050000
|
||||
subsampled_image.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
lay::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_pixmap = QPixmap::fromImage (subsampled_image);
|
||||
QImage img = subsampled_image.to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
*mp_pixmap = QPixmap::fromImage (img);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -697,24 +684,28 @@ LayoutCanvas::paintEvent (QPaintEvent *)
|
|||
|
||||
if (fg_bitmaps () > 0) {
|
||||
|
||||
QImage full_image (mp_image->size ().width (), mp_image->size ().height (), QImage::Format_ARGB32);
|
||||
lay::PixelBuffer full_image (mp_image->width (), mp_image->height ());
|
||||
full_image.set_transparent (true);
|
||||
full_image.fill (0);
|
||||
|
||||
#if QT_VERSION > 0x050000
|
||||
full_image.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
bitmaps_to_image (fg_view_op_vector (), fg_bitmap_vector (), dither_pattern (), line_styles (), &full_image, m_viewport_l.width (), m_viewport_l.height (), false, &m_mutex);
|
||||
|
||||
// render the foreground parts ..
|
||||
if (m_oversampling == 1) {
|
||||
painter.drawPixmap (QPoint (0, 0), QPixmap::fromImage (full_image));
|
||||
} else {
|
||||
QImage subsampled_image (m_viewport.width (), m_viewport.height (), QImage::Format_ARGB32);
|
||||
QImage img = full_image.to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
subsampled_image.setDevicePixelRatio (double (m_dpr));
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
painter.drawPixmap (QPoint (0, 0), QPixmap::fromImage (img));
|
||||
} else {
|
||||
lay::PixelBuffer subsampled_image (m_viewport.width (), m_viewport.height ());
|
||||
subsampled_image.set_transparent (true);
|
||||
subsample (full_image, subsampled_image, m_oversampling, m_gamma);
|
||||
painter.drawPixmap (QPoint (0, 0), QPixmap::fromImage (subsampled_image));
|
||||
QImage img = subsampled_image.to_image ();
|
||||
#if QT_VERSION > 0x050000
|
||||
img.setDevicePixelRatio (double (m_dpr));
|
||||
#endif
|
||||
painter.drawPixmap (QPoint (0, 0), QPixmap::fromImage (img));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -731,20 +722,20 @@ LayoutCanvas::paintEvent (QPaintEvent *)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
class DetachedViewObjectCanvas
|
||||
: public BitmapViewObjectCanvas
|
||||
{
|
||||
public:
|
||||
DetachedViewObjectCanvas (lay::Color bg, lay::Color fg, lay::Color ac, unsigned int width_l, unsigned int height_l, double resolution, QImage *img)
|
||||
DetachedViewObjectCanvas (lay::Color bg, lay::Color fg, lay::Color ac, unsigned int width_l, unsigned int height_l, double resolution, lay::PixelBuffer *img)
|
||||
: BitmapViewObjectCanvas (width_l, height_l, resolution),
|
||||
m_bg (bg), m_fg (fg), m_ac (ac), mp_image (img)
|
||||
{
|
||||
// TODO: Good choice?
|
||||
m_gamma = 2.0;
|
||||
|
||||
if (img->width () != int (width_l) || img->height () != int (height_l)) {
|
||||
mp_image_l = new QImage (width_l, height_l, img->format ());
|
||||
if (img->width () != width_l || img->height () != height_l) {
|
||||
mp_image_l = new lay::PixelBuffer (width_l, height_l);
|
||||
mp_image_l->set_transparent (img->transparent ());
|
||||
mp_image_l->fill (bg.rgb ());
|
||||
} else {
|
||||
mp_image_l = 0;
|
||||
|
|
@ -776,9 +767,9 @@ public:
|
|||
return m_ac;
|
||||
}
|
||||
|
||||
virtual QImage &bg_image ()
|
||||
virtual lay::PixelBuffer *bg_image ()
|
||||
{
|
||||
return mp_image_l ? *mp_image_l : *mp_image;
|
||||
return mp_image_l ? mp_image_l : mp_image;
|
||||
}
|
||||
|
||||
void transfer_to_image (const lay::DitherPattern &dp, const lay::LineStyles &ls, unsigned int width, unsigned int height)
|
||||
|
|
@ -804,23 +795,61 @@ public:
|
|||
|
||||
private:
|
||||
lay::Color m_bg, m_fg, m_ac;
|
||||
QImage *mp_image;
|
||||
QImage *mp_image_l;
|
||||
lay::PixelBuffer *mp_image;
|
||||
lay::PixelBuffer *mp_image_l;
|
||||
double m_gamma;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
QImage
|
||||
/**
|
||||
* @brief A simplistic monochrome canvas
|
||||
*
|
||||
* NOTE: this canvas does not support background painting (currently the background objects
|
||||
* do not support monochrome background painting anyway).
|
||||
* Nor does it support subsampling (that would mean grayscale).
|
||||
*/
|
||||
class DetachedViewObjectCanvasMono
|
||||
: public BitmapViewObjectCanvas
|
||||
{
|
||||
public:
|
||||
DetachedViewObjectCanvasMono (bool bg, bool fg, bool ac, unsigned int width, unsigned int height)
|
||||
: BitmapViewObjectCanvas (width, height, 1.0),
|
||||
m_bg (bg), m_fg (fg), m_ac (ac)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
~DetachedViewObjectCanvasMono ()
|
||||
{
|
||||
clear_fg_bitmaps ();
|
||||
}
|
||||
|
||||
lay::Color background_color () const
|
||||
{
|
||||
return m_bg ? 0xffffffff : 0;
|
||||
}
|
||||
|
||||
lay::Color foreground_color () const
|
||||
{
|
||||
return m_fg ? 0xffffffff : 0;
|
||||
}
|
||||
|
||||
lay::Color active_color () const
|
||||
{
|
||||
return m_ac ? 0xffffffff : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_bg, m_fg, m_ac;
|
||||
};
|
||||
|
||||
lay::PixelBuffer
|
||||
LayoutCanvas::image (unsigned int width, unsigned int height)
|
||||
{
|
||||
return image_with_options (width, height, -1, -1, -1.0, lay::Color (), lay::Color (), lay::Color (), db::DBox (), false);
|
||||
return image_with_options (width, height, -1, -1, -1.0, lay::Color (), lay::Color (), lay::Color (), db::DBox ());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
QImage
|
||||
LayoutCanvas::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 is_mono)
|
||||
lay::PixelBuffer
|
||||
LayoutCanvas::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)
|
||||
{
|
||||
if (oversampling <= 0) {
|
||||
oversampling = m_oversampling;
|
||||
|
|
@ -842,19 +871,14 @@ LayoutCanvas::image_with_options (unsigned int width, unsigned int height, int l
|
|||
}
|
||||
|
||||
// TODO: for other architectures MonoLSB may not be the right format
|
||||
QImage img (width, height, is_mono ? QImage::Format_MonoLSB : QImage::Format_RGB32);
|
||||
lay::PixelBuffer img (width, height);
|
||||
|
||||
// this may happen for BIG images:
|
||||
if (img.width () != int (width) || img.height () != int (height)) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to create an image with size %dx%d pixels")), width, height);
|
||||
if (img.width () != width || img.height () != height) {
|
||||
throw tl::Exception (tl::to_string (tr ("Unable to create an image with size %dx%d pixels")), width, height);
|
||||
}
|
||||
|
||||
if (is_mono) {
|
||||
// in mono mode the background's color is white for green > 128 and black otherwise
|
||||
img.fill ((background.rgb () & 0x8000) >> 15);
|
||||
} else {
|
||||
img.fill (background.rgb ());
|
||||
}
|
||||
img.fill (background.rgb ());
|
||||
|
||||
// provide canvas objects for the layout bitmaps and the foreground/background objects
|
||||
BitmapRedrawThreadCanvas rd_canvas;
|
||||
|
|
@ -882,43 +906,71 @@ LayoutCanvas::image_with_options (unsigned int width, unsigned int height, int l
|
|||
redraw_thread.stop (); // safety
|
||||
|
||||
// paint the background objects. It uses "img" to paint on.
|
||||
if (! is_mono) {
|
||||
do_render_bg (vp, vo_canvas);
|
||||
|
||||
do_render_bg (vp, vo_canvas);
|
||||
// paint the layout bitmaps
|
||||
rd_canvas.to_image (view_ops, dither_pattern (), line_styles (), background, foreground, active, this, *vo_canvas.bg_image (), vp.width (), vp.height ());
|
||||
|
||||
// paint the layout bitmaps
|
||||
rd_canvas.to_image (view_ops, dither_pattern (), line_styles (), background, foreground, active, this, vo_canvas.bg_image (), vp.width (), vp.height ());
|
||||
// subsample current image to provide the background for the foreground objects
|
||||
vo_canvas.make_background ();
|
||||
|
||||
// subsample current image to provide the background for the foreground objects
|
||||
vo_canvas.make_background ();
|
||||
// render the foreground parts ..
|
||||
do_render (vp, vo_canvas, true);
|
||||
vo_canvas.transfer_to_image (dither_pattern (), line_styles (), width, height);
|
||||
|
||||
// render the foreground parts ..
|
||||
do_render (vp, vo_canvas, true);
|
||||
vo_canvas.transfer_to_image (dither_pattern (), line_styles (), width, height);
|
||||
|
||||
do_render (vp, vo_canvas, false);
|
||||
vo_canvas.transfer_to_image (dither_pattern (), line_styles (), width, height);
|
||||
|
||||
} else {
|
||||
|
||||
// TODO: Painting of background objects???
|
||||
// paint the layout bitmaps
|
||||
rd_canvas.to_image (view_ops, dither_pattern (), line_styles (), background, foreground, active, this, vo_canvas.bg_image (), vp.width (), vp.height ());
|
||||
|
||||
}
|
||||
do_render (vp, vo_canvas, false);
|
||||
vo_canvas.transfer_to_image (dither_pattern (), line_styles (), width, height);
|
||||
|
||||
return img;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
QImage
|
||||
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)
|
||||
{
|
||||
if (linewidth <= 0) {
|
||||
linewidth = 1;
|
||||
}
|
||||
|
||||
// provide canvas objects for the layout bitmaps and the foreground/background objects
|
||||
BitmapRedrawThreadCanvas rd_canvas;
|
||||
DetachedViewObjectCanvasMono vo_canvas (background, foreground, active, width, height);
|
||||
|
||||
// compute the new viewport
|
||||
db::DBox tb (target_box);
|
||||
if (tb.empty ()) {
|
||||
tb = m_viewport.target_box ();
|
||||
}
|
||||
Viewport vp (width, height, tb);
|
||||
vp.set_global_trans (m_viewport.global_trans ());
|
||||
|
||||
std::vector<lay::ViewOp> view_ops (m_view_ops);
|
||||
if (linewidth > 1) {
|
||||
for (std::vector<lay::ViewOp>::iterator vo = view_ops.begin (); vo != view_ops.end (); ++vo) {
|
||||
vo->width (std::min (31, vo->width () * linewidth));
|
||||
}
|
||||
}
|
||||
|
||||
lay::RedrawThread redraw_thread (&rd_canvas, mp_view);
|
||||
|
||||
// render the layout
|
||||
redraw_thread.start (0 /*synchronous*/, m_layers, vp, 1.0, true);
|
||||
redraw_thread.stop (); // safety
|
||||
|
||||
lay::BitmapBuffer img (width, height);
|
||||
img.fill (background);
|
||||
|
||||
rd_canvas.to_image_mono (view_ops, dither_pattern (), line_styles (), background, foreground, active, this, img, vp.width (), vp.height ());
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
lay::PixelBuffer
|
||||
LayoutCanvas::screenshot ()
|
||||
{
|
||||
// if required, start the redraw thread ..
|
||||
prepare_drawing ();
|
||||
|
||||
QImage img (m_viewport.width (), m_viewport.height (), QImage::Format_RGB32);
|
||||
lay::PixelBuffer img (m_viewport.width (), m_viewport.height ());
|
||||
img.fill (m_background);
|
||||
|
||||
DetachedViewObjectCanvas vo_canvas (background_color (), foreground_color (), active_color (), m_viewport_l.width (), m_viewport_l.height (), 1.0 / double (m_oversampling * m_dpr), &img);
|
||||
|
|
@ -927,7 +979,7 @@ LayoutCanvas::screenshot ()
|
|||
do_render_bg (m_viewport_l, vo_canvas);
|
||||
|
||||
// paint the layout bitmaps
|
||||
to_image (m_view_ops, dither_pattern (), line_styles (), background_color (), foreground_color (), active_color (), this, vo_canvas.bg_image (), m_viewport_l.width (), m_viewport_l.height ());
|
||||
to_image (m_view_ops, dither_pattern (), line_styles (), background_color (), foreground_color (), active_color (), this, *vo_canvas.bg_image (), m_viewport_l.width (), m_viewport_l.height ());
|
||||
|
||||
// subsample current image to provide the background for the foreground objects
|
||||
vo_canvas.make_background ();
|
||||
|
|
@ -941,7 +993,6 @@ LayoutCanvas::screenshot ()
|
|||
|
||||
return img;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
void
|
||||
|
|
@ -1036,7 +1087,7 @@ LayoutCanvas::event (QEvent *e)
|
|||
// GTF probe event
|
||||
// record the contents (the screenshot) as ASCII text
|
||||
if (gtf::Recorder::instance () && gtf::Recorder::instance ()->recording ()) {
|
||||
gtf::Recorder::instance ()->probe (this, gtf::image_to_variant (screenshot ()));
|
||||
gtf::Recorder::instance ()->probe (this, gtf::image_to_variant (screenshot ().to_image_copy ()));
|
||||
}
|
||||
|
||||
e->accept ();
|
||||
|
|
|
|||
|
|
@ -170,11 +170,10 @@ public:
|
|||
return m_view_ops;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
QImage screenshot ();
|
||||
QImage image (unsigned int width, unsigned int height);
|
||||
QImage 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
|
||||
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);
|
||||
|
||||
void update_image ();
|
||||
|
||||
|
|
@ -316,15 +315,13 @@ public:
|
|||
return lay::Color (m_active);
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
/**
|
||||
* @brief Reimplementation of ViewObjectCanvas: background image
|
||||
*/
|
||||
QImage &bg_image ()
|
||||
lay::PixelBuffer *bg_image ()
|
||||
{
|
||||
return *mp_image;
|
||||
return mp_image;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of RedrawThreadCanvas: signal end of drawing
|
||||
|
|
@ -362,9 +359,9 @@ public:
|
|||
|
||||
private:
|
||||
lay::LayoutViewBase *mp_view;
|
||||
lay::PixelBuffer *mp_image;
|
||||
lay::PixelBuffer *mp_image_bg;
|
||||
#if defined(HAVE_QT) // @@@
|
||||
QImage *mp_image;
|
||||
QImage *mp_image_bg;
|
||||
QPixmap *mp_pixmap;
|
||||
#endif
|
||||
db::DBox m_precious_box;
|
||||
|
|
|
|||
|
|
@ -2452,7 +2452,7 @@ LayoutViewBase::init_layer_properties (LayerProperties &p, const LayerProperties
|
|||
p.set_marked (false);
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#if defined(HAVE_QT) // @@@ add methods without QImage!!!!
|
||||
QImage
|
||||
LayoutViewBase::get_screenshot ()
|
||||
{
|
||||
|
|
@ -2461,7 +2461,7 @@ LayoutViewBase::get_screenshot ()
|
|||
// Execute all deferred methods - ensure there are no pending tasks
|
||||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
return mp_canvas->screenshot ();
|
||||
return mp_canvas->screenshot ().to_image_copy ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2491,7 +2491,7 @@ LayoutViewBase::save_screenshot (const std::string &fn)
|
|||
// Execute all deferred methods - ensure there are no pending tasks
|
||||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
if (! writer.write (mp_canvas->screenshot ())) {
|
||||
if (! writer.write (mp_canvas->screenshot ().to_image ())) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ()));
|
||||
}
|
||||
|
||||
|
|
@ -2506,19 +2506,23 @@ LayoutViewBase::get_image (unsigned int width, unsigned int height)
|
|||
// Execute all deferred methods - ensure there are no pending tasks
|
||||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
return mp_canvas->image (width, height);
|
||||
return mp_canvas->image (width, height).to_image_copy ();
|
||||
}
|
||||
|
||||
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)
|
||||
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")));
|
||||
|
||||
// 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, monochrome);
|
||||
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 ();
|
||||
} else {
|
||||
return mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box).to_image_copy ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2544,7 +2548,7 @@ LayoutViewBase::save_image (const std::string &fn, unsigned int width, unsigned
|
|||
// Execute all deferred methods - ensure there are no pending tasks
|
||||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
if (! writer.write (mp_canvas->image (width, height))) {
|
||||
if (! writer.write (mp_canvas->image (width, height).to_image ())) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ()));
|
||||
}
|
||||
|
||||
|
|
@ -2575,9 +2579,15 @@ LayoutViewBase::save_image_with_options (const std::string &fn,
|
|||
|
||||
// Execute all deferred methods - ensure there are no pending tasks
|
||||
tl::DeferredMethodScheduler::execute ();
|
||||
|
||||
if (! writer.write (mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, background, foreground, active, target_box, monochrome))) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ()));
|
||||
|
||||
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 ())) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unable to write screenshot to file: %s (%s)")), fn, tl::to_string (writer.errorString ()));
|
||||
}
|
||||
} else {
|
||||
if (! writer.write (mp_canvas->image_with_options (width, height, linewidth, oversampling, resolution, 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 ()));
|
||||
}
|
||||
}
|
||||
|
||||
tl::log << "Saved screen shot to " << fn;
|
||||
|
|
@ -2741,7 +2751,6 @@ LayoutViewBase::reload_layout (unsigned int cv_index)
|
|||
set_properties (new_props);
|
||||
|
||||
goto_view (state);
|
||||
|
||||
}
|
||||
|
||||
unsigned int
|
||||
|
|
|
|||
|
|
@ -0,0 +1,171 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "layPixelBufferPainter.h"
|
||||
|
||||
#include "layFixedFont.h"
|
||||
#include "layPixelBuffer.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
PixelBufferPainter::PixelBufferPainter (lay::PixelBuffer &img, unsigned int width, unsigned int height, double resolution)
|
||||
: mp_img (&img),
|
||||
m_resolution (resolution), m_width (width), m_height (height)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
PixelBufferPainter::set (const db::Point &p, lay::Color c)
|
||||
{
|
||||
if (p.x () >= 0 && p.x () < m_width && p.y () >= 0 && p.y () < m_height) {
|
||||
((unsigned int *) mp_img->scan_line (p.y ())) [p.x ()] = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PixelBufferPainter::draw_line (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
if (p1.x () == p2.x ()) {
|
||||
|
||||
int x = p1.x ();
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
if ((y2 >= 0 || y1 < m_height) && x >= 0 && x < m_width) {
|
||||
y1 = std::max (y1, 0);
|
||||
y2 = std::min (y2, m_height - 1);
|
||||
for (int y = y1; y <= y2; ++y) {
|
||||
((unsigned int *) mp_img->scan_line (y)) [x] = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (p1.y () == p2.y ()) {
|
||||
|
||||
int y = p1.y ();
|
||||
int x1 = std::min (p1.x (), p2.x ());
|
||||
int x2 = std::max (p1.x (), p2.x ());
|
||||
if ((x2 >= 0 || x1 < m_width) && y >= 0 && y < m_height) {
|
||||
x1 = std::max (x1, 0);
|
||||
x2 = std::min (x2, m_width - 1);
|
||||
unsigned int *sl = (unsigned int *) mp_img->scan_line (y) + x1;
|
||||
for (int x = x1; x <= x2; ++x) {
|
||||
*sl++ = c.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// TODO: not implemented yet.
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PixelBufferPainter::fill_rect (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
for (int y = y1; y <= y2; ++y) {
|
||||
draw_line (db::Point (p1.x (), y), db::Point (p2.x (), y), c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PixelBufferPainter::draw_rect (const db::Point &p1, const db::Point &p2, lay::Color c)
|
||||
{
|
||||
int y1 = std::min (p1.y (), p2.y ());
|
||||
int y2 = std::max (p1.y (), p2.y ());
|
||||
int x1 = std::min (p1.x (), p2.x ());
|
||||
int x2 = std::max (p1.x (), p2.x ());
|
||||
draw_line (db::Point (x1, y1), db::Point (x2, y1), c);
|
||||
draw_line (db::Point (x1, y2), db::Point (x2, y2), c);
|
||||
draw_line (db::Point (x1, y1), db::Point (x1, y2), c);
|
||||
draw_line (db::Point (x2, y1), db::Point (x2, y2), c);
|
||||
}
|
||||
|
||||
void
|
||||
PixelBufferPainter::draw_text (const char *t, const db::Point &p, lay::Color c, int halign, int valign)
|
||||
{
|
||||
const lay::FixedFont &ff = lay::FixedFont::get_font (m_resolution);
|
||||
int x = p.x (), y = p.y ();
|
||||
|
||||
if (halign < 0) {
|
||||
x -= ff.width () * int (strlen (t));
|
||||
} else if (halign == 0) {
|
||||
x -= ff.width () * int (strlen (t)) / 2;
|
||||
}
|
||||
|
||||
if (valign < 0) {
|
||||
y += ff.height ();
|
||||
} else if (valign == 0) {
|
||||
y += ff.height () / 2;
|
||||
}
|
||||
|
||||
// TODO: simple implementation
|
||||
for (; *t; ++t) {
|
||||
|
||||
unsigned char ch = *t;
|
||||
|
||||
if (x < -int (ff.width ()) || x >= int (mp_img->width ()) || y < 0 || y >= int (mp_img->height () + ff.height ())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch < ff.first_char () || (ch - ff.first_char ()) >= ff.n_chars ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t *dc = ff.data () + size_t (ch - ff.first_char ()) * ff.height () * ff.stride ();
|
||||
for (unsigned int i = 0; i < ff.height (); ++i, dc += ff.stride ()) {
|
||||
|
||||
int iy = y - ff.height () + i + 1;
|
||||
if (iy >= 0 || iy < int (mp_img->height ())) {
|
||||
|
||||
uint32_t *d = (uint32_t *) mp_img->scan_line (y - ff.height () + i);
|
||||
uint32_t m = 1;
|
||||
int ix = x;
|
||||
const uint32_t *ds = dc;
|
||||
|
||||
for (unsigned int j = 0; j < ff.width (); ++j, ++ix) {
|
||||
|
||||
if ((*ds & m) && ix >= 0 && ix < int (mp_img->width ())) {
|
||||
d[ix] = c.rgb ();
|
||||
}
|
||||
|
||||
m <<= 1;
|
||||
// word wrap
|
||||
if (m == 0) {
|
||||
++ds;
|
||||
m = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
x += ff.width ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2022 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HDR_layPixelBufferPainter
|
||||
#define HDR_layPixelBufferPainter
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
|
||||
#include "layColor.h"
|
||||
#include "dbPoint.h"
|
||||
|
||||
namespace lay {
|
||||
|
||||
class PixelBuffer;
|
||||
|
||||
/**
|
||||
* @brief A very simplistic painter for lay::PixelBuffer
|
||||
*
|
||||
* This painter supports very few primitives currently and is used to paint the
|
||||
* background grid for example.
|
||||
*/
|
||||
class LAYBASIC_PUBLIC PixelBufferPainter
|
||||
{
|
||||
public:
|
||||
PixelBufferPainter (lay::PixelBuffer &img, unsigned int width, unsigned int height, double resolution);
|
||||
|
||||
void set (const db::Point &p, lay::Color c);
|
||||
void draw_line (const db::Point &p1, const db::Point &p2, lay::Color c);
|
||||
void fill_rect (const db::Point &p1, const db::Point &p2, lay::Color c);
|
||||
void draw_rect (const db::Point &p1, const db::Point &p2, lay::Color c);
|
||||
void draw_text (const char *t, const db::Point &p, lay::Color c, int halign, int valign);
|
||||
|
||||
private:
|
||||
lay::PixelBuffer *mp_img;
|
||||
double m_resolution;
|
||||
int m_width, m_height;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -23,16 +23,10 @@
|
|||
|
||||
#include "layRedrawThreadCanvas.h"
|
||||
#include "layCanvasPlane.h"
|
||||
#if defined(HAVE_QT)
|
||||
#include "layBitmapsToImage.h"
|
||||
#endif
|
||||
#include "layDrawing.h"
|
||||
#include "layBitmap.h"
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#include <QImage>
|
||||
#endif
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
|
|
@ -397,9 +391,8 @@ BitmapRedrawThreadCanvas::initialize_plane (lay::CanvasPlane *plane, unsigned in
|
|||
unlock ();
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
void
|
||||
BitmapRedrawThreadCanvas::to_image (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, lay::Color background, lay::Color foreground, lay::Color active, const lay::Drawings *drawings, QImage &img, unsigned int width, unsigned int height)
|
||||
void
|
||||
BitmapRedrawThreadCanvas::to_image (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, lay::Color background, lay::Color foreground, lay::Color active, const lay::Drawings *drawings, lay::PixelBuffer &img, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (width > m_width) {
|
||||
width = m_width;
|
||||
|
|
@ -417,7 +410,27 @@ BitmapRedrawThreadCanvas::to_image (const std::vector <lay::ViewOp> &view_ops, c
|
|||
bitmaps_to_image (d->get_view_ops (*this, background, foreground, active), *bt, dp, ls, &img, width, height, true, &mutex ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
BitmapRedrawThreadCanvas::to_image_mono (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, bool background, bool foreground, bool active, const lay::Drawings *drawings, lay::BitmapBuffer &img, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (width > m_width) {
|
||||
width = m_width;
|
||||
}
|
||||
if (height > m_height) {
|
||||
height = m_height;
|
||||
}
|
||||
|
||||
unsigned int all_one = 0xffffffff;
|
||||
|
||||
// convert the plane data to image data
|
||||
bitmaps_to_image (view_ops, mp_plane_buffers, dp, ls, &img, width, height, true, &mutex ());
|
||||
|
||||
// convert the planes of the "drawing" objects too:
|
||||
std::vector <std::vector <lay::Bitmap *> >::const_iterator bt = mp_drawing_plane_buffers.begin ();
|
||||
for (lay::Drawings::const_iterator d = drawings->begin (); d != drawings->end () && bt != mp_drawing_plane_buffers.end (); ++d, ++bt) {
|
||||
bitmaps_to_image (d->get_view_ops (*this, background ? all_one : 0, foreground ? all_one : 0, active ? all_one : 0), *bt, dp, ls, &img, width, height, true, &mutex ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbTrans.h"
|
||||
#include "layViewOp.h"
|
||||
#include "layBitmapRenderer.h"
|
||||
#include "layPixelBuffer.h"
|
||||
#include "tlThreads.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -315,12 +316,15 @@ public:
|
|||
return new lay::BitmapRenderer (m_width, m_height, resolution ());
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
/**
|
||||
* @brief Transfer the content to an QImage
|
||||
* @brief Transfer the content to a PixelBuffer
|
||||
*/
|
||||
void to_image (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, lay::Color background, lay::Color foreground, lay::Color active, const lay::Drawings *drawings, QImage &img, unsigned int width, unsigned int height);
|
||||
#endif
|
||||
void to_image (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, lay::Color background, lay::Color foreground, lay::Color active, const lay::Drawings *drawings, PixelBuffer &img, unsigned int width, unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief Transfer the content to a BitmapBuffer (monochrome)
|
||||
*/
|
||||
void to_image_mono (const std::vector <lay::ViewOp> &view_ops, const lay::DitherPattern &dp, const lay::LineStyles &ls, bool background, bool foreground, bool active, const lay::Drawings *drawings, lay::BitmapBuffer &img, unsigned int width, unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief Gets the current bitmap data as a BitmapCanvasData object
|
||||
|
|
|
|||
|
|
@ -1244,5 +1244,18 @@ BitmapViewObjectCanvas::set_size (double resolution)
|
|||
m_resolution = resolution;
|
||||
}
|
||||
|
||||
lay::PixelBuffer *
|
||||
BitmapViewObjectCanvas::bg_image ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
lay::BitmapBuffer *
|
||||
BitmapViewObjectCanvas::bg_bitmap ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ class ViewObjectWidget;
|
|||
class ViewObjectCanvas;
|
||||
class CanvasPlane;
|
||||
class Bitmap;
|
||||
class PixelBuffer;
|
||||
class BitmapBuffer;
|
||||
|
||||
LAYBASIC_PUBLIC const char *drag_drop_mime_type ();
|
||||
|
||||
|
|
@ -1350,13 +1352,6 @@ public:
|
|||
*/
|
||||
void clear_fg_bitmaps ();
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
/**
|
||||
* @brief Return the background image
|
||||
*/
|
||||
virtual QImage &bg_image () = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the width and height and resolution
|
||||
*/
|
||||
|
|
@ -1388,6 +1383,16 @@ public:
|
|||
return m_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the pixel buffer that background objects render to
|
||||
*/
|
||||
virtual lay::PixelBuffer *bg_image ();
|
||||
|
||||
/**
|
||||
* @brief Gets the monochrome pixel buffer that background objects render to
|
||||
*/
|
||||
virtual lay::BitmapBuffer *bg_bitmap ();
|
||||
|
||||
private:
|
||||
std::map <lay::ViewOp, unsigned int> m_fg_bitmap_table;
|
||||
std::map <std::vector <lay::ViewOp>, unsigned int> m_fgv_bitmap_table;
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
|
|||
layNetlistBrowserPage.cc \
|
||||
layNetlistBrowserTreeModel.cc \
|
||||
layNetlistCrossReferenceModel.cc \
|
||||
layPixelBuffer.cc \
|
||||
layPixelBuffer.cc \
|
||||
layPixelBufferPainter.cc \
|
||||
layPluginConfigPage.cc \
|
||||
layProperties.cc \
|
||||
layPropertiesDialog.cc \
|
||||
|
|
@ -212,7 +213,8 @@ DEFINES += MAKE_LAYBASIC_LIBRARY
|
|||
layNetlistBrowserPage.h \
|
||||
layNetlistBrowserTreeModel.h \
|
||||
layNetlistCrossReferenceModel.h \
|
||||
layPixelBuffer.h \
|
||||
layPixelBuffer.h \
|
||||
layPixelBufferPainter.h \
|
||||
layPluginConfigPage.h \
|
||||
layProperties.h \
|
||||
layPropertiesDialog.h \
|
||||
|
|
|
|||
|
|
@ -20,23 +20,19 @@
|
|||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QT) // @@@
|
||||
#include "layBitmapsToImage.h"
|
||||
#include "layBitmap.h"
|
||||
#include "layDitherPattern.h"
|
||||
#include "layLineStyles.h"
|
||||
#include "layPixelBuffer.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QColor>
|
||||
#include <QMutex>
|
||||
|
||||
std::string
|
||||
to_string (const QImage &img, unsigned int mask)
|
||||
to_string (const lay::PixelBuffer &img, unsigned int mask)
|
||||
{
|
||||
std::string s;
|
||||
for (unsigned int i = 0; i < 32; ++i) {
|
||||
const unsigned int *data = (const unsigned int *)img.scanLine (i);
|
||||
const unsigned int *data = (const unsigned int *)img.scan_line (i);
|
||||
for (unsigned int j = 0; j < 32; ++j) {
|
||||
s += (data[j] & mask) ? "x" : ".";
|
||||
}
|
||||
|
|
@ -89,7 +85,7 @@ TEST(1)
|
|||
view_ops.push_back (lay::ViewOp (0x000080, lay::ViewOp::Copy, 0, 0, 0, lay::ViewOp::Rect, 1));
|
||||
view_ops.push_back (lay::ViewOp (0x0000c0, lay::ViewOp::Or, 0, 0, 0, lay::ViewOp::Rect, 3));
|
||||
|
||||
QImage img (QSize (32, 32), QImage::Format_RGB32);
|
||||
lay::PixelBuffer img (32, 32);
|
||||
img.fill (0);
|
||||
|
||||
lay::DitherPattern dp;
|
||||
|
|
@ -939,5 +935,3 @@ TEST(1)
|
|||
);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue