Qt Reference Documentation

svgalibscreen.cpp Example File

qws/svgalib/svgalibscreen.cpp
 /****************************************************************************
 **
 ** Copyright (C) 2015 The Qt Company Ltd.
 ** Contact: http://www.qt.io/licensing/
 **
 ** This file is part of the examples of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:BSD$
 ** You may use this file under the terms of the BSD license as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of The Qt Company Ltd nor the names of its
 **     contributors may be used to endorse or promote products derived
 **     from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/

 #include "svgalibscreen.h"
 #include "svgalibsurface.h"

 #include <QVector>
 #include <QApplication>
 #include <QColor>
 #include <QWidget>

 #include <math.h>

 static int getModeDepth(vga_modeinfo *mode)
 {
     const int bits = int(log2(mode->colors));
     if (bits == 24 && mode->bytesperpixel == 4)
         return 32;
     return bits;
 }

 bool SvgalibScreen::connect(const QString &displaySpec)
 {
     int mode = vga_getdefaultmode();
     if (mode <= 0) {
         qCritical("SvgalibScreen::connect(): invalid vga mode");
         return false;
     }

     vga_modeinfo *modeinfo = vga_getmodeinfo(mode);

     QScreen::lstep = modeinfo->linewidth;
     QScreen::dw = QScreen::w = modeinfo->width;
     QScreen::dh = QScreen::h = modeinfo->height;
     QScreen::d = getModeDepth(modeinfo);
     QScreen::size = QScreen::lstep * dh;
     QScreen::data = 0;

     switch (depth()) {
     case 32:
         setPixelFormat(QImage::Format_ARGB32_Premultiplied);
         break;
     case 24:
         setPixelFormat(QImage::Format_RGB888);
         break;
     case 16:
         setPixelFormat(QImage::Format_RGB16);
         break;
     case 15:
         setPixelFormat(QImage::Format_RGB555);
         break;
     default:
         break;
     }

     const int dpi = 72;
     QScreen::physWidth = qRound(QScreen::dw * 25.4 / dpi);
     QScreen::physHeight = qRound(QScreen::dh * 25.4 / dpi);

     const QStringList args = displaySpec.split(QLatin1Char(':'),
                                                QString::SkipEmptyParts);
     grayscale = args.contains(QLatin1String("grayscale"), Qt::CaseInsensitive);

     return true;
 }

 void SvgalibScreen::initColorMap()
 {
     const int numColors = vga_getcolors();
     if (numColors == 2 || numColors > 256) {
         screencols = 0;
         return; // not a palette based mode
     }

     if (numColors == 16) {
         if (grayscale) {
             for (int i = 0; i < 256; ++i) {
                 const int c = i * 16 / 256;
                 vga_setpalette(i, c, c, c);
             }
             screencols = 256; // XXX: takes advantage of optimization in alloc()
         } else { // read in EGA palette
             int r, g, b;
             for (int i = 0; i < 16; ++i) {
                 vga_getpalette(i, &r, &g, &b);
                 screenclut[i] = qRgb(r, g, b);
             }
             screencols = 16;
         }

         return;
     }

     Q_ASSERT(numColors == 256);

     if (grayscale) {
         for (int i = 0; i < 256; ++i) {
             const int c = i * 64 / 256;
             vga_setpalette(i, c, c, c);
         }
     } else {
         int i = 0;

 #if 0
         // read in EGA palette
         while (i < 16) {
             int r, g, b;
             vga_getpalette(i, &r, &g, &b);
             screenclut[i] = qRgb(r, g, b);
             ++i;
         }
         screencols = 16;
 #endif

         // 6 * 6 * 6 color cube
         for (int r = 0; r < 6; ++r) {
             for (int g = 0; g < 6; ++g) {
                 for (int b = 0; b < 6; ++b) {
                     vga_setpalette(i, r * 64/6, g * 64/6, b * 64/6);
                     screenclut[i] = qRgb(r * 256/6, g * 256/6, b * 256/6);
                     ++i;
                 }
             }
         }
         screencols = i;

         while (i < 256) {
             screenclut[i] = qRgb(0, 0, 0);
             ++i;
         }
     }
 }

 bool SvgalibScreen::initDevice()
 {
     if (vga_init() != 0) {
         qCritical("SvgalibScreen::initDevice(): unable to initialize svgalib");
         return false;
     }

     int mode = vga_getdefaultmode();
     if (vga_setmode(mode) == -1) {
         qCritical("SvgalibScreen::initialize(): unable to set graphics mode");
         return false;
     }

     if (gl_setcontextvga(mode) != 0) {
         qCritical("SvgalibScreen::initDevice(): unable to set vga context");
         return false;
     }
     context = gl_allocatecontext();
     gl_getcontext(context);

     vga_modeinfo *modeinfo = vga_getmodeinfo(mode);
     if (modeinfo->flags & IS_LINEAR)
         QScreen::data = vga_getgraphmem();

     initColorMap();

     QScreenCursor::initSoftwareCursor();
     return true;
 }

 void SvgalibScreen::shutdownDevice()
 {
     gl_freecontext(context);
     vga_setmode(TEXT);
 }

 void SvgalibScreen::disconnect()
 {
 }

 void SvgalibScreen::solidFill(const QColor &color, const QRegion &reg)
 {
     int c;
     if (depth() == 4 || depth() == 8)
         c = alloc(color.red(), color.green(), color.blue());
     else
         c = gl_rgbcolor(color.red(), color.green(), color.blue());

     const QVector<QRect> rects = (reg & region()).rects();
     for (int i = 0; i < rects.size(); ++i) {
         const QRect r = rects.at(i);
         gl_fillbox(r.left(), r.top(), r.width(), r.height(), c);
     }
 }

 void SvgalibScreen::blit16To8(const QImage &image,
                               const QPoint &topLeft, const QRegion &region)
 {
     const int imageStride = image.bytesPerLine() / 2;
     const QVector<QRect> rects = region.rects();

     for (int i = 0; i < rects.size(); ++i) {
         const QRect r = rects.at(i).translated(-topLeft);
         int y = r.y();
         const quint16 *s = reinterpret_cast<const quint16*>(image.scanLine(y));

         while (y <= r.bottom()) {
             int x1 = r.x();
             while (x1 <= r.right()) {
                 const quint16 c = s[x1];
                 int x2 = x1;
                 // find span length
                 while ((x2+1 < r.right()) && (s[x2+1] == c))
                     ++x2;
                 gl_hline(x1 + topLeft.x(), y + topLeft.y(), x2 + topLeft.x(),
                          qt_colorConvert<quint8, quint16>(c, 0));
                 x1 = x2 + 1;
             }
             s += imageStride;
             ++y;
         }
     }
 }

 void SvgalibScreen::blit32To8(const QImage &image,
                               const QPoint &topLeft, const QRegion &region)
 {
     const int imageStride = image.bytesPerLine() / 4;
     const QVector<QRect> rects = region.rects();

     for (int i = 0; i < rects.size(); ++i) {
         const QRect r = rects.at(i).translated(-topLeft);
         int y = r.y();
         const quint32 *s = reinterpret_cast<const quint32*>(image.scanLine(y));

         while (y <= r.bottom()) {
             int x1 = r.x();
             while (x1 <= r.right()) {
                 const quint32 c = s[x1];
                 int x2 = x1;
                 // find span length
                 while ((x2+1 < r.right()) && (s[x2+1] == c))
                     ++x2;
                 gl_hline(x1 + topLeft.x(), y + topLeft.y(), x2 + topLeft.x(),
                          qt_colorConvert<quint8, quint32>(c, 0));
                 x1 = x2 + 1;
             }
             s += imageStride;
             ++y;
         }
     }
 }

 void SvgalibScreen::blit(const QImage &img, const QPoint &topLeft,
                          const QRegion &reg)
 {
     if (depth() == 8) {
         switch (img.format()) {
         case QImage::Format_RGB16:
             blit16To8(img, topLeft, reg);
             return;
         case QImage::Format_RGB32:
         case QImage::Format_ARGB32:
         case QImage::Format_ARGB32_Premultiplied:
             blit32To8(img, topLeft, reg);
             return;
         default:
             break;
         }
     }

     if (img.format() != pixelFormat()) {
         if (base())
             QScreen::blit(img, topLeft, reg);
         return;
     }

     const QVector<QRect> rects = (reg & region()).rects();

     for (int i = 0; i < rects.size(); ++i) {
         const QRect r = rects.at(i);
         gl_putboxpart(r.x(), r.y(), r.width(), r.height(),
                       img.width(), img.height(),
                       static_cast<void*>(const_cast<uchar*>(img.bits())),
                       r.x() - topLeft.x(), r.y() - topLeft.y());
     }
 }

 QWSWindowSurface* SvgalibScreen::createSurface(QWidget *widget) const
 {
     if (base()) {
         static int onScreenPaint = -1;
         if (onScreenPaint == -1)
             onScreenPaint = qgetenv("QT_ONSCREEN_PAINT").toInt();

         if (onScreenPaint > 0 || widget->testAttribute(Qt::WA_PaintOnScreen))
             return new SvgalibSurface(widget);
     }
     return QScreen::createSurface(widget);
 }

 QWSWindowSurface* SvgalibScreen::createSurface(const QString &key) const
 {
     if (key == QLatin1String("svgalib"))
         return new SvgalibSurface;
     return QScreen::createSurface(key);
 }