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 |
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(); |
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; |
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, |
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) |
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 { |