Commit 06164dc27c310b7b8c05b98fd8ce9bafdb8e71f6

  • avatar
  • Antti Koivisto <antti @esdhcp…7161.research.nokia.com>
  • Mon Jan 25 17:43:10 CET 2010
Fix some rounding related drawing issues:

- keep dirty rects and tile rects in tile cache coordinates (pixels in cached bitmaps).
- make tile cache internal functions operate in tile coordinates.
- add conversion functions to/from document coordinates.
  
7777 void setTile(const TileCoordinate& coordinate, PassRefPtr<Tile> tile);
7878 void removeTile(const TileCoordinate& coordinate);
7979
80 FloatRect tileRectForCoordinate(const TileCoordinate&) const;
80 IntRect rectToDocument(const IntRect&) const;
81 IntRect rectFromDocument(const IntRect&) const;
82
83 IntRect contentRect() const;
84
85 IntRect tileRectForCoordinate(const TileCoordinate&) const;
8186 TileCache::TileCoordinate tileCoordinateForPoint(const IntPoint&) const;
8287 double tileDistance(const IntRect& viewport, const TileCache::TileCoordinate&);
8388
  
135135 ~Tile();
136136
137137 bool isDirty() const { return !m_dirtyRegion.isEmpty(); }
138 const QRegion& dirtyRegion() const { return m_dirtyRegion; }
138139 void invalidate(const IntRect&);
139140 void updateBuffer();
140141 void swapBuffer();
143143 void paint(QPainter* painter, const IntRect& rect);
144144
145145 const TileCache::TileCoordinate coordinate() const { return m_tileCoordinate; }
146 const FloatRect& rect() const { return m_tileRect; }
147 IntRect enclosingIntRect() const { return WebCore::enclosingIntRect(m_tileRect); }
146 const IntRect& rect() const { return m_tileRect; }
147 const IntRect rectToDocument() const { return m_cache->rectToDocument(m_tileRect); }
148148
149149private:
150150 Tile(TileCache* cache, const TileCache::TileCoordinate& tileCoordinate);
151151
152152 TileCache* m_cache;
153153 TileCache::TileCoordinate m_tileCoordinate;
154 FloatRect m_tileRect;
154 IntRect m_tileRect;
155155 QImage* m_buffer;
156156 QImage* m_backBuffer;
157157 QRegion m_dirtyRegion;
169169 , m_tileRect(m_cache->tileRectForCoordinate(tileCoordinate))
170170 , m_buffer(0)
171171 , m_backBuffer(0)
172 , m_dirtyRegion(enclosingIntRect())
172 , m_dirtyRegion(m_tileRect)
173173 , m_pixmapNeedsReset(false)
174174{
175175#if ENABLE(ENGINE_THREAD)
190190
191191void Tile::invalidate(const IntRect& dirtyRect)
192192{
193 IntRect tileDirtyRect = intersection(dirtyRect, enclosingIntRect());
193 IntRect tileDirtyRect = intersection(dirtyRect, m_tileRect);
194194 if (tileDirtyRect.isEmpty())
195195 return;
196196#if ENABLE(ENGINE_THREAD)
229229 // Paint to backbuffer, no locks held.
230230 QPainter painter(m_backBuffer);
231231 GraphicsContext context(&painter);
232 context.scale(m_cache->tileScale());
233232 context.translate(-m_tileRect.x(), -m_tileRect.y());
234233
235234 int size = dirtyRects.size();
236235 for (int n = 0; n < size; ++n) {
237236 context.save();
238 QRect rect = dirtyRects[n];
239 context.clip(FloatRect(rect.x(), rect.y(), rect.width(), rect.height()));
240 m_cache->m_client->tileCachePaint(&context, rect);
237 IntRect rect = dirtyRects[n];
238 context.clip(FloatRect(rect));
239 context.scale(m_cache->tileScale());
240 m_cache->m_client->tileCachePaint(&context, m_cache->rectToDocument(rect));
241241 context.restore();
242242 }
243243}
261261 // m_bufferPixmap = QPixmap::fromImage(*m_buffer);
262262 m_pixmapNeedsReset = false;
263263
264 FloatRect target = intersection(FloatRect(rect), m_tileRect);
265 FloatRect source((target.x() - m_tileRect.x()),
264 IntRect target = intersection(rect, m_tileRect);
265 IntRect source((target.x() - m_tileRect.x()),
266266 (target.y() - m_tileRect.y()),
267267 target.width(),
268268 target.height());
269
270 FloatSize scale = m_cache->tileScale();
271 source.scale(scale.width(), scale.height());
272269
273270#if ENABLE(ENGINE_THREAD)
274271 // qDebug() << (EngineThread::isCurrent() ? "EngineThread " : "MainThread ") << "painting tile " << QRectF(m_tileRect) << " source " << QRectF(source) << " target " << QRectF(target);
293293 m_tileCreationTimer = 0;
294294}
295295
296void TileCache::invalidate(const IntRect& dirtyRect)
296void TileCache::invalidate(const IntRect& documentDirtyRect)
297297{
298 IntRect dirtyRect(rectFromDocument(documentDirtyRect));
299
298300 TileCoordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
299301 TileCoordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
300302
324324 if (!it->second->isDirty())
325325 continue;
326326 m_dirtyTiles.append(it->second);
327 fullDirtyRegion += it->second->enclosingIntRect();
327 // FIXME: should not request system repaint for the full tile.
328 fullDirtyRegion += it->second->rect();
329 //fullDirtyRegion += it->second->dirtyRegion();
328330 }
329331
330332 if (m_dirtyTiles.isEmpty())
351351 Vector<IntRect> paintedArea;
352352 unsigned rectCount = qrects.size();
353353 for (unsigned n = 0; n < rectCount; ++n)
354 paintedArea.append(qrects[n]);
354 paintedArea.append(rectToDocument(qrects[n]));
355355
356356 m_client->tileCachePaintEnd(paintedArea);
357357}
392392 MutexLocker locker(m_paintMutex);
393393#endif
394394 QPainter* painter = context->platformContext();
395 TileCoordinate topLeft = tileCoordinateForPoint(rect.topLeft());
396 TileCoordinate bottomRight = tileCoordinateForPoint(rect.bottomRight());
397395
396 painter->save();
397
398 if (m_state == StateNoTileCreation) {
399 painter->scale(1.f / m_scale.width(), 1.f / m_scale.height());
400 } else {
401 QTransform t = painter->worldTransform();
402 QTransform nt(1., t.m12(), t.m13(),
403 t.m21(), 1., t.m23(),
404 t.m31(), t.m32(), t.m33());
405 painter->setWorldTransform(nt);
406 }
407
408 IntRect dirtyRect = rectFromDocument(rect);
409
410 TileCoordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft());
411 TileCoordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight());
412
398413 for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) {
399414 for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) {
400415 TileCoordinate currentCoordinate(xCoordinate, yCoordinate);
401416 RefPtr<Tile> currentTile = tile(currentCoordinate);
402417 if (currentTile && currentTile->isReadyToPaint())
403 currentTile->paint(painter, rect);
418 currentTile->paint(painter, dirtyRect);
404419 else
405 paintCheckerPattern(painter, rect, currentCoordinate);
420 paintCheckerPattern(painter, dirtyRect, currentCoordinate);
406421 }
407422 }
423 painter->restore();
408424}
409425
410void TileCache::viewportChanged(const IntRect& viewport, const FloatSize& scale)
426void TileCache::viewportChanged(const IntRect& docViewport, const FloatSize& scale)
411427{
412 if (m_viewport == viewport && m_scale == scale)
428 bool scaleChanged = m_scale != scale;
429 m_scale = scale;
430 IntRect viewport = rectFromDocument(docViewport);
431 if (m_viewport == viewport && !scaleChanged)
413432 return;
414433
415 if (m_viewport.size() != viewport.size() || m_scale != scale)
416 invalidate(m_client->tileCacheContentRect());
434 bool needsInvalidate = m_viewport.size() != viewport.size() || scaleChanged;
417435
418436 m_viewport = viewport;
419 if (m_scale != scale)
437
438 if (scaleChanged)
420439 m_client->tileCacheViewportScaleChanged();
421 m_scale = scale;
440
441 if (needsInvalidate)
442 invalidate(m_client->tileCacheContentRect());
422443
423444 startTileCreationTimer();
424445}
465465 if (m_viewport.isEmpty())
466466 return;
467467
468
469468 dropOverhangingTiles();
470469
471470 // FIXME: Make adapt to memory.
472471 IntRect keepRect = m_viewport;
473472 keepRect.inflateX(m_viewport.width());
474473 keepRect.inflateY(2 * m_viewport.height());
475 keepRect.intersect(m_client->tileCacheContentRect());
474 keepRect.intersect(contentRect());
476475
477476 dropTilesOutsideRect(keepRect);
478477
479478 IntRect coverRect = m_viewport;
480479 coverRect.inflateX(m_viewport.width() / 2);
481480 coverRect.inflateY(m_viewport.height());
482 coverRect.intersect(m_client->tileCacheContentRect());
481 coverRect.intersect(contentRect());
483482
484483 double shortestDistance = std::numeric_limits<double>::infinity();
485484 Vector<TileCoordinate> tilesToCreate;
524524
525525void TileCache::dropOverhangingTiles()
526526{
527 FloatRect contentRect = m_client->tileCacheContentRect();
527 IntRect contentRect = this->contentRect();
528528
529529 Vector<TileCoordinate> tilesToRemove;
530530 TileMap::iterator end = m_tiles.end();
531531 for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) {
532532 TileCoordinate tileCoordinate = it->second->coordinate();
533 FloatRect tileRect = it->second->rect();
534 FloatRect expectedTileRect = tileRectForCoordinate(tileCoordinate);
533 IntRect tileRect = it->second->rect();
534 IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate);
535535 if (expectedTileRect != tileRect || !contentRect.contains(tileRect))
536536 tilesToRemove.append(tileCoordinate);
537537 }
572572 m_tiles.remove(coordinate.hash());
573573}
574574
575FloatRect TileCache::tileRectForCoordinate(const TileCoordinate& coordinate) const
575IntRect TileCache::rectToDocument(const IntRect& rect) const
576576{
577577 float sx = m_scale.width();
578578 float sy = m_scale.height();
579
580 return enclosingIntRect(FloatRect(rect.x() / sx,
581 rect.y() / sy,
582 rect.width() / sx,
583 rect.height() / sy));
584}
579585
580 FloatRect rect(coordinate.x() * m_tileSize.width() / sx,
581 coordinate.y() * m_tileSize.height() / sy,
582 m_tileSize.width() / sx,
583 m_tileSize.height() / sy);
586IntRect TileCache::rectFromDocument(const IntRect& rect) const
587{
588 float sx = m_scale.width();
589 float sy = m_scale.height();
590
591 return enclosingIntRect(FloatRect(rect.x() * sx,
592 rect.y() * sy,
593 rect.width() * sx,
594 rect.height() * sy));
595}
584596
585 rect.intersect(FloatRect(m_client->tileCacheContentRect()));
586 return rect;
597IntRect TileCache::contentRect() const
598{
599 return rectFromDocument(m_client->tileCacheContentRect());
587600}
588601
602IntRect TileCache::tileRectForCoordinate(const TileCoordinate& coordinate) const
603{
604 IntRect rect(coordinate.x() * m_tileSize.width(),
605 coordinate.y() * m_tileSize.height(),
606 m_tileSize.width(),
607 m_tileSize.height());
608
609 rect.intersect(contentRect());
610 return rect;
611}
612
589613TileCache::TileCoordinate TileCache::tileCoordinateForPoint(const IntPoint& point) const
590614{
591 int x = point.x() * m_scale.width() / m_tileSize.width();
592 int y = point.y() * m_scale.height() / m_tileSize.height();
615 int x = point.x() / m_tileSize.width();
616 int y = point.y() / m_tileSize.height();
593617 return TileCoordinate(std::max(x, 0), std::max(y, 0));
594618}
595619