~ubuntu-branches/ubuntu/quantal/qgis/quantal

« back to all changes in this revision

Viewing changes to src/gui/qgslabel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): William Grant
  • Date: 2007-05-06 13:42:32 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070506134232-pyli6t388w5asd8x
Tags: 0.8.0-3ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
  - debian/rules, debian/qgis.install, debian/qgis.dirs debian/qgis.desktop:
    Add and install .desktop.
* debian/qgis.desktop: Remove Applications category; it's not real.
* Modify Maintainer value to match Debian-Maintainer-Field Spec

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