LCOV - code coverage report
Current view: top level - core/scalebar - qgsticksscalebarrenderer.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 10 126 7.9 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                             qgsticksscalebarrenderer.cpp
       3                 :            :                             ----------------------------
       4                 :            :     begin                : June 2008
       5                 :            :     copyright            : (C) 2008 by Marco Hugentobler
       6                 :            :     email                : marco.hugentobler@karto.baug.ethz.ch
       7                 :            :  ***************************************************************************/
       8                 :            : /***************************************************************************
       9                 :            :  *                                                                         *
      10                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      11                 :            :  *   it under the terms of the GNU General Public License as published by  *
      12                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      13                 :            :  *   (at your option) any later version.                                   *
      14                 :            :  *                                                                         *
      15                 :            :  ***************************************************************************/
      16                 :            : 
      17                 :            : #include "qgsticksscalebarrenderer.h"
      18                 :            : #include "qgsscalebarsettings.h"
      19                 :            : #include "qgslayoututils.h"
      20                 :            : #include "qgssymbol.h"
      21                 :            : #include "qgstextrenderer.h"
      22                 :            : #include <QPainter>
      23                 :            : 
      24                 :         15 : QgsTicksScaleBarRenderer::QgsTicksScaleBarRenderer( QgsTicksScaleBarRenderer::TickPosition position )
      25                 :         15 :   : mTickPosition( position )
      26                 :         30 : {
      27                 :            : 
      28                 :         15 : }
      29                 :            : 
      30                 :         15 : QString QgsTicksScaleBarRenderer::id() const
      31                 :            : {
      32                 :         15 :   switch ( mTickPosition )
      33                 :            :   {
      34                 :            :     case TicksUp:
      35                 :         10 :       return QStringLiteral( "Line Ticks Up" );
      36                 :            :     case TicksDown:
      37                 :         10 :       return QStringLiteral( "Line Ticks Down" );
      38                 :            :     case TicksMiddle:
      39                 :         10 :       return QStringLiteral( "Line Ticks Middle" );
      40                 :            :   }
      41                 :          0 :   return QString();  // to make gcc happy
      42                 :         15 : }
      43                 :            : 
      44                 :          0 : QString QgsTicksScaleBarRenderer::visibleName() const
      45                 :            : {
      46                 :          0 :   switch ( mTickPosition )
      47                 :            :   {
      48                 :            :     case TicksUp:
      49                 :          0 :       return QObject::tr( "Line Ticks Up" );
      50                 :            :     case TicksDown:
      51                 :          0 :       return QObject::tr( "Line Ticks Down" );
      52                 :            :     case TicksMiddle:
      53                 :          0 :       return QObject::tr( "Line Ticks Middle" );
      54                 :            :   }
      55                 :          0 :   return QString();  // to make gcc happy
      56                 :            : 
      57                 :          0 : }
      58                 :            : 
      59                 :          0 : int QgsTicksScaleBarRenderer::sortKey() const
      60                 :            : {
      61                 :          0 :   switch ( mTickPosition )
      62                 :            :   {
      63                 :            :     case TicksUp:
      64                 :          0 :       return 5;
      65                 :            :     case TicksDown:
      66                 :          0 :       return 4;
      67                 :            :     case TicksMiddle:
      68                 :          0 :       return 3;
      69                 :            :   }
      70                 :          0 :   return 6;
      71                 :          0 : }
      72                 :            : 
      73                 :          0 : QgsScaleBarRenderer::Flags QgsTicksScaleBarRenderer::flags() const
      74                 :            : {
      75                 :          0 :   return Flag::FlagUsesLineSymbol |
      76                 :          0 :          Flag::FlagUsesDivisionSymbol |
      77                 :          0 :          Flag::FlagUsesSubdivisionSymbol |
      78                 :          0 :          Flag::FlagRespectsUnits |
      79                 :          0 :          Flag::FlagRespectsMapUnitsPerScaleBarUnit |
      80                 :          0 :          Flag::FlagUsesUnitLabel |
      81                 :          0 :          Flag::FlagUsesSegments |
      82                 :          0 :          Flag::FlagUsesLabelBarSpace |
      83                 :          0 :          Flag::FlagUsesLabelVerticalPlacement |
      84                 :          0 :          Flag::FlagUsesLabelHorizontalPlacement |
      85                 :          0 :          Flag::FlagUsesSubdivisions |
      86                 :            :          Flag::FlagUsesSubdivisionsHeight;
      87                 :            : }
      88                 :            : 
      89                 :          0 : QgsTicksScaleBarRenderer *QgsTicksScaleBarRenderer::clone() const
      90                 :            : {
      91                 :          0 :   return new QgsTicksScaleBarRenderer( * this );
      92                 :            : }
      93                 :            : 
      94                 :          0 : void QgsTicksScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBarSettings &settings, const ScaleBarContext &scaleContext ) const
      95                 :            : {
      96                 :          0 :   if ( !context.painter() )
      97                 :          0 :     return;
      98                 :            : 
      99                 :          0 :   QPainter *painter = context.painter();
     100                 :            : 
     101                 :          0 :   const double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
     102                 :          0 :   const double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
     103                 :          0 :   const QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
     104                 :          0 :   const double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
     105                 :          0 :   const double scaledHeight = context.convertToPainterUnits( settings.height(), QgsUnitTypes::RenderMillimeters );
     106                 :          0 :   const double scaledSubdivisionsHeight = context.convertToPainterUnits( settings.subdivisionsHeight(), QgsUnitTypes::RenderMillimeters );
     107                 :          0 :   const double scaledMaxHeight = ( ( settings.numberOfSubdivisions() > 1 ) && ( scaledSubdivisionsHeight > scaledHeight ) ) ? scaledSubdivisionsHeight : scaledHeight;
     108                 :          0 :   const double middlePosition = barTopPosition + scaledMaxHeight / 2.0;
     109                 :          0 :   const double bottomPosition = barTopPosition + scaledMaxHeight;
     110                 :            : 
     111                 :          0 :   const double xOffset = firstLabelXOffset( settings, context, scaleContext );
     112                 :            : 
     113                 :          0 :   painter->save();
     114                 :          0 :   context.setPainterFlagsUsingContext( painter );
     115                 :            : 
     116                 :          0 :   std::unique_ptr< QgsLineSymbol > symbol( settings.lineSymbol()->clone() );
     117                 :          0 :   symbol->startRender( context );
     118                 :            : 
     119                 :          0 :   std::unique_ptr< QgsLineSymbol > divisionSymbol( settings.divisionLineSymbol()->clone() );
     120                 :          0 :   divisionSymbol->startRender( context );
     121                 :            : 
     122                 :          0 :   std::unique_ptr< QgsLineSymbol > subdivisionSymbol( settings.subdivisionLineSymbol()->clone() );
     123                 :          0 :   subdivisionSymbol->startRender( context );
     124                 :            : 
     125                 :          0 :   const QList<double> positions = segmentPositions( context, scaleContext, settings );
     126                 :            : 
     127                 :            :   // vertical positions
     128                 :          0 :   double verticalPos = 0.0;
     129                 :          0 :   QList<double> subTickPositionsY;
     130                 :          0 :   QList<double> tickPositionsY;
     131                 :          0 :   switch ( mTickPosition )
     132                 :            :   {
     133                 :            :     case TicksDown:
     134                 :          0 :       verticalPos = barTopPosition;
     135                 :          0 :       subTickPositionsY << verticalPos;
     136                 :          0 :       subTickPositionsY << verticalPos + scaledSubdivisionsHeight;
     137                 :          0 :       tickPositionsY << verticalPos;
     138                 :          0 :       tickPositionsY << verticalPos + scaledHeight;
     139                 :          0 :       break;
     140                 :            :     case TicksMiddle:
     141                 :          0 :       verticalPos = middlePosition;
     142                 :          0 :       subTickPositionsY << verticalPos + scaledSubdivisionsHeight / 2.0;
     143                 :          0 :       subTickPositionsY << verticalPos - scaledSubdivisionsHeight / 2.0;
     144                 :          0 :       tickPositionsY << verticalPos + scaledHeight / 2.0;
     145                 :          0 :       tickPositionsY << verticalPos - scaledHeight / 2.0;
     146                 :          0 :       break;
     147                 :            :     case TicksUp:
     148                 :          0 :       verticalPos = bottomPosition;
     149                 :          0 :       subTickPositionsY << verticalPos;
     150                 :          0 :       subTickPositionsY << verticalPos - scaledSubdivisionsHeight;
     151                 :          0 :       tickPositionsY << verticalPos;
     152                 :          0 :       tickPositionsY << verticalPos - scaledHeight;
     153                 :          0 :       break;
     154                 :            :   }
     155                 :            : 
     156                 :          0 :   int symbolLayerCount = symbol->symbolLayerCount();
     157                 :          0 :   symbolLayerCount = std::max( symbolLayerCount, divisionSymbol->symbolLayerCount() );
     158                 :          0 :   symbolLayerCount = std::max( symbolLayerCount, subdivisionSymbol->symbolLayerCount() );
     159                 :            : 
     160                 :            :   // we render the bar symbol-layer-by-symbol-layer, to avoid ugliness where the lines overlap in multi-layer symbols
     161                 :          0 :   for ( int layer = 0; layer < symbolLayerCount; ++ layer )
     162                 :            :   {
     163                 :          0 :     const bool drawDivisionsForThisSymbolLayer = layer < divisionSymbol->symbolLayerCount();
     164                 :          0 :     const bool drawSubdivisionsForThisSymbolLayer = layer < subdivisionSymbol->symbolLayerCount();
     165                 :          0 :     const bool drawLineForThisSymbolLayer = layer < symbol->symbolLayerCount();
     166                 :            : 
     167                 :          0 :     if ( drawDivisionsForThisSymbolLayer )
     168                 :            :     {
     169                 :            :       // first draw the vertical lines for segments
     170                 :          0 :       for ( int i = 0; i < positions.size(); ++i )
     171                 :            :       {
     172                 :          0 :         const double thisX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
     173                 :          0 :         divisionSymbol->renderPolyline( QPolygonF() << QPointF( thisX, tickPositionsY.at( 0 ) )
     174                 :          0 :                                         << QPointF( thisX, tickPositionsY.at( 1 ) ), nullptr, context, layer );
     175                 :          0 :       }
     176                 :          0 :     }
     177                 :            : 
     178                 :            :     // draw the vertical lines for right subdivisions
     179                 :          0 :     if ( drawSubdivisionsForThisSymbolLayer )
     180                 :            :     {
     181                 :          0 :       for ( int i = settings.numberOfSegmentsLeft(); i < positions.size(); ++i )
     182                 :            :       {
     183                 :          0 :         for ( int j = 1; j < settings.numberOfSubdivisions(); ++j )
     184                 :            :         {
     185                 :          0 :           const double thisSubX = context.convertToPainterUnits( positions.at( i ) + j * scaleContext.segmentWidth / settings.numberOfSubdivisions(), QgsUnitTypes::RenderMillimeters ) + xOffset;
     186                 :          0 :           subdivisionSymbol->renderPolyline( QPolygonF() << QPointF( thisSubX, subTickPositionsY.at( 0 ) )
     187                 :          0 :                                              << QPointF( thisSubX, subTickPositionsY.at( 1 ) ), nullptr, context, layer );
     188                 :          0 :         }
     189                 :          0 :       }
     190                 :          0 :     }
     191                 :            : 
     192                 :            :     //draw last tick and horizontal line
     193                 :          0 :     if ( !positions.isEmpty() )
     194                 :            :     {
     195                 :          0 :       double lastTickPositionX = context.convertToPainterUnits( positions.at( positions.size() - 1 ) + scaleContext.segmentWidth, QgsUnitTypes::RenderMillimeters ) + xOffset;
     196                 :            : 
     197                 :            :       //last vertical line
     198                 :          0 :       if ( drawDivisionsForThisSymbolLayer )
     199                 :            :       {
     200                 :          0 :         divisionSymbol->renderPolyline( QPolygonF() << QPointF( lastTickPositionX, tickPositionsY.at( 0 ) )
     201                 :          0 :                                         << QPointF( lastTickPositionX, tickPositionsY.at( 1 ) ),
     202                 :          0 :                                         nullptr, context, layer );
     203                 :          0 :       }
     204                 :            : 
     205                 :            :       //horizontal line
     206                 :          0 :       if ( drawLineForThisSymbolLayer )
     207                 :            :       {
     208                 :          0 :         symbol->renderPolyline( QPolygonF() << QPointF( xOffset + context.convertToPainterUnits( positions.at( 0 ), QgsUnitTypes::RenderMillimeters ), verticalPos )
     209                 :          0 :                                 << QPointF( lastTickPositionX, verticalPos ), nullptr, context, layer );
     210                 :          0 :       }
     211                 :          0 :     }
     212                 :          0 :   }
     213                 :            : 
     214                 :          0 :   symbol->stopRender( context );
     215                 :          0 :   divisionSymbol->stopRender( context );
     216                 :          0 :   subdivisionSymbol->stopRender( context );
     217                 :            : 
     218                 :          0 :   painter->restore();
     219                 :            : 
     220                 :            :   //draw labels using the default method
     221                 :          0 :   drawDefaultLabels( context, settings, scaleContext );
     222                 :          0 : }
     223                 :            : 
     224                 :            : 

Generated by: LCOV version 1.14