qmlfrontend/renderer/tiled_image_item.cpp
branchqmlrenderer
changeset 16089 02304ad06381
equal deleted inserted replaced
16087:8da5a118120b 16089:02304ad06381
       
     1 #include "tiled_image_item.h"
       
     2 
       
     3 #include <QSGImageNode>
       
     4 #include <QSGTexture>
       
     5 
       
     6 TiledImageItem::TiledImageItem(QQuickItem *parent) : QQuickItem{parent} {
       
     7   setFlag(ItemHasContents, true);
       
     8   setFlag(ItemObservesViewport, true);
       
     9 }
       
    10 
       
    11 TiledImageItem::~TiledImageItem() {}
       
    12 
       
    13 void TiledImageItem::setImageData(int width, int height, uchar *pixels,
       
    14                                   QImage::Format format) {
       
    15   m_texture = QImage{pixels, width, height, width * 4, format};
       
    16 
       
    17   setImplicitWidth(width / window()->effectiveDevicePixelRatio());
       
    18   setImplicitHeight(height / window()->effectiveDevicePixelRatio());
       
    19 
       
    20   buildTiles();
       
    21 
       
    22   update();
       
    23 }
       
    24 
       
    25 void TiledImageItem::buildTiles() {
       
    26   m_tiles.clear();
       
    27   if (m_texture.isNull()) {
       
    28     return;
       
    29   }
       
    30 
       
    31   const auto imageWidth = m_texture.width();
       
    32   const auto imageHeight = m_texture.height();
       
    33 
       
    34   for (int y = 0; y < imageHeight; y += m_tileSize) {
       
    35     for (int x = 0; x < imageWidth; x += m_tileSize) {
       
    36       int w = qMin(m_tileSize, imageWidth - x);
       
    37       int h = qMin(m_tileSize, imageHeight - y);
       
    38       QImage tileImage{&m_texture.scanLine(y)[x * m_texture.depth() / 8],
       
    39                        m_tileSize, m_tileSize, m_texture.bytesPerLine(),
       
    40                        m_texture.format()};
       
    41 
       
    42       QRectF tileRect = QRect{x, y, w, h}.toRectF();
       
    43       tileRect.setTopLeft(tileRect.topLeft() /
       
    44                           window()->effectiveDevicePixelRatio());
       
    45       tileRect.setBottomRight(tileRect.bottomRight() /
       
    46                               window()->effectiveDevicePixelRatio());
       
    47 
       
    48       Tile tile;
       
    49       tile.outRect = tileRect;
       
    50       tile.image = tileImage;
       
    51       tile.dirty = true;
       
    52       m_tiles.emplace_back(std::move(tile));
       
    53     }
       
    54   }
       
    55 }
       
    56 int TiledImageItem::tileSize() const { return m_tileSize; }
       
    57 
       
    58 void TiledImageItem::setTileSize(int newTileSize) {
       
    59   if (m_tileSize == newTileSize) {
       
    60     return;
       
    61   }
       
    62 
       
    63   m_tileSize = newTileSize;
       
    64 
       
    65   m_tiles.clear();
       
    66   m_dirty = true;
       
    67 
       
    68   Q_EMIT tileSizeChanged();
       
    69 }
       
    70 
       
    71 void TiledImageItem::test(const QString &fileName) {
       
    72   auto image = new QImage(fileName);
       
    73 
       
    74   setImageData(image->width(), image->height(), image->bits(), image->format());
       
    75 }
       
    76 
       
    77 QSGNode *TiledImageItem::updatePaintNode(QSGNode *oldNode,
       
    78                                          UpdatePaintNodeData *) {
       
    79   auto rootNode = oldNode;
       
    80   if (!rootNode) {
       
    81     rootNode = new QSGNode{};
       
    82   }
       
    83 
       
    84   if (!window()) {
       
    85     return rootNode;
       
    86   }
       
    87 
       
    88   const auto rect = clipRect();
       
    89 
       
    90   for (auto &tile : m_tiles) {
       
    91     if (!rect.intersects(tile.outRect)) {
       
    92       if (tile.node) {
       
    93         rootNode->removeChildNode(tile.node.get());
       
    94         tile.node.reset();
       
    95       }
       
    96 
       
    97       continue;
       
    98     }
       
    99 
       
   100     if (tile.dirty) {
       
   101       tile.texture.reset(window()->createTextureFromImage(tile.image));
       
   102       if (tile.node) {
       
   103         tile.node->setTexture(tile.texture.get());
       
   104       }
       
   105 
       
   106       tile.dirty = false;
       
   107     }
       
   108 
       
   109     if (!tile.node) {
       
   110       tile.node.reset(window()->createImageNode());
       
   111       tile.node->setRect(tile.outRect);
       
   112       tile.node->setTexture(tile.texture.get());
       
   113       rootNode->appendChildNode(tile.node.get());
       
   114     }
       
   115   }
       
   116 
       
   117   return rootNode;
       
   118 }
       
   119 
       
   120 TiledImageItem::Tile::Tile(Tile &&other) noexcept
       
   121     : outRect{other.outRect},
       
   122       image{std::move(other.image)},
       
   123       dirty{other.dirty},
       
   124       texture{std::move(other.texture)} {}