~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/gui/qgslabel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
                         qgslabel.cpp - render vector labels
3
 
                             -------------------
4
 
    begin                : August 2004
5
 
    copyright            : (C) 2004 by Radim Blazek
6
 
    email                : blazek@itc.it
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
 
#include <iostream>
17
 
#include <fstream>
18
 
#include <math.h> //needed for win32 build (ts)
19
 
 
20
 
#include <QString>
21
 
#include <QFont>
22
 
#include <QFontMetrics>
23
 
 
24
 
#include <QPainter>
25
 
#include <QDomNode>
26
 
#include <QDomElement>
27
 
 
28
 
#include "qgis.h"
29
 
#include "qgsfeature.h"
30
 
#include "qgsfield.h"
31
 
#include "qgsrect.h"
32
 
#include "qgsmaptopixel.h"
33
 
#include "qgscoordinatetransform.h"
34
 
 
35
 
#include "qgslabelattributes.h"
36
 
#include "qgslabeldialog.h"
37
 
#include "qgslabel.h"
38
 
 
39
 
// use M_PI define PI 3.141592654
40
 
#ifdef WIN32
41
 
#undef M_PI
42
 
#define M_PI 4*atan(1.0)
43
 
#endif
44
 
 
45
 
static const char * const ident_ =
46
 
    "$Id: qgslabel.cpp 5686 2006-08-10 16:19:19Z rblazek $";
47
 
 
48
 
 
49
 
QgsLabel::QgsLabel( std::vector<QgsField> const & fields )
50
 
{
51
 
 
52
 
    mField = fields;
53
 
    mLabelField.resize ( LabelFieldCount );
54
 
    mLabelFieldIdx.resize ( LabelFieldCount );
55
 
    for ( int i = 0; i < LabelFieldCount; i++ )
56
 
    {
57
 
        mLabelField[i] = "";
58
 
        mLabelFieldIdx[i] = -1;
59
 
    }
60
 
    mLabelAttributes = new QgsLabelAttributes ( true );
61
 
}
62
 
 
63
 
QgsLabel::~QgsLabel()
64
 
{}
65
 
 
66
 
QString QgsLabel::fieldValue ( int attr, QgsFeature *feature )
67
 
{
68
 
    if ( mLabelField[attr].isEmpty() )
69
 
      {
70
 
        return QString();
71
 
      }
72
 
 
73
 
    std::vector<QgsFeatureAttribute> fields =  feature->attributeMap();
74
 
 
75
 
    for ( unsigned int i = 0; i < fields.size(); i++ )
76
 
    {
77
 
      if ( fields[i].fieldName().compare(mLabelField[attr]) == 0 )
78
 
        {
79
 
            return fields[i].fieldValue();
80
 
        }
81
 
    }
82
 
    return QString();
83
 
}
84
 
 
85
 
void QgsLabel::renderLabel( QPainter * painter, QgsRect *viewExtent,
86
 
                            const QgsCoordinateTransform& coordTransform,
87
 
                            bool doCoordTransform, QgsMapToPixel *transform,
88
 
                            QgsFeature *feature, bool selected, QgsLabelAttributes *classAttributes,
89
 
                            double sizeScale )
90
 
{
91
 
#if QGISDEBUG > 3
92
 
    std::cerr << "QgsLabel::renderLabel()" << std::endl;
93
 
#endif
94
 
 
95
 
    QPen pen;
96
 
    QFont font;
97
 
    QString value;
98
 
    QString text;
99
 
 
100
 
    /* Calc scale (not nice) */
101
 
    QgsPoint point;
102
 
    point = transform->transform ( 0, 0 );
103
 
    double x1 = point.x();
104
 
    point = transform->transform ( 1000, 0 );
105
 
    double x2 = point.x();
106
 
    double scale = (x2-x1)*0.001;
107
 
 
108
 
    /* Text */
109
 
    value = fieldValue ( Text, feature );
110
 
    if ( value.isEmpty() )
111
 
    {
112
 
        text = mLabelAttributes->text();
113
 
    }
114
 
    else
115
 
    {
116
 
        text = value;
117
 
    }
118
 
 
119
 
    /* Font */
120
 
    value = fieldValue ( Family, feature );
121
 
    if ( value.isEmpty() )
122
 
    {
123
 
        font.setFamily ( mLabelAttributes->family() );
124
 
    }
125
 
    else
126
 
    {
127
 
        font.setFamily ( value );
128
 
    }
129
 
 
130
 
    double size;
131
 
    value = fieldValue ( Size, feature );
132
 
    if ( value.isEmpty() )
133
 
    {
134
 
        size =  mLabelAttributes->size();
135
 
    }
136
 
    else
137
 
    {
138
 
        size =  value.toDouble();
139
 
    }
140
 
    if (  mLabelAttributes->sizeType() == QgsLabelAttributes::MapUnits )
141
 
    {
142
 
        size *= scale;
143
 
    } else {
144
 
        size *= sizeScale;
145
 
    }
146
 
    font.setPointSizeFloat ( size );
147
 
 
148
 
    value = fieldValue ( Color, feature );
149
 
    if ( value.isEmpty() )
150
 
    {
151
 
        pen.setColor ( mLabelAttributes->color() );
152
 
    }
153
 
    else
154
 
    {
155
 
        pen.setColor ( QColor(value) );
156
 
    }
157
 
 
158
 
    value = fieldValue ( Bold, feature );
159
 
    if ( value.isEmpty() )
160
 
    {
161
 
        font.setBold ( mLabelAttributes->bold() );
162
 
    }
163
 
    else
164
 
    {
165
 
        font.setBold ( (bool) value.toInt() );
166
 
    }
167
 
 
168
 
    value = fieldValue ( Italic, feature );
169
 
    if ( value.isEmpty() )
170
 
    {
171
 
        font.setItalic ( mLabelAttributes->italic() );
172
 
    }
173
 
    else
174
 
    {
175
 
        font.setItalic ( (bool) value.toInt() );
176
 
    }
177
 
 
178
 
    value = fieldValue ( Underline, feature );
179
 
    if ( value.isEmpty() )
180
 
    {
181
 
        font.setUnderline ( mLabelAttributes->underline() );
182
 
    }
183
 
    else
184
 
    {
185
 
        font.setUnderline ( (bool) value.toInt() );
186
 
    }
187
 
 
188
 
    // 
189
 
    QgsPoint overridePoint;
190
 
    bool useOverridePoint = false;
191
 
    value = fieldValue ( XCoordinate, feature );
192
 
    if ( !value.isEmpty() )
193
 
    {
194
 
        overridePoint.setX ( value.toDouble() );
195
 
        useOverridePoint = true;
196
 
    }
197
 
    value = fieldValue ( YCoordinate, feature );
198
 
    if ( !value.isEmpty() )
199
 
    {
200
 
        overridePoint.setY ( value.toDouble() );
201
 
        useOverridePoint = true;
202
 
    }
203
 
 
204
 
    /* Alignment */
205
 
    int alignment;
206
 
    QFontMetrics fm ( font );
207
 
    int width = fm.width ( text );
208
 
    int height = fm.height();
209
 
    int dx, dy;
210
 
 
211
 
    value = fieldValue ( Alignment, feature );
212
 
    if ( value.isEmpty() )
213
 
    {
214
 
        alignment = mLabelAttributes->alignment();
215
 
    }
216
 
    else
217
 
    {
218
 
        value = value.lower();
219
 
        alignment = Qt::AlignCenter;
220
 
        if ( value.compare("left") == 0 )
221
 
        {
222
 
            alignment = Qt::AlignLeft | Qt::AlignVCenter;
223
 
        }
224
 
        else if ( value.compare("right") == 0 )
225
 
        {
226
 
            alignment = Qt::AlignRight | Qt::AlignVCenter;
227
 
        }
228
 
        else if ( value.compare("bottom") == 0 )
229
 
        {
230
 
            alignment = Qt::AlignBottom | Qt::AlignHCenter;
231
 
        }
232
 
        else if ( value.compare("top") == 0 )
233
 
        {
234
 
            alignment = Qt::AlignTop | Qt::AlignHCenter;
235
 
        }
236
 
    }
237
 
 
238
 
    if ( alignment & Qt::AlignLeft )
239
 
    {
240
 
        dx = 0;
241
 
    }
242
 
    else if ( alignment & Qt::AlignHCenter )
243
 
    {
244
 
        dx = -width/2;
245
 
    }
246
 
    else if ( alignment & Qt::AlignRight )
247
 
    {
248
 
        dx = -width;
249
 
    }
250
 
 
251
 
    if ( alignment & Qt::AlignBottom )
252
 
    {
253
 
        dy = 0;
254
 
    }
255
 
    else if ( alignment & Qt::AlignVCenter )
256
 
    {
257
 
        dy = height/2;
258
 
    }
259
 
    else if ( alignment & Qt::AlignTop )
260
 
    {
261
 
        dy = height;
262
 
    }
263
 
 
264
 
    // Offset 
265
 
    double xoffset, yoffset;
266
 
    value = fieldValue ( XOffset, feature );
267
 
    if ( value.isEmpty() )
268
 
    {
269
 
        xoffset = mLabelAttributes->xOffset();
270
 
    }
271
 
    else
272
 
    {
273
 
        xoffset = value.toDouble();
274
 
    }
275
 
    value = fieldValue ( YOffset, feature );
276
 
    if ( value.isEmpty() )
277
 
    {
278
 
        yoffset = mLabelAttributes->yOffset();
279
 
    }
280
 
    else
281
 
    {
282
 
        yoffset = value.toDouble();
283
 
    }
284
 
 
285
 
    // recalc offset to points
286
 
    if (  mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits )
287
 
    {
288
 
        xoffset *= scale;
289
 
        yoffset *= scale;
290
 
    }
291
 
 
292
 
    // Angle 
293
 
    double ang;
294
 
    value = fieldValue ( Angle, feature );
295
 
    if ( value.isEmpty() )
296
 
    {
297
 
        ang = mLabelAttributes->angle();
298
 
    }
299
 
    else
300
 
    {
301
 
        ang = value.toDouble();
302
 
    }
303
 
 
304
 
 
305
 
    // Work out a suitable position to put the label for the
306
 
    // feature. For multi-geometries, put the same label on each
307
 
    // part.
308
 
    if (useOverridePoint)
309
 
    {
310
 
      renderLabel(painter, overridePoint, doCoordTransform, coordTransform, 
311
 
                  transform, text, font, pen, dx, dy,
312
 
                  xoffset, yoffset, ang);
313
 
    }
314
 
    else
315
 
    {
316
 
      std::vector<QgsPoint> points;
317
 
      labelPoint ( points, feature );
318
 
      for (int i = 0; i < points.size(); ++i)
319
 
      {
320
 
        renderLabel(painter, points[i], doCoordTransform, coordTransform, 
321
 
                    transform, text, font, pen, dx, dy,
322
 
                    xoffset, yoffset, ang);
323
 
      }
324
 
    }
325
 
}
326
 
 
327
 
void QgsLabel::renderLabel(QPainter* painter, QgsPoint point, 
328
 
                           bool doCoordTransform,
329
 
                           const QgsCoordinateTransform& coordTransform,
330
 
                           QgsMapToPixel* transform,
331
 
                           QString text, QFont font, QPen pen,
332
 
                           int dx, int dy, 
333
 
                           double xoffset, double yoffset, 
334
 
                           double ang)
335
 
{
336
 
    // Convert point to projected units
337
 
    if (doCoordTransform)
338
 
    {
339
 
      try
340
 
      {
341
 
        point = (const_cast<QgsCoordinateTransform&>(coordTransform)).transform(point);
342
 
      }
343
 
      catch(QgsCsException &cse)
344
 
      {
345
 
#ifdef QGISDEBUG
346
 
        std::cout << "Caught transform error in QgsLabel::renderLabel(). "
347
 
                  << "Skipping rendering this label" << std::endl;
348
 
#endif  
349
 
        return;
350
 
      }
351
 
    }
352
 
 
353
 
    // and then to canvas units
354
 
    transform->transform(&point);
355
 
    double x = point.x();
356
 
    double y = point.y();
357
 
 
358
 
    static const double rad = ang * M_PI/180;
359
 
 
360
 
    x = x + xoffset * cos(rad) - yoffset * sin(rad);
361
 
    y = y - xoffset * sin(rad) - yoffset * cos(rad);
362
 
 
363
 
    painter->save();
364
 
    painter->setFont ( font );
365
 
    painter->translate ( x, y );
366
 
    painter->rotate ( -ang );
367
 
    //
368
 
    // Draw a buffer behind the text if one is desired
369
 
    //
370
 
    if (mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled())
371
 
    {
372
 
        int myBufferSize = static_cast<int>(mLabelAttributes->bufferSize());
373
 
        if (mLabelAttributes->bufferColorIsSet())
374
 
        {
375
 
            painter->setPen( mLabelAttributes->bufferColor());
376
 
        }
377
 
        else //default to a white buffer
378
 
        {
379
 
            painter->setPen( Qt::white);
380
 
        }
381
 
        for (int i = dx-myBufferSize; i <= dx+myBufferSize; i++)
382
 
        {
383
 
            for (int j = dy-myBufferSize; j <= dy+myBufferSize; j++)
384
 
            {
385
 
                painter->drawText( i ,j, text);
386
 
            }
387
 
        }
388
 
    }
389
 
 
390
 
    painter->setPen ( pen );
391
 
    painter->drawText ( dx, dy, text );
392
 
    painter->restore();
393
 
}
394
 
 
395
 
void QgsLabel::addRequiredFields ( std::list<int> *fields )
396
 
{
397
 
    for ( int i = 0; i < LabelFieldCount; i++ )
398
 
    {
399
 
        if ( mLabelFieldIdx[i] == -1 )
400
 
            continue;
401
 
        bool found = false;
402
 
        for (std::list<int>::iterator it = fields->
403
 
                                           begin();
404
 
                it != fields->end();
405
 
                ++it)
406
 
        {
407
 
            if ( *it == mLabelFieldIdx[i] )
408
 
            {
409
 
                found = true;
410
 
                break;
411
 
            }
412
 
        }
413
 
        if (!found)
414
 
        {
415
 
            fields->push_back(mLabelFieldIdx[i])
416
 
            ;
417
 
        }
418
 
    }
419
 
}
420
 
 
421
 
void QgsLabel::setFields( std::vector<QgsField> const & fields  )
422
 
{
423
 
    mField = fields;
424
 
}
425
 
 
426
 
std::vector<QgsField> & QgsLabel::fields ( void )
427
 
{
428
 
    return mField;
429
 
}
430
 
 
431
 
void QgsLabel::setLabelField ( int attr, const QString str )
432
 
{
433
 
    if ( attr >= LabelFieldCount )
434
 
        return;
435
 
 
436
 
 
437
 
    mLabelField[attr] = str;
438
 
 
439
 
    mLabelFieldIdx[attr] = -1;
440
 
    for ( int i = 0; i < mField.size(); i++ )
441
 
    {
442
 
        if ( mField[i].name().compare(str) == 0 )
443
 
        {
444
 
            mLabelFieldIdx[attr] = i;
445
 
        }
446
 
    }
447
 
}
448
 
 
449
 
QString QgsLabel::labelField ( int attr )
450
 
{
451
 
    if ( attr > LabelFieldCount )
452
 
        return QString();
453
 
 
454
 
    return mLabelField[attr];
455
 
}
456
 
 
457
 
QgsLabelAttributes *QgsLabel::layerAttributes ( void )
458
 
{
459
 
    return mLabelAttributes;
460
 
}
461
 
 
462
 
void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature *feature )
463
 
{
464
 
  unsigned char *geom = feature->getGeometry();
465
 
  int wkbType;
466
 
  memcpy(&wkbType, (geom+1), sizeof(wkbType));
467
 
 
468
 
  QgsPoint point;
469
 
 
470
 
  switch (wkbType)
471
 
  {
472
 
  case QGis::WKBPoint:
473
 
  case QGis::WKBLineString:
474
 
  case QGis::WKBPolygon:
475
 
    {
476
 
      labelPoint(point, geom);
477
 
      points.push_back(point);
478
 
    }
479
 
    break;
480
 
  case QGis::WKBMultiPoint:
481
 
  case QGis::WKBMultiLineString:
482
 
  case QGis::WKBMultiPolygon:
483
 
    // Return a position for each individual in the multi-feature
484
 
    {
485
 
      int numFeatures = (int)(*(geom + 5));
486
 
      geom += 9; // now points to start of array of WKB's
487
 
      for (int i = 0; i < numFeatures; ++i)
488
 
      {
489
 
        geom = labelPoint(point, geom);
490
 
        points.push_back(point);
491
 
      }
492
 
    }
493
 
    break;
494
 
  default:
495
 
    std::cerr << "Unknown geometry type of " << wkbType << '\n';
496
 
  }
497
 
}
498
 
 
499
 
unsigned char* QgsLabel::labelPoint ( QgsPoint& point, unsigned char* geom)
500
 
{
501
 
    // Number of bytes that ints and doubles take in the WKB format.
502
 
    static const unsigned int sizeOfInt = 4;
503
 
    static const unsigned int sizeOfDouble = 8;
504
 
 
505
 
    int wkbType;
506
 
    double *x, *y;
507
 
    unsigned char *ptr;
508
 
    int *nPoints;
509
 
    // Upon return from this function, this variable will contain a
510
 
    // pointer to the first byte beyond the current feature.
511
 
    unsigned char *nextFeature = geom;
512
 
 
513
 
    memcpy(&wkbType, (geom+1), sizeof(wkbType));
514
 
 
515
 
    switch (wkbType)
516
 
    {
517
 
    case QGis::WKBPoint:
518
 
      {
519
 
        x = (double *) (geom + 5);
520
 
        y = (double *) (geom + 5 + sizeof(double));
521
 
        point.set(*x, *y);
522
 
        nextFeature += 1 + sizeOfInt + sizeOfDouble*2;
523
 
      }
524
 
      break;
525
 
 
526
 
    case QGis::WKBLineString: // Line center
527
 
      {
528
 
        double dx, dy, tl, l;
529
 
        ptr = geom + 5;
530
 
        nPoints = (int *)ptr;
531
 
        nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*2;
532
 
        ptr = geom + 1 + 2 * sizeof(int);
533
 
 
534
 
        tl = 0;
535
 
        for (int i = 1; i < *nPoints; i++)
536
 
        {
537
 
            dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
538
 
            dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
539
 
            tl += sqrt(dx*dx + dy*dy);
540
 
        }
541
 
        tl /= 2;
542
 
 
543
 
        l = 0;
544
 
        for (int i = 1; i < *nPoints; i++)
545
 
        {
546
 
            double dl;
547
 
 
548
 
            dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
549
 
            dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
550
 
            dl = sqrt(dx*dx + dy*dy);
551
 
 
552
 
            if ( l+dl > tl )
553
 
            {
554
 
                l = tl - l;
555
 
                double k = l/dl;
556
 
 
557
 
                point.setX ( ((double *)ptr)[2*i-2] +  k * dx  );
558
 
                point.setY ( ((double *)ptr)[2*i-1] + k * dy );
559
 
                break;
560
 
            }
561
 
            l += dl;
562
 
        }
563
 
      }
564
 
      break;
565
 
 
566
 
    case QGis::WKBPolygon:
567
 
      {
568
 
        double sx, sy;
569
 
        ptr = geom + 1 + 2 * sizeof(int); // set pointer to the first ring
570
 
        nPoints = (int *) ptr;
571
 
        ptr += 4;
572
 
        sx = sy = 0;
573
 
        for (int i = 0; i < *nPoints-1; i++)
574
 
        {
575
 
            sx += ((double *)ptr)[2*i];
576
 
            sy += ((double *)ptr)[2*i+1];
577
 
        }
578
 
        point.setX ( sx/(*nPoints-1) );
579
 
        point.setY ( sy/(*nPoints-1) );
580
 
        // Work out a pointer to the next feature after this one.
581
 
        int numRings = (int)(*(geom+1+sizeOfInt));
582
 
        unsigned char* nextRing = nextFeature + 1 + 2*sizeOfInt; 
583
 
        for (int i = 0; i < numRings; ++i)
584
 
        {
585
 
          int numPoints = (int)(*nextRing);
586
 
          // get the start of the next ring
587
 
          nextRing += sizeOfInt + numPoints*sizeOfDouble*2;
588
 
        }
589
 
        nextFeature = nextRing;
590
 
      }
591
 
      break;
592
 
 
593
 
    default:
594
 
      // To get here is a bug because our caller should be filtering
595
 
      // on wkb type.
596
 
      break;
597
 
    }
598
 
    return nextFeature;
599
 
}
600
 
 
601
 
void QgsLabel::readXML( const QDomNode& node )
602
 
{
603
 
#if QGISDEBUG
604
 
    std::cout << "QgsLabel::readXML() called for layer label properties \n" << std::endl;
605
 
#endif
606
 
 
607
 
    qDebug( "%s:%d QgsLabel::readXML() got node %s", __FILE__, __LINE__, (const char *)node.nodeName().toLocal8Bit().data() );
608
 
 
609
 
    QDomNode scratchNode;       // DOM node re-used to get current QgsLabel attribute
610
 
    QDomElement el;
611
 
    
612
 
    int red, green, blue;
613
 
    int type;
614
 
 
615
 
    /* Text */
616
 
    scratchNode = node.namedItem("label");
617
 
 
618
 
    if ( scratchNode.isNull() )
619
 
    {
620
 
        qDebug( "%s:%d couldn't find QgsLabel ``label'' attribute", __FILE__, __LINE__ );
621
 
    }
622
 
    else
623
 
    {
624
 
        el = scratchNode.toElement();
625
 
        mLabelAttributes->setText ( el.attribute("text","") );
626
 
        setLabelField ( Text, el.attribute("field","") );
627
 
    }
628
 
 
629
 
    /* Family */
630
 
    scratchNode = node.namedItem("family");
631
 
 
632
 
    if ( scratchNode.isNull() )
633
 
    {
634
 
        qDebug( "%s:%d couldn't find QgsLabel ``family'' attribute", __FILE__, __LINE__  );
635
 
    }
636
 
    else
637
 
    {
638
 
        el = scratchNode.toElement();
639
 
        mLabelAttributes->setFamily ( el.attribute("name","") );
640
 
        setLabelField ( Family, el.attribute("field","") );
641
 
    }
642
 
 
643
 
    /* Size */
644
 
    scratchNode = node.namedItem("size");
645
 
 
646
 
    if ( scratchNode.isNull() )
647
 
    {
648
 
        qDebug( "%s:%d couldn't find QgsLabel ``size'' attribute", __FILE__, __LINE__  );
649
 
    }
650
 
    else
651
 
    {
652
 
        el = scratchNode.toElement();
653
 
        type = QgsLabelAttributes::unitsCode( el.attribute("units","") );
654
 
        mLabelAttributes->setSize ( el.attribute("value", "0.0").toDouble(), type );
655
 
        setLabelField ( Size, el.attribute("field","") );
656
 
    }
657
 
 
658
 
    /* Bold */
659
 
    scratchNode = node.namedItem("bold");
660
 
 
661
 
    if ( scratchNode.isNull() )
662
 
    {
663
 
        qDebug( "%s:%d couldn't find QgsLabel ``bold'' attribute", __FILE__, __LINE__  );
664
 
    }
665
 
    else
666
 
    {
667
 
        el = scratchNode.toElement();
668
 
        mLabelAttributes->setBold ( (bool)el.attribute("on","0").toInt() );
669
 
        setLabelField ( Bold, el.attribute("field","") );
670
 
    }
671
 
 
672
 
    /* Italic */
673
 
    scratchNode = node.namedItem("italic");
674
 
 
675
 
    if ( scratchNode.isNull() )
676
 
    {
677
 
        qDebug( "%s:%d couldn't find QgsLabel ``italic'' attribute", __FILE__, __LINE__  );
678
 
    }
679
 
    else
680
 
    {
681
 
        el = scratchNode.toElement();
682
 
        mLabelAttributes->setItalic ( (bool)el.attribute("on","0").toInt() );
683
 
        setLabelField ( Italic, el.attribute("field","") );
684
 
    }
685
 
 
686
 
    /* Underline */
687
 
    scratchNode = node.namedItem("underline");
688
 
 
689
 
    if ( scratchNode.isNull() )
690
 
    {
691
 
        qDebug( "%s:%d couldn't find QgsLabel ``underline'' attribute", __FILE__, __LINE__  );
692
 
    }
693
 
    else
694
 
    {
695
 
        el = scratchNode.toElement();
696
 
        mLabelAttributes->setUnderline ( (bool)el.attribute("on","0").toInt() );
697
 
        setLabelField ( Underline, el.attribute("field","") );
698
 
    }
699
 
 
700
 
    /* Color */
701
 
    scratchNode = node.namedItem("color");
702
 
 
703
 
    if ( scratchNode.isNull() )
704
 
    {
705
 
        qDebug( "%s:%d couldn't find QgsLabel ``color'' attribute", __FILE__, __LINE__  );
706
 
    }
707
 
    else
708
 
    {
709
 
        el = scratchNode.toElement();
710
 
 
711
 
        red = el.attribute("red","0").toInt();
712
 
        green = el.attribute("green","0").toInt();
713
 
        blue = el.attribute("blue","0").toInt();
714
 
 
715
 
        mLabelAttributes->setColor( QColor(red, green, blue) );
716
 
 
717
 
        setLabelField ( Color, el.attribute("field","") );
718
 
    }
719
 
 
720
 
    /* X */
721
 
    scratchNode = node.namedItem("x");
722
 
 
723
 
    if ( scratchNode.isNull() )
724
 
    {
725
 
        qDebug( "%s:%d couldn't find QgsLabel ``x'' attribute", __FILE__, __LINE__  );
726
 
    }
727
 
    else
728
 
    {
729
 
        el = scratchNode.toElement();
730
 
        setLabelField ( XCoordinate, el.attribute("field","") );
731
 
    }
732
 
 
733
 
    /* Y */
734
 
    scratchNode = node.namedItem("y");
735
 
 
736
 
    if ( scratchNode.isNull() )
737
 
    {
738
 
        qDebug( "%s:%d couldn't find QgsLabel ``y'' attribute", __FILE__, __LINE__  );
739
 
    }
740
 
    else
741
 
    {
742
 
        el = scratchNode.toElement();
743
 
        setLabelField ( YCoordinate, el.attribute("field","") );
744
 
    }
745
 
 
746
 
 
747
 
    /* X,Y offset */
748
 
    scratchNode = node.namedItem("offset");
749
 
 
750
 
    if ( scratchNode.isNull() )
751
 
    {
752
 
        qDebug( "%s:%d couldn't find QgsLabel ``offset'' attribute", __FILE__, __LINE__  );
753
 
    }
754
 
    else
755
 
    {
756
 
        double xoffset, yoffset;
757
 
 
758
 
        el = scratchNode.toElement();
759
 
 
760
 
        type = QgsLabelAttributes::unitsCode( el.attribute("units","") );
761
 
        xoffset = el.attribute("x","0.0").toDouble();
762
 
        yoffset = el.attribute("y","0.0").toDouble();
763
 
 
764
 
        mLabelAttributes->setOffset ( xoffset, yoffset, type );
765
 
        setLabelField ( XOffset, el.attribute("xfield","0") );
766
 
        setLabelField ( YOffset, el.attribute("yfield","0") );
767
 
    }
768
 
 
769
 
    /* Angle */
770
 
    scratchNode = node.namedItem("angle");
771
 
 
772
 
    if ( scratchNode.isNull() )
773
 
    {
774
 
        qDebug( "%s:%d couldn't find QgsLabel ``angle'' attribute", __FILE__, __LINE__  );
775
 
    }
776
 
    else
777
 
    {
778
 
        el = scratchNode.toElement();
779
 
        mLabelAttributes->setAngle ( el.attribute("value","0.0").toDouble() );
780
 
        setLabelField ( Angle, el.attribute("field","0.0") );
781
 
    }
782
 
 
783
 
    /* Alignment */
784
 
    scratchNode = node.namedItem("alignment");
785
 
 
786
 
    if ( scratchNode.isNull() )
787
 
    {
788
 
        qDebug( "%s:%d couldn't find QgsLabel ``alignment'' attribute", __FILE__, __LINE__  );
789
 
    }
790
 
    else
791
 
    {
792
 
        el = scratchNode.toElement();
793
 
        mLabelAttributes->setAlignment ( QgsLabelAttributes::alignmentCode(el.attribute("value","")) );
794
 
        setLabelField ( Alignment, el.attribute("field","") );
795
 
    }
796
 
 
797
 
 
798
 
    // Buffer
799
 
    scratchNode = node.namedItem("buffercolor");
800
 
 
801
 
    if ( scratchNode.isNull() )
802
 
    {
803
 
        qDebug( "%s:%d couldn't find QgsLabel ``buffercolor'' attribute", __FILE__, __LINE__  );
804
 
    }
805
 
    else
806
 
    {
807
 
        el = scratchNode.toElement();
808
 
 
809
 
        red = el.attribute("red","0").toInt();
810
 
        green = el.attribute("green","0").toInt();
811
 
        blue = el.attribute("blue","0").toInt();
812
 
 
813
 
        mLabelAttributes->setBufferColor( QColor(red, green, blue) );
814
 
        setLabelField ( BufferColor, el.attribute("field","") );
815
 
    }
816
 
 
817
 
    scratchNode = node.namedItem("buffersize");
818
 
 
819
 
    if ( scratchNode.isNull() )
820
 
    {
821
 
        qDebug( "%s:%d couldn't find QgsLabel ``buffersize'' attribute", __FILE__, __LINE__  );
822
 
    }
823
 
    else
824
 
    {
825
 
        el = scratchNode.toElement();
826
 
 
827
 
        type = QgsLabelAttributes::unitsCode( el.attribute("units","") );
828
 
        mLabelAttributes->setBufferSize ( el.attribute("value","0.0").toDouble(), type );
829
 
        setLabelField ( BufferSize, el.attribute("field","") );
830
 
    }
831
 
 
832
 
    scratchNode = node.namedItem("bufferenabled");
833
 
 
834
 
    if ( scratchNode.isNull() )
835
 
    {
836
 
        qDebug( "%s:%d couldn't find QgsLabel ``bufferenabled'' attribute", __FILE__, __LINE__  );
837
 
    }
838
 
    else
839
 
    {
840
 
        el = scratchNode.toElement();
841
 
 
842
 
        mLabelAttributes->setBufferEnabled ( (bool)el.attribute("on","0").toInt() );
843
 
        setLabelField ( BufferEnabled, el.attribute("field","") );
844
 
    }
845
 
 
846
 
} // QgsLabel::readXML()
847
 
 
848
 
 
849
 
 
850
 
void QgsLabel::writeXML(std::ostream& xml)
851
 
{
852
 
 
853
 
    xml << "\t\t<labelattributes>\n";
854
 
 
855
 
    // else
856
 
    if ( mLabelAttributes->textIsSet() && !mLabelField[Text].isEmpty() )
857
 
    {
858
 
        xml << "\t\t\t<label text=\"" << (const char*)(mLabelAttributes->text().utf8()) << "\" field=\"" << (const char*)(mLabelField[Text].utf8()) << "\" />\n";
859
 
    }
860
 
    else if ( mLabelAttributes->textIsSet() )
861
 
    {
862
 
        xml << "\t\t\t<label text=\"" << (const char*)(mLabelAttributes->text().utf8()) << "\" field=\"\" />\n";
863
 
    }
864
 
    else
865
 
    {
866
 
        xml << "\t\t\t<label text=\"" << (const char*)(mLabelAttributes->text().utf8()) << "\" field=\"" << (const char*)(mLabelField[Text].utf8()) << "\" />\n";
867
 
    }
868
 
 
869
 
    if ( mLabelAttributes->familyIsSet() && ! mLabelAttributes->family().isNull() && mLabelField[Family].isNull())
870
 
    {
871
 
        xml << "\t\t\t<family name=\"" << mLabelAttributes->family().utf8().data() << "\" field=\"" << (const char*)(mLabelField[Family].utf8().data()) << "\" />\n";
872
 
    }
873
 
    else if ( mLabelAttributes->familyIsSet() && ! mLabelAttributes->family().isNull() )
874
 
    {
875
 
        xml << "\t\t\t<family name=\"" << mLabelAttributes->family().utf8().data() << "\" field=\"\" />\n";
876
 
    }
877
 
    else
878
 
    {
879
 
        xml << "\t\t\t<family name=\"Arial\" field=\"\" />\n";
880
 
    }
881
 
 
882
 
    //size and units
883
 
    if ( mLabelAttributes->sizeIsSet() && !mLabelField[Size].isEmpty())
884
 
    {
885
 
        xml << "\t\t\t<size value=\"" << mLabelAttributes->size() << "\" units=\""
886
 
            << (const char *)QgsLabelAttributes::unitsName(mLabelAttributes->sizeType()).utf8() << "\" field=\"" << (const char*)(mLabelField[Size].utf8()) << "\" />\n";
887
 
    }
888
 
    else if ( mLabelAttributes->sizeIsSet() )
889
 
    {
890
 
        xml << "\t\t\t<size value=\"" << mLabelAttributes->size() << "\" units=\""
891
 
            << (const char *)QgsLabelAttributes::unitsName(mLabelAttributes->sizeType()).utf8() << "\" field=\"\" />\n";
892
 
    }
893
 
    else
894
 
    {
895
 
        xml << "\t\t\t<size value=\"12\" units=\"Points\" field=\"\" />\n";
896
 
    }
897
 
 
898
 
 
899
 
 
900
 
    //bold
901
 
    if ( mLabelAttributes->boldIsSet() && !mLabelField[Bold].isEmpty() )
902
 
    {
903
 
        xml << "\t\t\t<bold on=\"" << mLabelAttributes->bold() << "\" field=\"" << (const char*)(mLabelField[Bold].utf8()) << "\" />\n";
904
 
    }
905
 
    else if ( mLabelAttributes->boldIsSet() )
906
 
    {
907
 
        xml << "\t\t\t<bold on=\"" << mLabelAttributes->bold() << "\" field=\"\" />\n";
908
 
    }
909
 
    else
910
 
    {
911
 
        xml << "\t\t\t<bold on=\"0\" field=\"0\" />\n";
912
 
    }
913
 
 
914
 
    //italics
915
 
    if ( mLabelAttributes->italicIsSet() && ! mLabelField[Italic].isEmpty())
916
 
    {
917
 
        xml << "\t\t\t<italic on=\"" << mLabelAttributes->italic() << "\" field=\"" << (const char*)(mLabelField[Italic].utf8()) << "\" />\n";
918
 
    }
919
 
    else if ( mLabelAttributes->italicIsSet() )
920
 
    {
921
 
        xml << "\t\t\t<italic on=\"" << mLabelAttributes->italic() << "\" field=\"\" />\n";
922
 
    }
923
 
    else
924
 
    {
925
 
        xml << "\t\t\t<italic on=\"0\" field=\"\" />\n";
926
 
    }
927
 
    //underline
928
 
    if ( mLabelAttributes->underlineIsSet() && !mLabelField[Underline].isEmpty())
929
 
    {
930
 
        xml << "\t\t\t<underline on=\"" << mLabelAttributes->underline() << "\" field=\"" << (const char*)(mLabelField[Underline].utf8()) << "\" />\n";
931
 
    }
932
 
    else if ( mLabelAttributes->underlineIsSet() )
933
 
    {
934
 
        xml << "\t\t\t<underline on=\"" << mLabelAttributes->underline() << "\" field=\"\" />\n";
935
 
    }
936
 
    else
937
 
    {
938
 
        xml << "\t\t\t<underline on=\"0\" field=\"\" />\n";
939
 
    }
940
 
 
941
 
    if ( mLabelAttributes->colorIsSet() && ! mLabelField[Color].isNull() )
942
 
    {
943
 
        xml << "\t\t\t<color red=\"" << mLabelAttributes->color().red() << "\" green=\"" << mLabelAttributes->color().green()
944
 
            << "\" blue=\"" << mLabelAttributes->color().blue() << "\" field=\"" << (const char*)(mLabelField[Color].utf8()) << "\" />\n";
945
 
    }
946
 
    else if ( mLabelAttributes->colorIsSet() )
947
 
    {
948
 
        xml << "\t\t\t<color red=\"" << mLabelAttributes->color().red() << "\" green=\"" << mLabelAttributes->color().green()
949
 
            << "\" blue=\"" << mLabelAttributes->color().blue() << "\" field=\"\" />\n";
950
 
    }
951
 
    else
952
 
    {
953
 
        xml << "\t\t\t<color red=\"0\" green=\"0\" blue=\"0\" field=\"\" />\n";
954
 
    }
955
 
 
956
 
 
957
 
    /* X */
958
 
    if (! mLabelField[XCoordinate].isEmpty() )
959
 
    {
960
 
      xml << "\t\t\t<x field=\"" << (const char*)(mLabelField[XCoordinate].utf8()) << "\" />\n";
961
 
    }
962
 
    else
963
 
    {
964
 
     xml << "\t\t\t<x field=\"" << "\" />\n";
965
 
    }
966
 
 
967
 
    /* Y */
968
 
    if (! mLabelField[YCoordinate].isEmpty() )
969
 
    {
970
 
      xml << "\t\t\t<y field=\"" << (const char*)(mLabelField[YCoordinate].utf8()) << "\" />\n";
971
 
    }
972
 
    else
973
 
    {
974
 
     xml << "\t\t\t<y field=\"" << "\" />\n";
975
 
    }
976
 
 
977
 
    // offset
978
 
    if ( mLabelAttributes->offsetIsSet() )
979
 
    {
980
 
            xml << "\t\t\t<offset  units=\"" << QgsLabelAttributes::unitsName(mLabelAttributes->offsetType()).utf8().data()
981
 
            << "\" x=\"" << mLabelAttributes->xOffset() << "\" xfield=\"" << (const char*)(mLabelField[XOffset].utf8().data())
982
 
            << "\" y=\"" << mLabelAttributes->yOffset() << "\" yfield=\"" << (const char*)(mLabelField[YOffset].utf8().data())
983
 
            << "\" />\n";
984
 
    }
985
 
 
986
 
    // Angle
987
 
    if ( mLabelAttributes->angleIsSet() )
988
 
    {
989
 
        xml << "\t\t\t<angle value=\"" << mLabelAttributes->angle() << "\" field=\"" << (const char*)(mLabelField[Angle].utf8()) << "\" />\n";
990
 
    }
991
 
    else if ( mLabelAttributes->angleIsSet() )
992
 
    {
993
 
        xml << "\t\t\t<angle value=\"" << mLabelAttributes->angle() << "\" field=\"" << "\" />\n";
994
 
    }
995
 
    else
996
 
    {
997
 
        xml << "\t\t\t<angle value=\"" << "\" field=\"" << "\" />\n";
998
 
    }
999
 
 
1000
 
    // alignment
1001
 
    if ( mLabelAttributes->alignmentIsSet() )
1002
 
    {
1003
 
      xml << "\t\t\t<alignment value=\"" << QgsLabelAttributes::alignmentName(mLabelAttributes->alignment()).utf8().data()
1004
 
            << "\" field=\"" << (const char*)(mLabelField[Alignment].utf8().data()) << "\" />\n";
1005
 
    }
1006
 
 
1007
 
 
1008
 
    if ( mLabelAttributes->bufferColorIsSet() && ! mLabelField[BufferColor].isNull() )
1009
 
    {
1010
 
        xml << "\t\t\t<buffercolor red=\"" << mLabelAttributes->bufferColor().red() << "\" green=\"" << mLabelAttributes->bufferColor().green()
1011
 
            << "\" blue=\"" << mLabelAttributes->bufferColor().blue() << "\" field=\"" << (const char*)(mLabelField[BufferColor].utf8()) << "\" />\n";
1012
 
    }
1013
 
    else if ( mLabelAttributes->bufferColorIsSet() )
1014
 
    {
1015
 
        xml << "\t\t\t<buffercolor red=\"" << mLabelAttributes->bufferColor().red() << "\" green=\"" << mLabelAttributes->bufferColor().green()
1016
 
            << "\" blue=\"" << mLabelAttributes->bufferColor().blue() << "\" field=\"" <<  "\" />\n";
1017
 
    }
1018
 
    else
1019
 
    {
1020
 
        xml << "\t\t\t<buffercolor red=\""  << "\" green=\""
1021
 
            << "\" blue=\""  << "\" field=\"" <<  "\" />\n";
1022
 
    }
1023
 
 
1024
 
 
1025
 
    if ( mLabelAttributes->bufferSizeIsSet() && ! mLabelField[BufferSize].isNull() )
1026
 
    {
1027
 
        xml << "\t\t\t<buffersize value=\"" << mLabelAttributes->bufferSize() << "\" units=\""
1028
 
            << (const char *)QgsLabelAttributes::unitsName(mLabelAttributes->bufferSizeType()).utf8() << "\" field=\"" << (const char*)(mLabelField[BufferSize].utf8()) << "\" />\n";
1029
 
    }
1030
 
    else if ( mLabelAttributes->bufferSizeIsSet() )
1031
 
    {
1032
 
        xml << "\t\t\t<buffersize value=\"" << mLabelAttributes->bufferSize() << "\" units=\""
1033
 
            << (const char *)QgsLabelAttributes::unitsName(mLabelAttributes->bufferSizeType()).utf8() << "\" field=\"" << "\" />\n";
1034
 
    }
1035
 
    else
1036
 
    {
1037
 
        xml << "\t\t\t<buffersize value=\"" << "\" units=\""
1038
 
            <<  "\" field=\"" <<  "\" />\n";
1039
 
    }
1040
 
 
1041
 
 
1042
 
    if ( mLabelAttributes->bufferEnabled() && ! mLabelField[BufferEnabled].isNull() )
1043
 
    {
1044
 
        xml << "\t\t\t<bufferenabled on=\"" << mLabelAttributes->bufferEnabled() << "\" field=\"" << (const char*)(mLabelField[BufferEnabled].utf8()) << "\" />\n";
1045
 
    }
1046
 
    else if ( mLabelAttributes->bufferEnabled())
1047
 
    {
1048
 
        xml << "\t\t\t<bufferenabled on=\"" << mLabelAttributes->bufferEnabled() << "\" field=\"" << "\" />\n";
1049
 
    }
1050
 
    else
1051
 
    {
1052
 
        xml << "\t\t\t<bufferenabled on=\"" << "\" field=\"" << "\" />\n";
1053
 
    }
1054
 
    xml << "\t\t</labelattributes>\n";
1055
 
}
1056