Beispiel #1
0
void GeoPolygonGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport )
{
    painter->save();

    bool const isBuildingFrame = isDecoration();
    bool const isBuildingRoof = !isDecoration() && !decorations().isEmpty();

    QPen currentPen = painter->pen();

    if ( !style() ) {
        painter->setPen( QPen() );
    }
    else {
        if ( !style()->polyStyle().outline() || isBuildingFrame ) {
            currentPen.setColor( Qt::transparent );
        }
        else {
            if ( currentPen.color() != style()->lineStyle().paintedColor() ||
                 currentPen.widthF() != style()->lineStyle().width() ) {
                currentPen.setColor( style()->lineStyle().paintedColor() );
                currentPen.setWidthF( style()->lineStyle().width() );
            }

            if ( currentPen.capStyle() != style()->lineStyle().capStyle() )
                currentPen.setCapStyle( style()->lineStyle().capStyle() );

            if ( currentPen.style() != style()->lineStyle().penStyle() )
                currentPen.setStyle( style()->lineStyle().penStyle() );
        }

        if ( painter->pen() != currentPen )
            painter->setPen( currentPen );

        if ( !style()->polyStyle().fill() ) {
            if ( painter->brush().color() != Qt::transparent )
                painter->setBrush( QColor( Qt::transparent ) );
        }
        else {
            if ( isBuildingFrame ) {
                painter->setBrush( style()->polyStyle().paintedColor().darker(150) );
            } else if ( painter->brush().color() != style()->polyStyle().paintedColor() ) {
                QImage textureImage = style()->polyStyle().textureImage();
                if( !textureImage.isNull()){
                    GeoDataCoordinates coords = latLonAltBox().center();
                    qreal x, y;
                    viewport->screenCoordinates(coords, x, y);
                    if (m_cachedTexturePath != style()->polyStyle().texturePath() || m_cachedTextureColor != style()->polyStyle().paintedColor() ) {
                        m_cachedTexture = QImage ( textureImage.size(), QImage::Format_ARGB32_Premultiplied );
                        m_cachedTexture.fill(style()->polyStyle().paintedColor());
                        QPainter imagePainter(&m_cachedTexture );
                        imagePainter.drawImage(0, 0, textureImage);
                        imagePainter.end();
                        m_cachedTexturePath = style()->polyStyle().texturePath();
                        m_cachedTextureColor = style()->polyStyle().paintedColor();
                    }
                    QBrush brush;
                    brush.setTextureImage(m_cachedTexture);
                    QTransform transform;
                    brush.setTransform(transform.translate(x,y));
                    painter->setBrush(brush);
                } else {
                    painter->setBrush( style()->polyStyle().paintedColor() );
                }
            }
        }
    }

    if ( isBuildingFrame || isBuildingRoof ) {

        bool drawAccurate3D = false;
        bool isCameraAboveBuilding = false;

        QPointF offsetAtCorner = buildingOffset(QPointF(0, 0), viewport, &isCameraAboveBuilding);
        qreal maxOffset = qMax( qAbs( offsetAtCorner.x() ), qAbs( offsetAtCorner.y() ) );
        drawAccurate3D = painter->mapQuality() == HighQuality ? maxOffset > 5.0 : maxOffset > 8.0;

        // Since subtracting one fully contained polygon from another results in a single
        // polygon with a "connecting line" between the inner and outer part we need
        // to first paint the inner area with no pen and then the outlines with the correct pen.
        QVector<QPolygonF*> outlines;
        QVector<QPolygonF*> innerPolygons;
        QVector<QPolygonF*> polygons;
        bool const hasInnerBoundaries = m_polygon ? !m_polygon->innerBoundaries().isEmpty() : false;
        if (m_polygon) {
            if (hasInnerBoundaries) {
                screenPolygons(viewport, m_polygon, innerPolygons, outlines);
            }
            viewport->screenCoordinates(m_polygon->outerBoundary(), polygons);
        } else if (m_ring) {
            viewport->screenCoordinates(*m_ring, polygons);
        }

        if ( isBuildingFrame ) {
            QVector<QPolygonF*> sides = (hasInnerBoundaries && drawAccurate3D && isCameraAboveBuilding) ? outlines : polygons;

            foreach(QPolygonF* polygon, sides) {
                if (polygon->isEmpty()) {
                    continue;
                }
                if ( drawAccurate3D && isCameraAboveBuilding ) {
                    // draw the building sides
                    int const size = polygon->size();
                    QPointF & a = (*polygon)[0];
                    QPointF shiftA = a + buildingOffset(a, viewport);
                    for (int i=1; i<size; ++i) {
                        QPointF const & b = (*polygon)[i];
                        QPointF const shiftB = b + buildingOffset(b, viewport);
                        QPolygonF buildingSide = QPolygonF() << a << shiftA << shiftB << b;
                        if (hasInnerBoundaries) {
                            //smoothen away our loss of antialiasing due to the QRegion Qt-bug workaround
                            painter->setPen(QPen(painter->brush().color(), 1.5));
                        }
                        painter->drawPolygon(buildingSide);
                        a = b;
                        shiftA = shiftB;
                    }
                } else {
                    // don't draw the building sides - just draw the base frame instead
                    if (hasInnerBoundaries) {
                        QRegion clip(polygon->toPolygon());

                        foreach(QPolygonF* clipPolygon, innerPolygons) {
                            clip-=QRegion(clipPolygon->toPolygon());
                        }
                        painter->setClipRegion(clip);
                    }
                    painter->drawPolygon(*polygon);
                }
            }
        } else if (isBuildingRoof) {
void GeoLineStringGraphicsItem::paint( GeoPainter* painter, const ViewportParams* viewport )
{
    LabelPositionFlags labelPositionFlags = NoLabel;

    painter->save();

    QPen currentPen = painter->pen();
    if ( !style() ) {
        painter->setPen( QPen() );
    }
    else {

        if ( currentPen.color() != style()->lineStyle().paintedColor() )
            currentPen.setColor( style()->lineStyle().paintedColor() );

        if ( currentPen.widthF() != style()->lineStyle().width() ||
                style()->lineStyle().physicalWidth() != 0.0 ) {
            if ( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() < style()->lineStyle().width() )
                currentPen.setWidthF( style()->lineStyle().width() );
            else
                currentPen.setWidthF( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() );
        }
        else if ( style()->lineStyle().width() != 0.0 ) {
            currentPen.setWidthF( style()->lineStyle().width() );
        }

        if ( currentPen.capStyle() != style()->lineStyle().capStyle() )
            currentPen.setCapStyle( style()->lineStyle().capStyle() );

        if ( currentPen.style() != style()->lineStyle().penStyle() )
            currentPen.setStyle( style()->lineStyle().penStyle() );

        if ( style()->lineStyle().penStyle() == Qt::CustomDashLine )
            currentPen.setDashPattern( style()->lineStyle().dashPattern() );

        if ( painter->mapQuality() != Marble::HighQuality
                && painter->mapQuality() != Marble::PrintQuality ) {
            QColor penColor = currentPen.color();
            penColor.setAlpha( 255 );
            currentPen.setColor( penColor );
        }

        if ( painter->pen() != currentPen )
            painter->setPen( currentPen );

        if ( style()->lineStyle().background() ) {
            QBrush brush = painter->background();
            brush.setColor( style()->polyStyle().paintedColor() );
            painter->setBackground( brush );

            painter->setBackgroundMode( Qt::OpaqueMode );
        }

        // label styles
        painter->setFont( style()->labelStyle().font() );
        switch ( style()->labelStyle().alignment() ) {
        case GeoDataLabelStyle::Corner:
        case GeoDataLabelStyle::Right:
            labelPositionFlags |= LineStart;
            break;
        case GeoDataLabelStyle::Center:
            labelPositionFlags |= LineCenter;
            break;
        }
    }

    if ( ! ( isDecoration() && currentPen.widthF() < 2.5f ) )
    {
        if( style()->lineStyle().cosmeticOutline() &&
            style()->lineStyle().penStyle() == Qt::SolidLine ) {
            if ( isDecoration() ) {
                painter->drawPolyline( *m_lineString, "", NoLabel );
            } else {
                if ( currentPen.widthF() > 2.5f ) {
                    currentPen.setWidthF( currentPen.widthF() - 2.0f );
                }
                currentPen.setColor( style()->polyStyle().paintedColor() );
                painter->setPen( currentPen );
                painter->drawPolyline( *m_lineString, feature()->name(), FollowLine,
                                        style()->labelStyle().paintedColor(),
                                        style()->labelStyle().font());
            }
        } else {
            painter->drawPolyline( *m_lineString, feature()->name(), labelPositionFlags );
        }
    }

    painter->restore();
}