<commit_before>#include "zxing/ZXing.h"
#include "QZXingFilter.h"

#include <QDebug>
#include <QtConcurrent/QtConcurrent>
//#include "QZXingImageProvider.h"

namespace {
    uchar gray(uchar r, uchar g, uchar b)
    {
        return (306 * (r & 0xFF) +
                601 * (g & 0xFF) +
                117 * (b & 0xFF) +
                0x200) >> 10;
    }
    uchar yuvToGray(uchar Y, uchar U, uchar V)
    {
        const int C = int(Y) - 16;
        const int D = int(U) - 128;
        const int E = int(V) - 128;
        return gray(
            qBound(0, ((298 * C + 409 * E + 128) >> 8), 255),
            qBound(0, ((298 * C - 100 * D - 208 * E + 128) >> 8), 255),
            qBound(0, ((298 * C + 516 * D + 128) >> 8), 255)
        );
    }

    uchar yuvToGray2(uchar y, uchar u, uchar v)
    {
        double rD = y + 1.4075 * (v - 128);
        double gD = y - 0.3455 * (u - 128) - (0.7169 * (v - 128));
        double bD = y + 1.7790 * (u - 128);

        return gray(
            qBound<uchar>(0, (uchar)::floor(rD), 255),
            qBound<uchar>(0, (uchar)::floor(gD), 255),
            qBound<uchar>(0, (uchar)::floor(bD), 255)
        );
    }
}

QZXingFilter::QZXingFilter(QObject *parent)
    : QAbstractVideoFilter(parent)
    , decoder(QZXing::DecoderFormat_QR_CODE)
    , decoding(false)
{
    /// Connecting signals to handlers that will send signals to QML
    connect(&decoder, &QZXing::decodingStarted,
            this, &QZXingFilter::handleDecodingStarted);
    connect(&decoder, &QZXing::decodingFinished,
            this, &QZXingFilter::handleDecodingFinished);
}

QZXingFilter::~QZXingFilter()
{
    if(!processThread.isFinished()) {
      processThread.cancel();
      processThread.waitForFinished();
    }
}

void QZXingFilter::handleDecodingStarted()
{
    decoding = true;
    emit decodingStarted();
    emit isDecodingChanged();
}

void QZXingFilter::handleDecodingFinished(bool succeeded)
{
    decoding = false;
    emit decodingFinished(succeeded, decoder.getProcessTimeOfLastDecoding());
    emit isDecodingChanged();
}

QVideoFilterRunnable * QZXingFilter::createFilterRunnable()
{
    return new QZXingFilterRunnable(this);
}

///
/// QZXingFilterRunnable
///

QZXingFilterRunnable::QZXingFilterRunnable(QZXingFilter * filter)
    : QObject(ZXING_NULLPTR)
    , filter(filter)
{

}
QZXingFilterRunnable::~QZXingFilterRunnable()
{
    filter = ZXING_NULLPTR;
}

QVideoFrame QZXingFilterRunnable::run(QVideoFrame * input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags)
{
    Q_UNUSED(surfaceFormat);
    Q_UNUSED(flags);

    /// We dont want to decode every single frame we get, as this would be very costly
    /// These checks are attempt on having only 1 frame being processed at a time.
    if(!input || !input->isValid())
    {
        //qDebug() << "[QZXingFilterRunnable] Invalid Input ";
        return QVideoFrame();
    }
    if(filter->isDecoding())
    {
        //qDebug() << "------ decoder busy.";
        return * input;
    }
    if(!filter->processThread.isFinished())
    {
        //qDebug() << "--[]-- decoder busy.";
        return * input;
    }

    filter->decoding = true;

    /// Copy the data we need to the filter.
	/// TODO: Depending on the system / platform, this copy hangs up the UI for some seconds. Fix this.
    filter->frame.copyData(* input);

    /// All processing that has to happen in another thread, as we are now in the UI thread.
    filter->processThread = QtConcurrent::run(this, &QZXingFilterRunnable::processVideoFrameProbed, filter->frame, filter->captureRect.toRect());

    return * input;
}

static bool isRectValid(const QRect& rect)
{
  return rect.x() >= 0 && rect.y() >= 0 && rect.isValid();
}

struct CaptureRect
{
    CaptureRect(const QRect& captureRect, int sourceWidth, int sourceHeight)
        : isValid(isRectValid(captureRect))
        , sourceWidth(sourceWidth)
        , sourceHeight(sourceHeight)
        , startX(isValid ? captureRect.x() : 0)
        , targetWidth(isValid ? captureRect.width() : sourceWidth)
        , endX(startX + targetWidth)
        , startY(isValid ? captureRect.y() : 0)
        , targetHeight(isValid ? captureRect.height() : sourceHeight)
        , endY(startY + targetHeight)
    {}

    bool isValid;
    char pad[3]; // avoid warning about padding

    int sourceWidth;
    int sourceHeight;

    int startX;
    int targetWidth;
    int endX;

    int startY;
    int targetHeight;
    int endY;
};

static QImage* rgbDataToGrayscale(const uchar* data, const CaptureRect& captureRect,
                                 const int alpha, const int red,
                                 const int green, const int blue,
                                 const bool isPremultiplied = false)
{
    const int stride = (alpha < 0) ? 3 : 4;

    const int endX = captureRect.sourceWidth - captureRect.startX - captureRect.targetWidth;
    const int skipX = (endX + captureRect.startX) * stride;

    QImage *image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
    uchar* pixelInit = image_ptr->bits();
    data += (captureRect.startY * captureRect.sourceWidth + captureRect.startX) * stride;
    for (int y = 1; y <= captureRect.targetHeight; ++y) {

    //Quick fix for iOS devices. Will be handled better in the future
#ifdef Q_OS_IOS
        uchar* pixel = pixelInit + (y - 1) * captureRect.targetWidth;
#else
        uchar* pixel = pixelInit + (captureRect.targetHeight - y) * captureRect.targetWidth;
#endif
        for (int x = 0; x < captureRect.targetWidth; ++x) {
            uchar r = data[red];
            uchar g = data[green];
            uchar b = data[blue];
            if (isPremultiplied) {
                uchar a = data[alpha];
                r = uchar((uint(r) * 255) / a);
                g = uchar((uint(g) * 255) / a);
                b = uchar((uint(b) * 255) / a);
            }
            *pixel = gray(r, g, b);
            ++pixel;
            data += stride;
        }
        data += skipX;
    }

    return image_ptr;
}

void QZXingFilterRunnable::processVideoFrameProbed(SimpleVideoFrame & videoFrame, const QRect& _captureRect)
{
    if (videoFrame.data.length() < 1) {
        qDebug() << "QZXingFilterRunnable: Buffer is empty";
        filter->decoding = false;
        return;
    }

    static unsigned int i = 0; i++;
//    qDebug() << "Future: Going to process frame: " << i;

    const int width = videoFrame.size.width();
    const int height = videoFrame.size.height();
    const CaptureRect captureRect(_captureRect, width, height);
    const uchar* data = reinterpret_cast<const uchar *>(videoFrame.data.constData());

    uchar* pixel;
    int wh;
    int w_2;
    int wh_54;

    const uint32_t *yuvPtr = reinterpret_cast<const uint32_t *>(data);

    /// Create QImage from QVideoFrame.
    QImage *image_ptr = ZXING_NULLPTR;

    switch (videoFrame.pixelFormat) {
    case QVideoFrame::Format_RGB32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3);
        break;
    case QVideoFrame::Format_ARGB32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3);
	break;
    case QVideoFrame::Format_ARGB32_Premultiplied:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3, true);
        break;
    case QVideoFrame::Format_BGRA32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGRA32_Premultiplied:
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0, true);
        break;
    case QVideoFrame::Format_BGR32:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
    case QVideoFrame::Format_ABGR32:
#endif
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGR24:
        image_ptr = rgbDataToGrayscale(data, captureRect, -1, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGR555:
        /// This is a forced "conversion", colors end up swapped.
        image_ptr = new QImage(data, width, height, QImage::Format_RGB555);
        break;
    case QVideoFrame::Format_BGR565:
        /// This is a forced "conversion", colors end up swapped.
        image_ptr = new QImage(data, width, height, QImage::Format_RGB16);
        break;
    case QVideoFrame::Format_YUV420P:
    case QVideoFrame::Format_NV12:
        /// nv12 format, encountered on macOS
        image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
        pixel = image_ptr->bits();
        wh = width * height;
        w_2 = width / 2;
        wh_54 = wh * 5 / 4;

        for (int y = captureRect.startY; y < captureRect.endY; y++) {
            const int Y_offset = y * width;
            const int y_2 = y / 2;
            const int U_offset = y_2 * w_2 + wh;
            const int V_offset = y_2 * w_2 + wh_54;
            for (int x = captureRect.startX; x < captureRect.endX; x++) {
                const int x_2 = x / 2;
                const uchar Y = data[Y_offset + x];
                const uchar U = data[U_offset + x_2];
                const uchar V = data[V_offset + x_2];
                *pixel = yuvToGray(Y, U, V);
                ++pixel;
            }
        }

        break;
    case QVideoFrame::Format_YUYV:
        image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
        pixel = image_ptr->bits();

        for (int y = captureRect.startY; y < captureRect.endY; y++){
            const uint32_t *row = &yuvPtr[y*(width/2)];
            int end = captureRect.startX/2 + (captureRect.endX - captureRect.startX)/2;
            for (int x = captureRect.startX/2; x < end; x++){
                const uint8_t *pxl = reinterpret_cast<const uint8_t *>(&row[x]);
                const uint8_t y0 = pxl[0];
                const uint8_t u  = pxl[1];
                const uint8_t v  = pxl[3];
                const uint8_t y1 = pxl[2];

                *pixel = yuvToGray2(y0, u, v);
                ++pixel;
                *pixel = yuvToGray2(y1, u, v);
                ++pixel;
            }
        }

        break;
        /// TODO: Handle (create QImages from) YUV formats.
    default:
        QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(videoFrame.pixelFormat);
        image_ptr = new QImage(data, width, height, imageFormat);
        break;
    }

    if(!image_ptr || image_ptr->isNull())
    {
        qDebug() << "QZXingFilterRunnable error: Cant create image file to process.";
        qDebug() << "Maybe it was a format conversion problem? ";
        qDebug() << "VideoFrame format: " << videoFrame.pixelFormat;
        qDebug() << "Image corresponding format: " << QVideoFrame::imageFormatFromPixelFormat(videoFrame.pixelFormat);
        filter->decoding = false;
        return;
    }

    if (captureRect.isValid && image_ptr->size() != _captureRect.size())
        image_ptr = new QImage(image_ptr->copy(_captureRect));

    //qDebug() << "image.size()" << image_ptr->size();
    //qDebug() << "image.format()" << image_ptr->format();
    //qDebug() << "videoFrame.pixelFormat" << videoFrame.pixelFormat;
    //const QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/qrtest/test_" + QString::number(i % 100) + ".png";
    //qDebug() << "saving image" << i << "at:" << path << image_ptr->save(path);

    //QZXingImageProvider::getInstance()->storeImage(image);

    decode(*image_ptr);

    delete image_ptr;
}

QString QZXingFilterRunnable::decode(const QImage &image)
{
    return (filter != ZXING_NULLPTR) ?
      filter->decoder.decodeImage(image, image.width(), image.height()) : QString();
}
<commit_msg>Fix NV21 conversion (#124)<commit_after>#include "zxing/ZXing.h"
#include "QZXingFilter.h"

#include <QDebug>
#include <QtConcurrent/QtConcurrent>
//#include "QZXingImageProvider.h"

namespace {
    uchar gray(uchar r, uchar g, uchar b)
    {
        return (306 * (r & 0xFF) +
                601 * (g & 0xFF) +
                117 * (b & 0xFF) +
                0x200) >> 10;
    }
    uchar yuvToGray(uchar Y, uchar U, uchar V)
    {
        const int C = int(Y) - 16;
        const int D = int(U) - 128;
        const int E = int(V) - 128;
        return gray(
            qBound(0, ((298 * C + 409 * E + 128) >> 8), 255),
            qBound(0, ((298 * C - 100 * D - 208 * E + 128) >> 8), 255),
            qBound(0, ((298 * C + 516 * D + 128) >> 8), 255)
        );
    }

    uchar yuvToGray2(uchar y, uchar u, uchar v)
    {
        double rD = y + 1.4075 * (v - 128);
        double gD = y - 0.3455 * (u - 128) - (0.7169 * (v - 128));
        double bD = y + 1.7790 * (u - 128);

        return gray(
            qBound<uchar>(0, (uchar)::floor(rD), 255),
            qBound<uchar>(0, (uchar)::floor(gD), 255),
            qBound<uchar>(0, (uchar)::floor(bD), 255)
        );
    }
}

QZXingFilter::QZXingFilter(QObject *parent)
    : QAbstractVideoFilter(parent)
    , decoder(QZXing::DecoderFormat_QR_CODE)
    , decoding(false)
{
    /// Connecting signals to handlers that will send signals to QML
    connect(&decoder, &QZXing::decodingStarted,
            this, &QZXingFilter::handleDecodingStarted);
    connect(&decoder, &QZXing::decodingFinished,
            this, &QZXingFilter::handleDecodingFinished);
}

QZXingFilter::~QZXingFilter()
{
    if(!processThread.isFinished()) {
      processThread.cancel();
      processThread.waitForFinished();
    }
}

void QZXingFilter::handleDecodingStarted()
{
    decoding = true;
    emit decodingStarted();
    emit isDecodingChanged();
}

void QZXingFilter::handleDecodingFinished(bool succeeded)
{
    decoding = false;
    emit decodingFinished(succeeded, decoder.getProcessTimeOfLastDecoding());
    emit isDecodingChanged();
}

QVideoFilterRunnable * QZXingFilter::createFilterRunnable()
{
    return new QZXingFilterRunnable(this);
}

///
/// QZXingFilterRunnable
///

QZXingFilterRunnable::QZXingFilterRunnable(QZXingFilter * filter)
    : QObject(ZXING_NULLPTR)
    , filter(filter)
{

}
QZXingFilterRunnable::~QZXingFilterRunnable()
{
    filter = ZXING_NULLPTR;
}

QVideoFrame QZXingFilterRunnable::run(QVideoFrame * input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags)
{
    Q_UNUSED(surfaceFormat);
    Q_UNUSED(flags);

    /// We dont want to decode every single frame we get, as this would be very costly
    /// These checks are attempt on having only 1 frame being processed at a time.
    if(!input || !input->isValid())
    {
        //qDebug() << "[QZXingFilterRunnable] Invalid Input ";
        return QVideoFrame();
    }
    if(filter->isDecoding())
    {
        //qDebug() << "------ decoder busy.";
        return * input;
    }
    if(!filter->processThread.isFinished())
    {
        //qDebug() << "--[]-- decoder busy.";
        return * input;
    }

    filter->decoding = true;

    /// Copy the data we need to the filter.
	/// TODO: Depending on the system / platform, this copy hangs up the UI for some seconds. Fix this.
    filter->frame.copyData(* input);

    /// All processing that has to happen in another thread, as we are now in the UI thread.
    filter->processThread = QtConcurrent::run(this, &QZXingFilterRunnable::processVideoFrameProbed, filter->frame, filter->captureRect.toRect());

    return * input;
}

static bool isRectValid(const QRect& rect)
{
  return rect.x() >= 0 && rect.y() >= 0 && rect.isValid();
}

struct CaptureRect
{
    CaptureRect(const QRect& captureRect, int sourceWidth, int sourceHeight)
        : isValid(isRectValid(captureRect))
        , sourceWidth(sourceWidth)
        , sourceHeight(sourceHeight)
        , startX(isValid ? captureRect.x() : 0)
        , targetWidth(isValid ? captureRect.width() : sourceWidth)
        , endX(startX + targetWidth)
        , startY(isValid ? captureRect.y() : 0)
        , targetHeight(isValid ? captureRect.height() : sourceHeight)
        , endY(startY + targetHeight)
    {}

    bool isValid;
    char pad[3]; // avoid warning about padding

    int sourceWidth;
    int sourceHeight;

    int startX;
    int targetWidth;
    int endX;

    int startY;
    int targetHeight;
    int endY;
};

static QImage* rgbDataToGrayscale(const uchar* data, const CaptureRect& captureRect,
                                 const int alpha, const int red,
                                 const int green, const int blue,
                                 const bool isPremultiplied = false)
{
    const int stride = (alpha < 0) ? 3 : 4;

    const int endX = captureRect.sourceWidth - captureRect.startX - captureRect.targetWidth;
    const int skipX = (endX + captureRect.startX) * stride;

    QImage *image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
    uchar* pixelInit = image_ptr->bits();
    data += (captureRect.startY * captureRect.sourceWidth + captureRect.startX) * stride;
    for (int y = 1; y <= captureRect.targetHeight; ++y) {

    //Quick fix for iOS devices. Will be handled better in the future
#ifdef Q_OS_IOS
        uchar* pixel = pixelInit + (y - 1) * captureRect.targetWidth;
#else
        uchar* pixel = pixelInit + (captureRect.targetHeight - y) * captureRect.targetWidth;
#endif
        for (int x = 0; x < captureRect.targetWidth; ++x) {
            uchar r = data[red];
            uchar g = data[green];
            uchar b = data[blue];
            if (isPremultiplied) {
                uchar a = data[alpha];
                r = uchar((uint(r) * 255) / a);
                g = uchar((uint(g) * 255) / a);
                b = uchar((uint(b) * 255) / a);
            }
            *pixel = gray(r, g, b);
            ++pixel;
            data += stride;
        }
        data += skipX;
    }

    return image_ptr;
}

static void YUV_NV21_TO_RGB(uchar* argb, const uchar* yuv, int width, int height) {
    int frameSize = width * height;

    int ii = 0;
    int ij = 0;
    int di = +1;
    int dj = +1;

    int a = 0;
    for (int i = 0, ci = ii; i < height; ++i, ci += di) {
        for (int j = 0, cj = ij; j < width; ++j, cj += dj) {
            int y = (0xff & ((int) yuv[ci * width + cj]));
            int v = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 0]));
            int u = (0xff & ((int) yuv[frameSize + (ci >> 1) * width + (cj & ~1) + 1]));
            y = y < 16 ? 16 : y;

            int r = (int) (1.164f * (y - 16) + 1.596f * (v - 128));
            int g = (int) (1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
            int b = (int) (1.164f * (y - 16) + 2.018f * (u - 128));

            r = r < 0 ? 0 : (r > 255 ? 255 : r);
            g = g < 0 ? 0 : (g > 255 ? 255 : g);
            b = b < 0 ? 0 : (b > 255 ? 255 : b);

            argb[a++] = 0xff000000 | (r << 16) | (g << 8) | b;
        }
    }
}

void QZXingFilterRunnable::processVideoFrameProbed(SimpleVideoFrame & videoFrame, const QRect& _captureRect)
{
    if (videoFrame.data.length() < 1) {
        qDebug() << "QZXingFilterRunnable: Buffer is empty";
        filter->decoding = false;
        return;
    }

    static unsigned int i = 0; i++;
//    qDebug() << "Future: Going to process frame: " << i;

    const int width = videoFrame.size.width();
    const int height = videoFrame.size.height();
    const CaptureRect captureRect(_captureRect, width, height);
    const uchar* data = reinterpret_cast<const uchar *>(videoFrame.data.constData());

    uchar* pixel;
    int wh;
    int w_2;
    int wh_54;

    const uint32_t *yuvPtr = reinterpret_cast<const uint32_t *>(data);

    /// Create QImage from QVideoFrame.
    QImage *image_ptr = ZXING_NULLPTR;

    switch (videoFrame.pixelFormat) {
    case QVideoFrame::Format_RGB32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3);
        break;
    case QVideoFrame::Format_ARGB32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3);
	break;
    case QVideoFrame::Format_ARGB32_Premultiplied:
        image_ptr = rgbDataToGrayscale(data, captureRect, 0, 1, 2, 3, true);
        break;
    case QVideoFrame::Format_BGRA32:
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGRA32_Premultiplied:
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0, true);
        break;
    case QVideoFrame::Format_BGR32:
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
    case QVideoFrame::Format_ABGR32:
#endif
        image_ptr = rgbDataToGrayscale(data, captureRect, 3, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGR24:
        image_ptr = rgbDataToGrayscale(data, captureRect, -1, 2, 1, 0);
        break;
    case QVideoFrame::Format_BGR555:
        /// This is a forced "conversion", colors end up swapped.
        image_ptr = new QImage(data, width, height, QImage::Format_RGB555);
        break;
    case QVideoFrame::Format_BGR565:
        /// This is a forced "conversion", colors end up swapped.
        image_ptr = new QImage(data, width, height, QImage::Format_RGB16);
        break;
    case QVideoFrame::Format_YUV420P:
    case QVideoFrame::Format_NV12:
        /// nv12 format, encountered on macOS
        image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
        YUV_NV21_TO_RGB((uchar*) image_ptr->bits(), (const uchar*) yuvPtr, width, height);
        break;
    case QVideoFrame::Format_YUYV:
        image_ptr = new QImage(captureRect.targetWidth, captureRect.targetHeight, QImage::Format_Grayscale8);
        pixel = image_ptr->bits();

        for (int y = captureRect.startY; y < captureRect.endY; y++){
            const uint32_t *row = &yuvPtr[y*(width/2)];
            int end = captureRect.startX/2 + (captureRect.endX - captureRect.startX)/2;
            for (int x = captureRect.startX/2; x < end; x++){
                const uint8_t *pxl = reinterpret_cast<const uint8_t *>(&row[x]);
                const uint8_t y0 = pxl[0];
                const uint8_t u  = pxl[1];
                const uint8_t v  = pxl[3];
                const uint8_t y1 = pxl[2];

                *pixel = yuvToGray2(y0, u, v);
                ++pixel;
                *pixel = yuvToGray2(y1, u, v);
                ++pixel;
            }
        }

        break;
        /// TODO: Handle (create QImages from) YUV formats.
    default:
        QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(videoFrame.pixelFormat);
        image_ptr = new QImage(data, width, height, imageFormat);
        break;
    }

    if(!image_ptr || image_ptr->isNull())
    {
        qDebug() << "QZXingFilterRunnable error: Cant create image file to process.";
        qDebug() << "Maybe it was a format conversion problem? ";
        qDebug() << "VideoFrame format: " << videoFrame.pixelFormat;
        qDebug() << "Image corresponding format: " << QVideoFrame::imageFormatFromPixelFormat(videoFrame.pixelFormat);
        filter->decoding = false;
        return;
    }

    if (captureRect.isValid && image_ptr->size() != _captureRect.size())
        image_ptr = new QImage(image_ptr->copy(_captureRect));

    //qDebug() << "image.size()" << image_ptr->size();
    //qDebug() << "image.format()" << image_ptr->format();
    //qDebug() << "videoFrame.pixelFormat" << videoFrame.pixelFormat;
    //const QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/qrtest/test_" + QString::number(i % 100) + ".png";
    //qDebug() << "saving image" << i << "at:" << path << image_ptr->save(path);

    //QZXingImageProvider::getInstance()->storeImage(image);

    decode(*image_ptr);

    delete image_ptr;
}

QString QZXingFilterRunnable::decode(const QImage &image)
{
    return (filter != ZXING_NULLPTR) ?
      filter->decoder.decodeImage(image, image.width(), image.height()) : QString();
}
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/ts/layerattr_.h"

template class std::pair<bool, std::string>;
template class std::map<std::string, std::pair<bool, std::string> >;
template class std::map< std::string, std::pair<elm::LayerIOKeyType, std::string> >;
<commit_msg>remove extern template instantiation of obsolete type<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/ts/layerattr_.h"

template class std::pair<bool, std::string>;
template class std::map< std::string, std::pair<elm::LayerIOKeyType, std::string> >;
<|endoftext|>


<commit_before>#include "heap.h"

#include <iostream>

Heap::Heap(size_t timestamp, size_t id, std::string type, std::string name)
    : MemoryObject(timestamp, 0, 0, 0), id_(id), type_(type), name_(name)
{

}

Heap::~Heap() {
    //maps manages themselves
}

void Heap::printContent() const {
    std::cout << "printing content for heap " << id_ << " of type: "<< type_.c_str() << "\n";
    for(auto it = cores_.begin(); it != cores_.end(); ++it) {
        it->second.printContent();
    }
}

Core* Heap::getCore(size_t pointer) {
    auto found = cores_.find(pointer);
    if(found == cores_.end()) {
        return nullptr;
    }
    return (&found->second);
}

Core* Heap::getCoreForAllocation(size_t pointer) {
    auto found = alloc_to_core.find(pointer);
    if(found == alloc_to_core.end()) {
        return nullptr;
    }
    return getCore(found->second);
}

bool Heap::removeCore(size_t timestamp, size_t pointer) {
    auto it = cores_.find(pointer);
    if(it == cores_.end()) {
        std::cout << "remove Core failed in heap " << id_ << std::endl;
        return false;
    }
    size_t managed = it->second.getManagedSize();
    managed_memory_ -= managed;
    cores_.erase(it);
    return true;
}

bool Heap::addCore(size_t timestamp, size_t pointer, size_t managed_size) {
    Core c(timestamp, pointer, managed_size);
    auto emp = cores_.insert(std::make_pair(pointer, c));
    if(!emp.second) {
        std::cout << "tryint to add already existing core: " << std::hex << pointer << std::dec << std::endl;
        return false;
    }
    managed_memory_ += managed_size;
    return true;
}

bool Heap::growCore(size_t timestamp, size_t pointer, size_t size) {
    Core* core = getCore(pointer);
    if(core != nullptr) {
        core->grow(size);
        return true;
    }
    return false;
}

bool Heap::shrinkCore(size_t timestamp, size_t pointer, size_t size) {
    Core* core = getCore(pointer);
    if(core != nullptr) {
        core->shrink(size);
        return true;
    }
    return false;
}

bool Heap::addAllocation(size_t timestamp, size_t pointer, size_t size) {
        for(auto it = cores_.begin(); it != cores_.end(); ++it) {
            if(it->second.addAllocation(timestamp, pointer, size)) {
                alloc_to_core.emplace(pointer,it->second.getPointer());
                used_memory_ += size;
                simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
                return true;
            }
        }
        //does the allocation span over two cores?
        for(auto it = cores_.begin(); it != cores_.end(); ++it) {
            auto next = std::next(it);
            if(next != cores_.end()) {
                if(it->second.pointerInside(pointer) && next->second.pointerInside(pointer + size)) {
                    it->second.addAllocation(timestamp,pointer,size, true);
                    alloc_to_core.emplace(pointer,it->second.getPointer());
                    used_memory_ += size;
                    simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
                    return true;
                }
            }
        }
        std::cout << "did not find a core for allocation in heap: " << id_ << " pointer: " << std::hex << pointer << std::dec << " size: " << size << " at timestamp " << timestamp << "\n";
    return false;
}

bool Heap::removeAllocation(size_t timestamp, size_t pointer) {
    Core* core = getCoreForAllocation(pointer);
    if(core == nullptr) {
        std::cout << "core was null for: " << std::hex << pointer << std::dec << "at " << timestamp << std::endl;
        printContent();
        return false;
    }
    size_t removed_memory = core->removeAllocation(timestamp, pointer);
    used_memory_ -= removed_memory;
    simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
    return true;
}

bool Heap::setBackingAllocator(size_t alloc) {
    backing_allocator_ids.push_back(alloc);
    return true;
}

void Heap::printBacking() {
    for(int i = 0; i < backing_allocator_ids.size(); ++i) {
        std::cout << " " << backing_allocator_ids[i];
    }
}<commit_msg>now allocations are removed from alloc-to-core, Added hits when adding to alloc_to_core.<commit_after>#include "heap.h"

#include <iostream>

Heap::Heap(size_t timestamp, size_t id, std::string type, std::string name)
    : MemoryObject(timestamp, 0, 0, 0), id_(id), type_(type), name_(name)
{

}

Heap::~Heap() {
    //maps manages themselves
}

void Heap::printContent() const {
    std::cout << "printing content for heap " << id_ << " of type: "<< type_.c_str() << "\n";
    for(auto it = cores_.begin(); it != cores_.end(); ++it) {
        it->second.printContent();
    }
}

Core* Heap::getCore(size_t pointer) {
    auto found = cores_.find(pointer);
    if(found == cores_.end()) {
        return nullptr;
    }
    return (&found->second);
}

Core* Heap::getCoreForAllocation(size_t pointer) {
    auto found = alloc_to_core.find(pointer);
    if(found == alloc_to_core.end()) {
        return nullptr;
    }
    return getCore(found->second);
}

bool Heap::removeCore(size_t timestamp, size_t pointer) {
    auto it = cores_.find(pointer);
    if(it == cores_.end()) {
        std::cout << "remove Core failed in heap " << id_ << std::endl;
        return false;
    }
    size_t managed = it->second.getManagedSize();
    managed_memory_ -= managed;
    cores_.erase(it);
    return true;
}

bool Heap::addCore(size_t timestamp, size_t pointer, size_t managed_size) {
    Core c(timestamp, pointer, managed_size);
    auto emp = cores_.insert(std::make_pair(pointer, c));
    if(!emp.second) {
        std::cout << "tryint to add already existing core: " << std::hex << pointer << std::dec << std::endl;
        return false;
    }
    managed_memory_ += managed_size;
    return true;
}

bool Heap::growCore(size_t timestamp, size_t pointer, size_t size) {
    Core* core = getCore(pointer);
    if(core != nullptr) {
        core->grow(size);
        return true;
    }
    return false;
}

bool Heap::shrinkCore(size_t timestamp, size_t pointer, size_t size) {
    Core* core = getCore(pointer);
    if(core != nullptr) {
        core->shrink(size);
        return true;
    }
    return false;
}

bool Heap::addAllocation(size_t timestamp, size_t pointer, size_t size) {
        for(auto it = cores_.begin(); it != cores_.end(); ++it) {
            if(it->second.addAllocation(timestamp, pointer, size)) {
                alloc_to_core.emplace_hint(alloc_to_core.cend(), pointer,it->second.getPointer());
                used_memory_ += size;
                simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
                return true;
            }
        }
        //does the allocation span over two cores?
        for(auto it = cores_.begin(); it != cores_.end(); ++it) {
            auto next = std::next(it);
            if(next != cores_.end()) {
                if(it->second.pointerInside(pointer) && next->second.pointerInside(pointer + size)) {
                    it->second.addAllocation(timestamp,pointer,size, true);
                    alloc_to_core.emplace_hint(alloc_to_core.cend(), pointer,it->second.getPointer());
                    used_memory_ += size;
                    simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
                    return true;
                }
            }
        }
        std::cout << "did not find a core for allocation in heap: " << id_ << " pointer: " << std::hex << pointer << std::dec << " size: " << size << " at timestamp " << timestamp << "\n";
    return false;
}

bool Heap::removeAllocation(size_t timestamp, size_t pointer) {
    Core* core = getCoreForAllocation(pointer);
    if(core == nullptr) {
        std::cout << "core was null for: " << std::hex << pointer << std::dec << "at " << timestamp << std::endl;
        printContent();
        return false;
    }
    size_t removed_memory = core->removeAllocation(timestamp, pointer);
    alloc_to_core.erase(pointer);
    used_memory_ -= removed_memory;
    simple_allocation_events_[timestamp] = heap_usage(used_memory_, managed_memory_);
    return true;
}

bool Heap::setBackingAllocator(size_t alloc) {
    backing_allocator_ids.push_back(alloc);
    return true;
}

void Heap::printBacking() {
    for(int i = 0; i < backing_allocator_ids.size(); ++i) {
        std::cout << " " << backing_allocator_ids[i];
    }
}<|endoftext|>


<commit_before>#if WITH_EDITOR
#include "UnrealEnginePythonPrivatePCH.h"

#include "UEPySPythonEditorViewport.h"

#define sw_python_editor_viewport StaticCastSharedRef<SPythonEditorViewport>(self->s_editor_viewport.s_compound_widget.s_widget.s_widget)

static PyObject *py_ue_spython_editor_viewport_get_world(ue_PySPythonEditorViewport *self, PyObject * args) {

	ue_PyUObject *ret = ue_get_python_wrapper(sw_python_editor_viewport->GetPythonWorld());
	if (!ret)
		return PyErr_Format(PyExc_Exception, "uobject is in invalid state");
	Py_INCREF(ret);
	return (PyObject *)ret;
}

static PyObject *py_ue_spython_editor_viewport_set_show_bounds(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:set_show_bounds", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetShowBounds(PyObject_IsTrue(py_bool) ? true : false);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_show_stats(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:set_show_stats", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetShowStats(PyObject_IsTrue(py_bool) ? true : false);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_view_mode(ue_PySPythonEditorViewport *self, PyObject * args) {
	int mode;
	if (!PyArg_ParseTuple(args, "i:set_view_mode", &mode)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetViewMode((EViewModeIndex)mode);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_exposure_settings(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_settings;
	if (!PyArg_ParseTuple(args, "O:set_exposure_settings", &py_settings)) {
		return NULL;
	}

	FExposureSettings *settings = ue_py_check_struct<FExposureSettings>(py_settings);
	if (!settings) {
		return PyErr_Format(PyExc_Exception, "argument is not a FExposureSettings");
	}

	sw_python_editor_viewport->GetViewportClient()->ExposureSettings = *settings;

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_simulate(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:simulate", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->Simulate(PyObject_IsTrue(py_bool) != 0);

	Py_RETURN_NONE;
}

static PyMethodDef ue_PySPythonEditorViewport_methods[] = {
	{ "simulate", (PyCFunction)py_ue_spython_editor_viewport_simulate, METH_VARARGS, "" },
	{ "get_world", (PyCFunction)py_ue_spython_editor_viewport_get_world, METH_VARARGS, "" },
	{ "set_show_bounds", (PyCFunction)py_ue_spython_editor_viewport_set_show_bounds, METH_VARARGS, "" },
	{ "set_show_stats", (PyCFunction)py_ue_spython_editor_viewport_set_show_stats, METH_VARARGS, "" },
	{ "set_view_mode", (PyCFunction)py_ue_spython_editor_viewport_set_view_mode, METH_VARARGS, "" },
	{ "set_exposure_settings", (PyCFunction)py_ue_spython_editor_viewport_set_exposure_settings, METH_VARARGS, "" },
	{ NULL }  /* Sentinel */
};

UWorld *SPythonEditorViewport::GetPythonWorld() {
	return GetWorld();
}

TSharedRef<FEditorViewportClient> SPythonEditorViewport::MakeEditorViewportClient() {
	TSharedPtr<FEditorViewportClient> client = MakeShareable(new FEditorViewportClient(nullptr, new FPreviewScene(), SharedThis(this)));

	client->SetRealtime(true);

	client->SetViewportType(ELevelViewportType::LVT_Perspective);

	FExposureSettings settings;
	settings.bFixed = true;
	settings.LogOffset = 0;

	client->ExposureSettings = settings;

	return client.ToSharedRef();
}

TSharedPtr<FExtender> SPythonEditorViewport::GetExtenders() const {
	TSharedPtr<FExtender> Result(MakeShareable(new FExtender()));
	return Result;
}

TSharedRef<SEditorViewport> SPythonEditorViewport::GetViewportWidget() {
	return SharedThis(this);
}

TSharedPtr<SWidget> SPythonEditorViewport::MakeViewportToolbar() {
	return SNew(SCommonEditorViewportToolbarBase, SharedThis(this));
}

void SPythonEditorViewport::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) {
	SEditorViewport::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	if (bSimulate) {
		GetWorld()->Tick(ELevelTick::LEVELTICK_All, InDeltaTime);
	}
}

PyTypeObject ue_PySPythonEditorViewportType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"unreal_engine.SPythonEditorViewport", /* tp_name */
	sizeof(ue_PySPythonEditorViewport), /* tp_basicsize */
	0,                         /* tp_itemsize */
	0,       /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_reserved */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	0,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /* tp_flags */
	"Unreal Engine SPythonEditorViewport",           /* tp_doc */
	0,                         /* tp_traverse */
	0,                         /* tp_clear */
	0,                         /* tp_richcompare */
	0,                         /* tp_weaklistoffset */
	0,                         /* tp_iter */
	0,                         /* tp_iternext */
	ue_PySPythonEditorViewport_methods,             /* tp_methods */
};

static int ue_py_spython_editor_viewport_init(ue_PySPythonEditorViewport *self, PyObject *args, PyObject *kwargs) {
	ue_py_snew_simple(SPythonEditorViewport, s_editor_viewport.s_compound_widget.s_widget);
	return 0;
}

void ue_python_init_spython_editor_viewport(PyObject *ue_module) {

	ue_PySPythonEditorViewportType.tp_init = (initproc)ue_py_spython_editor_viewport_init;

	ue_PySPythonEditorViewportType.tp_base = &ue_PySEditorViewportType;

	if (PyType_Ready(&ue_PySPythonEditorViewportType) < 0)
		return;

	Py_INCREF(&ue_PySPythonEditorViewportType);
	PyModule_AddObject(ue_module, "SPythonEditorViewport", (PyObject *)&ue_PySPythonEditorViewportType);
}
#endif<commit_msg>improved SPythonEditorViewport<commit_after>#if WITH_EDITOR
#include "UnrealEnginePythonPrivatePCH.h"

#include "UEPySPythonEditorViewport.h"

#define sw_python_editor_viewport StaticCastSharedRef<SPythonEditorViewport>(self->s_editor_viewport.s_compound_widget.s_widget.s_widget)

static PyObject *py_ue_spython_editor_viewport_get_world(ue_PySPythonEditorViewport *self, PyObject * args) {

	ue_PyUObject *ret = ue_get_python_wrapper(sw_python_editor_viewport->GetPythonWorld());
	if (!ret)
		return PyErr_Format(PyExc_Exception, "uobject is in invalid state");
	Py_INCREF(ret);
	return (PyObject *)ret;
}

static PyObject *py_ue_spython_editor_viewport_set_show_bounds(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:set_show_bounds", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetShowBounds(PyObject_IsTrue(py_bool) ? true : false);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_show_stats(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:set_show_stats", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetShowStats(PyObject_IsTrue(py_bool) ? true : false);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_view_mode(ue_PySPythonEditorViewport *self, PyObject * args) {
	int mode;
	if (!PyArg_ParseTuple(args, "i:set_view_mode", &mode)) {
		return NULL;
	}

	sw_python_editor_viewport->GetViewportClient()->SetViewMode((EViewModeIndex)mode);

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_set_exposure_settings(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_settings;
	if (!PyArg_ParseTuple(args, "O:set_exposure_settings", &py_settings)) {
		return NULL;
	}

	FExposureSettings *settings = ue_py_check_struct<FExposureSettings>(py_settings);
	if (!settings) {
		return PyErr_Format(PyExc_Exception, "argument is not a FExposureSettings");
	}

	sw_python_editor_viewport->GetViewportClient()->ExposureSettings = *settings;

	Py_INCREF(self);
	return (PyObject *)self;
}

static PyObject *py_ue_spython_editor_viewport_simulate(ue_PySPythonEditorViewport *self, PyObject * args) {
	PyObject *py_bool;
	if (!PyArg_ParseTuple(args, "O:simulate", &py_bool)) {
		return NULL;
	}

	sw_python_editor_viewport->Simulate(PyObject_IsTrue(py_bool) != 0);

	Py_RETURN_NONE;
}

static PyMethodDef ue_PySPythonEditorViewport_methods[] = {
	{ "simulate", (PyCFunction)py_ue_spython_editor_viewport_simulate, METH_VARARGS, "" },
	{ "get_world", (PyCFunction)py_ue_spython_editor_viewport_get_world, METH_VARARGS, "" },
	{ "set_show_bounds", (PyCFunction)py_ue_spython_editor_viewport_set_show_bounds, METH_VARARGS, "" },
	{ "set_show_stats", (PyCFunction)py_ue_spython_editor_viewport_set_show_stats, METH_VARARGS, "" },
	{ "set_view_mode", (PyCFunction)py_ue_spython_editor_viewport_set_view_mode, METH_VARARGS, "" },
	{ "set_exposure_settings", (PyCFunction)py_ue_spython_editor_viewport_set_exposure_settings, METH_VARARGS, "" },
	{ NULL }  /* Sentinel */
};

class FPythonEditorViewportClient : public FEditorViewportClient {
public:
	FPythonEditorViewportClient(FEditorModeTools * InModeTools, FPreviewScene * InPreviewScene, const TWeakPtr<SEditorViewport> & InEditorViewportWidget) :
		FEditorViewportClient(InModeTools, InPreviewScene, InEditorViewportWidget) {

		EngineShowFlags.SetSelection(true);
		EngineShowFlags.SetSelectionOutline(true);

		SelectedActor = nullptr;
	}

	virtual void ProcessClick(FSceneView & InView, HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY) {
		if (!HitProxy) {
			GEditor->SelectNone(true, true, true);
			SelectedActor = nullptr;
			return;
		}

		if (HitProxy->IsA(HActor::StaticGetType())) {
			HActor *h_actor = (HActor *)HitProxy;
			GEditor->SelectNone(true, true, true);
			GEditor->SelectActor(h_actor->Actor, true, true);

			SelectedActor = h_actor->Actor;

			SetWidgetMode(FWidget::WM_Translate);
		}
		else if (HitProxy->IsA(HWidgetAxis::StaticGetType())) {
			// TODO do something ?
		}
		else {
			GEditor->SelectNone(true, true, true);
			SelectedActor = nullptr;
		}
	}

	virtual FWidget::EWidgetMode GetWidgetMode() const {
		if (SelectedActor == nullptr)
			return FWidget::WM_None;
		return FEditorViewportClient::GetWidgetMode();
	}

	virtual FMatrix GetWidgetCoordSystem() const {
		if (!SelectedActor)
			return FMatrix::Identity;
		return FRotationMatrix(SelectedActor->GetActorTransform().Rotator());
	}

	virtual FVector GetWidgetLocation() const {
		if (!SelectedActor)
			return FVector(0, 0, 0);
		return SelectedActor->GetActorLocation();
	}

	virtual bool InputWidgetDelta(FViewport * InViewport, EAxisList::Type CurrentAxis, FVector & Drag, FRotator & Rot, FVector &Scale) {
		if (SelectedActor) {
			SelectedActor->AddActorWorldOffset(Drag);
			SelectedActor->AddActorWorldRotation(Rot);
			SelectedActor->SetActorScale3D(SelectedActor->GetActorScale3D() + Scale);
			Invalidate();
			return true;
		}

		return false;
	}

protected:

	AActor *SelectedActor;
};

UWorld *SPythonEditorViewport::GetPythonWorld() {
	return GetWorld();
}

TSharedRef<FEditorViewportClient> SPythonEditorViewport::MakeEditorViewportClient() {
	TSharedPtr<FEditorViewportClient> client = MakeShareable(new FPythonEditorViewportClient(nullptr, new FPreviewScene(), SharedThis(this)));

	client->SetRealtime(true);

	client->SetViewportType(ELevelViewportType::LVT_Perspective);

	FExposureSettings settings;
	settings.bFixed = true;
	settings.LogOffset = 0;

	client->ExposureSettings = settings;

	return client.ToSharedRef();
}

TSharedPtr<FExtender> SPythonEditorViewport::GetExtenders() const {
	TSharedPtr<FExtender> Result(MakeShareable(new FExtender()));
	return Result;
}

TSharedRef<SEditorViewport> SPythonEditorViewport::GetViewportWidget() {
	return SharedThis(this);
}

TSharedPtr<SWidget> SPythonEditorViewport::MakeViewportToolbar() {
	return SNew(SCommonEditorViewportToolbarBase, SharedThis(this));
}

void SPythonEditorViewport::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) {
	SEditorViewport::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	if (bSimulate) {
		GetWorld()->Tick(ELevelTick::LEVELTICK_All, InDeltaTime);
	}
}

PyTypeObject ue_PySPythonEditorViewportType = {
	PyVarObject_HEAD_INIT(NULL, 0)
	"unreal_engine.SPythonEditorViewport", /* tp_name */
	sizeof(ue_PySPythonEditorViewport), /* tp_basicsize */
	0,                         /* tp_itemsize */
	0,       /* tp_dealloc */
	0,                         /* tp_print */
	0,                         /* tp_getattr */
	0,                         /* tp_setattr */
	0,                         /* tp_reserved */
	0,                         /* tp_repr */
	0,                         /* tp_as_number */
	0,                         /* tp_as_sequence */
	0,                         /* tp_as_mapping */
	0,                         /* tp_hash  */
	0,                         /* tp_call */
	0,                         /* tp_str */
	0,                         /* tp_getattro */
	0,                         /* tp_setattro */
	0,                         /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /* tp_flags */
	"Unreal Engine SPythonEditorViewport",           /* tp_doc */
	0,                         /* tp_traverse */
	0,                         /* tp_clear */
	0,                         /* tp_richcompare */
	0,                         /* tp_weaklistoffset */
	0,                         /* tp_iter */
	0,                         /* tp_iternext */
	ue_PySPythonEditorViewport_methods,             /* tp_methods */
};

static int ue_py_spython_editor_viewport_init(ue_PySPythonEditorViewport *self, PyObject *args, PyObject *kwargs) {
	ue_py_snew_simple(SPythonEditorViewport, s_editor_viewport.s_compound_widget.s_widget);
	return 0;
}

void ue_python_init_spython_editor_viewport(PyObject *ue_module) {

	ue_PySPythonEditorViewportType.tp_init = (initproc)ue_py_spython_editor_viewport_init;

	ue_PySPythonEditorViewportType.tp_base = &ue_PySEditorViewportType;

	if (PyType_Ready(&ue_PySPythonEditorViewportType) < 0)
		return;

	Py_INCREF(&ue_PySPythonEditorViewportType);
	PyModule_AddObject(ue_module, "SPythonEditorViewport", (PyObject *)&ue_PySPythonEditorViewportType);
}
#endif<|endoftext|>


<commit_before><commit_msg>Fix: `#include` guard: systematic macro name.<commit_after><|endoftext|>


<commit_before><commit_msg>Remove obsolete comment.<commit_after><|endoftext|>


<commit_before>// ImageProcessor
// Class to handle the processing of the image sequence

#include "imageProcessor.h"

ImageProcessor::ImageProcessor()
{
	width = 480;
	height = 480;

	minVal = 0;
	maxVal = 255;
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;

	fileStem = "picpick";
	fileType = ".png";
}

ImageProcessor::~ImageProcessor()
{
}

void ImageProcessor::addFile(string fileName)
{
	if(!fileName.empty())
		fileNames.push_back(fileName);
}

void ImageProcessor::setFrames(int newFrames)
{
	frames = newFrames;
}

void ImageProcessor::setInputDirectory(string newDir)
{
	inputDirectory = newDir;
}

void ImageProcessor::setBucketSize(int newSize)
{
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;
}

int ImageProcessor::getABucket(int value)
{
	if (value < minVal)
		return 0;

	if (value > maxVal)
		return buckets - 1;

	return value / bucketSize;
}

int ImageProcessor::getBBucket(int value)
{
	return getABucket(value + (bucketSize / 2));
}

void ImageProcessor::processSequence()
{
	CImg<unsigned char> visu(width, height, 1, 3, 0);
	CImgDisplay main_disp(width, height, "Reconstructed background");

	// Buckets store the number of times in the image sequence that the pixel has a value that falls in the given range, or "bucket"
	// A-buckets span the whole range from 0 to 255
	// B-buckets are offset from A-buckets by half of the bucket size and cover a subset of the whole color range
	//
	// The motivation for having two sets of buckets are cases when the pixel values cluster around a bucket boundary and would be split in two.
	// Having an additional set of buckets which are centered around these boundaries helps catch these values and keeps them together.
	vector<int> valueBucketA(width * height * buckets);
	vector<int> valueBucketB(width * height * buckets);
	vector<BucketEntry> finalBucket(width * height);

	// Read image frames and count the buckets
	for (int frame = 0; frame < fileNames.size(); frame++)
	{
		CImg<unsigned char> newImage(fileNames[frame].c_str());

		std::cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixel = newImage(i, j, 0, 0);

				int a_bucket = getABucket(pixel);
				valueBucketA[i + j * width + a_bucket * (width * height)]++;

				int b_bucket = getBBucket(pixel);
				valueBucketB[i + j * width + b_bucket * (width * height)]++;

				visu(i, j) = 127;
			}
		}
	}

	// Find the biggest bucket
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			int maxCount = 0;
			int maxBucket = -1;
			bool maxTypeA = true;

			for (int bucket = 0; bucket < buckets; bucket++)
			{
				if (valueBucketA[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = valueBucketA[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = true;
				}
				if (valueBucketB[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = valueBucketB[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = false;
				}
			}

			finalBucket[i + j * width].id = maxBucket;
			finalBucket[i + j * width].isABucket = maxTypeA;
		}
	}

	vector<int> accRed(width * height);
	vector<int> accGreen(width * height);
	vector<int> accBlue(width * height);
	vector<int> count(width * height);

	// Average out all the pixel values from the biggest bucket
	for (int frame = 0; frame < fileNames.size(); frame++)
	{
		CImg<unsigned char> newImage(fileNames[frame].c_str());

		cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixelRed = newImage(i, j, 0, 0);

				if (finalBucket[i + j * width].isABucket)
				{
					int pixABucket = getABucket(pixelRed);

					if (pixABucket == finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
				else
				{
					int pixBBucket = getBBucket(pixelRed);

					if (pixBBucket == finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
			}
		}
	}

	// Paint the final result in a window
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			visu(i, j, 0, 0) = accRed[i + j * width] / count[i + j * width];
			visu(i, j, 0, 1) = accGreen[i + j * width] / count[i + j * width];
			visu(i, j, 0, 2) = accBlue[i + j * width] / count[i + j * width];
		}
		main_disp.render(visu);
		main_disp.paint();

	}

	cout << endl;

	while (!main_disp.is_closed())
	{
		main_disp.wait();
	}
}
<commit_msg>Prettier printing<commit_after>// ImageProcessor
// Class to handle the processing of the image sequence

#include "imageProcessor.h"

ImageProcessor::ImageProcessor()
{
	width = 480;
	height = 480;

	minVal = 0;
	maxVal = 255;
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;

	fileStem = "picpick";
	fileType = ".png";
}

ImageProcessor::~ImageProcessor()
{
}

void ImageProcessor::addFile(string fileName)
{
	if(!fileName.empty())
		fileNames.push_back(fileName);
}

void ImageProcessor::setFrames(int newFrames)
{
	frames = newFrames;
}

void ImageProcessor::setInputDirectory(string newDir)
{
	inputDirectory = newDir;
}

void ImageProcessor::setBucketSize(int newSize)
{
	bucketSize = 8;
	buckets = (maxVal + 1) / bucketSize;
}

int ImageProcessor::getABucket(int value)
{
	if (value < minVal)
		return 0;

	if (value > maxVal)
		return buckets - 1;

	return value / bucketSize;
}

int ImageProcessor::getBBucket(int value)
{
	return getABucket(value + (bucketSize / 2));
}

void ImageProcessor::processSequence()
{
	CImg<unsigned char> visu(width, height, 1, 3, 0);
	CImgDisplay main_disp(width, height, "Reconstructed background");

	// Buckets store the number of times in the image sequence that the pixel has a value that falls in the given range, or "bucket"
	// A-buckets span the whole range from 0 to 255
	// B-buckets are offset from A-buckets by half of the bucket size and cover a subset of the whole color range
	//
	// The motivation for having two sets of buckets are cases when the pixel values cluster around a bucket boundary and would be split in two.
	// Having an additional set of buckets which are centered around these boundaries helps catch these values and keeps them together.
	vector<int> valueBucketA(width * height * buckets);
	vector<int> valueBucketB(width * height * buckets);
	vector<BucketEntry> finalBucket(width * height);

	cout << endl << "Reading:\t";

	// Read image frames and count the buckets
	for (int frame = 0; frame < fileNames.size(); frame++)
	{
		CImg<unsigned char> newImage(fileNames[frame].c_str());

		std::cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixel = newImage(i, j, 0, 0);

				int a_bucket = getABucket(pixel);
				valueBucketA[i + j * width + a_bucket * (width * height)]++;

				int b_bucket = getBBucket(pixel);
				valueBucketB[i + j * width + b_bucket * (width * height)]++;

				visu(i, j) = 127;
			}
		}
	}

	// Find the biggest bucket
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			int maxCount = 0;
			int maxBucket = -1;
			bool maxTypeA = true;

			for (int bucket = 0; bucket < buckets; bucket++)
			{
				if (valueBucketA[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = valueBucketA[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = true;
				}
				if (valueBucketB[i + j * width + bucket * (width * height)] > maxCount)
				{
					maxCount = valueBucketB[i + j * width + bucket * (width * height)];
					maxBucket = bucket;
					maxTypeA = false;
				}
			}

			finalBucket[i + j * width].id = maxBucket;
			finalBucket[i + j * width].isABucket = maxTypeA;
		}
	}

	vector<int> accRed(width * height);
	vector<int> accGreen(width * height);
	vector<int> accBlue(width * height);
	vector<int> count(width * height);

	cout << endl << "Averaging:\t";

	// Average out all the pixel values from the biggest bucket
	for (int frame = 0; frame < fileNames.size(); frame++)
	{
		CImg<unsigned char> newImage(fileNames[frame].c_str());

		cout << "|";

		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; j++)
			{
				int pixelRed = newImage(i, j, 0, 0);

				if (finalBucket[i + j * width].isABucket)
				{
					int pixABucket = getABucket(pixelRed);

					if (pixABucket == finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
				else
				{
					int pixBBucket = getBBucket(pixelRed);

					if (pixBBucket == finalBucket[i + j * width].id)
					{
						accRed[i + j * width] += pixelRed;
						accGreen[i + j * width] += newImage(i, j, 0, 1);
						accBlue[i + j * width] += newImage(i, j, 0, 2);
						count[i + j * width]++;
					}
				}
			}
		}
	}

	// Paint the final result in a window
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < height; j++)
		{
			visu(i, j, 0, 0) = accRed[i + j * width] / count[i + j * width];
			visu(i, j, 0, 1) = accGreen[i + j * width] / count[i + j * width];
			visu(i, j, 0, 2) = accBlue[i + j * width] / count[i + j * width];
		}
		main_disp.render(visu);
		main_disp.paint();

	}

	cout << endl;

	while (!main_disp.is_closed())
	{
		main_disp.wait();
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: virdev.cxx,v $
 *
 *  $Revision: 1.25 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 19:32:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALFRAME_HXX
#include <salframe.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <wrkwin.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_VIRDEV_HXX
#include <virdev.hxx>
#endif

using namespace ::com::sun::star::uno;

// =======================================================================

void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
                                    long nDX, long nDY, USHORT nBitCount, const SystemGraphicsData *pData )
{
    DBG_ASSERT( nBitCount <= 1,
                "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );

    if ( nDX < 1 )
        nDX = 1;

    if ( nDY < 1 )
        nDY = 1;

    ImplSVData* pSVData = ImplGetSVData();

    if ( !pOutDev )
        pOutDev = ImplGetDefaultWindow();
    if( !pOutDev )
        return;

    SalGraphics* pGraphics;
    if ( !pOutDev->mpGraphics )
        ((OutputDevice*)pOutDev)->ImplGetGraphics();
    pGraphics = pOutDev->mpGraphics;
    if ( pGraphics )
        mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
    else
        mpVirDev = NULL;
    if ( !mpVirDev )
    {
        // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
        throw ::com::sun::star::uno::RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system bitmap!" ) ),
            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
        //GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
    }

    mnBitCount      = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
    mnOutWidth      = nDX;
    mnOutHeight     = nDY;
    mbScreenComp    = TRUE;
    mbScreenComp    = FALSE;
    mnAlphaDepth    = -1;

    // #i59315# init vdev size from system object, when passed a
    // SystemGraphicsData. Otherwise, output size will always
    // incorrectly stay at (1,1)
    if( pData && mpVirDev )
        mpVirDev->GetSize(mnOutWidth,mnOutHeight);

    if( mnBitCount < 8 )
        SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

    if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
        mbScreenComp = FALSE;
    else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
        mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;

    meOutDevType    = OUTDEV_VIRDEV;
    mbDevOutput     = TRUE;
    mpFontList      = pSVData->maGDIData.mpScreenFontList;
    mpFontCache     = pSVData->maGDIData.mpScreenFontCache;
    mnDPIX          = pOutDev->mnDPIX;
    mnDPIY          = pOutDev->mnDPIY;
    maFont          = pOutDev->maFont;

    if( maTextColor != pOutDev->maTextColor )
    {
        maTextColor = pOutDev->maTextColor;
        mbInitTextColor = true;
    }

    // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
    SetBackground( Wallpaper( Color( COL_WHITE ) ) );

    // #i59283# don't erase user-provided surface
    if( !pData )
        Erase();

    // VirDev in Liste eintragen
    mpNext = pSVData->maGDIData.mpFirstVirDev;
    mpPrev = NULL;
    if ( mpNext )
        mpNext->mpPrev = this;
    else
        pSVData->maGDIData.mpLastVirDev = this;
    pSVData->maGDIData.mpFirstVirDev = this;
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
    : mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount, USHORT nAlphaBitCount )
    : mpVirDev( NULL )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );

    // #110958# Enable alpha channel
    mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount);
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData );
}

// -----------------------------------------------------------------------

VirtualDevice::~VirtualDevice()
{
    DBG_TRACE( "VirtualDevice::~VirtualDevice()" );

    ImplSVData* pSVData = ImplGetSVData();

    ImplReleaseGraphics();

    if ( mpVirDev )
        pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );

    // remove this VirtualDevice from the double-linked global list
    if( mpPrev )
        mpPrev->mpNext = mpNext;
    else
        pSVData->maGDIData.mpFirstVirDev = mpNext;

    if( mpNext )
        mpNext->mpPrev = mpPrev;
    else
        pSVData->maGDIData.mpLastVirDev = mpPrev;
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );

    if ( !mpVirDev )
        return FALSE;
    else if ( rNewSize == GetOutputSizePixel() )
    {
        if ( bErase )
            Erase();
        return TRUE;
    }

    BOOL bRet;
    long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();

    if ( nNewWidth < 1 )
        nNewWidth = 1;

    if ( nNewHeight < 1 )
        nNewHeight = 1;

    if ( bErase )
    {
        bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );

        if ( bRet )
        {
            mnOutWidth  = rNewSize.Width();
            mnOutHeight = rNewSize.Height();
            Erase();
        }
    }
    else
    {
        SalVirtualDevice*   pNewVirDev;
        ImplSVData*         pSVData = ImplGetSVData();

        // we need a graphics
        if ( !mpGraphics )
        {
            if ( !ImplGetGraphics() )
                return FALSE;
        }

        pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
        if ( pNewVirDev )
        {
            SalGraphics* pGraphics = pNewVirDev->GetGraphics();
            if ( pGraphics )
            {
                SalTwoRect aPosAry;
                long nWidth;
                long nHeight;
                if ( mnOutWidth < nNewWidth )
                    nWidth = mnOutWidth;
                else
                    nWidth = nNewWidth;
                if ( mnOutHeight < nNewHeight )
                    nHeight = mnOutHeight;
                else
                    nHeight = nNewHeight;
                aPosAry.mnSrcX       = 0;
                aPosAry.mnSrcY       = 0;
                aPosAry.mnSrcWidth   = nWidth;
                aPosAry.mnSrcHeight  = nHeight;
                aPosAry.mnDestX      = 0;
                aPosAry.mnDestY      = 0;
                aPosAry.mnDestWidth  = nWidth;
                aPosAry.mnDestHeight = nHeight;

                pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
                pNewVirDev->ReleaseGraphics( pGraphics );
                ImplReleaseGraphics();
                pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
                mpVirDev = pNewVirDev;
                mnOutWidth  = rNewSize.Width();
                mnOutHeight = rNewSize.Height();
                bRet = TRUE;
            }
            else
            {
                bRet = FALSE;
                pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
            }
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

// -----------------------------------------------------------------------

// #i32109#: Fill opaque areas correctly (without relying on
// fill/linecolor state)
void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect )
{
    // Set line and fill color to black (->opaque),
    // fill rect with that (linecolor, too, because of
    // those pesky missing pixel problems)
    Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
    SetLineColor( COL_BLACK );
    SetFillColor( COL_BLACK );
    DrawRect( rRect );
    Pop();
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    if( ImplSetOutputSizePixel(rNewSize, bErase) )
    {
        if( mnAlphaDepth != -1 )
        {
            // #110958# Setup alpha bitmap
            if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
            {
                delete mpAlphaVDev;
                mpAlphaVDev = 0L;
            }

            if( !mpAlphaVDev )
            {
                mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
                mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase);
            }

            // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
            if( GetLineColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetLineColor( COL_BLACK );

            if( GetFillColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetFillColor( COL_BLACK );

            mpAlphaVDev->SetMapMode( GetMapMode() );
        }

        return TRUE;
    }

    return FALSE;
}

// -----------------------------------------------------------------------

void VirtualDevice::SetReferenceDevice( RefDevMode eRefDevMode )
{
    switch( eRefDevMode )
    {
    case REFDEV_NONE:
    default:
        DBG_ASSERT( FALSE, "VDev::SetRefDev illegal argument!" );
        // fall through
    case REFDEV_MODE06:
        mnDPIX = mnDPIY = 600;
        break;
    case REFDEV_MODE48:
        mnDPIX = mnDPIY = 4800;
        break;
    case REFDEV_MODE_MSO1:
        mnDPIX = mnDPIY = 6*1440;
        break;
    }

    EnableOutput( FALSE );  // prevent output on reference device
    mbScreenComp = FALSE;

    // invalidate currently selected fonts
    mbInitFont = TRUE;
    mbNewFont = TRUE;

    // avoid adjusting font lists when already in refdev mode
    BYTE nOldRefDevMode = meRefDevMode;
    meRefDevMode = (BYTE)eRefDevMode;
    if( nOldRefDevMode != REFDEV_NONE )
        return;

    // the reference device should have only scalable fonts
    // => clean up the original font lists before getting new ones
    if ( mpFontEntry )
    {
        mpFontCache->Release( mpFontEntry );
        mpFontEntry = NULL;
    }
    if ( mpGetDevFontList )
    {
        delete mpGetDevFontList;
        mpGetDevFontList = NULL;
    }
    if ( mpGetDevSizeList )
    {
        delete mpGetDevSizeList;
        mpGetDevSizeList = NULL;
    }

    // preserve global font lists
    ImplSVData* pSVData = ImplGetSVData();
    if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
        delete mpFontList;
    if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
        delete mpFontCache;

    // get font list with scalable fonts only
    ImplGetGraphics();
    mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );

    // prepare to use new font lists
    mpFontCache = new ImplFontCache( false );
}

// -----------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS pdf03 (1.23.48); FILE MERGED 2006/06/27 10:15:19 pl 1.23.48.2: RESYNC: (1.23-1.25); FILE MERGED 2006/06/08 14:09:14 pl 1.23.48.1: #i53411# minimize rounding issues<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: virdev.cxx,v $
 *
 *  $Revision: 1.26 $
 *
 *  last change: $Author: obo $ $Date: 2006-07-10 17:26:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_SVSYS_HXX
#include <svsys.h>
#endif

#ifndef _SV_SALINST_HXX
#include <salinst.hxx>
#endif
#ifndef _SV_SALGDI_HXX
#include <salgdi.hxx>
#endif
#ifndef _SV_SALFRAME_HXX
#include <salframe.hxx>
#endif
#ifndef _SV_SALVD_HXX
#include <salvd.hxx>
#endif

#ifndef _DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVDATA_HXX
#include <svdata.hxx>
#endif
#ifndef _SV_SETTINGS_HXX
#include <settings.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <wrkwin.hxx>
#endif
#ifndef _SV_OUTDEV_H
#include <outdev.h>
#endif
#ifndef _SV_VIRDEV_HXX
#include <virdev.hxx>
#endif

using namespace ::com::sun::star::uno;

// =======================================================================

void VirtualDevice::ImplInitVirDev( const OutputDevice* pOutDev,
                                    long nDX, long nDY, USHORT nBitCount, const SystemGraphicsData *pData )
{
    DBG_ASSERT( nBitCount <= 1,
                "VirtualDevice::VirtualDevice(): Only 0 or 1 is for BitCount allowed" );

    if ( nDX < 1 )
        nDX = 1;

    if ( nDY < 1 )
        nDY = 1;

    ImplSVData* pSVData = ImplGetSVData();

    if ( !pOutDev )
        pOutDev = ImplGetDefaultWindow();
    if( !pOutDev )
        return;

    SalGraphics* pGraphics;
    if ( !pOutDev->mpGraphics )
        ((OutputDevice*)pOutDev)->ImplGetGraphics();
    pGraphics = pOutDev->mpGraphics;
    if ( pGraphics )
        mpVirDev = pSVData->mpDefInst->CreateVirtualDevice( pGraphics, nDX, nDY, nBitCount, pData );
    else
        mpVirDev = NULL;
    if ( !mpVirDev )
    {
        // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
        throw ::com::sun::star::uno::RuntimeException(
            OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not create system bitmap!" ) ),
            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
        //GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
    }

    mnBitCount      = ( nBitCount ? nBitCount : pOutDev->GetBitCount() );
    mnOutWidth      = nDX;
    mnOutHeight     = nDY;
    mbScreenComp    = TRUE;
    mbScreenComp    = FALSE;
    mnAlphaDepth    = -1;

    // #i59315# init vdev size from system object, when passed a
    // SystemGraphicsData. Otherwise, output size will always
    // incorrectly stay at (1,1)
    if( pData && mpVirDev )
        mpVirDev->GetSize(mnOutWidth,mnOutHeight);

    if( mnBitCount < 8 )
        SetAntialiasing( ANTIALIASING_DISABLE_TEXT );

    if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
        mbScreenComp = FALSE;
    else if ( pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
        mbScreenComp = ((VirtualDevice*)pOutDev)->mbScreenComp;

    meOutDevType    = OUTDEV_VIRDEV;
    mbDevOutput     = TRUE;
    mpFontList      = pSVData->maGDIData.mpScreenFontList;
    mpFontCache     = pSVData->maGDIData.mpScreenFontCache;
    mnDPIX          = pOutDev->mnDPIX;
    mnDPIY          = pOutDev->mnDPIY;
    maFont          = pOutDev->maFont;

    if( maTextColor != pOutDev->maTextColor )
    {
        maTextColor = pOutDev->maTextColor;
        mbInitTextColor = true;
    }

    // Virtuelle Devices haben defaultmaessig einen weissen Hintergrund
    SetBackground( Wallpaper( Color( COL_WHITE ) ) );

    // #i59283# don't erase user-provided surface
    if( !pData )
        Erase();

    // VirDev in Liste eintragen
    mpNext = pSVData->maGDIData.mpFirstVirDev;
    mpPrev = NULL;
    if ( mpNext )
        mpNext->mpPrev = this;
    else
        pSVData->maGDIData.mpLastVirDev = this;
    pSVData->maGDIData.mpFirstVirDev = this;
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount )
    : mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, USHORT nBitCount, USHORT nAlphaBitCount )
    : mpVirDev( NULL )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( &rCompDev, 1, 1, nBitCount );

    // #110958# Enable alpha channel
    mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount);
}

// -----------------------------------------------------------------------

VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, USHORT nBitCount )
:   mpVirDev( NULL ),
    meRefDevMode( REFDEV_NONE )
{
    DBG_TRACE1( "VirtualDevice::VirtualDevice( %hu )", nBitCount );

    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData );
}

// -----------------------------------------------------------------------

VirtualDevice::~VirtualDevice()
{
    DBG_TRACE( "VirtualDevice::~VirtualDevice()" );

    ImplSVData* pSVData = ImplGetSVData();

    ImplReleaseGraphics();

    if ( mpVirDev )
        pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );

    // remove this VirtualDevice from the double-linked global list
    if( mpPrev )
        mpPrev->mpNext = mpNext;
    else
        pSVData->maGDIData.mpFirstVirDev = mpNext;

    if( mpNext )
        mpNext->mpPrev = mpPrev;
    else
        pSVData->maGDIData.mpLastVirDev = mpPrev;
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    DBG_TRACE3( "VirtualDevice::ImplSetOutputSizePixel( %ld, %ld, %d )", rNewSize.Width(), rNewSize.Height(), (int)bErase );

    if ( !mpVirDev )
        return FALSE;
    else if ( rNewSize == GetOutputSizePixel() )
    {
        if ( bErase )
            Erase();
        return TRUE;
    }

    BOOL bRet;
    long nNewWidth = rNewSize.Width(), nNewHeight = rNewSize.Height();

    if ( nNewWidth < 1 )
        nNewWidth = 1;

    if ( nNewHeight < 1 )
        nNewHeight = 1;

    if ( bErase )
    {
        bRet = mpVirDev->SetSize( nNewWidth, nNewHeight );

        if ( bRet )
        {
            mnOutWidth  = rNewSize.Width();
            mnOutHeight = rNewSize.Height();
            Erase();
        }
    }
    else
    {
        SalVirtualDevice*   pNewVirDev;
        ImplSVData*         pSVData = ImplGetSVData();

        // we need a graphics
        if ( !mpGraphics )
        {
            if ( !ImplGetGraphics() )
                return FALSE;
        }

        pNewVirDev = pSVData->mpDefInst->CreateVirtualDevice( mpGraphics, nNewWidth, nNewHeight, mnBitCount );
        if ( pNewVirDev )
        {
            SalGraphics* pGraphics = pNewVirDev->GetGraphics();
            if ( pGraphics )
            {
                SalTwoRect aPosAry;
                long nWidth;
                long nHeight;
                if ( mnOutWidth < nNewWidth )
                    nWidth = mnOutWidth;
                else
                    nWidth = nNewWidth;
                if ( mnOutHeight < nNewHeight )
                    nHeight = mnOutHeight;
                else
                    nHeight = nNewHeight;
                aPosAry.mnSrcX       = 0;
                aPosAry.mnSrcY       = 0;
                aPosAry.mnSrcWidth   = nWidth;
                aPosAry.mnSrcHeight  = nHeight;
                aPosAry.mnDestX      = 0;
                aPosAry.mnDestY      = 0;
                aPosAry.mnDestWidth  = nWidth;
                aPosAry.mnDestHeight = nHeight;

                pGraphics->CopyBits( &aPosAry, mpGraphics, this, this );
                pNewVirDev->ReleaseGraphics( pGraphics );
                ImplReleaseGraphics();
                pSVData->mpDefInst->DestroyVirtualDevice( mpVirDev );
                mpVirDev = pNewVirDev;
                mnOutWidth  = rNewSize.Width();
                mnOutHeight = rNewSize.Height();
                bRet = TRUE;
            }
            else
            {
                bRet = FALSE;
                pSVData->mpDefInst->DestroyVirtualDevice( pNewVirDev );
            }
        }
        else
            bRet = FALSE;
    }

    return bRet;
}

// -----------------------------------------------------------------------

// #i32109#: Fill opaque areas correctly (without relying on
// fill/linecolor state)
void VirtualDevice::ImplFillOpaqueRectangle( const Rectangle& rRect )
{
    // Set line and fill color to black (->opaque),
    // fill rect with that (linecolor, too, because of
    // those pesky missing pixel problems)
    Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
    SetLineColor( COL_BLACK );
    SetFillColor( COL_BLACK );
    DrawRect( rRect );
    Pop();
}

// -----------------------------------------------------------------------

BOOL VirtualDevice::SetOutputSizePixel( const Size& rNewSize, BOOL bErase )
{
    if( ImplSetOutputSizePixel(rNewSize, bErase) )
    {
        if( mnAlphaDepth != -1 )
        {
            // #110958# Setup alpha bitmap
            if(mpAlphaVDev && mpAlphaVDev->GetOutputSizePixel() != rNewSize)
            {
                delete mpAlphaVDev;
                mpAlphaVDev = 0L;
            }

            if( !mpAlphaVDev )
            {
                mpAlphaVDev = new VirtualDevice( *this, mnAlphaDepth );
                mpAlphaVDev->ImplSetOutputSizePixel(rNewSize, bErase);
            }

            // TODO: copy full outdev state to new one, here. Also needed in outdev2.cxx:DrawOutDev
            if( GetLineColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetLineColor( COL_BLACK );

            if( GetFillColor() != Color( COL_TRANSPARENT ) )
                mpAlphaVDev->SetFillColor( COL_BLACK );

            mpAlphaVDev->SetMapMode( GetMapMode() );
        }

        return TRUE;
    }

    return FALSE;
}

// -----------------------------------------------------------------------

void VirtualDevice::SetReferenceDevice( RefDevMode eRefDevMode )
{
    switch( eRefDevMode )
    {
    case REFDEV_NONE:
    default:
        DBG_ASSERT( FALSE, "VDev::SetRefDev illegal argument!" );
        // fall through
    case REFDEV_MODE06:
        mnDPIX = mnDPIY = 600;
        break;
    case REFDEV_MODE48:
        mnDPIX = mnDPIY = 4800;
        break;
    case REFDEV_MODE_MSO1:
        mnDPIX = mnDPIY = 6*1440;
        break;
    case REFDEV_MODE_PDF1:
        mnDPIX = mnDPIY = 720;
        break;
    }

    EnableOutput( FALSE );  // prevent output on reference device
    mbScreenComp = FALSE;

    // invalidate currently selected fonts
    mbInitFont = TRUE;
    mbNewFont = TRUE;

    // avoid adjusting font lists when already in refdev mode
    BYTE nOldRefDevMode = meRefDevMode;
    meRefDevMode = (BYTE)eRefDevMode;
    if( nOldRefDevMode != REFDEV_NONE )
        return;

    // the reference device should have only scalable fonts
    // => clean up the original font lists before getting new ones
    if ( mpFontEntry )
    {
        mpFontCache->Release( mpFontEntry );
        mpFontEntry = NULL;
    }
    if ( mpGetDevFontList )
    {
        delete mpGetDevFontList;
        mpGetDevFontList = NULL;
    }
    if ( mpGetDevSizeList )
    {
        delete mpGetDevSizeList;
        mpGetDevSizeList = NULL;
    }

    // preserve global font lists
    ImplSVData* pSVData = ImplGetSVData();
    if( mpFontList && (mpFontList != pSVData->maGDIData.mpScreenFontList) )
        delete mpFontList;
    if( mpFontCache && (mpFontCache != pSVData->maGDIData.mpScreenFontCache) )
        delete mpFontCache;

    // get font list with scalable fonts only
    ImplGetGraphics();
    mpFontList = pSVData->maGDIData.mpScreenFontList->Clone( true, false );

    // prepare to use new font lists
    mpFontCache = new ImplFontCache( false );
}

// -----------------------------------------------------------------------
<|endoftext|>