예제 #1
0
int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c ) const
{
  double pixelSize;
  if ( fontSizeInMapUnits )
  {
    pixelSize = size / c.mapToPixel().mapUnitsPerPixel() * c.rasterScaleFactor();
  }
  else //font size in points
  {
    // set font size from points to output size
    pixelSize = 0.3527 * size * c.scaleFactor() * c.rasterScaleFactor();
  }
  return ( int )( pixelSize + 0.5 );
}
int QgsPieDiagramFactory::getDiagramDimensions( int size, const QgsFeature& f, const QgsRenderContext& context, int& width, int& height ) const
{
  double squareSide = size * diagramSizeScaleFactor( context ) * context.rasterScaleFactor() + 2 * mMaximumPenWidth + 2 * mMaximumGap;
  width = squareSide;
  height = squareSide;
  return 0;
}
void QgsUniqueValueRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature& f, QImage* img, bool selected, double opacity )
{
  QPainter *p = renderContext.painter();
  QgsSymbol* symbol = symbolForFeature( &f );
  if ( !symbol ) //no matching symbol
  {
    if ( img && mGeometryType == QGis::Point )
    {
      img->fill( 0 );
    }
    else if ( mGeometryType != QGis::Point )
    {
      p->setPen( Qt::NoPen );
      p->setBrush( Qt::NoBrush );
    }
    return;
  }

  // Point
  if ( img && mGeometryType == QGis::Point )
  {
    double fieldScale = 1.0;
    double rotation = 0.0;

    if ( symbol->scaleClassificationField() >= 0 )
    {
      //first find out the value for the scale classification attribute
      fieldScale = sqrt( qAbs( f.attribute( symbol->scaleClassificationField() ).toDouble() ) );
    }
    if ( symbol->rotationClassificationField() >= 0 )
    {
      rotation = f.attribute( symbol->rotationClassificationField() ).toDouble();
    }

    QString oldName;

    if ( symbol->symbolField() >= 0 )
    {
      QString name = f.attribute( symbol->symbolField() ).toString();
      oldName = symbol->pointSymbolName();
      symbol->setNamedPointSymbol( name );
    }

    double scale = renderContext.scaleFactor();

    if ( symbol->pointSizeUnits() )
    {
      scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel();
    }

    *img = symbol->getPointSymbolAsImage( scale, selected, mSelectionColor,
                                          fieldScale, rotation, renderContext.rasterScaleFactor(),
                                          opacity );
    if ( !oldName.isNull() )
    {
      symbol->setNamedPointSymbol( oldName );
    }
  }
  // Line, polygon
  else if ( mGeometryType != QGis::Point )
  {
    if ( !selected )
    {
      QPen pen = symbol->pen();
      pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
      p->setPen( pen );
      if ( mGeometryType == QGis::Polygon )
      {
        QBrush brush = symbol->brush();
        scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
        p->setBrush( brush );
      }
    }
    else
    {
      QPen pen = symbol->pen();
      pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
      if ( mGeometryType == QGis::Polygon )
      {
        QBrush brush = symbol->brush();
        scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
        brush.setColor( mSelectionColor );
        p->setBrush( brush );
      }
      else //don't draw outlines of polygons in selection color otherwise they appear merged
      {
        pen.setColor( mSelectionColor );
      }
      p->setPen( pen );
    }
  }
}
QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer* layer, QgsRenderContext& rendererContext )
    : QgsMapLayerRenderer( layer->id() )
    , mRasterViewPort( nullptr )
    , mPipe( nullptr )
{

  mPainter = rendererContext.painter();
  const QgsMapToPixel& theQgsMapToPixel = rendererContext.mapToPixel();
  mMapToPixel = &theQgsMapToPixel;

  QgsMapToPixel mapToPixel = theQgsMapToPixel;
  if ( mapToPixel.mapRotation() )
  {
    // unset rotation for the sake of local computations.
    // Rotation will be handled by QPainter later
    // TODO: provide a method of QgsMapToPixel to fetch map center
    //       in geographical units
    QgsPoint center = mapToPixel.toMapCoordinates(
                        mapToPixel.mapWidth() / 2.0,
                        mapToPixel.mapHeight() / 2.0
                      );
    mapToPixel.setMapRotation( 0, center.x(), center.y() );
  }

  QgsRectangle myProjectedViewExtent;
  QgsRectangle myProjectedLayerExtent;

  if ( rendererContext.coordinateTransform() )
  {
    QgsDebugMsg( "coordinateTransform set -> project extents." );
    try
    {
      myProjectedViewExtent = rendererContext.coordinateTransform()->transformBoundingBox( rendererContext.extent() );
    }
    catch ( QgsCsException &cs )
    {
      QgsMessageLog::logMessage( QObject::tr( "Could not reproject view extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) );
      myProjectedViewExtent.setMinimal();
    }

    try
    {
      myProjectedLayerExtent = rendererContext.coordinateTransform()->transformBoundingBox( layer->extent() );
    }
    catch ( QgsCsException &cs )
    {
      QgsMessageLog::logMessage( QObject::tr( "Could not reproject layer extent: %1" ).arg( cs.what() ), QObject::tr( "Raster" ) );
      myProjectedLayerExtent.setMinimal();
    }
  }
  else
  {
    QgsDebugMsg( "coordinateTransform not set" );
    myProjectedViewExtent = rendererContext.extent();
    myProjectedLayerExtent = layer->extent();
  }

  // clip raster extent to view extent
  QgsRectangle myRasterExtent = myProjectedViewExtent.intersect( &myProjectedLayerExtent );
  if ( myRasterExtent.isEmpty() )
  {
    QgsDebugMsg( "draw request outside view extent." );
    // nothing to do
    return;
  }

  QgsDebugMsg( "theViewExtent is " + rendererContext.extent().toString() );
  QgsDebugMsg( "myProjectedViewExtent is " + myProjectedViewExtent.toString() );
  QgsDebugMsg( "myProjectedLayerExtent is " + myProjectedLayerExtent.toString() );
  QgsDebugMsg( "myRasterExtent is " + myRasterExtent.toString() );

  //
  // The first thing we do is set up the QgsRasterViewPort. This struct stores all the settings
  // relating to the size (in pixels and coordinate system units) of the raster part that is
  // in view in the map window. It also stores the origin.
  //
  //this is not a class level member because every time the user pans or zooms
  //the contents of the rasterViewPort will change
  mRasterViewPort = new QgsRasterViewPort();

  mRasterViewPort->mDrawnExtent = myRasterExtent;
  if ( rendererContext.coordinateTransform() )
  {
    mRasterViewPort->mSrcCRS = layer->crs();
    mRasterViewPort->mDestCRS = rendererContext.coordinateTransform()->destCRS();
    mRasterViewPort->mSrcDatumTransform = rendererContext.coordinateTransform()->sourceDatumTransform();
    mRasterViewPort->mDestDatumTransform = rendererContext.coordinateTransform()->destinationDatumTransform();
  }
  else
  {
    mRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
    mRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
    mRasterViewPort->mSrcDatumTransform = -1;
    mRasterViewPort->mDestDatumTransform = -1;
  }

  // get dimensions of clipped raster image in device coordinate space (this is the size of the viewport)
  mRasterViewPort->mTopLeftPoint = mapToPixel.transform( myRasterExtent.xMinimum(), myRasterExtent.yMaximum() );
  mRasterViewPort->mBottomRightPoint = mapToPixel.transform( myRasterExtent.xMaximum(), myRasterExtent.yMinimum() );

  // align to output device grid, i.e. floor/ceil to integers
  // TODO: this should only be done if paint device is raster - screen, image
  // for other devices (pdf) it can have floating point origin
  // we could use floating point for raster devices as well, but respecting the
  // output device grid should make it more effective as the resampling is done in
  // the provider anyway
  mRasterViewPort->mTopLeftPoint.setX( floor( mRasterViewPort->mTopLeftPoint.x() ) );
  mRasterViewPort->mTopLeftPoint.setY( floor( mRasterViewPort->mTopLeftPoint.y() ) );
  mRasterViewPort->mBottomRightPoint.setX( ceil( mRasterViewPort->mBottomRightPoint.x() ) );
  mRasterViewPort->mBottomRightPoint.setY( ceil( mRasterViewPort->mBottomRightPoint.y() ) );
  // recalc myRasterExtent to aligned values
  myRasterExtent.set(
    mapToPixel.toMapCoordinatesF( mRasterViewPort->mTopLeftPoint.x(),
                                  mRasterViewPort->mBottomRightPoint.y() ),
    mapToPixel.toMapCoordinatesF( mRasterViewPort->mBottomRightPoint.x(),
                                  mRasterViewPort->mTopLeftPoint.y() )
  );

  //raster viewport top left / bottom right are already rounded to int
  mRasterViewPort->mWidth = static_cast<int>( mRasterViewPort->mBottomRightPoint.x() - mRasterViewPort->mTopLeftPoint.x() );
  mRasterViewPort->mHeight = static_cast<int>( mRasterViewPort->mBottomRightPoint.y() - mRasterViewPort->mTopLeftPoint.y() );

  //the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue
  //mapToPixel.mapUnitsPerPixel() is less then 1,
  //so we will just get the pixel data and then render these special cases differently in paintImageToCanvas()

  QgsDebugMsgLevel( QString( "mapUnitsPerPixel = %1" ).arg( mapToPixel.mapUnitsPerPixel() ), 3 );
  QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( layer->width() ), 3 );
  QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( layer->height() ), 3 );
  QgsDebugMsgLevel( QString( "myRasterExtent.xMinimum() = %1" ).arg( myRasterExtent.xMinimum() ), 3 );
  QgsDebugMsgLevel( QString( "myRasterExtent.xMaximum() = %1" ).arg( myRasterExtent.xMaximum() ), 3 );
  QgsDebugMsgLevel( QString( "myRasterExtent.yMinimum() = %1" ).arg( myRasterExtent.yMinimum() ), 3 );
  QgsDebugMsgLevel( QString( "myRasterExtent.yMaximum() = %1" ).arg( myRasterExtent.yMaximum() ), 3 );

  QgsDebugMsgLevel( QString( "mTopLeftPoint.x() = %1" ).arg( mRasterViewPort->mTopLeftPoint.x() ), 3 );
  QgsDebugMsgLevel( QString( "mBottomRightPoint.x() = %1" ).arg( mRasterViewPort->mBottomRightPoint.x() ), 3 );
  QgsDebugMsgLevel( QString( "mTopLeftPoint.y() = %1" ).arg( mRasterViewPort->mTopLeftPoint.y() ), 3 );
  QgsDebugMsgLevel( QString( "mBottomRightPoint.y() = %1" ).arg( mRasterViewPort->mBottomRightPoint.y() ), 3 );

  QgsDebugMsgLevel( QString( "mWidth = %1" ).arg( mRasterViewPort->mWidth ), 3 );
  QgsDebugMsgLevel( QString( "mHeight = %1" ).arg( mRasterViewPort->mHeight ), 3 );

  // /\/\/\ - added to handle zoomed-in rasters

  // TODO R->mLastViewPort = *mRasterViewPort;

  // TODO: is it necessary? Probably WMS only?
  layer->dataProvider()->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() );


  // copy the whole raster pipe!
  mPipe = new QgsRasterPipe( *layer->pipe() );
}
예제 #5
0
void QgsLabel::renderLabel( QgsRenderContext &renderContext,
                            QgsFeature &feature, bool selected,
                            QgsLabelAttributes *classAttributes )
{
  Q_UNUSED( classAttributes );

  if ( mLabelAttributes->selectedOnly() && !selected )
    return;

  QPen pen;
  QFont font;
  QString value;
  QString text;

  /* Calc scale (not nice) */
  QgsPoint point;
  point = renderContext.mapToPixel().transform( 0, 0 );
  double x1 = point.x();
  point = renderContext.mapToPixel().transform( 1000, 0 );
  double x2 = point.x();
  double scale = ( x2 - x1 ) * 0.001;

  /* Text */
  value = fieldValue( Text, feature );
  if ( value.isEmpty() )
  {
    text = mLabelAttributes->text();
  }
  else
  {
    text = value;
  }

  /* Font */
  value = fieldValue( Family, feature );
  if ( value.isEmpty() )
  {
    font.setFamily( mLabelAttributes->family() );
  }
  else
  {
    font.setFamily( value );
  }

  double size;
  value = fieldValue( Size, feature );
  if ( value.isEmpty() )
  {
    size =  mLabelAttributes->size();
  }
  else
  {
    size =  value.toDouble();
  }
  int sizeType;
  value = fieldValue( SizeType, feature );
  if ( value.isEmpty() )
    sizeType = mLabelAttributes->sizeType();
  else
  {
    value = value.toLower();
    if ( value.compare( "mapunits" ) == 0 )
      sizeType = QgsLabelAttributes::MapUnits;
    else
      sizeType = QgsLabelAttributes::PointUnits;
  }
  if ( sizeType == QgsLabelAttributes::MapUnits )
  {
    size *= scale;
  }
  else //point units
  {
    double sizeMM = size * 0.3527;
    size = sizeMM * renderContext.scaleFactor();
  }

  //Request font larger (multiplied by rasterScaleFactor) as a workaround for the Qt font bug
  //and scale the painter down by rasterScaleFactor when drawing the label
  size *= renderContext.rasterScaleFactor();

  if (( int )size <= 0 )
    // skip too small labels
    return;

  font.setPixelSize( size );

  value = fieldValue( Color, feature );
  if ( value.isEmpty() )
  {
    pen.setColor( mLabelAttributes->color() );
  }
  else
  {
    pen.setColor( QColor( value ) );
  }

  value = fieldValue( Bold, feature );
  if ( value.isEmpty() )
  {
    font.setBold( mLabelAttributes->bold() );
  }
  else
  {
    font.setBold(( bool ) value.toInt() );
  }

  value = fieldValue( Italic, feature );
  if ( value.isEmpty() )
  {
    font.setItalic( mLabelAttributes->italic() );
  }
  else
  {
    font.setItalic(( bool ) value.toInt() );
  }

  value = fieldValue( Underline, feature );
  if ( value.isEmpty() )
  {
    font.setUnderline( mLabelAttributes->underline() );
  }
  else
  {
    font.setUnderline(( bool ) value.toInt() );
  }

  value = fieldValue( StrikeOut, feature );
  if ( value.isEmpty() )
  {
    font.setStrikeOut( mLabelAttributes->strikeOut() );
  }
  else
  {
    font.setStrikeOut(( bool ) value.toInt() );
  }

  //
  QgsPoint overridePoint;
  bool useOverridePoint = false;
  value = fieldValue( XCoordinate, feature );
  if ( !value.isEmpty() )
  {
    overridePoint.setX( value.toDouble() );
    useOverridePoint = true;
  }
  value = fieldValue( YCoordinate, feature );
  if ( !value.isEmpty() )
  {
    overridePoint.setY( value.toDouble() );
    useOverridePoint = true;
  }

  /* Alignment */
  int alignment;
  QFontMetrics fm( font );
  int width, height;

  if ( mLabelAttributes->multilineEnabled() )
  {
    QStringList texts = text.split( "\n" );

    width = 0;
    for ( int i = 0; i < texts.size(); i++ )
    {
      int w = fm.width( texts[i] );
      if ( w > width )
        width = w;
    }

    height = fm.height() * texts.size();
  }
  else
  {
    width = fm.width( text );
    height = fm.height();
  }

  int dx = 0;
  int dy = 0;

  value = fieldValue( Alignment, feature );
  if ( value.isEmpty() )
  {
    alignment = mLabelAttributes->alignment();
  }
  else
  {
    value = value.toLower();

    alignment = 0;

    if ( value.contains( "left" ) )
      alignment |= Qt::AlignLeft;
    else if ( value.contains( "right" ) )
      alignment |= Qt::AlignRight;
    else
      alignment |= Qt::AlignHCenter;

    if ( value.contains( "bottom" ) )
      alignment |= Qt::AlignBottom;
    else if ( value.contains( "top" ) )
      alignment |= Qt::AlignTop;
    else
      alignment |= Qt::AlignVCenter;
  }

  if ( alignment & Qt::AlignLeft )
  {
    dx = 0;
  }
  else if ( alignment & Qt::AlignHCenter )
  {
    dx = -width / 2;
  }
  else if ( alignment & Qt::AlignRight )
  {
    dx = -width;
  }

  if ( alignment & Qt::AlignBottom )
  {
    dy = 0;
  }
  else if ( alignment & Qt::AlignVCenter )
  {
    dy = height / 2;
  }
  else if ( alignment & Qt::AlignTop )
  {
    dy = height;
  }

  // Offset
  double xoffset, yoffset;
  value = fieldValue( XOffset, feature );
  if ( value.isEmpty() )
  {
    xoffset = mLabelAttributes->xOffset();
  }
  else
  {
    xoffset = value.toDouble();
  }
  value = fieldValue( YOffset, feature );
  if ( value.isEmpty() )
  {
    yoffset = mLabelAttributes->yOffset();
  }
  else
  {
    yoffset = value.toDouble();
  }

  // recalc offset to pixels
  if ( mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits )
  {
    xoffset *= scale;
    yoffset *= scale;
  }
  else
  {
    xoffset = xoffset * 0.3527 * renderContext.scaleFactor();
    yoffset = yoffset * 0.3527 * renderContext.scaleFactor();
  }

  // Angle
  double ang;
  value = fieldValue( Angle, feature );
  if ( value.isEmpty() )
  {
    ang = mLabelAttributes->angle();
  }
  else
  {
    ang = value.toDouble();
  }


  // Work out a suitable position to put the label for the
  // feature. For multi-geometries, put the same label on each
  // part.
  if ( useOverridePoint )
  {
    renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
                 xoffset, yoffset, ang, width, height, alignment );
  }
  else
  {
    std::vector<labelpoint> points;
    labelPoint( points, feature );
    for ( uint i = 0; i < points.size(); ++i )
    {
      renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
                   xoffset, yoffset, mLabelAttributes->angleIsAuto() ? points[i].angle : ang, width, height, alignment );
    }
  }
}
예제 #6
0
void QgsLabel::renderLabel( QgsRenderContext &renderContext,
                            QgsPoint point,
                            QString text, QFont font, QPen pen,
                            int dx, int dy,
                            double xoffset, double yoffset,
                            double ang,
                            int width, int height, int alignment )
{
  QPainter *painter = renderContext.painter();

  // Convert point to projected units
  if ( renderContext.coordinateTransform() )
  {
    try
    {
      point = renderContext.coordinateTransform()->transform( point );
    }
    catch ( QgsCsException &cse )
    {
      Q_UNUSED( cse ); // unused otherwise
      QgsDebugMsg( "Caught transform error. Skipping rendering this label" );
      return;
    }
  }

  // and then to canvas units
  renderContext.mapToPixel().transform( &point );
  double x = point.x();
  double y = point.y();

  double rad = ang * M_PI / 180;

  x = x + xoffset * cos( rad ) - yoffset * sin( rad );
  y = y - xoffset * sin( rad ) - yoffset * cos( rad );

  painter->save();
  painter->setFont( font );
  painter->translate( x, y );
  //correct oversampled font size back by scaling painter down
  painter->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
  painter->rotate( -ang );

  //
  // Draw a buffer behind the text if one is desired
  //
  if ( mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled() )
  {
    double myBufferSize = mLabelAttributes->bufferSize() * 0.3527 * renderContext.scaleFactor() * renderContext.rasterScaleFactor();
    QPen bufferPen;
    if ( mLabelAttributes->bufferColorIsSet() )
    {
      bufferPen.setColor( mLabelAttributes->bufferColor() );
    }
    else //default to a white buffer
    {
      bufferPen.setColor( Qt::white );
    }
    painter->setPen( bufferPen );

    double bufferStepSize; //hack to distinguish pixel devices from logical devices
    if (( renderContext.scaleFactor() - 1 ) > 1.5 )
    {
      bufferStepSize = 1;
    }
    else //draw more dense in case of logical devices
    {
      bufferStepSize = 1 / renderContext.rasterScaleFactor();
    }

    for ( double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize )
    {
      for ( double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize )
      {
        if ( mLabelAttributes->multilineEnabled() )
          painter->drawText( QRectF( i, j - height, width, height ), alignment, text );
        else
          painter->drawText( QPointF( i, j ), text );
      }
    }
  }

  painter->setPen( pen );
  if ( mLabelAttributes->multilineEnabled() )
    painter->drawText( dx, dy - height, width, height, alignment, text );
  else
    painter->drawText( dx, dy, text );
  painter->restore();
}
예제 #7
0
int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx )
{
  Q_ASSERT( mMapRenderer != NULL );

  // start with a temporary settings class, find out labeling info
  QgsPalLayerSettings lyrTmp;
  lyrTmp.readFromLayer( layer );

  if ( !lyrTmp.enabled )
    return 0;

  // find out which field will be needed
  int fldIndex = layer->fieldNameIndex( lyrTmp.fieldName );
  if ( fldIndex == -1 )
    return 0;
  attrIndices.insert( fldIndex );

  //add indices of data defined fields
  QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator dIt = lyrTmp.dataDefinedProperties.constBegin();
  for ( ; dIt != lyrTmp.dataDefinedProperties.constEnd(); ++dIt )
  {
    attrIndices.insert( dIt.value() );
  }

  // add layer settings to the pallabeling hashtable: <QgsVectorLayer*, QgsPalLayerSettings>
  mActiveLayers.insert( layer, lyrTmp );
  // start using the reference to the layer in hashtable instead of local instance
  QgsPalLayerSettings& lyr = mActiveLayers[layer];

  // how to place the labels
  Arrangement arrangement;
  switch ( lyr.placement )
  {
    case QgsPalLayerSettings::AroundPoint: arrangement = P_POINT; break;
    case QgsPalLayerSettings::OverPoint:   arrangement = P_POINT_OVER; break;
    case QgsPalLayerSettings::Line:        arrangement = P_LINE; break;
    case QgsPalLayerSettings::Curved:      arrangement = P_CURVED; break;
    case QgsPalLayerSettings::Horizontal:  arrangement = P_HORIZ; break;
    case QgsPalLayerSettings::Free:        arrangement = P_FREE; break;
    default: Q_ASSERT( "unsupported placement" && 0 ); return 0;
  }

  // create the pal layer
  double priority = 1 - lyr.priority / 10.0; // convert 0..10 --> 1..0
  double min_scale = -1, max_scale = -1;
  if ( lyr.scaleMin != 0 && lyr.scaleMax != 0 )
  {
    min_scale = lyr.scaleMin;
    max_scale = lyr.scaleMax;
  }

  Layer* l = mPal->addLayer( layer->id().toUtf8().data(),
                             min_scale, max_scale, arrangement,
                             METER, priority, lyr.obstacle, true, true );

  if ( lyr.placementFlags )
    l->setArrangementFlags( lyr.placementFlags );

  // set label mode (label per feature is the default)
  l->setLabelMode( lyr.labelPerPart ? Layer::LabelPerFeaturePart : Layer::LabelPerFeature );

  // set whether adjacent lines should be merged
  l->setMergeConnectedLines( lyr.mergeLines );

  lyr.textFont.setPixelSize( lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx ) );

  //raster and vector scale factors
  lyr.vectorScaleFactor = ctx.scaleFactor();
  lyr.rasterCompressFactor = ctx.rasterScaleFactor();

  // save the pal layer to our layer context (with some additional info)
  lyr.palLayer = l;
  lyr.fieldIndex = fldIndex;
  lyr.fontMetrics = new QFontMetricsF( lyr.textFont );

  lyr.xform = mMapRenderer->coordinateTransform();
  if ( mMapRenderer->hasCrsTransformEnabled() )
    lyr.ct = new QgsCoordinateTransform( layer->crs(), mMapRenderer->destinationCrs() );
  else
    lyr.ct = NULL;
  lyr.ptZero = lyr.xform->toMapCoordinates( 0, 0 );
  lyr.ptOne = lyr.xform->toMapCoordinates( 1, 0 );

  // rect for clipping
  lyr.extentGeom = QgsGeometry::fromRect( mMapRenderer->extent() );

  return 1; // init successful
}
void QgsGraduatedSymbolRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity )
{
  QPainter *p = renderContext.painter();
  QgsSymbol* theSymbol = symbolForFeature( &f );
  if ( !theSymbol )
  {
    if ( img && mGeometryType == QGis::Point )
    {
      img->fill( 0 );
    }
    else if ( mGeometryType != QGis::Point )
    {
      p->setPen( Qt::NoPen );
      p->setBrush( Qt::NoBrush );
    }
    return;
  }

  //set the qpen and qpainter to the right values
  // Point
  if ( img && mGeometryType == QGis::Point )
  {
    double fieldScale = 1.0;
    double rotation = 0.0;

    if ( theSymbol->scaleClassificationField() >= 0 )
    {
      //first find out the value for the scale classification attribute
      const QgsAttributeMap& attrs = f.attributeMap();
      fieldScale = sqrt( qAbs( attrs[theSymbol->scaleClassificationField()].toDouble() ) );
      QgsDebugMsgLevel( QString( "Feature has field scale factor %1" ).arg( fieldScale ), 3 );
    }
    if ( theSymbol->rotationClassificationField() >= 0 )
    {
      const QgsAttributeMap& attrs = f.attributeMap();
      rotation = attrs[theSymbol->rotationClassificationField()].toDouble();
      QgsDebugMsgLevel( QString( "Feature has rotation factor %1" ).arg( rotation ), 3 );
    }

    QString oldName;

    if ( theSymbol->symbolField() >= 0 )
    {
      const QgsAttributeMap& attrs = f.attributeMap();
      QString name = attrs[theSymbol->symbolField()].toString();
      QgsDebugMsgLevel( QString( "Feature has name %1" ).arg( name ), 3 );
      oldName = theSymbol->pointSymbolName();
      theSymbol->setNamedPointSymbol( name );
    }

    double scale = renderContext.scaleFactor();

    if ( theSymbol->pointSizeUnits() )
    {
      scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel();
    }

    *img = theSymbol->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale,
           rotation, renderContext.rasterScaleFactor(), opacity );

    if ( !oldName.isNull() )
    {
      theSymbol->setNamedPointSymbol( oldName );
    }
  }

  // Line, polygon
  if ( mGeometryType != QGis::Point )
  {
    if ( !selected )
    {
      QPen pen = theSymbol->pen();
      pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
      p->setPen( pen );

      if ( mGeometryType == QGis::Polygon )
      {
        QBrush brush = theSymbol->brush();
        scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
        p->setBrush( brush );
      }
    }
    else
    {
      QPen pen = theSymbol->pen();
      pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );

      if ( mGeometryType == QGis::Polygon )
      {
        QBrush brush = theSymbol->brush();
        scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout
        brush.setColor( mSelectionColor );
        p->setBrush( brush );
      }
      else //don't draw outlines in selection color for polys otherwise they appear merged
      {
        pen.setColor( mSelectionColor );
      }
      p->setPen( pen );
    }
  }
}
void QgsContinuousColorRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity )
{
  QPainter *p = renderContext.painter();

  if (( mMinimumSymbol && mMaximumSymbol ) )
  {
    //first find out the value for the classification attribute
    const QgsAttributes& attrs = f.attributes();
    if ( attrs[mClassificationField].isNull() )
    {
      if ( img )
        *img = QImage();
    }
    double fvalue = attrs[mClassificationField].toDouble();

    //double fvalue = vec[mClassificationField].fieldValue().toDouble();
    double minvalue = mMinimumSymbol->lowerValue().toDouble();
    double maxvalue = mMaximumSymbol->lowerValue().toDouble();

    QColor mincolor, maxcolor;

    if ( mGeometryType == QGis::Line || mGeometryType == QGis::Point )
    {
      mincolor = mMinimumSymbol->pen().color();
      maxcolor = mMaximumSymbol->pen().color();
    }
    else                    //if polygon
    {
      p->setPen( mMinimumSymbol->pen() );
      mincolor = mMinimumSymbol->fillColor();
      maxcolor = mMaximumSymbol->fillColor();
    }

    int red, green, blue;

    if (( maxvalue - minvalue ) != 0 )
    {
      red = int ( maxcolor.red() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.red() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
      green = int ( maxcolor.green() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.green() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
      blue =  int ( maxcolor.blue() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.blue() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
    }
    else
    {
      red = int ( mincolor.red() );
      green = int ( mincolor.green() );
      blue = int ( mincolor.blue() );
    }

    if ( mGeometryType == QGis::Point && img )
    {
      // TODO we must get always new marker -> slow, but continuous color for points
      // probably is not used frequently


      // Use color for both pen and brush (user can add another layer with outpine)
      // later add support for both pen and brush to dialog
      QPen pen = mMinimumSymbol->pen();
      pen.setColor( QColor( red, green, blue ) );
      pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );

      QBrush brush = mMinimumSymbol->brush();

      if ( selected )
      {
        pen.setColor( mSelectionColor );
        brush.setColor( mSelectionColor );
      }
      else
      {
        brush.setColor( QColor( red, green, blue ) );
      }
      brush.setStyle( Qt::SolidPattern );

      *img = QgsMarkerCatalogue::instance()->imageMarker( mMinimumSymbol->pointSymbolName(),
             mMinimumSymbol->pointSize() * renderContext.scaleFactor() * renderContext.rasterScaleFactor(),
             pen, brush, opacity );

    }
    else if ( mGeometryType == QGis::Line )
    {
      QPen linePen;
      linePen.setColor( QColor( red, green, blue ) );
      linePen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
      p->setPen( linePen );
    }
    else //polygon
    {
      p->setBrush( QColor( red, green, blue ) );
      if ( mDrawPolygonOutline )
      {
        QPen pen;
        pen.setColor( QColor( 0, 0, 0 ) );
        pen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
        p->setPen( pen );
      }
      else
      {
        p->setPen( Qt::NoPen );
      }
    }
    if ( selected )
    {
      //for polygons we don't use selection color for outline
      //otherwise adjacent features appear merged when selected
      if ( mGeometryType != QGis::Polygon )
      {
        QPen pen = mMinimumSymbol->pen();
        pen.setColor( mSelectionColor );
        p->setPen( pen );
      }
      QBrush brush = mMinimumSymbol->brush();
      brush.setColor( mSelectionColor );
      p->setBrush( brush );
    }
  }
}