//protected
void MapGraphicsView::doTileLayout()
{
    //Calculate the center point and polygon of the viewport in QGraphicsScene coordinates
    const QPointF centerPointQGS = _childView->mapToScene(_childView->width()/2.0,
                                                          _childView->height()/2.0);
    QPolygon viewportPolygonQGV;
    viewportPolygonQGV << QPoint(0,0) << QPoint(0,_childView->height()) << QPoint(_childView->width(),_childView->height()) << QPoint(_childView->width(),0);

    const QPolygonF viewportPolygonQGS = _childView->mapToScene(viewportPolygonQGV);
    const QRectF boundingRect = viewportPolygonQGS.boundingRect();

    //We exaggerate the bounding rect for some purposes!
    QRectF exaggeratedBoundingRect = boundingRect;
    exaggeratedBoundingRect.setSize(boundingRect.size()*2.0);
    exaggeratedBoundingRect.moveCenter(boundingRect.center());

    //We'll mark tiles that aren't being displayed as free so we can use them
    QQueue<MapTileGraphicsObject *> freeTiles;

    QSet<QPointF> placesWhereTilesAre;
    foreach(MapTileGraphicsObject * tileObject, _tileObjects)
    {
        if (!tileObject->isVisible() || !exaggeratedBoundingRect.contains(tileObject->pos()))
        {
            freeTiles.enqueue(tileObject);
            tileObject->setVisible(false);
        }
        else
            placesWhereTilesAre.insert(tileObject->pos());
    }

    const quint16 tileSize = _tileSource->tileSize();
    const quint32 tilesPerRow = sqrt((long double)_tileSource->tilesOnZoomLevel(this->zoomLevel()));
    const quint32 tilesPerCol = tilesPerRow;

    const qint32 perSide = qMax(boundingRect.width()/tileSize,
                       boundingRect.height()/tileSize) + 3;
    const qint32 xc = qMax((qint32)0,
                     (qint32)(centerPointQGS.x() / tileSize) - perSide/2);
    const qint32 yc = qMax((qint32)0,
                     (qint32)(centerPointQGS.y() / tileSize) - perSide/2);
    const qint32 xMax = qMin((qint32)tilesPerRow,
                              xc + perSide);
    const qint32 yMax = qMin(yc + perSide,
                              (qint32)tilesPerCol);

    for (qint32 x = xc; x < xMax; x++)
    {
        for (qint32 y = yc; y < yMax; y++)
        {
            const QPointF scenePos(x*tileSize + tileSize/2,
                                   y*tileSize + tileSize/2);


            bool tileIsThere = false;
            if (placesWhereTilesAre.contains(scenePos))
                tileIsThere = true;

            if (tileIsThere)
                continue;

            //Just in case we're running low on free tiles, add one
            if (freeTiles.isEmpty())
            {
                MapTileGraphicsObject * tileObject = new MapTileGraphicsObject(tileSize);
                tileObject->setTileSource(_tileSource);
                _tileObjects.insert(tileObject);
                _childScene->addItem(tileObject);
                freeTiles.enqueue(tileObject);
            }
            //Get the first free tile and make it do its thing
            MapTileGraphicsObject * tileObject = freeTiles.dequeue();
            if (tileObject->pos() != scenePos)
                tileObject->setPos(scenePos);
            if (tileObject->isVisible() != true)
                tileObject->setVisible(true);
            tileObject->setTile(x,y,this->zoomLevel());
        }
    }

    //If we've got a lot of free tiles left over, delete some of them
    while (freeTiles.size() > 2)
    {
        MapTileGraphicsObject * tileObject = freeTiles.dequeue();
        _tileObjects.remove(tileObject);
        _childScene->removeItem(tileObject);
        delete tileObject;
    }

}
Esempio n. 2
0
void ChessBoard::renderBoard( QPainter &p, const QRectF &rc, bool flip,
    const std::vector<cheng4::Square> *excludeSquares )
{
    qreal maxh = std::max( rc.width(), rc.height() )/14;
    maxh = 18;
	qreal bordersz = maxh;
	if ( !border )
		bordersz = 0;
	qreal sw = (rc.width() - 2*bordersz) / 8;
	qreal sh = (rc.height() - 2*bordersz) / 8;
    sh = sw = std::min(sw, sh);

    QColor wb[2] = { QColor(255, 255, 255, 255), QColor(0, 0, 0, 255) };

	QColor bord = borderColor;

	QBrush lightb(lightColor);
	QBrush darkb(darkColor);
    p.setPen(Qt::transparent);
    // render border...
    p.setBrush( QBrush(bord) );
	p.drawRect(QRectF(rc.left(), rc.top(), 8*sw + 2*bordersz+1, 8*sh + 2*bordersz+1));

    QPen bpen( QColor(0, 0, 0, 128) );
    bpen.setWidth(1);
    p.setPen( bpen );
    p.setBrush( Qt::transparent );
    QRectF brect;
	brect.setTopLeft( QPoint(bordersz-1, bordersz-1) );
    brect.setSize( QSizeF(8*sw+2, 8*sh+2) );
    p.drawRect( brect );

    brect.setTopLeft( QPoint(0, 0) );
	brect.setSize( QSizeF(8*sw+2*bordersz, 8*sh+2*bordersz) );
    p.drawRect( brect );

    p.setPen( Qt::transparent );

    for (cheng4::Square s = 0; s < 64; s++)
    {
        cheng4::File f = cheng4::SquarePack::file(s);
        cheng4::Rank r = cheng4::SquarePack::rank(s);
		QRectF sub(rc.left() + sw*f + bordersz, rc.top() + sh*r + bordersz, sw, sh);
        cheng4::Square sq = flip ? cheng4::SquarePack::flipH(cheng4::SquarePack::flipV(s)) : s;


        p.setBrush( ((f+r) & 1) ? darkb : lightb );
        p.drawRect( sub );
        if ( excludeSquares && std::find(excludeSquares->begin(), excludeSquares->end(), sq)
             != excludeSquares->end() )
            continue;

        cheng4::Piece pc = board.piece(sq);
        cheng4::Piece pt = cheng4::PiecePack::type(pc);
        if ( pt == cheng4::ptNone )
            continue;
        cheng4::Color c = cheng4::PiecePack::color(pc);
		if ( !pieceSet || !pieceSet->pieces[c][pt-1] )
			continue;
        pieceSet->pieces[c][pt-1]->renderer()->render(&p, sub);
	}

	// FIXME: better!!!
	for (cheng4::Square s = 0; s < 64; s++)
	{
		cheng4::File f = cheng4::SquarePack::file(s);
		cheng4::Rank r = cheng4::SquarePack::rank(s);
		QRectF sub(rc.left() + sw*f + bordersz, rc.top() + sh*r + bordersz, sw, sh);
		cheng4::Square sq = flip ? cheng4::SquarePack::flipH(cheng4::SquarePack::flipV(s)) : s;
		// now highlight!!!
		if ( highlight == cheng4::mcNone || highlight == cheng4::mcNull )
			continue;
		cheng4::Square from, to;
		from = cheng4::MovePack::from(highlight);
		to = cheng4::MovePack::to(highlight);
		if ( sq != from && sq != to )
			continue;

		QPen hpen( highlightColor );
		hpen.setWidth(2);
		p.setPen( hpen );
		p.setBrush( Qt::transparent );
		p.drawRect( sub );
		p.setPen( Qt::transparent );
	}

	if ( !border )
		return;

    // draw board letters
	p.setPen( letterColor );
    QTextOption opt;
    opt.setAlignment(Qt::AlignCenter);
    QFont font;
    font.setBold(0);
    font.setPixelSize(12);
    p.setFont(font);
    for (uint i=0; i<8; i++)
    {
        // rows:
		QPointF pt( 0, bordersz + sh*i );
        QRectF rct;
        rct.setTopLeft( pt );
		rct.setSize( QSizeF( bordersz, sh ) );
        QString text;
        int irow = 7-(int)i;
        if ( flip )
            irow = 8-1-irow;
        text.sprintf("%d", irow+1);
        p.drawText(rct, text, opt);
		pt.setX( bordersz+sw*8 );
        rct.setTopLeft( pt );
		rct.setSize( QSizeF( bordersz, sh ) );
        p.drawText(rct, text, opt);
        // cols:
        int icol = (int)i;
        if ( flip )
            icol = 8-1-i;
        text.sprintf("%c", 'a' + icol);
		pt.setX( bordersz + sw*i );
        pt.setY( 0 );
        rct.setTopLeft(pt);
		rct.setSize( QSizeF( sw, bordersz ) );
        p.drawText(rct, text, opt);
		pt.setY( bordersz+sh*8 );
        rct.setTopLeft( pt );
		rct.setSize( QSizeF( sw, bordersz ) );
        p.drawText(rct, text, opt);
    }
    // draw stm
    QRectF upr;
	upr.setTopLeft( QPointF( bordersz + sw*8 + bordersz/8, bordersz/8 ) );
	upr.setSize( QSizeF( bordersz - 2*bordersz/8, bordersz - 2*bordersz/8 ) );

    bool upper = board.turn() == (flip ? cheng4::ctWhite : cheng4::ctBlack);

    p.setPen( wb[ cheng4::flip(board.turn()) ] );
    p.setBrush( wb[ board.turn() ] );

    if ( upper )
        p.drawRect( upr );

    QRectF lwr;
	lwr.setTopLeft( QPointF( bordersz + sw*8 + bordersz/8, bordersz + sh*8 + bordersz/8 ) );
	lwr.setSize( QSizeF( bordersz - 2*bordersz/8, bordersz - 2*bordersz/8 ) );

    if ( !upper )
        p.drawRect( lwr );
}
Esempio n. 3
0
        void paintEvent(QPaintEvent *event)
        {
            Q_UNUSED (event)

            // XXX Maybe we should cache this and recompute separately for
            //     transform changes, shape movement and viewport changes?

            // Draw a white background.
            QPainter painter(this);
            painter.setRenderHint(QPainter::Antialiasing);
            painter.setPen(Qt::white);
            painter.setBrush(Qt::white);
            QRectF drawingRect = QRectF(0, 0, width(), height());
            painter.drawRect(drawingRect);

            if (m_canvasview == NULL)
            {
                return;
            }

            // Compute the diagram bounds.
            Canvas *canvas = m_canvasview->canvas();
            QRectF diagramBounds =  diagramBoundingRect(canvas->items());
            double buffer = 50;
            diagramBounds.adjust(-buffer, -buffer, buffer, buffer);

            // Compute the scale to with the drawing into the overview rect.
            qreal xscale = drawingRect.width() / diagramBounds.width();
            qreal yscale = drawingRect.height() /  diagramBounds.height();

            // Choose the smallest of the two scale values.
            qreal scale = std::min(xscale, yscale);

            // Scale uniformly, and transform to center in the overview.
            QTransform scaleTransform = QTransform::fromScale(scale, scale);
            QRectF targetRect = scaleTransform.mapRect(diagramBounds);
            QPointF diff = drawingRect.center() - targetRect.center();
            m_transform = QTransform();
            m_transform.translate(diff.x(), diff.y());
            m_transform.scale(scale, scale);

            // Draw edges in overview for each connector on the canvas.
            painter.setPen(QColor(0, 0, 0, 100));
            QList<CanvasItem *> items = canvas->items();
            for (int i = 0; i < items.count(); ++i)
            {
                Connector *connector = dynamic_cast<Connector *> (items.at(i));
                if (connector)
                {
                    QPair<ShapeObj *, ShapeObj *> endShapes =
                            connector->getAttachedShapes();
                    if (!endShapes.first || !endShapes.second)
                    {
                        continue;
                    }

                    QLineF line(endShapes.first->centrePos(),
                                endShapes.second->centrePos());
                    painter.drawLine(m_transform.map(line));
                }
            }

            // Draw Rectangles in overview for each shape on the canvas.
            painter.setPen(Qt::black);
            painter.setBrush(Qt::darkGray);
            QRectF shapeRect;
            for (int i = 0; i < items.count(); ++i)
            {
                ShapeObj *shape = dynamic_cast<ShapeObj *> (items.at(i));
                if (shape)
                {
                    shapeRect.setSize(shape->size());
                    shapeRect.moveCenter(shape->centrePos());
                    painter.drawRect(m_transform.mapRect(shapeRect));
                }
            }

            // Show where the visible viewport is (by making everything
            // outside this have a light grey overlay).
            QColor grey(0, 0, 0, 60);
            painter.setPen(QPen(Qt::transparent));
            painter.setBrush(QBrush(grey));
            QRectF viewRect = m_transform.mapRect(m_canvasview->viewportRect());
            QPolygon polygon = QPolygon(drawingRect.toRect()).subtracted(
                    QPolygon(viewRect.toRect()));
            painter.drawPolygon(polygon);
        }
Esempio n. 4
0
void QQuickTextNodeEngine::processCurrentLine()
{
    // No glyphs, do nothing
    if (m_currentLineTree.isEmpty())
        return;

    // 1. Go through current line and get correct decoration position for each node based on
    // neighbouring decorations. Add decoration to global list
    // 2. Create clip nodes for all selected text. Try to merge as many as possible within
    // the line.
    // 3. Add QRects to a list of selection rects.
    // 4. Add all nodes to a global processed list
    QVarLengthArray<int> sortedIndexes; // Indexes in tree sorted by x position
    BinaryTreeNode::inOrder(m_currentLineTree, &sortedIndexes);

    Q_ASSERT(sortedIndexes.size() == m_currentLineTree.size());

    SelectionState currentSelectionState = Unselected;
    QRectF currentRect;

    QQuickTextNode::Decorations currentDecorations = QQuickTextNode::NoDecoration;
    qreal underlineOffset = 0.0;
    qreal underlineThickness = 0.0;

    qreal overlineOffset = 0.0;
    qreal overlineThickness = 0.0;

    qreal strikeOutOffset = 0.0;
    qreal strikeOutThickness = 0.0;

    QRectF decorationRect = currentRect;

    QColor lastColor;
    QColor lastBackgroundColor;

    QVarLengthArray<TextDecoration> pendingUnderlines;
    QVarLengthArray<TextDecoration> pendingOverlines;
    QVarLengthArray<TextDecoration> pendingStrikeOuts;
    if (!sortedIndexes.isEmpty()) {
        QQuickDefaultClipNode *currentClipNode = m_hasSelection ? new QQuickDefaultClipNode(QRectF()) : 0;
        bool currentClipNodeUsed = false;
        for (int i=0; i<=sortedIndexes.size(); ++i) {
            BinaryTreeNode *node = 0;
            if (i < sortedIndexes.size()) {
                int sortedIndex = sortedIndexes.at(i);
                Q_ASSERT(sortedIndex < m_currentLineTree.size());

                node = m_currentLineTree.data() + sortedIndex;
            }

            if (i == 0)
                currentSelectionState = node->selectionState;

            // Update decorations
            if (currentDecorations != QQuickTextNode::NoDecoration) {
                decorationRect.setY(m_position.y() + m_currentLine.y());
                decorationRect.setHeight(m_currentLine.height());

                if (node != 0)
                    decorationRect.setRight(node->boundingRect.left());

                TextDecoration textDecoration(currentSelectionState, decorationRect, lastColor);
                if (currentDecorations & QQuickTextNode::Underline)
                    pendingUnderlines.append(textDecoration);

                if (currentDecorations & QQuickTextNode::Overline)
                    pendingOverlines.append(textDecoration);

                if (currentDecorations & QQuickTextNode::StrikeOut)
                    pendingStrikeOuts.append(textDecoration);

                if (currentDecorations & QQuickTextNode::Background)
                    m_backgrounds.append(qMakePair(decorationRect, lastBackgroundColor));
            }

            // If we've reached an unselected node from a selected node, we add the
            // selection rect to the graph, and we add decoration every time the
            // selection state changes, because that means the text color changes
            if (node == 0 || node->selectionState != currentSelectionState) {
                if (node != 0)
                    currentRect.setRight(node->boundingRect.left());
                currentRect.setY(m_position.y() + m_currentLine.y());
                currentRect.setHeight(m_currentLine.height());

                // Draw selection all the way up to the left edge of the unselected item
                if (currentSelectionState == Selected)
                    m_selectionRects.append(currentRect);

                if (currentClipNode != 0) {
                    if (!currentClipNodeUsed) {
                        delete currentClipNode;
                    } else {
                        currentClipNode->setIsRectangular(true);
                        currentClipNode->setRect(currentRect);
                        currentClipNode->update();
                    }
                }

                if (node != 0 && m_hasSelection)
                    currentClipNode = new QQuickDefaultClipNode(QRectF());
                else
                    currentClipNode = 0;
                currentClipNodeUsed = false;

                if (node != 0) {
                    currentSelectionState = node->selectionState;
                    currentRect = node->boundingRect;

                    // Make sure currentRect is valid, otherwise the unite won't work
                    if (currentRect.isNull())
                        currentRect.setSize(QSizeF(1, 1));
                }
            } else {
                if (currentRect.isNull())
                    currentRect = node->boundingRect;
                else
                    currentRect = currentRect.united(node->boundingRect);
            }

            if (node != 0) {
                node->clipNode = currentClipNode;
                currentClipNodeUsed = true;

                decorationRect = node->boundingRect;

                // If previous item(s) had underline and current does not, then we add the
                // pending lines to the lists and likewise for overlines and strikeouts
                if (!pendingUnderlines.isEmpty()
                        && !(node->decorations & QQuickTextNode::Underline)) {
                    addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);

                    pendingUnderlines.clear();

                    underlineOffset = 0.0;
                    underlineThickness = 0.0;
                }

                // ### Add pending when overlineOffset/thickness changes to minimize number of
                // nodes
                if (!pendingOverlines.isEmpty()) {
                    addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);

                    pendingOverlines.clear();

                    overlineOffset = 0.0;
                    overlineThickness = 0.0;
                }

                // ### Add pending when overlineOffset/thickness changes to minimize number of
                // nodes
                if (!pendingStrikeOuts.isEmpty()) {
                    addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);

                    pendingStrikeOuts.clear();

                    strikeOutOffset = 0.0;
                    strikeOutThickness = 0.0;
                }

                // Merge current values with previous. Prefer greatest thickness
                QRawFont rawFont = node->glyphRun.rawFont();
                if (node->decorations & QQuickTextNode::Underline) {
                    if (rawFont.lineThickness() > underlineThickness) {
                        underlineThickness = rawFont.lineThickness();
                        underlineOffset = rawFont.underlinePosition();
                    }
                }

                if (node->decorations & QQuickTextNode::Overline) {
                    overlineOffset = -rawFont.ascent();
                    overlineThickness = rawFont.lineThickness();
                }

                if (node->decorations & QQuickTextNode::StrikeOut) {
                    strikeOutThickness = rawFont.lineThickness();
                    strikeOutOffset = rawFont.ascent() / -3.0;
                }

                currentDecorations = node->decorations;
                lastColor = node->color;
                lastBackgroundColor = node->backgroundColor;
                m_processedNodes.append(*node);
            }
        }

        if (!pendingUnderlines.isEmpty())
            addTextDecorations(pendingUnderlines, underlineOffset, underlineThickness);

        if (!pendingOverlines.isEmpty())
            addTextDecorations(pendingOverlines, overlineOffset, overlineThickness);

        if (!pendingStrikeOuts.isEmpty())
            addTextDecorations(pendingStrikeOuts, strikeOutOffset, strikeOutThickness);
    }

    m_currentLineTree.clear();
    m_currentLine = QTextLine();
    m_hasSelection = false;
}