65 #include <private/qfontengine_p.h> |
65 #include <private/qfontengine_p.h> |
66 #include <private/qpixmap_raster_p.h> |
66 #include <private/qpixmap_raster_p.h> |
67 // #include <private/qpolygonclipper_p.h> |
67 // #include <private/qpolygonclipper_p.h> |
68 // #include <private/qrasterizer_p.h> |
68 // #include <private/qrasterizer_p.h> |
69 #include <private/qimage_p.h> |
69 #include <private/qimage_p.h> |
|
70 #include <private/qstatictext_p.h> |
70 |
71 |
71 #include "qpaintengine_raster_p.h" |
72 #include "qpaintengine_raster_p.h" |
72 // #include "qbezier_p.h" |
73 // #include "qbezier_p.h" |
73 #include "qoutlinemapper_p.h" |
74 #include "qoutlinemapper_p.h" |
74 |
75 |
248 fprintf(stderr," - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); |
249 fprintf(stderr," - %3d:: %s, (%.2f, %.2f)\n", i, names[e.type], e.x, e.y); |
249 } |
250 } |
250 } |
251 } |
251 #endif |
252 #endif |
252 |
253 |
|
254 QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : |
|
255 QPaintEngineExPrivate(), |
|
256 cachedLines(0) |
|
257 { |
|
258 } |
253 |
259 |
254 |
260 |
255 /*! |
261 /*! |
256 \class QRasterPaintEngine |
262 \class QRasterPaintEngine |
257 \preliminary |
263 \preliminary |
333 |
339 |
334 #ifdef Q_WS_WIN |
340 #ifdef Q_WS_WIN |
335 d->hdc = 0; |
341 d->hdc = 0; |
336 #endif |
342 #endif |
337 |
343 |
338 d->rasterPoolSize = 8192; |
|
339 d->rasterPoolBase = |
|
340 #if defined(Q_WS_WIN64) |
|
341 // We make use of setjmp and longjmp in qgrayraster.c which requires |
|
342 // 16-byte alignment, hence we hardcode this requirement here.. |
|
343 (unsigned char *) _aligned_malloc(d->rasterPoolSize, sizeof(void*) * 2); |
|
344 #else |
|
345 (unsigned char *) malloc(d->rasterPoolSize); |
|
346 #endif |
|
347 Q_CHECK_PTR(d->rasterPoolBase); |
|
348 |
|
349 // The antialiasing raster. |
344 // The antialiasing raster. |
350 d->grayRaster.reset(new QT_FT_Raster); |
345 d->grayRaster.reset(new QT_FT_Raster); |
351 Q_CHECK_PTR(d->grayRaster.data()); |
346 Q_CHECK_PTR(d->grayRaster.data()); |
352 if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data())) |
347 if (qt_ft_grays_raster.raster_new(0, d->grayRaster.data())) |
353 QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc |
348 QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc |
354 |
349 |
355 |
|
356 qt_ft_grays_raster.raster_reset(*d->grayRaster.data(), d->rasterPoolBase, d->rasterPoolSize); |
|
357 |
350 |
358 d->rasterizer.reset(new QRasterizer); |
351 d->rasterizer.reset(new QRasterizer); |
359 d->rasterBuffer.reset(new QRasterBuffer()); |
352 d->rasterBuffer.reset(new QRasterBuffer()); |
360 d->outlineMapper.reset(new QOutlineMapper); |
353 d->outlineMapper.reset(new QOutlineMapper); |
361 d->outlinemapper_xform_dirty = true; |
354 d->outlinemapper_xform_dirty = true; |
433 Destroys this paint engine. |
426 Destroys this paint engine. |
434 */ |
427 */ |
435 QRasterPaintEngine::~QRasterPaintEngine() |
428 QRasterPaintEngine::~QRasterPaintEngine() |
436 { |
429 { |
437 Q_D(QRasterPaintEngine); |
430 Q_D(QRasterPaintEngine); |
438 |
|
439 #if defined(Q_WS_WIN64) |
|
440 _aligned_free(d->rasterPoolBase); |
|
441 #else |
|
442 free(d->rasterPoolBase); |
|
443 #endif |
|
444 |
431 |
445 qt_ft_grays_raster.raster_done(*d->grayRaster.data()); |
432 qt_ft_grays_raster.raster_done(*d->grayRaster.data()); |
446 } |
433 } |
447 |
434 |
448 /*! |
435 /*! |
1722 patternLength += pattern.at(i); |
1709 patternLength += pattern.at(i); |
1723 |
1710 |
1724 if (patternLength > 0) { |
1711 if (patternLength > 0) { |
1725 int n = qFloor(dashOffset / patternLength); |
1712 int n = qFloor(dashOffset / patternLength); |
1726 dashOffset -= n * patternLength; |
1713 dashOffset -= n * patternLength; |
1727 while (dashOffset > pattern.at(dashIndex)) { |
1714 while (dashOffset >= pattern.at(dashIndex)) { |
1728 dashOffset -= pattern.at(dashIndex); |
1715 dashOffset -= pattern.at(dashIndex); |
1729 dashIndex = (dashIndex + 1) % pattern.size(); |
1716 if (++dashIndex >= pattern.size()) |
|
1717 dashIndex = 0; |
1730 inDash = !inDash; |
1718 inDash = !inDash; |
1731 } |
1719 } |
1732 } |
1720 } |
1733 |
1721 |
1734 Q_D(QRasterPaintEngine); |
1722 Q_D(QRasterPaintEngine); |
1735 d->initializeRasterizer(&s->penData); |
1723 d->initializeRasterizer(&s->penData); |
1736 int lineCount = path.elementCount() / 2; |
1724 int lineCount = path.elementCount() / 2; |
1737 const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); |
1725 const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); |
1738 |
1726 |
1739 for (int i = 0; i < lineCount; ++i) { |
1727 for (int i = 0; i < lineCount; ++i) { |
1740 dashOffset = s->lastPen.dashOffset(); |
|
1741 if (lines[i].p1() == lines[i].p2()) { |
1728 if (lines[i].p1() == lines[i].p2()) { |
1742 if (s->lastPen.capStyle() != Qt::FlatCap) { |
1729 if (s->lastPen.capStyle() != Qt::FlatCap) { |
1743 QPointF p = lines[i].p1(); |
1730 QPointF p = lines[i].p1(); |
1744 QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()), |
1731 QLineF line = s->matrix.map(QLineF(QPointF(p.x() - width*0.5, p.y()), |
1745 QPointF(p.x() + width*0.5, p.y()))); |
1732 QPointF(p.x() + width*0.5, p.y()))); |
2549 int sr_l = qFloor(sr.left()); |
2536 int sr_l = qFloor(sr.left()); |
2550 int sr_r = qCeil(sr.right()) - 1; |
2537 int sr_r = qCeil(sr.right()) - 1; |
2551 int sr_t = qFloor(sr.top()); |
2538 int sr_t = qFloor(sr.top()); |
2552 int sr_b = qCeil(sr.bottom()) - 1; |
2539 int sr_b = qCeil(sr.bottom()) - 1; |
2553 |
2540 |
2554 if (!s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { |
2541 if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { |
2555 // as fillRect will apply the aliased coordinate delta we need to |
2542 // as fillRect will apply the aliased coordinate delta we need to |
2556 // subtract it here as we don't use it for image drawing |
2543 // subtract it here as we don't use it for image drawing |
2557 QTransform old = s->matrix; |
2544 QTransform old = s->matrix; |
2558 s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); |
2545 s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); |
2559 |
2546 |
3000 // Call span func for current set of spans. |
2987 // Call span func for current set of spans. |
3001 if (current != 0) |
2988 if (current != 0) |
3002 blend(current, spans, &s->penData); |
2989 blend(current, spans, &s->penData); |
3003 } |
2990 } |
3004 |
2991 |
3005 void QRasterPaintEngine::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti) |
2992 void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, |
|
2993 const QFixedPoint *positions, QFontEngine *fontEngine) |
3006 { |
2994 { |
3007 Q_D(QRasterPaintEngine); |
2995 Q_D(QRasterPaintEngine); |
3008 QRasterPaintEngineState *s = state(); |
2996 QRasterPaintEngineState *s = state(); |
3009 |
2997 |
3010 QVarLengthArray<QFixedPoint> positions; |
2998 QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType; |
3011 QVarLengthArray<glyph_t> glyphs; |
|
3012 QTransform matrix = s->matrix; |
|
3013 matrix.translate(p.x(), p.y()); |
|
3014 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
|
3015 |
|
3016 QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : d->glyphCacheType; |
|
3017 |
2999 |
3018 QImageTextureGlyphCache *cache = |
3000 QImageTextureGlyphCache *cache = |
3019 (QImageTextureGlyphCache *) ti.fontEngine->glyphCache(0, glyphType, s->matrix); |
3001 static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix)); |
3020 if (!cache) { |
3002 if (!cache) { |
3021 cache = new QImageTextureGlyphCache(glyphType, s->matrix); |
3003 cache = new QImageTextureGlyphCache(glyphType, s->matrix); |
3022 ti.fontEngine->setGlyphCache(0, cache); |
3004 fontEngine->setGlyphCache(0, cache); |
3023 } |
3005 } |
3024 |
3006 |
3025 cache->populate(ti, glyphs, positions); |
3007 cache->populate(fontEngine, numGlyphs, glyphs, positions); |
3026 |
3008 |
3027 const QImage &image = cache->image(); |
3009 const QImage &image = cache->image(); |
3028 int bpl = image.bytesPerLine(); |
3010 int bpl = image.bytesPerLine(); |
3029 |
3011 |
3030 int depth = image.depth(); |
3012 int depth = image.depth(); |
3038 int margin = cache->glyphMargin(); |
3020 int margin = cache->glyphMargin(); |
3039 |
3021 |
3040 const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); |
3022 const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); |
3041 |
3023 |
3042 const uchar *bits = image.bits(); |
3024 const uchar *bits = image.bits(); |
3043 for (int i=0; i<glyphs.size(); ++i) { |
3025 for (int i=0; i<numGlyphs; ++i) { |
3044 const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); |
3026 const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); |
3045 int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; |
3027 int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; |
3046 int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; |
3028 int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; |
3047 |
3029 |
3048 // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", |
3030 // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", |
3216 const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF()); |
3198 const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF()); |
3217 return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend; |
3199 return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend; |
3218 } |
3200 } |
3219 |
3201 |
3220 /*! |
3202 /*! |
|
3203 \reimp |
|
3204 */ |
|
3205 void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) |
|
3206 { |
|
3207 ensurePen(); |
|
3208 ensureState(); |
|
3209 |
|
3210 drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions, |
|
3211 textItem->fontEngine); |
|
3212 } |
|
3213 |
|
3214 /*! |
3221 \reimp |
3215 \reimp |
3222 */ |
3216 */ |
3223 void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) |
3217 void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) |
3224 { |
3218 { |
3225 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); |
3219 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); |
3263 #else |
3257 #else |
3264 if (s->matrix.type() > QTransform::TxTranslate) |
3258 if (s->matrix.type() > QTransform::TxTranslate) |
3265 drawCached = false; |
3259 drawCached = false; |
3266 #endif |
3260 #endif |
3267 if (drawCached) { |
3261 if (drawCached) { |
3268 drawCachedGlyphs(p, ti); |
3262 QRasterPaintEngineState *s = state(); |
|
3263 |
|
3264 QVarLengthArray<QFixedPoint> positions; |
|
3265 QVarLengthArray<glyph_t> glyphs; |
|
3266 |
|
3267 QTransform matrix = s->matrix; |
|
3268 matrix.translate(p.x(), p.y()); |
|
3269 |
|
3270 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
|
3271 |
|
3272 drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine); |
3269 return; |
3273 return; |
3270 } |
3274 } |
3271 |
3275 |
3272 #elif defined (Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // Q_WS_WIN || Q_WS_MAC |
3276 #elif defined (Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // Q_WS_WIN || Q_WS_MAC |
3273 if (s->matrix.type() <= QTransform::TxTranslate |
3277 if (s->matrix.type() <= QTransform::TxTranslate |
3370 Q_ASSERT(false); |
3374 Q_ASSERT(false); |
3371 depth = 0; |
3375 depth = 0; |
3372 }; |
3376 }; |
3373 |
3377 |
3374 for(int i = 0; i < glyphs.size(); i++) { |
3378 for(int i = 0; i < glyphs.size(); i++) { |
3375 QFontEngineFT::Glyph *glyph = gset->glyph_data.value(glyphs[i]); |
3379 QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]); |
3376 |
3380 |
3377 if (!glyph || glyph->format != neededFormat) { |
3381 if (!glyph || glyph->format != neededFormat) { |
3378 if (!lockedFace) |
3382 if (!lockedFace) |
3379 lockedFace = fe->lockFace(); |
3383 lockedFace = fe->lockFace(); |
3380 glyph = fe->loadGlyph(gset, glyphs[i], neededFormat); |
3384 glyph = fe->loadGlyph(gset, glyphs[i], neededFormat); |
3606 *dashOffset += dash / width; |
3610 *dashOffset += dash / width; |
3607 length = 0; |
3611 length = 0; |
3608 } else { |
3612 } else { |
3609 *dashOffset = 0; |
3613 *dashOffset = 0; |
3610 *inDash = !(*inDash); |
3614 *inDash = !(*inDash); |
3611 *dashIndex = (*dashIndex + 1) % pattern.size(); |
3615 if (++*dashIndex >= pattern.size()) |
|
3616 *dashIndex = 0; |
3612 length -= dash; |
3617 length -= dash; |
3613 l.setLength(dash); |
3618 l.setLength(dash); |
3614 line.setP1(l.p2()); |
3619 line.setP1(l.p2()); |
3615 } |
3620 } |
3616 |
3621 |
3617 if (rasterize && dash != 0) |
3622 if (rasterize && dash > 0) |
3618 rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap); |
3623 rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap); |
3619 } |
3624 } |
3620 } |
3625 } |
3621 |
3626 |
3622 /*! |
3627 /*! |
4069 |
4074 |
4070 rasterizer->rasterize(outline, fillRule); |
4075 rasterizer->rasterize(outline, fillRule); |
4071 return; |
4076 return; |
4072 } |
4077 } |
4073 |
4078 |
|
4079 const int rasterPoolInitialSize = 8192; |
|
4080 int rasterPoolSize = rasterPoolInitialSize; |
|
4081 unsigned char *rasterPoolBase; |
|
4082 #if defined(Q_WS_WIN64) |
|
4083 rasterPoolBase = |
|
4084 // We make use of setjmp and longjmp in qgrayraster.c which requires |
|
4085 // 16-byte alignment, hence we hardcode this requirement here.. |
|
4086 (unsigned char *) _aligned_malloc(rasterPoolSize, sizeof(void*) * 2); |
|
4087 #else |
|
4088 unsigned char rasterPoolOnStack[rasterPoolInitialSize]; |
|
4089 rasterPoolBase = rasterPoolOnStack; |
|
4090 #endif |
|
4091 Q_CHECK_PTR(rasterPoolBase); |
|
4092 |
|
4093 qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); |
|
4094 |
4074 void *data = userData; |
4095 void *data = userData; |
4075 |
4096 |
4076 QT_FT_BBox clip_box = { deviceRect.x(), |
4097 QT_FT_BBox clip_box = { deviceRect.x(), |
4077 deviceRect.y(), |
4098 deviceRect.y(), |
4078 deviceRect.x() + deviceRect.width(), |
4099 deviceRect.x() + deviceRect.width(), |
4101 // Out of memory, reallocate some more and try again... |
4122 // Out of memory, reallocate some more and try again... |
4102 if (error == -6) { // -6 is Result_err_OutOfMemory |
4123 if (error == -6) { // -6 is Result_err_OutOfMemory |
4103 int new_size = rasterPoolSize * 2; |
4124 int new_size = rasterPoolSize * 2; |
4104 if (new_size > 1024 * 1024) { |
4125 if (new_size > 1024 * 1024) { |
4105 qWarning("QPainter: Rasterization of primitive failed"); |
4126 qWarning("QPainter: Rasterization of primitive failed"); |
4106 return; |
4127 break; |
4107 } |
4128 } |
4108 |
4129 |
4109 #if defined(Q_WS_WIN64) |
4130 #if defined(Q_WS_WIN64) |
4110 _aligned_free(rasterPoolBase); |
4131 _aligned_free(rasterPoolBase); |
4111 #else |
4132 #else |
4112 free(rasterPoolBase); |
4133 if (rasterPoolBase != rasterPoolOnStack) // initially on the stack |
|
4134 free(rasterPoolBase); |
4113 #endif |
4135 #endif |
4114 |
4136 |
4115 rasterPoolSize = new_size; |
4137 rasterPoolSize = new_size; |
4116 rasterPoolBase = |
4138 rasterPoolBase = |
4117 #if defined(Q_WS_WIN64) |
4139 #if defined(Q_WS_WIN64) |
4128 qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); |
4150 qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize); |
4129 } else { |
4151 } else { |
4130 done = true; |
4152 done = true; |
4131 } |
4153 } |
4132 } |
4154 } |
|
4155 |
|
4156 #if defined(Q_WS_WIN64) |
|
4157 _aligned_free(rasterPoolBase); |
|
4158 #else |
|
4159 if (rasterPoolBase != rasterPoolOnStack) // initially on the stack |
|
4160 free(rasterPoolBase); |
|
4161 #endif |
4133 } |
4162 } |
4134 |
4163 |
4135 void QRasterPaintEnginePrivate::recalculateFastImages() |
4164 void QRasterPaintEnginePrivate::recalculateFastImages() |
4136 { |
4165 { |
4137 Q_Q(QRasterPaintEngine); |
4166 Q_Q(QRasterPaintEngine); |