Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsdoubleboxscalebarrenderer.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 "qgsdoubleboxscalebarrenderer.h"
18 : : #include "qgsscalebarsettings.h"
19 : : #include "qgslayoututils.h"
20 : : #include "qgssymbol.h"
21 : : #include "qgstextrenderer.h"
22 : : #include <QList>
23 : : #include <QPainter>
24 : :
25 : 5 : QString QgsDoubleBoxScaleBarRenderer::id() const
26 : : {
27 : 10 : return QStringLiteral( "Double Box" );
28 : : }
29 : :
30 : 0 : QString QgsDoubleBoxScaleBarRenderer::visibleName() const
31 : : {
32 : 0 : return QObject::tr( "Double Box" );
33 : : }
34 : :
35 : 0 : QgsScaleBarRenderer::Flags QgsDoubleBoxScaleBarRenderer::flags() const
36 : : {
37 : 0 : return Flag::FlagUsesLineSymbol |
38 : 0 : Flag::FlagUsesFillSymbol |
39 : 0 : Flag::FlagUsesAlternateFillSymbol |
40 : 0 : Flag::FlagRespectsUnits |
41 : 0 : Flag::FlagRespectsMapUnitsPerScaleBarUnit |
42 : 0 : Flag::FlagUsesUnitLabel |
43 : 0 : Flag::FlagUsesSegments |
44 : 0 : Flag::FlagUsesLabelBarSpace |
45 : 0 : Flag::FlagUsesLabelVerticalPlacement |
46 : : Flag::FlagUsesLabelHorizontalPlacement;
47 : : }
48 : :
49 : 0 : int QgsDoubleBoxScaleBarRenderer::sortKey() const
50 : : {
51 : 0 : return 2;
52 : : }
53 : :
54 : 0 : QgsDoubleBoxScaleBarRenderer *QgsDoubleBoxScaleBarRenderer::clone() const
55 : : {
56 : 0 : return new QgsDoubleBoxScaleBarRenderer( *this );
57 : : }
58 : :
59 : 0 : void QgsDoubleBoxScaleBarRenderer::draw( QgsRenderContext &context, const QgsScaleBarSettings &settings, const ScaleBarContext &scaleContext ) const
60 : : {
61 : 0 : if ( !context.painter() )
62 : : {
63 : 0 : return;
64 : : }
65 : 0 : QPainter *painter = context.painter();
66 : :
67 : 0 : const double scaledLabelBarSpace = context.convertToPainterUnits( settings.labelBarSpace(), QgsUnitTypes::RenderMillimeters );
68 : 0 : const double scaledBoxContentSpace = context.convertToPainterUnits( settings.boxContentSpace(), QgsUnitTypes::RenderMillimeters );
69 : 0 : const QFontMetricsF fontMetrics = QgsTextRenderer::fontMetrics( context, settings.textFormat() );
70 : 0 : const double barTopPosition = scaledBoxContentSpace + ( settings.labelVerticalPlacement() == QgsScaleBarSettings::LabelAboveSegment ? fontMetrics.ascent() + scaledLabelBarSpace : 0 );
71 : 0 : const double segmentHeight = context.convertToPainterUnits( settings.height() / 2, QgsUnitTypes::RenderMillimeters );
72 : :
73 : 0 : painter->save();
74 : 0 : context.setPainterFlagsUsingContext( painter );
75 : :
76 : 0 : std::unique_ptr< QgsLineSymbol > lineSymbol( settings.lineSymbol()->clone() );
77 : 0 : lineSymbol->startRender( context );
78 : :
79 : 0 : std::unique_ptr< QgsFillSymbol > fillSymbol1( settings.fillSymbol()->clone() );
80 : 0 : fillSymbol1->startRender( context );
81 : :
82 : 0 : std::unique_ptr< QgsFillSymbol > fillSymbol2( settings.alternateFillSymbol()->clone() );
83 : 0 : fillSymbol2->startRender( context );
84 : :
85 : 0 : painter->setPen( Qt::NoPen );
86 : 0 : painter->setBrush( Qt::NoBrush );
87 : :
88 : 0 : bool useColor = true; //alternate brush color/white
89 : :
90 : 0 : const double xOffset = firstLabelXOffset( settings, context, scaleContext );
91 : :
92 : 0 : const QList<double> positions = segmentPositions( context, scaleContext, settings );
93 : 0 : const QList<double> widths = segmentWidths( scaleContext, settings );
94 : :
95 : 0 : double minX = 0;
96 : 0 : double maxX = 0;
97 : 0 : QgsFillSymbol *currentSymbol = nullptr;
98 : 0 : for ( int i = 0; i < positions.size(); ++i )
99 : : {
100 : : //draw top half
101 : 0 : if ( useColor )
102 : : {
103 : 0 : currentSymbol = fillSymbol1.get();
104 : 0 : }
105 : : else //secondary symbol
106 : : {
107 : 0 : currentSymbol = fillSymbol2.get();
108 : : }
109 : :
110 : 0 : const double thisX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
111 : 0 : const double thisWidth = context.convertToPainterUnits( widths.at( i ), QgsUnitTypes::RenderMillimeters );
112 : :
113 : 0 : if ( i == 0 )
114 : 0 : minX = thisX;
115 : 0 : if ( i == positions.size() - 1 )
116 : 0 : maxX = thisX + thisWidth;
117 : :
118 : 0 : const QRectF segmentRectTop( thisX, barTopPosition, thisWidth, segmentHeight );
119 : 0 : currentSymbol->renderPolygon( QPolygonF()
120 : 0 : << segmentRectTop.topLeft()
121 : 0 : << segmentRectTop.topRight()
122 : 0 : << segmentRectTop.bottomRight()
123 : 0 : << segmentRectTop.bottomLeft()
124 : 0 : << segmentRectTop.topLeft(),
125 : 0 : nullptr, nullptr, context );
126 : 0 : painter->drawRect( segmentRectTop );
127 : :
128 : : //draw bottom half
129 : 0 : if ( useColor )
130 : : {
131 : : //secondary symbol
132 : 0 : currentSymbol = fillSymbol2.get();
133 : 0 : }
134 : : else //primary symbol
135 : : {
136 : 0 : currentSymbol = fillSymbol1.get(); ;
137 : : }
138 : :
139 : 0 : const QRectF segmentRectBottom( thisX, barTopPosition + segmentHeight, thisWidth, segmentHeight );
140 : :
141 : 0 : currentSymbol->renderPolygon( QPolygonF()
142 : 0 : << segmentRectBottom.topLeft()
143 : 0 : << segmentRectBottom.topRight()
144 : 0 : << segmentRectBottom.bottomRight()
145 : 0 : << segmentRectBottom.bottomLeft()
146 : 0 : << segmentRectBottom.topLeft(),
147 : 0 : nullptr, nullptr, context );
148 : 0 : useColor = !useColor;
149 : 0 : }
150 : :
151 : :
152 : : // and then the lines
153 : : // note that we do this layer-by-layer, to avoid ugliness where the lines touch the outer rect
154 : 0 : for ( int layer = 0; layer < lineSymbol->symbolLayerCount(); ++layer )
155 : : {
156 : : // vertical lines
157 : 0 : for ( int i = 1; i < positions.size(); ++i )
158 : : {
159 : 0 : const double lineX = context.convertToPainterUnits( positions.at( i ), QgsUnitTypes::RenderMillimeters ) + xOffset;
160 : 0 : lineSymbol->renderPolyline( QPolygonF()
161 : 0 : << QPointF( lineX, barTopPosition )
162 : 0 : << QPointF( lineX, barTopPosition + segmentHeight * 2 ),
163 : 0 : nullptr, context, layer );
164 : 0 : }
165 : :
166 : : // middle horizontal line
167 : 0 : lineSymbol->renderPolyline( QPolygonF()
168 : 0 : << QPointF( minX, barTopPosition + segmentHeight )
169 : 0 : << QPointF( maxX, barTopPosition + segmentHeight ),
170 : 0 : nullptr, context, layer );
171 : :
172 : :
173 : : // outside line
174 : 0 : lineSymbol->renderPolyline( QPolygonF()
175 : 0 : << QPointF( minX, barTopPosition )
176 : 0 : << QPointF( maxX, barTopPosition )
177 : 0 : << QPointF( maxX, barTopPosition + segmentHeight * 2 )
178 : 0 : << QPointF( minX, barTopPosition + segmentHeight * 2 )
179 : 0 : << QPointF( minX, barTopPosition ),
180 : 0 : nullptr, context, layer );
181 : 0 : }
182 : :
183 : 0 : lineSymbol->stopRender( context );
184 : 0 : fillSymbol1->stopRender( context );
185 : 0 : fillSymbol2->stopRender( context );
186 : :
187 : 0 : painter->restore();
188 : :
189 : : //draw labels using the default method
190 : 0 : drawDefaultLabels( context, settings, scaleContext );
191 : 0 : }
|