void  QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
                                            QQuickText::TextStyle style,
                                            const QColor &styleColor)
{
    if (m_currentLine.isValid())
        processCurrentLine();

    QList<BinaryTreeNode *> nodes;
    QList<BinaryTreeNode *> imageNodes;
    mergeProcessedNodes(&nodes, &imageNodes);

    for (int i = 0; i < m_backgrounds.size(); ++i) {
        const QRectF &rect = m_backgrounds.at(i).first;
        const QColor &color = m_backgrounds.at(i).second;

        parentNode->addRectangleNode(rect, color);
    }

    // Add all unselected text first
    for (int i = 0; i < nodes.size(); ++i) {
        const BinaryTreeNode *node = nodes.at(i);
        if (node->selectionState == Unselected)
            parentNode->addGlyphs(node->position, node->glyphRun, node->color, style, styleColor, 0);
    }

    for (int i = 0; i < imageNodes.size(); ++i) {
        const BinaryTreeNode *node = imageNodes.at(i);
        if (node->selectionState == Unselected)
            parentNode->addImage(node->boundingRect, node->image);
    }

    // Then, prepend all selection rectangles to the tree
    for (int i = 0; i < m_selectionRects.size(); ++i) {
        const QRectF &rect = m_selectionRects.at(i);

        parentNode->addRectangleNode(rect, m_selectionColor);
    }

    // Add decorations for each node to the tree.
    for (int i = 0; i < m_lines.size(); ++i) {
        const TextDecoration &textDecoration = m_lines.at(i);

        QColor color = textDecoration.selectionState == Selected
                ? m_selectedTextColor
                : textDecoration.color;

        parentNode->addRectangleNode(textDecoration.rect, color);
    }

    // Finally add the selected text on top of everything
    for (int i = 0; i < nodes.size(); ++i) {
        const BinaryTreeNode *node = nodes.at(i);
        QQuickDefaultClipNode *clipNode = node->clipNode;
        if (clipNode != 0 && clipNode->parent() == 0)
            parentNode->appendChildNode(clipNode);

        if (node->selectionState == Selected) {
            QColor color = m_selectedTextColor;
            int previousNodeIndex = i - 1;
            int nextNodeIndex = i + 1;
            const BinaryTreeNode *previousNode = previousNodeIndex < 0 ? 0 : nodes.at(previousNodeIndex);
            while (previousNode != 0 && qFuzzyCompare(previousNode->boundingRect.left(), node->boundingRect.left()))
                previousNode = --previousNodeIndex < 0 ? 0 : nodes.at(previousNodeIndex);

            const BinaryTreeNode *nextNode = nextNodeIndex == nodes.size() ? 0 : nodes.at(nextNodeIndex);

            if (previousNode != 0 && previousNode->selectionState == Unselected)
                parentNode->addGlyphs(previousNode->position, previousNode->glyphRun, color, style, styleColor, clipNode);

            if (nextNode != 0 && nextNode->selectionState == Unselected)
                parentNode->addGlyphs(nextNode->position, nextNode->glyphRun, color, style, styleColor, clipNode);

            // If the previous or next node completely overlaps this one, then we have already drawn the glyphs of
            // this node
            bool drawCurrent = false;
            if (previousNode != 0 || nextNode != 0) {
                for (int i = 0; i < node->ranges.size(); ++i) {
                    const QPair<int, int> &range = node->ranges.at(i);

                    int rangeLength = range.second - range.first + 1;
                    if (previousNode != 0) {
                        for (int j = 0; j < previousNode->ranges.size(); ++j) {
                            const QPair<int, int> &otherRange = previousNode->ranges.at(j);
                            if (range.first <= otherRange.second && range.second >= otherRange.first) {
                                int start = qMax(range.first, otherRange.first);
                                int end = qMin(range.second, otherRange.second);
                                rangeLength -= end - start + 1;
                                if (rangeLength == 0)
                                    break;
                            }
                        }
                    }

                    if (nextNode != 0 && rangeLength > 0) {
                        for (int j = 0; j < nextNode->ranges.size(); ++j) {
                            const QPair<int, int> &otherRange = nextNode->ranges.at(j);

                            if (range.first <= otherRange.second && range.second >= otherRange.first) {
                                int start = qMax(range.first, otherRange.first);
                                int end = qMin(range.second, otherRange.second);
                                rangeLength -= end - start + 1;
                                if (rangeLength == 0)
                                    break;
                            }
                        }
                    }

                    if (rangeLength > 0) {
                        drawCurrent = true;
                        break;
                    }
                }
            } else {
                drawCurrent = true;
            }

            if (drawCurrent)
                parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
        }
    }

    for (int i = 0; i < imageNodes.size(); ++i) {
        const BinaryTreeNode *node = imageNodes.at(i);
        if (node->selectionState == Selected) {
            parentNode->addImage(node->boundingRect, node->image);
            if (node->selectionState == Selected) {
                QColor color = m_selectionColor;
                color.setAlpha(128);
                parentNode->addRectangleNode(node->boundingRect, color);
            }
        }
    }
}
void  QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode,
                                            QQuickText::TextStyle style,
                                            const QColor &styleColor)
{
    if (m_currentLine.isValid())
        processCurrentLine();


    for (int i=0; i<m_backgrounds.size(); ++i) {
        const QRectF &rect = m_backgrounds.at(i).first;
        const QColor &color = m_backgrounds.at(i).second;

        parentNode->appendChildNode(new QSGSimpleRectNode(rect, color));
    }

    // First, prepend all selection rectangles to the tree
    for (int i=0; i<m_selectionRects.size(); ++i) {
        const QRectF &rect = m_selectionRects.at(i);

        parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor));
    }

    // Finally, add decorations for each node to the tree.
    for (int i=0; i<m_lines.size(); ++i) {
        const TextDecoration &textDecoration = m_lines.at(i);

        QColor color = textDecoration.selectionState == Selected
                ? m_selectedTextColor
                : textDecoration.color;

        parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color));
    }

    // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common
    // font, selection state and clip node.
    typedef QPair<QFontEngine *, QPair<QQuickDefaultClipNode *, QPair<QRgb, int> > > KeyType;
    QHash<KeyType, BinaryTreeNode *> map;
    QList<BinaryTreeNode *> nodes;
    for (int i = 0; i < m_processedNodes.size(); ++i) {
        BinaryTreeNode *node = m_processedNodes.data() + i;

        if (node->image.isNull()) {
            QGlyphRun glyphRun = node->glyphRun;
            QRawFont rawFont = glyphRun.rawFont();
            QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);

            QFontEngine *fontEngine = rawFontD->fontEngine;

            KeyType key(qMakePair(fontEngine,
                                  qMakePair(node->clipNode,
                                            qMakePair(node->color.rgba(), int(node->selectionState)))));

            BinaryTreeNode *otherNode = map.value(key, 0);
            if (otherNode != 0) {
                QGlyphRun &otherGlyphRun = otherNode->glyphRun;

                QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes();
                QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions();

                otherGlyphIndexes += glyphRun.glyphIndexes();

                QVector<QPointF> glyphPositions = glyphRun.positions();
                otherGlyphPositions.reserve(otherGlyphPositions.size() + glyphPositions.size());
                for (int j = 0; j < glyphPositions.size(); ++j) {
                    otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position);
                }

                otherGlyphRun.setGlyphIndexes(otherGlyphIndexes);
                otherGlyphRun.setPositions(otherGlyphPositions);

            } else {
                map.insert(key, node);
                nodes.append(node);
            }
        } else {
            parentNode->addImage(node->boundingRect, node->image);
            if (node->selectionState == Selected) {
                QColor color = m_selectionColor;
                color.setAlpha(128);
                parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color));
            }
        }
    }

    foreach (const BinaryTreeNode *node, nodes) {

        QQuickDefaultClipNode *clipNode = node->clipNode;
        if (clipNode != 0 && clipNode->parent() == 0 )
            parentNode->appendChildNode(clipNode);

        QColor color = node->selectionState == Selected
                ? m_selectedTextColor
                : node->color;

        parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode);
    }