42 #include "qpaintengine_vg_p.h" |
42 #include "qpaintengine_vg_p.h" |
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 #include "qvgfontglyphcache_p.h" |
47 #if !defined(QT_NO_EGL) |
48 #if !defined(QT_NO_EGL) |
48 #include <QtGui/private/qeglcontext_p.h> |
49 #include <QtGui/private/qeglcontext_p.h> |
49 #include "qwindowsurface_vgegl_p.h" |
50 #include "qwindowsurface_vgegl_p.h" |
50 #endif |
51 #endif |
51 #include <QtCore/qvarlengtharray.h> |
52 #include <QtCore/qvarlengtharray.h> |
52 #include <QtGui/private/qdrawhelper_p.h> |
53 #include <QtGui/private/qdrawhelper_p.h> |
53 #include <QtGui/private/qtextengine_p.h> |
54 #include <QtGui/private/qtextengine_p.h> |
54 #include <QtGui/private/qfontengine_p.h> |
55 #include <QtGui/private/qfontengine_p.h> |
55 #include <QtGui/private/qpainterpath_p.h> |
56 #include <QtGui/private/qpainterpath_p.h> |
56 #include <QtGui/private/qstatictext_p.h> |
57 #include <QtGui/private/qstatictext_p.h> |
|
58 #include <QtCore/qmath.h> |
57 #include <QDebug> |
59 #include <QDebug> |
58 #include <QSet> |
60 #include <QSet> |
59 |
61 |
60 QT_BEGIN_NAMESPACE |
62 QT_BEGIN_NAMESPACE |
61 |
63 |
77 |
79 |
78 Q_DECL_IMPORT extern int qt_defaultDpiX(); |
80 Q_DECL_IMPORT extern int qt_defaultDpiX(); |
79 Q_DECL_IMPORT extern int qt_defaultDpiY(); |
81 Q_DECL_IMPORT extern int qt_defaultDpiY(); |
80 |
82 |
81 class QVGPaintEnginePrivate; |
83 class QVGPaintEnginePrivate; |
82 |
|
83 class QVGFontGlyphCache |
|
84 { |
|
85 public: |
|
86 QVGFontGlyphCache(); |
|
87 ~QVGFontGlyphCache(); |
|
88 |
|
89 void cacheGlyphs(QVGPaintEnginePrivate *d, QFontEngine *fontEngine, const glyph_t *g, int count); |
|
90 |
|
91 void setScaleFromText(const QFont &font, QFontEngine *fontEngine); |
|
92 |
|
93 VGFont font; |
|
94 VGfloat scaleX; |
|
95 VGfloat scaleY; |
|
96 |
|
97 uint cachedGlyphsMask[256 / 32]; |
|
98 QSet<glyph_t> cachedGlyphs; |
|
99 }; |
|
100 |
84 |
101 typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache; |
85 typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache; |
102 |
86 |
103 #endif |
87 #endif |
104 |
88 |
1620 // Convert it into a QRect and apply. |
1604 // Convert it into a QRect and apply. |
1621 const qreal *points = path.points(); |
1605 const qreal *points = path.points(); |
1622 QRectF rect(points[0], points[1], points[2] - points[0], |
1606 QRectF rect(points[0], points[1], points[2] - points[0], |
1623 points[5] - points[1]); |
1607 points[5] - points[1]); |
1624 clip(rect.toRect(), op); |
1608 clip(rect.toRect(), op); |
1625 } else { |
1609 return; |
1626 // The best we can do is clip to the bounding rectangle |
1610 } |
1627 // of all control points. |
1611 |
1628 clip(path.controlPointRect().toRect(), op); |
1612 // Try converting the path into a QRegion that tightly follows |
1629 } |
1613 // the outline of the path we want to clip with. |
|
1614 QRegion region; |
|
1615 if (!path.isEmpty()) |
|
1616 region = QRegion(path.convertToPainterPath().toFillPolygon(QTransform()).toPolygon()); |
|
1617 |
|
1618 switch (op) { |
|
1619 case Qt::NoClip: |
|
1620 { |
|
1621 region = defaultClipRegion(); |
|
1622 } |
|
1623 break; |
|
1624 |
|
1625 case Qt::ReplaceClip: |
|
1626 { |
|
1627 region = d->transform.map(region); |
|
1628 } |
|
1629 break; |
|
1630 |
|
1631 case Qt::IntersectClip: |
|
1632 { |
|
1633 region = s->clipRegion.intersect(d->transform.map(region)); |
|
1634 } |
|
1635 break; |
|
1636 |
|
1637 case Qt::UniteClip: |
|
1638 { |
|
1639 region = s->clipRegion.unite(d->transform.map(region)); |
|
1640 } |
|
1641 break; |
|
1642 } |
|
1643 if (region.numRects() <= d->maxScissorRects) { |
|
1644 // We haven't reached the maximum scissor count yet, so we can |
|
1645 // still make use of this region. |
|
1646 s->clipRegion = region; |
|
1647 updateScissor(); |
|
1648 return; |
|
1649 } |
|
1650 |
|
1651 // The best we can do is clip to the bounding rectangle |
|
1652 // of all control points. |
|
1653 clip(path.controlPointRect().toRect(), op); |
1630 } |
1654 } |
1631 |
1655 |
1632 void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) |
1656 void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) |
1633 { |
1657 { |
1634 Q_D(QVGPaintEngine); |
1658 Q_D(QVGPaintEngine); |
3250 |
3274 |
3251 QVGFontGlyphCache::QVGFontGlyphCache() |
3275 QVGFontGlyphCache::QVGFontGlyphCache() |
3252 { |
3276 { |
3253 font = vgCreateFont(0); |
3277 font = vgCreateFont(0); |
3254 scaleX = scaleY = 0.0; |
3278 scaleX = scaleY = 0.0; |
|
3279 invertedGlyphs = false; |
3255 memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask)); |
3280 memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask)); |
3256 } |
3281 } |
3257 |
3282 |
3258 QVGFontGlyphCache::~QVGFontGlyphCache() |
3283 QVGFontGlyphCache::~QVGFontGlyphCache() |
3259 { |
3284 { |
3384 QVGFontCache::ConstIterator it = d->fontCache.constFind(fontEngine); |
3409 QVGFontCache::ConstIterator it = d->fontCache.constFind(fontEngine); |
3385 QVGFontGlyphCache *glyphCache; |
3410 QVGFontGlyphCache *glyphCache; |
3386 if (it != d->fontCache.constEnd()) { |
3411 if (it != d->fontCache.constEnd()) { |
3387 glyphCache = it.value(); |
3412 glyphCache = it.value(); |
3388 } else { |
3413 } else { |
|
3414 #ifdef Q_OS_SYMBIAN |
|
3415 glyphCache = new QSymbianVGFontGlyphCache(); |
|
3416 #else |
3389 glyphCache = new QVGFontGlyphCache(); |
3417 glyphCache = new QVGFontGlyphCache(); |
|
3418 #endif |
3390 if (glyphCache->font == VG_INVALID_HANDLE) { |
3419 if (glyphCache->font == VG_INVALID_HANDLE) { |
3391 qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine"); |
3420 qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine"); |
3392 delete glyphCache; |
3421 delete glyphCache; |
3393 return false; |
3422 return false; |
3394 } |
3423 } |
3400 d->fontEngineCleaner, SLOT(fontEngineDestroyed())); |
3429 d->fontEngineCleaner, SLOT(fontEngineDestroyed())); |
3401 } |
3430 } |
3402 |
3431 |
3403 // Set the transformation to use for drawing the current glyphs. |
3432 // Set the transformation to use for drawing the current glyphs. |
3404 QTransform glyphTransform(d->pathTransform); |
3433 QTransform glyphTransform(d->pathTransform); |
3405 glyphTransform.translate(p.x(), p.y()); |
3434 if (d->transform.type() <= QTransform::TxTranslate) { |
|
3435 // Prevent blurriness of unscaled, unrotated text by using integer coordinates. |
|
3436 // Using ceil(x-0.5) instead of qRound() or int-cast, behave like other paint engines. |
|
3437 glyphTransform.translate(ceil(p.x() - 0.5), ceil(p.y() - 0.5)); |
|
3438 } else { |
|
3439 glyphTransform.translate(p.x(), p.y()); |
|
3440 } |
3406 #if defined(QVG_NO_IMAGE_GLYPHS) |
3441 #if defined(QVG_NO_IMAGE_GLYPHS) |
3407 glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); |
3442 glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); |
3408 #endif |
3443 #endif |
|
3444 |
|
3445 // Some glyph caches can create the VGImage upright |
|
3446 if (glyphCache->invertedGlyphs) |
|
3447 glyphTransform.scale(1, -1); |
|
3448 |
3409 d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); |
3449 d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); |
3410 |
3450 |
3411 // Add the glyphs from the text item into the glyph cache. |
3451 // Add the glyphs from the text item into the glyph cache. |
3412 glyphCache->cacheGlyphs(d, fontEngine, glyphs, numGlyphs); |
3452 glyphCache->cacheGlyphs(d, fontEngine, glyphs, numGlyphs); |
3413 |
3453 |