src/openvg/qpaintengine_vg.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    43 #include "qpixmapdata_vg_p.h"
    43 #include "qpixmapdata_vg_p.h"
    44 #include "qpixmapfilter_vg_p.h"
    44 #include "qpixmapfilter_vg_p.h"
    45 #include "qvgcompositionhelper_p.h"
    45 #include "qvgcompositionhelper_p.h"
    46 #include "qvgimagepool_p.h"
    46 #include "qvgimagepool_p.h"
    47 #if !defined(QT_NO_EGL)
    47 #if !defined(QT_NO_EGL)
    48 #include <QtGui/private/qegl_p.h>
    48 #include <QtGui/private/qeglcontext_p.h>
    49 #include "qwindowsurface_vgegl_p.h"
    49 #include "qwindowsurface_vgegl_p.h"
    50 #endif
    50 #endif
    51 #include <QtCore/qvarlengtharray.h>
    51 #include <QtCore/qvarlengtharray.h>
    52 #include <QtGui/private/qdrawhelper_p.h>
    52 #include <QtGui/private/qdrawhelper_p.h>
    53 #include <QtGui/private/qtextureglyphcache_p.h>
       
    54 #include <QtGui/private/qtextengine_p.h>
    53 #include <QtGui/private/qtextengine_p.h>
    55 #include <QtGui/private/qfontengine_p.h>
    54 #include <QtGui/private/qfontengine_p.h>
    56 #include <QtGui/private/qpainterpath_p.h>
    55 #include <QtGui/private/qpainterpath_p.h>
       
    56 #include <QtGui/private/qstatictext_p.h>
    57 #include <QDebug>
    57 #include <QDebug>
    58 #include <QSet>
    58 #include <QSet>
    59 
    59 
    60 QT_BEGIN_NAMESPACE
    60 QT_BEGIN_NAMESPACE
    61 
    61 
    84 {
    84 {
    85 public:
    85 public:
    86     QVGFontGlyphCache();
    86     QVGFontGlyphCache();
    87     ~QVGFontGlyphCache();
    87     ~QVGFontGlyphCache();
    88 
    88 
    89     void cacheGlyphs(QVGPaintEnginePrivate *d,
    89     void cacheGlyphs(QVGPaintEnginePrivate *d, QFontEngine *fontEngine, const glyph_t *g, int count);
    90                      const QTextItemInt &ti,
    90 
    91                      const QVarLengthArray<glyph_t> &glyphs);
    91     void setScaleFromText(const QFont &font, QFontEngine *fontEngine);
    92     void setScaleFromText(const QTextItemInt &ti);
       
    93 
    92 
    94     VGFont font;
    93     VGFont font;
    95     VGfloat scaleX;
    94     VGfloat scaleX;
    96     VGfloat scaleY;
    95     VGfloat scaleY;
    97     
    96 
    98     uint cachedGlyphsMask[256 / 32];
    97     uint cachedGlyphsMask[256 / 32];
    99     QSet<glyph_t> cachedGlyphs;
    98     QSet<glyph_t> cachedGlyphs;
   100 };
    99 };
   101 
   100 
   102 typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache;
   101 typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache;
   118 };
   117 };
   119 
   118 
   120 class QVGPaintEnginePrivate : public QPaintEngineExPrivate
   119 class QVGPaintEnginePrivate : public QPaintEngineExPrivate
   121 {
   120 {
   122 public:
   121 public:
       
   122     // Extra blending modes from VG_KHR_advanced_blending extension.
       
   123     // Use the QT_VG prefix to avoid conflicts with any definitions
       
   124     // that may come in via <VG/vgext.h>.
       
   125     enum AdvancedBlending {
       
   126         QT_VG_BLEND_OVERLAY_KHR       = 0x2010,
       
   127         QT_VG_BLEND_HARDLIGHT_KHR     = 0x2011,
       
   128         QT_VG_BLEND_SOFTLIGHT_SVG_KHR = 0x2012,
       
   129         QT_VG_BLEND_SOFTLIGHT_KHR     = 0x2013,
       
   130         QT_VG_BLEND_COLORDODGE_KHR    = 0x2014,
       
   131         QT_VG_BLEND_COLORBURN_KHR     = 0x2015,
       
   132         QT_VG_BLEND_DIFFERENCE_KHR    = 0x2016,
       
   133         QT_VG_BLEND_SUBTRACT_KHR      = 0x2017,
       
   134         QT_VG_BLEND_INVERT_KHR        = 0x2018,
       
   135         QT_VG_BLEND_EXCLUSION_KHR     = 0x2019,
       
   136         QT_VG_BLEND_LINEARDODGE_KHR   = 0x201a,
       
   137         QT_VG_BLEND_LINEARBURN_KHR    = 0x201b,
       
   138         QT_VG_BLEND_VIVIDLIGHT_KHR    = 0x201c,
       
   139         QT_VG_BLEND_LINEARLIGHT_KHR   = 0x201d,
       
   140         QT_VG_BLEND_PINLIGHT_KHR      = 0x201e,
       
   141         QT_VG_BLEND_HARDMIX_KHR       = 0x201f,
       
   142         QT_VG_BLEND_CLEAR_KHR         = 0x2020,
       
   143         QT_VG_BLEND_DST_KHR           = 0x2021,
       
   144         QT_VG_BLEND_SRC_OUT_KHR       = 0x2022,
       
   145         QT_VG_BLEND_DST_OUT_KHR       = 0x2023,
       
   146         QT_VG_BLEND_SRC_ATOP_KHR      = 0x2024,
       
   147         QT_VG_BLEND_DST_ATOP_KHR      = 0x2025,
       
   148         QT_VG_BLEND_XOR_KHR           = 0x2026
       
   149     };
       
   150 
   123     QVGPaintEnginePrivate();
   151     QVGPaintEnginePrivate();
   124     ~QVGPaintEnginePrivate();
   152     ~QVGPaintEnginePrivate();
   125 
   153 
   126     void init();
   154     void init();
   127     void initObjects();
   155     void initObjects();
   181     QTransform transform;   // Currently active transform.
   209     QTransform transform;   // Currently active transform.
   182     bool simpleTransform;   // True if the transform is simple (non-projective).
   210     bool simpleTransform;   // True if the transform is simple (non-projective).
   183     qreal penScale;         // Pen scaling factor from "transform".
   211     qreal penScale;         // Pen scaling factor from "transform".
   184 
   212 
   185     QTransform pathTransform;  // Calculated VG path transformation.
   213     QTransform pathTransform;  // Calculated VG path transformation.
   186     QTransform glyphTransform; // Calculated VG glyph transformation.
       
   187     QTransform imageTransform; // Calculated VG image transformation.
   214     QTransform imageTransform; // Calculated VG image transformation.
   188     bool pathTransformSet;  // True if path transform set in the VG context.
   215     bool pathTransformSet;  // True if path transform set in the VG context.
   189 
   216 
   190     bool maskValid;         // True if vgMask() contains valid data.
   217     bool maskValid;         // True if vgMask() contains valid data.
   191     bool maskIsSet;         // True if mask would be fully set if it was valid.
   218     bool maskIsSet;         // True if mask would be fully set if it was valid.
   215 
   242 
   216 #if !defined(QVG_NO_DRAW_GLYPHS)
   243 #if !defined(QVG_NO_DRAW_GLYPHS)
   217     QVGFontCache fontCache;
   244     QVGFontCache fontCache;
   218     QVGFontEngineCleaner *fontEngineCleaner;
   245     QVGFontEngineCleaner *fontEngineCleaner;
   219 #endif
   246 #endif
       
   247 
       
   248     bool hasAdvancedBlending;
   220 
   249 
   221     QScopedPointer<QPixmapFilter> convolutionFilter;
   250     QScopedPointer<QPixmapFilter> convolutionFilter;
   222     QScopedPointer<QPixmapFilter> colorizeFilter;
   251     QScopedPointer<QPixmapFilter> colorizeFilter;
   223     QScopedPointer<QPixmapFilter> dropShadowFilter;
   252     QScopedPointer<QPixmapFilter> dropShadowFilter;
   224     QScopedPointer<QPixmapFilter> blurFilter;
   253     QScopedPointer<QPixmapFilter> blurFilter;
   368     clearOpacity = 1.0f;
   397     clearOpacity = 1.0f;
   369 
   398 
   370 #if !defined(QVG_NO_DRAW_GLYPHS)
   399 #if !defined(QVG_NO_DRAW_GLYPHS)
   371     fontEngineCleaner = 0;
   400     fontEngineCleaner = 0;
   372 #endif
   401 #endif
       
   402 
       
   403     hasAdvancedBlending = false;
   373 
   404 
   374     clearModes();
   405     clearModes();
   375 }
   406 }
   376 
   407 
   377 QVGPaintEnginePrivate::~QVGPaintEnginePrivate()
   408 QVGPaintEnginePrivate::~QVGPaintEnginePrivate()
   445                             2,    // segmentCapacityHint
   476                             2,    // segmentCapacityHint
   446                             4,    // coordCapacityHint
   477                             4,    // coordCapacityHint
   447                             VG_PATH_CAPABILITY_ALL);
   478                             VG_PATH_CAPABILITY_ALL);
   448     vgAppendPathData(linePath, 2, segments, coords);
   479     vgAppendPathData(linePath, 2, segments, coords);
   449 #endif
   480 #endif
       
   481 
       
   482     const char *extensions = reinterpret_cast<const char *>(vgGetString(VG_EXTENSIONS));
       
   483     if (extensions)
       
   484         hasAdvancedBlending = strstr(extensions, "VG_KHR_advanced_blending") != 0;
   450 }
   485 }
   451 
   486 
   452 void QVGPaintEnginePrivate::destroy()
   487 void QVGPaintEnginePrivate::destroy()
   453 {
   488 {
   454     if (penPaint)
   489     if (penPaint)
   506     // Construct the VG transform by combining the Qt transform with
   541     // Construct the VG transform by combining the Qt transform with
   507     // the following viewport transformation:
   542     // the following viewport transformation:
   508     //        | 1  0  0   |
   543     //        | 1  0  0   |
   509     //        | 0 -1 devh |
   544     //        | 0 -1 devh |
   510     //        | 0  0  1   |
   545     //        | 0  0  1   |
   511     // The glyph transform uses a slightly different transformation:
       
   512     //        | 1  0  0       |   | 1 0  0.5 |   | 1  0     0.5      |
       
   513     //        | 0 -1 devh - 1 | * | 0 1 -0.5 | = | 0 -1 (devh - 0.5) |
       
   514     //        | 0  0  1       |   | 0 0   1  |   | 0  0      1       |
       
   515     // The full VG transform is effectively:
   546     // The full VG transform is effectively:
   516     //      1. Apply the user's transformation matrix.
   547     //      1. Apply the user's transformation matrix.
   517     //      2. Translate glyphs by an extra (0.5, -0.5).
   548     //      2. Flip the co-ordinate system upside down.
   518     //      3. Flip the co-ordinate system upside down.
       
   519     QTransform viewport(1.0f, 0.0f, 0.0f,
   549     QTransform viewport(1.0f, 0.0f, 0.0f,
   520                         0.0f, -1.0f, 0.0f,
   550                         0.0f, -1.0f, 0.0f,
   521                         0.0f, devh, 1.0f);
   551                         0.0f, devh, 1.0f);
   522     QTransform gviewport(1.0f, 0.0f, 0.0f,
       
   523                         0.0f, -1.0f, 0.0f,
       
   524                         0.5f, devh - 0.5f, 1.0f);
       
   525 
   552 
   526     // Compute the path transform and determine if it is projective.
   553     // Compute the path transform and determine if it is projective.
   527     pathTransform = transform * viewport;
   554     pathTransform = transform * viewport;
   528     glyphTransform = transform * gviewport;
       
   529     bool projective = (pathTransform.m13() != 0.0f ||
   555     bool projective = (pathTransform.m13() != 0.0f ||
   530                        pathTransform.m23() != 0.0f ||
   556                        pathTransform.m23() != 0.0f ||
   531                        pathTransform.m33() != 1.0f);
   557                        pathTransform.m33() != 1.0f);
   532     if (projective) {
   558     if (projective) {
   533         // The engine cannot do projective path transforms for us,
   559         // The engine cannot do projective path transforms for us,
   534         // so we will have to convert the co-ordinates ourselves.
   560         // so we will have to convert the co-ordinates ourselves.
   535         // Change the matrix to just the viewport transformation.
   561         // Change the matrix to just the viewport transformation.
   536         pathTransform = viewport;
   562         pathTransform = viewport;
   537         glyphTransform = gviewport;
       
   538         simpleTransform = false;
   563         simpleTransform = false;
   539     } else {
   564     } else {
   540         simpleTransform = true;
   565         simpleTransform = true;
   541     }
   566     }
   542     pathTransformSet = false;
   567     pathTransformSet = false;
   986     QRgb bg = 0;
  1011     QRgb bg = 0;
   987 
  1012 
   988     int height = sourceImage.height();
  1013     int height = sourceImage.height();
   989     int width = sourceImage.width();
  1014     int width = sourceImage.width();
   990     for (int y=0; y<height; ++y) {
  1015     for (int y=0; y<height; ++y) {
   991         uchar *source = sourceImage.scanLine(y);
  1016         const uchar *source = sourceImage.constScanLine(y);
   992         QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
  1017         QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y));
   993         for (int x=0; x < width; ++x)
  1018         for (int x=0; x < width; ++x)
   994             target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
  1019             target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg;
   995     }
  1020     }
   996     return dest;
  1021     return dest;
   997 }
  1022 }
   998 
       
   999 // defined in qpixmapdata_vg.cpp.
       
  1000 const uchar *qt_vg_imageBits(const QImage& image);
       
  1001 
  1023 
  1002 static VGImage toVGImage
  1024 static VGImage toVGImage
  1003     (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
  1025     (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor)
  1004 {
  1026 {
  1005     QImage img(image);
  1027     QImage img(image);
  1030         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1052         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1031         format = VG_sARGB_8888_PRE;
  1053         format = VG_sARGB_8888_PRE;
  1032         break;
  1054         break;
  1033     }
  1055     }
  1034 
  1056 
  1035     const uchar *pixels = qt_vg_imageBits(img);
  1057     const uchar *pixels = img.constBits();
  1036 
  1058 
  1037     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1059     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1038         (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1060         (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1039     vgImageSubData
  1061     vgImageSubData
  1040         (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
  1062         (vgImg, pixels, img.bytesPerLine(), format, 0, 0,
  1074         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1096         img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags);
  1075         format = VG_sARGB_8888_PRE;
  1097         format = VG_sARGB_8888_PRE;
  1076         break;
  1098         break;
  1077     }
  1099     }
  1078 
  1100 
  1079     const uchar *pixels = qt_vg_imageBits(img) + bpp * sr.x() +
  1101     const uchar *pixels = img.constBits() + bpp * sr.x() +
  1080                           img.bytesPerLine() * sr.y();
  1102                           img.bytesPerLine() * sr.y();
  1081 
  1103 
  1082     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1104     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1083         (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
  1105         (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER);
  1084     vgImageSubData
  1106     vgImageSubData
  1096     painter.begin(&img);
  1118     painter.begin(&img);
  1097     painter.setOpacity(opacity);
  1119     painter.setOpacity(opacity);
  1098     painter.drawImage(0, 0, image);
  1120     painter.drawImage(0, 0, image);
  1099     painter.end();
  1121     painter.end();
  1100 
  1122 
  1101     const uchar *pixels = qt_vg_imageBits(img);
  1123     const uchar *pixels = img.constBits();
  1102 
  1124 
  1103     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1125     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1104         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1126         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1105     vgImageSubData
  1127     vgImageSubData
  1106         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1128         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1118     painter.begin(&img);
  1140     painter.begin(&img);
  1119     painter.setOpacity(opacity);
  1141     painter.setOpacity(opacity);
  1120     painter.drawImage(QPoint(0, 0), image, sr);
  1142     painter.drawImage(QPoint(0, 0), image, sr);
  1121     painter.end();
  1143     painter.end();
  1122 
  1144 
  1123     const uchar *pixels = qt_vg_imageBits(img);
  1145     const uchar *pixels = img.constBits();
  1124 
  1146 
  1125     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1147     VGImage vgImg = QVGImagePool::instance()->createPermanentImage
  1126         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1148         (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  1127     vgImageSubData
  1149     vgImageSubData
  1128         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  1150         (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0,
  2301 void QVGPaintEngine::compositionModeChanged()
  2323 void QVGPaintEngine::compositionModeChanged()
  2302 {
  2324 {
  2303     Q_D(QVGPaintEngine);
  2325     Q_D(QVGPaintEngine);
  2304     d->dirty |= QPaintEngine::DirtyCompositionMode;
  2326     d->dirty |= QPaintEngine::DirtyCompositionMode;
  2305 
  2327 
  2306     VGBlendMode vgMode = VG_BLEND_SRC_OVER;
  2328     VGint vgMode = VG_BLEND_SRC_OVER;
  2307 
  2329 
  2308     switch (state()->composition_mode) {
  2330     switch (state()->composition_mode) {
  2309     case QPainter::CompositionMode_SourceOver:
  2331     case QPainter::CompositionMode_SourceOver:
  2310         vgMode = VG_BLEND_SRC_OVER;
  2332         vgMode = VG_BLEND_SRC_OVER;
  2311         break;
  2333         break;
  2335         break;
  2357         break;
  2336     case QPainter::CompositionMode_Lighten:
  2358     case QPainter::CompositionMode_Lighten:
  2337         vgMode = VG_BLEND_LIGHTEN;
  2359         vgMode = VG_BLEND_LIGHTEN;
  2338         break;
  2360         break;
  2339     default:
  2361     default:
  2340         qWarning() << "QVGPaintEngine::compositionModeChanged unsupported mode" << state()->composition_mode;
  2362         if (d->hasAdvancedBlending) {
  2341         break;  // Fall back to VG_BLEND_SRC_OVER.
  2363             switch (state()->composition_mode) {
  2342     }
  2364             case QPainter::CompositionMode_Overlay:
  2343 
  2365                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_OVERLAY_KHR;
  2344     d->setBlendMode(vgMode);
  2366                 break;
       
  2367             case QPainter::CompositionMode_ColorDodge:
       
  2368                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_COLORDODGE_KHR;
       
  2369                 break;
       
  2370             case QPainter::CompositionMode_ColorBurn:
       
  2371                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_COLORBURN_KHR;
       
  2372                 break;
       
  2373             case QPainter::CompositionMode_HardLight:
       
  2374                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_HARDLIGHT_KHR;
       
  2375                 break;
       
  2376             case QPainter::CompositionMode_SoftLight:
       
  2377                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_SOFTLIGHT_KHR;
       
  2378                 break;
       
  2379             case QPainter::CompositionMode_Difference:
       
  2380                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_DIFFERENCE_KHR;
       
  2381                 break;
       
  2382             case QPainter::CompositionMode_Exclusion:
       
  2383                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_EXCLUSION_KHR;
       
  2384                 break;
       
  2385             case QPainter::CompositionMode_SourceOut:
       
  2386                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_SRC_OUT_KHR;
       
  2387                 break;
       
  2388             case QPainter::CompositionMode_DestinationOut:
       
  2389                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_DST_OUT_KHR;
       
  2390                 break;
       
  2391             case QPainter::CompositionMode_SourceAtop:
       
  2392                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_SRC_ATOP_KHR;
       
  2393                 break;
       
  2394             case QPainter::CompositionMode_DestinationAtop:
       
  2395                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_DST_ATOP_KHR;
       
  2396                 break;
       
  2397             case QPainter::CompositionMode_Xor:
       
  2398                 vgMode = QVGPaintEnginePrivate::QT_VG_BLEND_XOR_KHR;
       
  2399                 break;
       
  2400             default: break; // Fall back to VG_BLEND_SRC_OVER.
       
  2401             }
       
  2402         }
       
  2403         if (vgMode == VG_BLEND_SRC_OVER)
       
  2404             qWarning() << "QVGPaintEngine::compositionModeChanged unsupported mode" << state()->composition_mode;
       
  2405         break;
       
  2406     }
       
  2407 
       
  2408     d->setBlendMode(VGBlendMode(vgMode));
  2345 }
  2409 }
  2346 
  2410 
  2347 void QVGPaintEngine::renderHintsChanged()
  2411 void QVGPaintEngine::renderHintsChanged()
  2348 {
  2412 {
  2349     Q_D(QVGPaintEngine);
  2413     Q_D(QVGPaintEngine);
  3046 
  3110 
  3047 // Best performance will be achieved with QDrawPixmaps::OpaqueHint
  3111 // Best performance will be achieved with QDrawPixmaps::OpaqueHint
  3048 // (i.e. no opacity), no rotation or scaling, and drawing the full
  3112 // (i.e. no opacity), no rotation or scaling, and drawing the full
  3049 // pixmap rather than parts of the pixmap.  Even having just one of
  3113 // pixmap rather than parts of the pixmap.  Even having just one of
  3050 // these conditions will improve performance.
  3114 // these conditions will improve performance.
  3051 void QVGPaintEngine::drawPixmaps
  3115 void QVGPaintEngine::drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount,
  3052     (const QDrawPixmaps::Data *drawingData, int dataCount,
  3116                                          const QPixmap &pixmap, QFlags<QPainter::PixmapFragmentHint> hints)
  3053      const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints)
       
  3054 {
  3117 {
  3055 #if !defined(QT_SHIVAVG)
  3118 #if !defined(QT_SHIVAVG)
  3056     Q_D(QVGPaintEngine);
  3119     Q_D(QVGPaintEngine);
  3057 
  3120 
  3058     // If the pixmap is not VG, or the transformation is projective,
  3121     // If the pixmap is not VG, or the transformation is projective,
  3059     // then fall back to the default implementation.
  3122     // then fall back to the default implementation.
  3060     QPixmapData *pd = pixmap.pixmapData();
  3123     QPixmapData *pd = pixmap.pixmapData();
  3061     if (!pd)
  3124     if (!pd)
  3062         return; // null QPixmap
  3125         return; // null QPixmap
  3063     if (pd->classId() != QPixmapData::OpenVGClass || !d->simpleTransform) {
  3126     if (pd->classId() != QPixmapData::OpenVGClass || !d->simpleTransform) {
  3064         QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
  3127         QPaintEngineEx::drawPixmapFragments(drawingData, dataCount, pixmap, hints);
  3065         return;
  3128         return;
  3066     }
  3129     }
  3067 
  3130 
  3068     // Bail out if nothing to do.
  3131     // Bail out if nothing to do.
  3069     if (dataCount <= 0)
  3132     if (dataCount <= 0)
  3083     // isn't needed at all, so use full source rects where possible.
  3146     // isn't needed at all, so use full source rects where possible.
  3084     QVarLengthArray<VGImage> cachedImages;
  3147     QVarLengthArray<VGImage> cachedImages;
  3085     QVarLengthArray<QRect> cachedSources;
  3148     QVarLengthArray<QRect> cachedSources;
  3086 
  3149 
  3087     // Select the opacity paint object.
  3150     // Select the opacity paint object.
  3088     if ((hints & QDrawPixmaps::OpaqueHint) != 0 && d->opacity == 1.0f) {
  3151     if ((hints & QPainter::OpaqueHint) != 0 && d->opacity == 1.0f) {
  3089         d->setImageMode(VG_DRAW_IMAGE_NORMAL);
  3152         d->setImageMode(VG_DRAW_IMAGE_NORMAL);
  3090     }  else {
  3153     }  else {
  3091         hints = 0;
  3154         hints = 0;
  3092         if (d->fillPaint != d->opacityPaint) {
  3155         if (d->fillPaint != d->opacityPaint) {
  3093             vgSetPaint(d->opacityPaint, VG_FILL_PATH);
  3156             vgSetPaint(d->opacityPaint, VG_FILL_PATH);
  3095         }
  3158         }
  3096     }
  3159     }
  3097 
  3160 
  3098     for (int i = 0; i < dataCount; ++i) {
  3161     for (int i = 0; i < dataCount; ++i) {
  3099         QTransform transform(d->imageTransform);
  3162         QTransform transform(d->imageTransform);
  3100         transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
  3163         transform.translate(drawingData[i].x, drawingData[i].y);
  3101         transform.rotate(drawingData[i].rotation);
  3164         transform.rotate(drawingData[i].rotation);
  3102 
  3165 
  3103         VGImage child;
  3166         VGImage child;
  3104         QSize imageSize = vgpd->size();
  3167         QSize imageSize = vgpd->size();
  3105         QRectF sr = drawingData[i].source;
  3168         QRectF sr(drawingData[i].sourceLeft, drawingData[i].sourceTop,
       
  3169                   drawingData[i].width, drawingData[i].height);
  3106         if (sr.topLeft().isNull() && sr.size() == imageSize) {
  3170         if (sr.topLeft().isNull() && sr.size() == imageSize) {
  3107             child = vgImg;
  3171             child = vgImg;
  3108         } else {
  3172         } else {
  3109             // Look for a previous child with the same source rectangle
  3173             // Look for a previous child with the same source rectangle
  3110             // to avoid constantly calling vgChildImage()/vgDestroyImage().
  3174             // to avoid constantly calling vgChildImage()/vgDestroyImage().
  3129         transform.translate(-0.5 * scaleX * sr.width(),
  3193         transform.translate(-0.5 * scaleX * sr.width(),
  3130                             -0.5 * scaleY * sr.height());
  3194                             -0.5 * scaleY * sr.height());
  3131         transform.scale(scaleX, scaleY);
  3195         transform.scale(scaleX, scaleY);
  3132         d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
  3196         d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform);
  3133 
  3197 
  3134         if ((hints & QDrawPixmaps::OpaqueHint) == 0) {
  3198         if ((hints & QPainter::OpaqueHint) == 0) {
  3135             qreal opacity = d->opacity * drawingData[i].opacity;
  3199             qreal opacity = d->opacity * drawingData[i].opacity;
  3136             if (opacity != 1.0f) {
  3200             if (opacity != 1.0f) {
  3137                 if (d->paintOpacity != opacity) {
  3201                 if (d->paintOpacity != opacity) {
  3138                     VGfloat values[4];
  3202                     VGfloat values[4];
  3139                     values[0] = 1.0f;
  3203                     values[0] = 1.0f;
  3155 
  3219 
  3156     // Destroy the cached child sub-images.
  3220     // Destroy the cached child sub-images.
  3157     for (int i = 0; i < cachedImages.size(); ++i)
  3221     for (int i = 0; i < cachedImages.size(); ++i)
  3158         vgDestroyImage(cachedImages[i]);
  3222         vgDestroyImage(cachedImages[i]);
  3159 #else
  3223 #else
  3160     QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
  3224     QPaintEngineEx::drawPixmapFragments(drawingData, dataCount, pixmap, hints);
  3161 #endif
  3225 #endif
  3162 }
  3226 }
  3163 
  3227 
  3164 QVGFontEngineCleaner::QVGFontEngineCleaner(QVGPaintEnginePrivate *d)
  3228 QVGFontEngineCleaner::QVGFontEngineCleaner(QVGPaintEnginePrivate *d)
  3165     : QObject(), d_ptr(d)
  3229     : QObject(), d_ptr(d)
  3195 {
  3259 {
  3196     if (font != VG_INVALID_HANDLE)
  3260     if (font != VG_INVALID_HANDLE)
  3197         vgDestroyFont(font);
  3261         vgDestroyFont(font);
  3198 }
  3262 }
  3199 
  3263 
  3200 void QVGFontGlyphCache::setScaleFromText(const QTextItemInt &ti)
  3264 void QVGFontGlyphCache::setScaleFromText(const QFont &font, QFontEngine *fontEngine)
  3201 {
  3265 {
  3202     QFontInfo fi(ti.font());
  3266     QFontInfo fi(font);
  3203     qreal pixelSize = fi.pixelSize();
  3267     qreal pixelSize = fi.pixelSize();
  3204     qreal emSquare = ti.fontEngine->properties().emSquare.toReal();
  3268     qreal emSquare = fontEngine->properties().emSquare.toReal();
  3205     scaleX = scaleY = static_cast<VGfloat>(pixelSize / emSquare);
  3269     scaleX = scaleY = static_cast<VGfloat>(pixelSize / emSquare);
  3206 }
  3270 }
  3207 
  3271 
  3208 void QVGFontGlyphCache::cacheGlyphs
  3272 void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d,
  3209         (QVGPaintEnginePrivate *d, const QTextItemInt &ti,
  3273                                     QFontEngine *fontEngine,
  3210          const QVarLengthArray<glyph_t> &glyphs)
  3274                                     const glyph_t *g, int count)
  3211 {
  3275 {
  3212     VGfloat origin[2];
  3276     VGfloat origin[2];
  3213     VGfloat escapement[2];
  3277     VGfloat escapement[2];
  3214     const glyph_t *g = glyphs.constData();
       
  3215     int count = glyphs.size();
       
  3216     glyph_metrics_t metrics;
  3278     glyph_metrics_t metrics;
  3217     // Some Qt font engines don't set yoff in getUnscaledGlyph().
  3279     // Some Qt font engines don't set yoff in getUnscaledGlyph().
  3218     // Zero the metric structure so that everything has a default value.
  3280     // Zero the metric structure so that everything has a default value.
  3219     memset(&metrics, 0, sizeof(metrics));
  3281     memset(&metrics, 0, sizeof(metrics));
  3220     while (count-- > 0) {
  3282     while (count-- > 0) {
  3229         } else {
  3291         } else {
  3230             cachedGlyphs.insert(glyph);
  3292             cachedGlyphs.insert(glyph);
  3231         }
  3293         }
  3232 #if !defined(QVG_NO_IMAGE_GLYPHS)
  3294 #if !defined(QVG_NO_IMAGE_GLYPHS)
  3233         Q_UNUSED(d);
  3295         Q_UNUSED(d);
  3234         QImage scaledImage = ti.fontEngine->alphaMapForGlyph(glyph);
  3296         QImage scaledImage = fontEngine->alphaMapForGlyph(glyph);
  3235         VGImage vgImage = VG_INVALID_HANDLE;
  3297         VGImage vgImage = VG_INVALID_HANDLE;
  3236         metrics = ti.fontEngine->boundingBox(glyph);
  3298         metrics = fontEngine->boundingBox(glyph);
  3237         if (!scaledImage.isNull()) {  // Not a space character
  3299         if (!scaledImage.isNull()) {  // Not a space character
  3238             if (scaledImage.format() == QImage::Format_Indexed8) {
  3300             if (scaledImage.format() == QImage::Format_Indexed8) {
  3239                 vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
  3301                 vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER);
  3240                 vgImageSubData(vgImage, qt_vg_imageBits(scaledImage), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
  3302                 vgImageSubData(vgImage, scaledImage.constBits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height());
  3241             } else if (scaledImage.format() == QImage::Format_Mono) {
  3303             } else if (scaledImage.format() == QImage::Format_Mono) {
  3242                 QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
  3304                 QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8);
  3243                 vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3305                 vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3244                 vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
  3306                 vgImageSubData(vgImage, img.constBits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height());
  3245             } else {
  3307             } else {
  3246                 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
  3308                 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
  3247                 vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3309                 vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER);
  3248                 vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
  3310                 vgImageSubData(vgImage, img.constBits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height());
  3249             }
  3311             }
  3250         }
  3312         }
  3251         origin[0] = -metrics.x.toReal() + 0.5f;
  3313         origin[0] = -metrics.x.toReal();
  3252         origin[1] = -metrics.y.toReal() + 0.5f;
  3314         origin[1] = -metrics.y.toReal();
  3253         escapement[0] = metrics.xoff.toReal();
  3315         escapement[0] = 0;
  3254         escapement[1] = metrics.yoff.toReal();
  3316         escapement[1] = 0;
  3255         vgSetGlyphToImage(font, glyph, vgImage, origin, escapement);
  3317         vgSetGlyphToImage(font, glyph, vgImage, origin, escapement);
  3256         vgDestroyImage(vgImage);    // Reduce reference count.
  3318         vgDestroyImage(vgImage);    // Reduce reference count.
  3257 #else
  3319 #else
  3258         // Calculate the path for the glyph and cache it.
  3320         // Calculate the path for the glyph and cache it.
  3259         QPainterPath path;
  3321         QPainterPath path;
  3260         ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
  3322         fontEngine->getUnscaledGlyph(glyph, &path, &metrics);
  3261         VGPath vgPath;
  3323         VGPath vgPath;
  3262         if (!path.isEmpty()) {
  3324         if (!path.isEmpty()) {
  3263             vgPath = d->painterPathToVGPath(path);
  3325             vgPath = d->painterPathToVGPath(path);
  3264         } else {
  3326         } else {
  3265             // Probably a "space" character with no visible outline.
  3327             // Probably a "space" character with no visible outline.
  3266             vgPath = VG_INVALID_HANDLE;
  3328             vgPath = VG_INVALID_HANDLE;
  3267         }
  3329         }
  3268         origin[0] = 0;
  3330         origin[0] = 0;
  3269         origin[1] = 0;
  3331         origin[1] = 0;
  3270         escapement[0] = metrics.xoff.toReal();
  3332         escapement[0] = 0;
  3271         escapement[1] = metrics.yoff.toReal();
  3333         escapement[1] = 0;
  3272         vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement);
  3334         vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement);
  3273         vgDestroyPath(vgPath);      // Reduce reference count.
  3335         vgDestroyPath(vgPath);      // Reduce reference count.
  3274 #endif // !defined(QVG_NO_IMAGE_GLYPHS)
  3336 #endif // !defined(QVG_NO_IMAGE_GLYPHS)
  3275     }
  3337     }
  3276 }
  3338 }
  3287     // to the default Qt path stroking algorithm.
  3349     // to the default Qt path stroking algorithm.
  3288     if (!d->simpleTransform) {
  3350     if (!d->simpleTransform) {
  3289         QPaintEngineEx::drawTextItem(p, textItem);
  3351         QPaintEngineEx::drawTextItem(p, textItem);
  3290         return;
  3352         return;
  3291     }
  3353     }
  3292  
  3354 
  3293     // Get the glyphs and positions associated with the text item.
  3355     // Get the glyphs and positions associated with the text item.
  3294     QVarLengthArray<QFixedPoint> positions;
  3356     QVarLengthArray<QFixedPoint> positions;
  3295     QVarLengthArray<glyph_t> glyphs;
  3357     QVarLengthArray<glyph_t> glyphs;
  3296     QTransform matrix = d->transform;
  3358     QTransform matrix;
  3297     matrix.translate(p.x(), p.y());
  3359     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
  3298     ti.fontEngine->getGlyphPositions
  3360 
  3299         (ti.glyphs, matrix, ti.flags, glyphs, positions);
  3361     if (!drawCachedGlyphs(glyphs.size(), glyphs.data(), ti.font(), ti.fontEngine, p, positions.data()))
       
  3362         QPaintEngineEx::drawTextItem(p, textItem);
       
  3363 #else
       
  3364     // OpenGL 1.0 does not have support for VGFont and glyphs,
       
  3365     // so fall back to the default Qt path stroking algorithm.
       
  3366     QPaintEngineEx::drawTextItem(p, textItem);
       
  3367 #endif
       
  3368 }
       
  3369 
       
  3370 void QVGPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
       
  3371 {
       
  3372     drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->font, textItem->fontEngine,
       
  3373                      QPointF(0, 0), textItem->glyphPositions);
       
  3374 }
       
  3375 
       
  3376  bool QVGPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFont &font,
       
  3377                                        QFontEngine *fontEngine, const QPointF &p,
       
  3378                                        const QFixedPoint *positions)
       
  3379  {
       
  3380 #if !defined(QVG_NO_DRAW_GLYPHS)
       
  3381     Q_D(QVGPaintEngine);
  3300 
  3382 
  3301     // Find the glyph cache for this font.
  3383     // Find the glyph cache for this font.
  3302     QVGFontCache::ConstIterator it = d->fontCache.constFind(ti.fontEngine);
  3384     QVGFontCache::ConstIterator it = d->fontCache.constFind(fontEngine);
  3303     QVGFontGlyphCache *glyphCache;
  3385     QVGFontGlyphCache *glyphCache;
  3304     if (it != d->fontCache.constEnd()) {
  3386     if (it != d->fontCache.constEnd()) {
  3305         glyphCache = it.value();
  3387         glyphCache = it.value();
  3306     } else {
  3388     } else {
  3307         glyphCache = new QVGFontGlyphCache();
  3389         glyphCache = new QVGFontGlyphCache();
  3308         if (glyphCache->font == VG_INVALID_HANDLE) {
  3390         if (glyphCache->font == VG_INVALID_HANDLE) {
  3309             qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine");
  3391             qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine");
  3310             delete glyphCache;
  3392             delete glyphCache;
  3311             QPaintEngineEx::drawTextItem(p, textItem);
  3393             return false;
  3312             return;
  3394         }
  3313         }
  3395         glyphCache->setScaleFromText(font, fontEngine);
  3314         glyphCache->setScaleFromText(ti);
  3396         d->fontCache.insert(fontEngine, glyphCache);
  3315         d->fontCache.insert(ti.fontEngine, glyphCache);
       
  3316         if (!d->fontEngineCleaner)
  3397         if (!d->fontEngineCleaner)
  3317             d->fontEngineCleaner = new QVGFontEngineCleaner(d);
  3398             d->fontEngineCleaner = new QVGFontEngineCleaner(d);
  3318         QObject::connect(ti.fontEngine, SIGNAL(destroyed()),
  3399         QObject::connect(fontEngine, SIGNAL(destroyed()),
  3319                          d->fontEngineCleaner, SLOT(fontEngineDestroyed()));
  3400                          d->fontEngineCleaner, SLOT(fontEngineDestroyed()));
  3320     }
  3401     }
  3321 
  3402 
  3322     // Set the transformation to use for drawing the current glyphs.
  3403     // Set the transformation to use for drawing the current glyphs.
  3323     QTransform glyphTransform(d->glyphTransform);
  3404     QTransform glyphTransform(d->pathTransform);
  3324     glyphTransform.translate(p.x(), p.y());
  3405     glyphTransform.translate(p.x(), p.y());
  3325 #if defined(QVG_NO_IMAGE_GLYPHS)
  3406 #if defined(QVG_NO_IMAGE_GLYPHS)
  3326     glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
  3407     glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY);
  3327 #endif
  3408 #endif
  3328     d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform);
  3409     d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform);
  3329 
  3410 
  3330     // Add the glyphs from the text item into the glyph cache.
  3411     // Add the glyphs from the text item into the glyph cache.
  3331     glyphCache->cacheGlyphs(d, ti, glyphs);
  3412     glyphCache->cacheGlyphs(d, fontEngine, glyphs, numGlyphs);
       
  3413 
       
  3414     // Create the array of adjustments between glyphs
       
  3415     QVarLengthArray<VGfloat> adjustments_x(numGlyphs);
       
  3416     QVarLengthArray<VGfloat> adjustments_y(numGlyphs);
       
  3417     for (int i = 1; i < numGlyphs; ++i) {
       
  3418         adjustments_x[i-1] = (positions[i].x - positions[i-1].x).toReal();
       
  3419         adjustments_y[i-1] = (positions[i].y - positions[i-1].y).toReal();
       
  3420     }
  3332 
  3421 
  3333     // Set the glyph drawing origin.
  3422     // Set the glyph drawing origin.
  3334     VGfloat origin[2];
  3423     VGfloat origin[2];
  3335     origin[0] = 0;
  3424     origin[0] = positions[0].x.toReal();
  3336     origin[1] = 0;
  3425     origin[1] = positions[0].y.toReal();
  3337     vgSetfv(VG_GLYPH_ORIGIN, 2, origin);
  3426     vgSetfv(VG_GLYPH_ORIGIN, 2, origin);
  3338 
  3427 
  3339     // Fast anti-aliasing for paths, better for images.
  3428     // Fast anti-aliasing for paths, better for images.
  3340 #if !defined(QVG_NO_IMAGE_GLYPHS)
  3429 #if !defined(QVG_NO_IMAGE_GLYPHS)
  3341     d->setImageQuality(VG_IMAGE_QUALITY_BETTER);
  3430     d->setImageQuality(VG_IMAGE_QUALITY_BETTER);
  3345 #endif
  3434 #endif
  3346 
  3435 
  3347     // Draw the glyphs.  We need to fill with the brush associated with
  3436     // Draw the glyphs.  We need to fill with the brush associated with
  3348     // the Qt pen, not the Qt brush.
  3437     // the Qt pen, not the Qt brush.
  3349     d->ensureBrush(state()->pen.brush());
  3438     d->ensureBrush(state()->pen.brush());
  3350     vgDrawGlyphs(glyphCache->font, glyphs.size(), (VGuint*)glyphs.data(),
  3439     vgDrawGlyphs(glyphCache->font, numGlyphs, (VGuint*)glyphs,
  3351                  NULL, NULL, VG_FILL_PATH, VG_TRUE);
  3440                  adjustments_x.data(), adjustments_y.data(), VG_FILL_PATH, VG_TRUE);
       
  3441     return true;
  3352 #else
  3442 #else
  3353     // OpenGL 1.0 does not have support for VGFont and glyphs,
  3443     Q_UNUSED(numGlyphs);
  3354     // so fall back to the default Qt path stroking algorithm.
  3444     Q_UNUSED(glyphs);
  3355     QPaintEngineEx::drawTextItem(p, textItem);
  3445     Q_UNUSED(font);
       
  3446     Q_UNUSED(fontEngine);
       
  3447     Q_UNUSED(p);
       
  3448     Q_UNUSED(positions);
       
  3449     return false;
  3356 #endif
  3450 #endif
  3357 }
  3451 }
  3358 
  3452 
  3359 void QVGPaintEngine::setState(QPainterState *s)
  3453 void QVGPaintEngine::setState(QPainterState *s)
  3360 {
  3454 {
  3711             (VG_sARGB_8888_PRE, img.width(), img.height(),
  3805             (VG_sARGB_8888_PRE, img.width(), img.height(),
  3712              VG_IMAGE_QUALITY_FASTER);
  3806              VG_IMAGE_QUALITY_FASTER);
  3713         if (vgImage == VG_INVALID_HANDLE)
  3807         if (vgImage == VG_INVALID_HANDLE)
  3714             return;
  3808             return;
  3715         vgImageSubData
  3809         vgImageSubData
  3716             (vgImage, qt_vg_imageBits(img) + img.bytesPerLine() * (img.height() - 1),
  3810             (vgImage, img.constBits() + img.bytesPerLine() * (img.height() - 1),
  3717              -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
  3811              -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0,
  3718              img.width(), img.height());
  3812              img.width(), img.height());
  3719 
  3813 
  3720         vgDrawImage(vgImage);
  3814         vgDrawImage(vgImage);
  3721         vgDestroyImage(vgImage);
  3815         vgDestroyImage(vgImage);