Skip to content

Commit e8a95a5

Browse files
author
wonder
committedJun 12, 2009
Features for labeling are now extracted in the main drawing loop (using a pair of hooks).
This avoids one more iteration through the layer. git-svn-id: http://svn.osgeo.org/qgis/branches/symbology-ng-branch@10906 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

7 files changed

+254
-119
lines changed

7 files changed

+254
-119
lines changed
 

‎src/core/qgsvectorlayer.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
105105
mLabelOn( false ),
106106
mFetching( false ),
107107
mRendererV2( NULL ),
108-
mUsingRendererV2( false )
108+
mUsingRendererV2( false ),
109+
mLabelingPrepareLayerHook( NULL ),
110+
mLabelingRegisterFeatureHook( NULL )
109111
{
110112
mActions = new QgsAttributeAction;
111113

@@ -696,11 +698,29 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
696698

697699
QgsFeature fet;
698700
QgsAttributeList attributes = mRendererV2->usedAttributes();
701+
702+
bool labeling = FALSE;
703+
if (mLabelingPrepareLayerHook)
704+
{
705+
int attrIndex;
706+
if (mLabelingPrepareLayerHook(mLabelingContext, mLabelingLayerContext, attrIndex))
707+
{
708+
if (!attributes.contains(attrIndex))
709+
attributes << attrIndex;
710+
labeling = TRUE;
711+
}
712+
}
713+
699714
select( attributes, rendererContext.extent() );
700715

701716
while ( nextFeature( fet ) )
702717
{
703718
mRendererV2->renderFeature(fet, rendererContext);
719+
720+
if (labeling && mLabelingRegisterFeatureHook)
721+
{
722+
mLabelingRegisterFeatureHook(fet, mLabelingLayerContext);
723+
}
704724
}
705725

706726
mRendererV2->stopRender(rendererContext);
@@ -739,6 +759,19 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
739759
int featureCount = 0;
740760
QgsFeature fet;
741761
QgsAttributeList attributes = mRenderer->classificationAttributes();
762+
763+
bool labeling = FALSE;
764+
if (mLabelingPrepareLayerHook)
765+
{
766+
int attrIndex;
767+
if (mLabelingPrepareLayerHook(mLabelingContext, mLabelingLayerContext, attrIndex))
768+
{
769+
if (!attributes.contains(attrIndex))
770+
attributes << attrIndex;
771+
labeling = TRUE;
772+
}
773+
}
774+
742775
select( attributes, rendererContext.extent() );
743776

744777
try
@@ -801,6 +834,11 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
801834
rendererContext.rasterScaleFactor(),
802835
rendererContext.drawEditingInformation() );
803836

837+
if (labeling && mLabelingRegisterFeatureHook)
838+
{
839+
mLabelingRegisterFeatureHook(fet, mLabelingLayerContext);
840+
}
841+
804842
++featureCount;
805843
}
806844
}
@@ -2087,6 +2125,18 @@ bool QgsVectorLayer::hasLabelsEnabled( void ) const
20872125
return mLabelOn;
20882126
}
20892127

2128+
void QgsVectorLayer::setLabelingHooks(LabelingPrepareLayerHook prepareLayerHook,
2129+
LabelingRegisterFeatureHook registerFeatureHook,
2130+
void* context,
2131+
void* layerContext)
2132+
{
2133+
mLabelingPrepareLayerHook = prepareLayerHook;
2134+
mLabelingRegisterFeatureHook = registerFeatureHook;
2135+
mLabelingContext = context;
2136+
mLabelingLayerContext = layerContext;
2137+
}
2138+
2139+
20902140
bool QgsVectorLayer::startEditing()
20912141
{
20922142
if ( !mDataProvider )

‎src/core/qgsvectorlayer.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ typedef QList<int> QgsAttributeList;
5454
typedef QSet<int> QgsFeatureIds;
5555
typedef QSet<int> QgsAttributeIds;
5656

57+
typedef int (*LabelingPrepareLayerHook)(void*, void*, int&);
58+
typedef void (*LabelingRegisterFeatureHook)(QgsFeature&, void*);
59+
60+
5761
/** \ingroup core
5862
* Vector layer backed by a data source provider.
5963
*/
@@ -340,6 +344,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
340344
/** Label is on */
341345
bool hasLabelsEnabled( void ) const;
342346

347+
void setLabelingHooks(LabelingPrepareLayerHook prepareLayerHook,
348+
LabelingRegisterFeatureHook registerFeatureHook,
349+
void* mLabelingContext,
350+
void* mLabelingLayerContext);
351+
343352
/** Returns true if the provider is in editing mode */
344353
virtual bool isEditable() const;
345354

@@ -667,6 +676,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
667676
/** Label */
668677
QgsLabel *mLabel;
669678

679+
LabelingPrepareLayerHook mLabelingPrepareLayerHook;
680+
LabelingRegisterFeatureHook mLabelingRegisterFeatureHook;
681+
void* mLabelingContext;
682+
void* mLabelingLayerContext;
683+
684+
670685
/** Display labels */
671686
bool mLabelOn;
672687

‎src/plugins/labeling/labeling.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,6 @@ void Labeling::initGui()
8989

9090
void Labeling::doLabeling( QPainter * painter )
9191
{
92-
int w = painter->device()->width();
93-
int h = painter->device()->height();
94-
95-
96-
QgsMapLayer* layer = mQGisIface->activeLayer();
97-
if (layer == NULL || layer->type() != QgsMapLayer::VectorLayer)
98-
{
99-
painter->drawLine(0,0,w,h);
100-
return;
101-
}
102-
10392
mLBL->doLabeling(painter);
10493
}
10594

‎src/plugins/labeling/labelinggui.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ LabelingGui::LabelingGui( PalLabeling* lbl, QString layerId, QWidget* parent )
4242
populatePlacementMethods();
4343
populateFieldNames();
4444

45-
PalLabeling::LayerSettings lyr = lbl->layer(layerId);
45+
LayerSettings lyr = lbl->layer(layerId);
4646
if (!lyr.layerId.isEmpty())
4747
{
4848
// load the labeling settings
@@ -74,12 +74,12 @@ QgsVectorLayer* LabelingGui::layer()
7474
return static_cast<QgsVectorLayer*>(layer);
7575
}
7676

77-
PalLabeling::LayerSettings LabelingGui::layerSettings()
77+
LayerSettings LabelingGui::layerSettings()
7878
{
79-
PalLabeling::LayerSettings lyr;
79+
LayerSettings lyr;
8080
lyr.layerId = mLayerId;
8181
lyr.fieldName = cboFieldName->currentText();
82-
lyr.placement = (PalLabeling::Placement) cboPlacement->itemData(cboPlacement->currentIndex()).toInt();
82+
lyr.placement = (LayerSettings::Placement) cboPlacement->itemData(cboPlacement->currentIndex()).toInt();
8383
lyr.textColor = btnTextColor->color();
8484
lyr.textFont = lblFontPreview->font();
8585
lyr.enabled = chkEnableLabeling->isChecked();
@@ -94,18 +94,18 @@ void LabelingGui::populatePlacementMethods()
9494
switch (layer()->geometryType())
9595
{
9696
case QGis::Point:
97-
cboPlacement->addItem(tr("Around the point"), QVariant(PalLabeling::AroundPoint));
97+
cboPlacement->addItem(tr("Around the point"), QVariant(LayerSettings::AroundPoint));
9898
break;
9999
case QGis::Line:
100-
cboPlacement->addItem(tr("On the line"), QVariant(PalLabeling::OnLine));
101-
cboPlacement->addItem(tr("Around the line"), QVariant(PalLabeling::AroundLine));
100+
cboPlacement->addItem(tr("On the line"), QVariant(LayerSettings::OnLine));
101+
cboPlacement->addItem(tr("Around the line"), QVariant(LayerSettings::AroundLine));
102102
break;
103103
case QGis::Polygon:
104-
cboPlacement->addItem(tr("Horizontal"), QVariant(PalLabeling::Horizontal));
105-
cboPlacement->addItem(tr("Free"), QVariant(PalLabeling::Free));
106-
cboPlacement->addItem(tr("Around the centroid"), QVariant(PalLabeling::AroundPoint));
107-
cboPlacement->addItem(tr("On the perimeter"), QVariant(PalLabeling::OnLine));
108-
cboPlacement->addItem(tr("Around the perimeter"), QVariant(PalLabeling::AroundLine));
104+
cboPlacement->addItem(tr("Horizontal"), QVariant(LayerSettings::Horizontal));
105+
cboPlacement->addItem(tr("Free"), QVariant(LayerSettings::Free));
106+
cboPlacement->addItem(tr("Around the centroid"), QVariant(LayerSettings::AroundPoint));
107+
cboPlacement->addItem(tr("On the perimeter"), QVariant(LayerSettings::OnLine));
108+
cboPlacement->addItem(tr("Around the perimeter"), QVariant(LayerSettings::AroundLine));
109109
break;
110110
}
111111
}

‎src/plugins/labeling/labelinggui.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class LabelingGui : public QDialog, private Ui::LabelingGuiBase
3535
LabelingGui( PalLabeling* lbl, QString layerId, QWidget* parent );
3636
~LabelingGui();
3737

38-
PalLabeling::LayerSettings layerSettings();
38+
LayerSettings layerSettings();
3939

4040
public slots:
4141
void changeTextColor();

‎src/plugins/labeling/pallabeling.cpp

Lines changed: 119 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,48 @@ class MyLabel : public PalGeometry
5959
int mId;
6060
};
6161

62+
// -------------
63+
64+
LayerSettings::LayerSettings()
65+
: palLayer(NULL), fontMetrics(NULL)
66+
{
67+
}
68+
69+
LayerSettings::~LayerSettings()
70+
{
71+
// pal layer is deleted internally in PAL
72+
delete fontMetrics;
73+
}
74+
75+
void LayerSettings::calculateLabelSize(QString text, double& labelX, double& labelY)
76+
{
77+
//QFontMetrics fontMetrics(textFont);
78+
QRect labelRect = /*QRect(0,0,20,20);*/ fontMetrics->boundingRect(text);
79+
80+
// 2px border...
81+
QgsPoint ptSize = xform->toMapCoordinates( labelRect.width()+2,labelRect.height()+2 );
82+
labelX = fabs(ptSize.x()-ptZero.x());
83+
labelY = fabs(ptSize.y()-ptZero.y());
84+
}
85+
86+
void LayerSettings::registerFeature(QgsFeature& f)
87+
{
88+
QString labelText = f.attributeMap()[fieldIndex].toString();
89+
double labelX, labelY; // will receive label size
90+
calculateLabelSize(labelText, labelX, labelY);
91+
92+
//std::cout << labelX << " " << labelY << std::endl;
93+
MyLabel* lbl = new MyLabel(f.id(), labelText, GEOSGeom_clone( f.geometry()->asGeos() ) );
94+
95+
// register feature to the layer
96+
palLayer->registerFeature(lbl->strId(), lbl, labelX, labelY);
97+
}
6298

6399

64100
// -------------
65101

66102
PalLabeling::PalLabeling(QgsMapCanvas* mapCanvas)
67-
: mMapCanvas(mapCanvas)
103+
: mMapCanvas(mapCanvas), mPal(NULL)
68104
{
69105
// find out engine defaults
70106
Pal p;
@@ -79,11 +115,31 @@ PalLabeling::PalLabeling(QgsMapCanvas* mapCanvas)
79115
case POPMUSIC_CHAIN: mSearch = Popmusic_Chain; break;
80116
case POPMUSIC_TABU_CHAIN: mSearch = Popmusic_Tabu_Chain; break;
81117
}
118+
119+
initPal();
120+
}
121+
122+
123+
PalLabeling::~PalLabeling()
124+
{
125+
delete mPal;
126+
127+
// make sure to remove hooks from all layers
128+
while (mLayers.count())
129+
{
130+
removeLayer(mLayers[0].layerId);
131+
}
82132
}
83133

134+
84135
void PalLabeling::addLayer(LayerSettings layerSettings)
85136
{
86137
mLayers.append(layerSettings);
138+
139+
QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(layerSettings.layerId);
140+
141+
LayerSettings& lyr = mLayers[ mLayers.count()-1 ]; // make sure we have the right pointer
142+
vlayer->setLabelingHooks(PalLabeling::prepareLayerHook, PalLabeling::registerFeatureHook, this, &lyr);
87143
}
88144

89145
void PalLabeling::removeLayer(QString layerId)
@@ -92,13 +148,16 @@ void PalLabeling::removeLayer(QString layerId)
92148
{
93149
if (mLayers.at(i).layerId == layerId)
94150
{
151+
QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(mLayers.at(i).layerId);
152+
if (vlayer) { vlayer->setLabelingHooks(NULL, NULL, NULL, NULL); }
153+
95154
mLayers.removeAt(i);
96155
return;
97156
}
98157
}
99158
}
100159

101-
PalLabeling::LayerSettings PalLabeling::layer(QString layerId)
160+
LayerSettings PalLabeling::layer(QString layerId)
102161
{
103162
for (int i = 0; i < mLayers.count(); i++)
104163
{
@@ -111,71 +170,63 @@ PalLabeling::LayerSettings PalLabeling::layer(QString layerId)
111170
}
112171

113172

114-
int PalLabeling::prepareLayer(Pal& pal, const LayerSettings& lyr)
173+
174+
int PalLabeling::prepareLayerHook(void* context, void* layerContext, int& attrIndex)
115175
{
116-
if (!lyr.enabled)
117-
return 0;
176+
PalLabeling* thisClass = (PalLabeling*) context;
177+
LayerSettings* lyr = (LayerSettings*) layerContext;
118178

119-
QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(lyr.layerId);
179+
QgsVectorLayer* vlayer = (QgsVectorLayer*) QgsMapLayerRegistry::instance()->mapLayer(lyr->layerId);
120180
if (vlayer == NULL)
121181
return 0;
122182

123-
QgsAttributeList attrs;
124-
125-
int fldName = vlayer->dataProvider()->fieldNameIndex(lyr.fieldName);
126-
if (fldName == -1)
183+
// find out which field will be needed
184+
int fldIndex = vlayer->dataProvider()->fieldNameIndex(lyr->fieldName);
185+
if (fldIndex == -1)
127186
return 0;
128-
attrs << fldName;
129-
vlayer->select(attrs, mMapCanvas->extent());
187+
attrIndex = fldIndex;
130188

131189

132190
// how to place the labels
133191
Arrangement arrangement;
134-
switch (lyr.placement)
192+
switch (lyr->placement)
135193
{
136-
case AroundPoint: arrangement = P_POINT; break;
137-
case OnLine: arrangement = P_LINE; break;
138-
case AroundLine: arrangement = P_LINE_AROUND; break;
139-
case Horizontal: arrangement = P_HORIZ; break;
140-
case Free: arrangement = P_FREE; break;
194+
case LayerSettings::AroundPoint: arrangement = P_POINT; break;
195+
case LayerSettings::OnLine: arrangement = P_LINE; break;
196+
case LayerSettings::AroundLine: arrangement = P_LINE_AROUND; break;
197+
case LayerSettings::Horizontal: arrangement = P_HORIZ; break;
198+
case LayerSettings::Free: arrangement = P_FREE; break;
141199
}
142200

143201
// create the pal layer
144-
double priority = 1 - lyr.priority/10.0; // convert 0..10 --> 1..0
145-
Layer* l = pal.addLayer(lyr.layerId.toLocal8Bit().data(), -1, -1, arrangement, METER, priority, lyr.obstacle, true, true);
146-
147-
QFontMetrics fm(lyr.textFont);
148-
149-
QgsFeature f;
150-
int feats = 0;
151-
const QgsMapToPixel* xform = mMapCanvas->mapRenderer()->coordinateTransform();
152-
QgsPoint ptZero = xform->toMapCoordinates( 0,0 );
153-
154-
while (vlayer->nextFeature(f))
155-
{
156-
QString labelText = f.attributeMap()[fldName].toString();
157-
QRect labelRect = fm.boundingRect(labelText);
158-
//std::cout << "bound: " << labelRect.width() << "x" << labelRect.height() << std::endl;
159-
// 2px border...
160-
QgsPoint ptSize = xform->toMapCoordinates( labelRect.width()+2,labelRect.height()+2 );
161-
double labelX = fabs(ptSize.x()-ptZero.x());
162-
double labelY = fabs(ptSize.y()-ptZero.y());
163-
//std::cout << "L " << labelX << " " << labelY << std::endl;
164-
165-
MyLabel* lbl = new MyLabel(f.id(), labelText, GEOSGeom_clone( f.geometry()->asGeos() ) );
166-
167-
// TODO: owner of the id?
168-
l->registerFeature(lbl->strId(), lbl, labelX, labelY);
169-
feats++;
170-
}
202+
double priority = 1 - lyr->priority/10.0; // convert 0..10 --> 1..0
203+
Layer* l = thisClass->mPal->addLayer(lyr->layerId.toLocal8Bit().data(), -1, -1, arrangement, METER, priority, lyr->obstacle, true, true);
204+
205+
// save the pal layer to our layer context (with some additional info)
206+
lyr->palLayer = l;
207+
lyr->fieldIndex = fldIndex;
208+
lyr->fontMetrics = new QFontMetrics(lyr->textFont);
209+
lyr->fontBaseline = lyr->fontMetrics->boundingRect("X").bottom(); // dummy text to find out how many pixels of the text are below the baseline
210+
lyr->xform = thisClass->mMapCanvas->mapRenderer()->coordinateTransform();
211+
lyr->ptZero = lyr->xform->toMapCoordinates( 0,0 );
212+
213+
return 1; // init successful
214+
}
171215

172-
return feats;
216+
void PalLabeling::registerFeatureHook(QgsFeature& f, void* layerContext)
217+
{
218+
LayerSettings* lyr = (LayerSettings*) layerContext;
219+
lyr->registerFeature(f);
173220
}
174221

175222

176-
void PalLabeling::doLabeling(QPainter* painter)
223+
void PalLabeling::initPal()
177224
{
178-
Pal p;
225+
// delete if exists already
226+
if (mPal)
227+
delete mPal;
228+
229+
mPal = new Pal;
179230

180231
SearchMethod s;
181232
switch (mSearch)
@@ -185,32 +236,31 @@ void PalLabeling::doLabeling(QPainter* painter)
185236
case Popmusic_Chain: s = POPMUSIC_CHAIN; break;
186237
case Popmusic_Tabu_Chain: s = POPMUSIC_TABU_CHAIN; break;
187238
}
188-
p.setSearch(s);
239+
mPal->setSearch(s);
189240

190241
// set number of candidates generated per feature
191-
p.setPointP(mCandPoint);
192-
p.setLineP(mCandLine);
193-
p.setPolyP(mCandPolygon);
242+
mPal->setPointP(mCandPoint);
243+
mPal->setLineP(mCandLine);
244+
mPal->setPolyP(mCandPolygon);
245+
}
246+
247+
194248

195-
//p.setSearch(POPMUSIC_TABU_CHAIN);// this is really slow! // default is CHAIN (worst, fastest)
196-
// TODO: API 0.2 - no mention about changing map units!
197-
// pal map units = METER by default ... change setMapUnit
198-
//p.setMapUnit(METER);
199-
// pal label units ... to be chosen
200-
// pal dist label - pixels?
249+
void PalLabeling::doLabeling(QPainter* painter)
250+
{
201251

202252
QTime t;
203253
t.start();
204254

205-
int feats = 0;
255+
// make sure to delete fontmetrics otherwise it crashes inside Qt when drawing... :-(
256+
// probably gets invalid when setting fonts in the label drawing loop
206257
for (int i = 0; i < mLayers.count(); i++)
207258
{
208-
feats += prepareLayer(p, mLayers.at(i));
259+
LayerSettings& lyr = mLayers[i];
260+
delete lyr.fontMetrics;
261+
lyr.fontMetrics = NULL;
209262
}
210263

211-
std::cout << "LABELING prepare: " << t.elapsed() << "ms" << std::endl;
212-
t.restart();
213-
214264
// do the labeling itself
215265
double scale = 1; // scale denominator
216266
QgsRectangle r = mMapCanvas->extent();
@@ -219,22 +269,17 @@ void PalLabeling::doLabeling(QPainter* painter)
219269
std::list<Label*>* labels;
220270
try
221271
{
222-
labels = p.labeller(scale, bbox, NULL, false);
272+
labels = mPal->labeller(scale, bbox, NULL, false);
223273
}
224274
catch ( std::exception e )
225275
{
226276
std::cerr << "PAL EXCEPTION :-( " << e.what() << std::endl;
227277
return;
228278
}
229279

230-
std::cout << "LABELING work: " << t.elapsed() << "ms" << std::endl;
231-
std::cout << "-->> " << labels->size() << "/" << feats << std::endl;
280+
std::cout << "LABELING work: " << t.elapsed() << "ms ... labels# " << labels->size() << std::endl;
232281
t.restart();
233282

234-
QFontMetrics fm = painter->fontMetrics();
235-
QRect labelRect = fm.boundingRect("X"); // dummy text to find out height
236-
int baseline = labelRect.bottom(); // how many pixels of the text are below the baseline
237-
238283
// draw the labels
239284
const QgsMapToPixel* xform = mMapCanvas->mapRenderer()->coordinateTransform();
240285
std::list<Label*>::iterator it = labels->begin();
@@ -251,7 +296,7 @@ void PalLabeling::doLabeling(QPainter* painter)
251296
painter->save();
252297
painter->setPen( lyr.textColor );
253298
painter->setFont( lyr.textFont );
254-
painter->translate( QPointF(outPt.x()+1, outPt.y()-1-baseline) );
299+
painter->translate( QPointF(outPt.x()+1, outPt.y()-1-lyr.fontBaseline) );
255300
painter->rotate(-label->getRotation() * 180 / M_PI );
256301
painter->drawText(0,0, ((MyLabel*)label->getGeometry())->text());
257302
painter->restore();
@@ -263,6 +308,9 @@ void PalLabeling::doLabeling(QPainter* painter)
263308
std::cout << "LABELING draw: " << t.elapsed() << "ms" << std::endl;
264309

265310
delete labels;
311+
312+
// re-create PAL
313+
initPal();
266314
}
267315

268316
void PalLabeling::numCandidatePositions(int& candPoint, int& candLine, int& candPolygon)

‎src/plugins/labeling/pallabeling.h

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,58 @@ class QgsMapCanvas;
1111
namespace pal
1212
{
1313
class Pal;
14+
class Layer;
1415
}
1516

17+
class QgsMapToPixel;
18+
class QgsFeature;
19+
#include "qgspoint.h"
20+
21+
22+
class LayerSettings
23+
{
24+
public:
25+
LayerSettings();
26+
~LayerSettings();
27+
28+
enum Placement
29+
{
30+
AroundPoint, // Point / Polygon
31+
OnLine, // Line / Polygon
32+
AroundLine, // Line / Polygon
33+
Horizontal, // Polygon
34+
Free // Polygon
35+
};
36+
37+
QString layerId;
38+
QString fieldName;
39+
Placement placement;
40+
QFont textFont;
41+
QColor textColor;
42+
bool enabled;
43+
int priority; // 0 = low, 10 = high
44+
bool obstacle; // whether it's an obstacle
45+
46+
// called from register feature hook
47+
void calculateLabelSize(QString text, double& labelX, double& labelY);
48+
49+
// implementation of register feature hook
50+
void registerFeature(QgsFeature& f);
51+
52+
// temporary stuff: set when layer gets prepared
53+
pal::Layer* palLayer;
54+
int fieldIndex;
55+
QFontMetrics* fontMetrics;
56+
int fontBaseline;
57+
const QgsMapToPixel* xform;
58+
QgsPoint ptZero;
59+
};
60+
1661
class PalLabeling
1762
{
1863
public:
1964
PalLabeling(QgsMapCanvas* mapCanvas);
20-
21-
enum Placement
22-
{
23-
AroundPoint, // Point / Polygon
24-
OnLine, // Line / Polygon
25-
AroundLine, // Line / Polygon
26-
Horizontal, // Polygon
27-
Free // Polygon
28-
};
29-
30-
struct LayerSettings
31-
{
32-
//LayerSettings()
33-
QString layerId;
34-
QString fieldName;
35-
Placement placement;
36-
QFont textFont;
37-
QColor textColor;
38-
bool enabled;
39-
int priority; // 0 = low, 10 = high
40-
bool obstacle; // whether it's an obstacle
41-
};
65+
~PalLabeling();
4266

4367
void doLabeling(QPainter* painter);
4468

@@ -56,14 +80,23 @@ class PalLabeling
5680
void setSearchMethod(Search s);
5781
Search searchMethod() const;
5882

83+
84+
//! hook called when drawing layer before issuing select()
85+
static int prepareLayerHook(void* context, void* layerContext, int& attrIndex);
86+
//! hook called when drawing for every feature in a layer
87+
static void registerFeatureHook(QgsFeature& f, void* layerContext);
88+
5989
protected:
60-
int prepareLayer(pal::Pal& pal, const LayerSettings& lyr);
90+
91+
void initPal();
6192

6293
protected:
6394
QList<LayerSettings> mLayers;
6495
QgsMapCanvas* mMapCanvas;
6596
int mCandPoint, mCandLine, mCandPolygon;
6697
Search mSearch;
98+
99+
pal::Pal* mPal;
67100
};
68101

69102
#endif // PALLABELING_H

0 commit comments

Comments
 (0)
Please sign in to comment.