181 QTransform transform; // Currently active transform. |
181 QTransform transform; // Currently active transform. |
182 bool simpleTransform; // True if the transform is simple (non-projective). |
182 bool simpleTransform; // True if the transform is simple (non-projective). |
183 qreal penScale; // Pen scaling factor from "transform". |
183 qreal penScale; // Pen scaling factor from "transform". |
184 |
184 |
185 QTransform pathTransform; // Calculated VG path transformation. |
185 QTransform pathTransform; // Calculated VG path transformation. |
186 QTransform glyphTransform; // Calculated VG glyph transformation. |
|
187 QTransform imageTransform; // Calculated VG image transformation. |
186 QTransform imageTransform; // Calculated VG image transformation. |
188 bool pathTransformSet; // True if path transform set in the VG context. |
187 bool pathTransformSet; // True if path transform set in the VG context. |
189 |
188 |
190 bool maskValid; // True if vgMask() contains valid data. |
189 bool maskValid; // True if vgMask() contains valid data. |
191 bool maskIsSet; // True if mask would be fully set if it was valid. |
190 bool maskIsSet; // True if mask would be fully set if it was valid. |
495 mat[7] = transform.m32(); |
494 mat[7] = transform.m32(); |
496 mat[8] = transform.m33(); |
495 mat[8] = transform.m33(); |
497 vgLoadMatrix(mat); |
496 vgLoadMatrix(mat); |
498 } |
497 } |
499 |
498 |
500 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); |
499 Q_DECL_IMPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); |
501 |
500 |
502 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) |
501 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) |
503 { |
502 { |
504 VGfloat devh = pdev->height(); |
503 VGfloat devh = pdev->height(); |
505 |
504 |
506 // Construct the VG transform by combining the Qt transform with |
505 // Construct the VG transform by combining the Qt transform with |
507 // the following viewport transformation: |
506 // the following viewport transformation: |
508 // | 1 0 0 | |
507 // | 1 0 0 | |
509 // | 0 -1 devh | |
508 // | 0 -1 devh | |
510 // | 0 0 1 | |
509 // | 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: |
510 // The full VG transform is effectively: |
516 // 1. Apply the user's transformation matrix. |
511 // 1. Apply the user's transformation matrix. |
517 // 2. Translate glyphs by an extra (0.5, -0.5). |
512 // 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, |
513 QTransform viewport(1.0f, 0.0f, 0.0f, |
520 0.0f, -1.0f, 0.0f, |
514 0.0f, -1.0f, 0.0f, |
521 0.0f, devh, 1.0f); |
515 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 |
516 |
526 // Compute the path transform and determine if it is projective. |
517 // Compute the path transform and determine if it is projective. |
527 pathTransform = transform * viewport; |
518 pathTransform = transform * viewport; |
528 glyphTransform = transform * gviewport; |
|
529 bool projective = (pathTransform.m13() != 0.0f || |
519 bool projective = (pathTransform.m13() != 0.0f || |
530 pathTransform.m23() != 0.0f || |
520 pathTransform.m23() != 0.0f || |
531 pathTransform.m33() != 1.0f); |
521 pathTransform.m33() != 1.0f); |
532 if (projective) { |
522 if (projective) { |
533 // The engine cannot do projective path transforms for us, |
523 // The engine cannot do projective path transforms for us, |
534 // so we will have to convert the co-ordinates ourselves. |
524 // so we will have to convert the co-ordinates ourselves. |
535 // Change the matrix to just the viewport transformation. |
525 // Change the matrix to just the viewport transformation. |
536 pathTransform = viewport; |
526 pathTransform = viewport; |
537 glyphTransform = gviewport; |
|
538 simpleTransform = false; |
527 simpleTransform = false; |
539 } else { |
528 } else { |
540 simpleTransform = true; |
529 simpleTransform = true; |
541 } |
530 } |
542 pathTransformSet = false; |
531 pathTransformSet = false; |
3246 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); |
3235 QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); |
3247 vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); |
3236 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()); |
3237 vgImageSubData(vgImage, qt_vg_imageBits(img), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height()); |
3249 } |
3238 } |
3250 } |
3239 } |
3251 origin[0] = -metrics.x.toReal() + 0.5f; |
3240 origin[0] = -metrics.x.toReal(); |
3252 origin[1] = -metrics.y.toReal() + 0.5f; |
3241 origin[1] = -metrics.y.toReal(); |
3253 escapement[0] = metrics.xoff.toReal(); |
3242 escapement[0] = 0; |
3254 escapement[1] = metrics.yoff.toReal(); |
3243 escapement[1] = 0; |
3255 vgSetGlyphToImage(font, glyph, vgImage, origin, escapement); |
3244 vgSetGlyphToImage(font, glyph, vgImage, origin, escapement); |
3256 vgDestroyImage(vgImage); // Reduce reference count. |
3245 vgDestroyImage(vgImage); // Reduce reference count. |
3257 #else |
3246 #else |
3258 // Calculate the path for the glyph and cache it. |
3247 // Calculate the path for the glyph and cache it. |
3259 QPainterPath path; |
3248 QPainterPath path; |
3265 // Probably a "space" character with no visible outline. |
3254 // Probably a "space" character with no visible outline. |
3266 vgPath = VG_INVALID_HANDLE; |
3255 vgPath = VG_INVALID_HANDLE; |
3267 } |
3256 } |
3268 origin[0] = 0; |
3257 origin[0] = 0; |
3269 origin[1] = 0; |
3258 origin[1] = 0; |
3270 escapement[0] = metrics.xoff.toReal(); |
3259 escapement[0] = 0; |
3271 escapement[1] = metrics.yoff.toReal(); |
3260 escapement[1] = 0; |
3272 vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement); |
3261 vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement); |
3273 vgDestroyPath(vgPath); // Reduce reference count. |
3262 vgDestroyPath(vgPath); // Reduce reference count. |
3274 #endif // !defined(QVG_NO_IMAGE_GLYPHS) |
3263 #endif // !defined(QVG_NO_IMAGE_GLYPHS) |
3275 } |
3264 } |
3276 } |
3265 } |
3291 } |
3280 } |
3292 |
3281 |
3293 // Get the glyphs and positions associated with the text item. |
3282 // Get the glyphs and positions associated with the text item. |
3294 QVarLengthArray<QFixedPoint> positions; |
3283 QVarLengthArray<QFixedPoint> positions; |
3295 QVarLengthArray<glyph_t> glyphs; |
3284 QVarLengthArray<glyph_t> glyphs; |
3296 QTransform matrix = d->transform; |
3285 QTransform matrix; |
3297 matrix.translate(p.x(), p.y()); |
3286 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
3298 ti.fontEngine->getGlyphPositions |
|
3299 (ti.glyphs, matrix, ti.flags, glyphs, positions); |
|
3300 |
3287 |
3301 // Find the glyph cache for this font. |
3288 // Find the glyph cache for this font. |
3302 QVGFontCache::ConstIterator it = d->fontCache.constFind(ti.fontEngine); |
3289 QVGFontCache::ConstIterator it = d->fontCache.constFind(ti.fontEngine); |
3303 QVGFontGlyphCache *glyphCache; |
3290 QVGFontGlyphCache *glyphCache; |
3304 if (it != d->fontCache.constEnd()) { |
3291 if (it != d->fontCache.constEnd()) { |
3318 QObject::connect(ti.fontEngine, SIGNAL(destroyed()), |
3305 QObject::connect(ti.fontEngine, SIGNAL(destroyed()), |
3319 d->fontEngineCleaner, SLOT(fontEngineDestroyed())); |
3306 d->fontEngineCleaner, SLOT(fontEngineDestroyed())); |
3320 } |
3307 } |
3321 |
3308 |
3322 // Set the transformation to use for drawing the current glyphs. |
3309 // Set the transformation to use for drawing the current glyphs. |
3323 QTransform glyphTransform(d->glyphTransform); |
3310 QTransform glyphTransform(d->pathTransform); |
3324 glyphTransform.translate(p.x(), p.y()); |
3311 glyphTransform.translate(p.x(), p.y()); |
3325 #if defined(QVG_NO_IMAGE_GLYPHS) |
3312 #if defined(QVG_NO_IMAGE_GLYPHS) |
3326 glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); |
3313 glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); |
3327 #endif |
3314 #endif |
3328 d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); |
3315 d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); |
3329 |
3316 |
3330 // Add the glyphs from the text item into the glyph cache. |
3317 // Add the glyphs from the text item into the glyph cache. |
3331 glyphCache->cacheGlyphs(d, ti, glyphs); |
3318 glyphCache->cacheGlyphs(d, ti, glyphs); |
3332 |
3319 |
|
3320 // Create the array of adjustments between glyphs |
|
3321 QVarLengthArray<VGfloat> adjustments_x(glyphs.size()); |
|
3322 QVarLengthArray<VGfloat> adjustments_y(glyphs.size()); |
|
3323 for (int i = 1; i < glyphs.size(); ++i) { |
|
3324 adjustments_x[i-1] = (positions[i].x - positions[i-1].x).toReal(); |
|
3325 adjustments_y[i-1] = (positions[i].y - positions[i-1].y).toReal(); |
|
3326 } |
|
3327 |
3333 // Set the glyph drawing origin. |
3328 // Set the glyph drawing origin. |
3334 VGfloat origin[2]; |
3329 VGfloat origin[2]; |
3335 origin[0] = 0; |
3330 origin[0] = positions[0].x.toReal(); |
3336 origin[1] = 0; |
3331 origin[1] = positions[0].y.toReal(); |
3337 vgSetfv(VG_GLYPH_ORIGIN, 2, origin); |
3332 vgSetfv(VG_GLYPH_ORIGIN, 2, origin); |
3338 |
3333 |
3339 // Fast anti-aliasing for paths, better for images. |
3334 // Fast anti-aliasing for paths, better for images. |
3340 #if !defined(QVG_NO_IMAGE_GLYPHS) |
3335 #if !defined(QVG_NO_IMAGE_GLYPHS) |
3341 d->setImageQuality(VG_IMAGE_QUALITY_BETTER); |
3336 d->setImageQuality(VG_IMAGE_QUALITY_BETTER); |
3346 |
3341 |
3347 // Draw the glyphs. We need to fill with the brush associated with |
3342 // Draw the glyphs. We need to fill with the brush associated with |
3348 // the Qt pen, not the Qt brush. |
3343 // the Qt pen, not the Qt brush. |
3349 d->ensureBrush(state()->pen.brush()); |
3344 d->ensureBrush(state()->pen.brush()); |
3350 vgDrawGlyphs(glyphCache->font, glyphs.size(), (VGuint*)glyphs.data(), |
3345 vgDrawGlyphs(glyphCache->font, glyphs.size(), (VGuint*)glyphs.data(), |
3351 NULL, NULL, VG_FILL_PATH, VG_TRUE); |
3346 adjustments_x.data(), adjustments_y.data(), VG_FILL_PATH, VG_TRUE); |
3352 #else |
3347 #else |
3353 // OpenGL 1.0 does not have support for VGFont and glyphs, |
3348 // OpenGL 1.0 does not have support for VGFont and glyphs, |
3354 // so fall back to the default Qt path stroking algorithm. |
3349 // so fall back to the default Qt path stroking algorithm. |
3355 QPaintEngineEx::drawTextItem(p, textItem); |
3350 QPaintEngineEx::drawTextItem(p, textItem); |
3356 #endif |
3351 #endif |