src/gui/painting/qpaintengine_raster.cpp
changeset 30 5dc02b23752f
parent 22 79de32ba3296
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    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);