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(); }