Search code examples
qtcachingtransformqgraphicssceneqgraphicsitem

What is the difference between ItemCoordinateCache and DeviceCoordinateCache in QGraphicsItem?


I've read the documentation on them, but I'm still not clear what the actual difference is. The docs state for ItemCoordinateCache that:

Caching is enabled for the item's logical (local) coordinate system.

while for QGraphicsItem::DeviceCoordinateCache:

Caching is enabled at the paint device level, in device coordinates. This mode is for items that can move, but are not rotated, scaled or sheared.

This did not clear things up for me. OK, so DeviceCoordinateCache can't be used for rotation, scaling or shearing, and it uses "device coordinates".

But what does this mean, exactly? There is an off-screen buffer, and I assume for local coordinates the buffer is filled with the item's cached image, and then acts like a QGraphicsPixmapItem and any effects such as opacity and the transform matrix are applied to it. I assume the problem is that this rasterizes the item's image so that's why the docs warn that it won't be pixel-perfect.

But how does it work with a DeviceCoordinateCache? Is the item first rotated, sheared and scaled and then painted on the off-screen pixmap, or is it that it's rendered the same on the pixmap but no transformations are then applied?

Edit: Also I tried setting DeviceCoordinateCache to a rotated and scaled item and it displayed perfectly, even when I resized it, so I don't understand why the docs say it shouldn't be used with scaled, rotated or sheared items.


Solution

  • ItemCoordinateCache

    There is an off-screen buffer, and I assume for local coordinates the buffer is filled with the item's cached image, and then acts like a QGraphicsPixmapItem and any effects such as opacity and the transform matrix are applied to it. I assume the problem is that this rasterizes the item's image so that's why the docs warn that it won't be pixel-perfect.

    That's correct. The cache is stored in memory with the quality of your choice that you specify with setCacheMode(). Subsequent transformations will not invalidate the cache, it will be reused, that's why the quality can deteriorate. If it deteriorates too much, you can invalidate the cache by calling setCacheMode() again with a larger size.


    DeviceCoordinateCache

    But how does it work with a DeviceCoordinateCache? Is the item first rotated, sheared and scaled and then painted on the off-screen pixmap

    Again, you got it right: Transformations are applied, then the result is cached directly in device memory. The caching is always performed at maximum quality. Any new transformation other than moving will invalidate the cache, though, wich brings us to your last remark:

    Also I tried setting DeviceCoordinateCache to a rotated and scaled item and it displayed perfectly, even when I resized it, so I don't understand why the docs say it shouldn't be used with scaled, rotated or sheared items.

    Any new transformation other than moving will invalidate the cache. It still works and it will always display perfectly, but it's not efficient: you're forcing a new cache every time you resize it.


    TL;DR

    If you don't transform your item all the time, use DeviceCoordinateCache. If you do, use ItemCoordinateCache or don't use any cache at all.

    • With DeviceCoordinateCache, the cache will always be pixel perfect but will invalidate with each transformation.
    • With ItemCoordinateCache, the cache will not be invalidated with each transformation but the result will not be pixel perfect.