Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / symbol / line / impl / PictureLineSymbol.java @ 47790

History | View | Annotate | Download (22.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.impl;
25

    
26
import java.awt.BasicStroke;
27
import java.awt.Color;
28
import java.awt.Dimension;
29
import java.awt.Graphics2D;
30
import java.awt.Point;
31
import java.awt.Rectangle;
32
import java.awt.Shape;
33
import java.awt.geom.AffineTransform;
34
import java.awt.geom.PathIterator;
35
import java.awt.geom.Point2D;
36
import java.io.IOException;
37
import java.net.URL;
38
import org.apache.batik.ext.awt.geom.DefaultPathLength;
39
import org.apache.commons.lang3.StringUtils;
40
import org.gvsig.compat.print.PrintAttributes;
41
import org.gvsig.expressionevaluator.ExpressionUtils;
42
import org.gvsig.expressionevaluator.SymbolTable;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.exception.DataException;
45
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
46
import org.gvsig.fmap.dal.feature.Feature;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureStore;
49
import org.gvsig.fmap.dal.feature.FeatureType;
50
import org.gvsig.fmap.geom.Geometry;
51
import org.gvsig.fmap.mapcontext.MapContextLocator;
52
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
53
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
54
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolDrawingException;
55
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
56
import org.gvsig.i18n.Messages;
57
import org.gvsig.symbology.PathLength;
58
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.line.IPictureLineSymbol;
59
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.BackgroundFileStyle;
60
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.style.IMask;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dynobject.DynStruct;
63
import org.gvsig.tools.persistence.PersistenceManager;
64
import org.gvsig.tools.persistence.PersistentState;
65
import org.gvsig.tools.persistence.exception.PersistenceException;
66
import org.gvsig.tools.task.Cancellable;
67
import org.gvsig.tools.util.Callable;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70

    
71

    
72
/**
73
 * PictureLineSymbol allows to use any symbol defined as an image (by an image file)
74
 * supported  by gvSIG.This symbol will be used as an initial object.The line will be
75
 * painted as a succession of puntual symbols through the path defined by it(the line).
76
 */
77
public class PictureLineSymbol extends AbstractLineSymbol implements IPictureLineSymbol  {
78

    
79
        private static final Logger logger = LoggerFactory.getLogger(PictureLineSymbol.class);
80

    
81
    public static final String PICTURE_LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME =
82
        "PictureLineSymbol";
83
    private static final String SELECTED = "selected";
84
    private static final String SELECTION_SYMBOL = "selectionSym";
85
    private static final String BACKGROUND_IMAGE = "bgImage";
86
    private static final String BACKGROUND_SELECTION_IMAGE = "bgSelImage";
87
    private static final String WIDTH = "width";
88
    private static final String FIELD_SIZE_EXPRESSION = "sizeExpression";
89

    
90

    
91
        transient private PictureLineSymbol selectionSym;
92
        private double width;
93
        private boolean selected;
94

    
95
        private BackgroundFileStyle bgImage;
96
        private BackgroundFileStyle bgSelImage;
97
        private PrintAttributes properties;
98
        
99
        private double rotation;
100
        private Point2D offset = new Point2D.Double();
101
        private IMask mask;
102

    
103
        private Color lineToOffsetColor;
104
        private boolean drawLineToOffset;
105

    
106
        private String sizeExpression;
107
        private String offsetXExpression;
108
        private String offsetYExpression;
109
        private String rotationExpression;
110
        private String lineToOffsetColorExpression;
111
        
112

    
113
        /**
114
         * Constructor method
115
         *
116
         */
117
        public PictureLineSymbol() {
118
                super();
119
        }
120
        /**
121
         * Constructor method
122
         * @param imageURL, URL of the normal image
123
         * @param selImageURL, URL of the image when it is selected in the map
124
         * @throws IOException
125
         */
126
        public PictureLineSymbol(URL imageURL, URL selImageURL) throws IOException {
127
            setImage(imageURL);
128
            if (selImageURL != null) {
129
                setSelImage(selImageURL);
130
            } else {
131
                setSelImage(imageURL);
132
            }
133
        }
134
        
135
        /**
136
         * Sets the URL for the image to be used as a picture line symbol
137
         * @param imageFile, File
138
         * @throws IOException
139
         */
140
        @Override
141
        public void setImage(URL imageUrl) throws IOException{
142

    
143
                bgImage= BackgroundFileStyle.createStyleByURL(imageUrl);
144
        }
145
        /**
146
         * Sets the URL for the image to be used as a picture line symbol (when it is selected in the map)
147
         * @param imageFile, File
148
         * @throws IOException
149
         */
150
        @Override
151
        public void setSelImage(URL selImageUrl) throws IOException{
152
            bgSelImage= BackgroundFileStyle.createStyleByURL(selImageUrl);
153
        }
154

    
155

    
156
        @Override
157
        public void setLineWidth(double width) {
158
                this.width = width;
159
                getLineStyle().setLineWidth((float) width);
160
        }
161

    
162
        @Override
163
        public double getLineWidth() {
164
                return width;
165
        }
166

    
167
        @Override
168
        public ISymbol getSymbolForSelection(Color selectionColor) {
169
                if (selectionSym == null) {
170
                        selectionSym = (PictureLineSymbol) cloneForSelection(selectionColor);
171
                        selectionSym.selected=true;
172
                        selectionSym.selectionSym = selectionSym; // avoid too much lazy creations
173
                }else{
174
                    selectionSym.setColor(selectionColor);
175
                }
176
                if (selectionSym instanceof CartographicSupport) {
177
                    ((CartographicSupport) selectionSym).setUnit(this.getUnit());
178
                }
179
                return selectionSym;
180

    
181
        }
182

    
183
    @Override
184
    public void draw(Graphics2D g, AffineTransform affineTransform, Geometry geom, Feature f, Cancellable cancel, Rectangle r) {
185

    
186
        if(r != null){
187
            geom = getSampleGeometry(r);
188
        }
189

    
190
        double effectiveSize = getEfectiveSize(f);
191
        double scale = getScale(effectiveSize);
192
        if (scale <= 0 ) {
193
            return;
194
        }
195
        
196
        Shape geom_transf_clip = geom.getShape(affineTransform);
197

    
198
        BackgroundFileStyle bg = (!selected) ? bgImage : bgSelImage;
199

    
200
        Rectangle bounds = bg.getBounds();
201
        final double imageHeight = effectiveSize; //getCartographicSize(); //toCartographicUnits(getSize());
202
        final double imageWidth = bounds.getWidth() * scale;
203

    
204
        if (imageWidth <= 0 || imageHeight <= 0) {
205
            return;
206
        }
207
        int height = (int) imageHeight; //csWidth;
208
        float csWidth = height; //(float) toCartographicUnits(getLineStyle().getLineWidth());
209

    
210
        BasicStroke bs = new BasicStroke(
211
                (float) csWidth,
212
                BasicStroke.CAP_ROUND,
213
                BasicStroke.CAP_ROUND);
214

    
215
        g.setClip(bs.createStrokedShape(geom_transf_clip));
216

    
217
        PathLength pl = new DefaultPathLength(geom_transf_clip);
218
        PathIterator iterator = geom_transf_clip.getPathIterator(null, 0.8);
219
        double[] theData = new double[6];
220
        Point2D firstPoint = null, startPoint = null, endPoint = null;
221
        if (!iterator.isDone()) {
222
            if (iterator.currentSegment(theData) != PathIterator.SEG_CLOSE) {
223
                firstPoint = new Point2D.Double(theData[0], theData[1]);
224
            }
225
        }
226
        float currentPathLength = 1;
227

    
228
        Rectangle rect = new Rectangle();
229

    
230
        while ((cancel == null || !cancel.isCanceled()) && !iterator.isDone()) {
231

    
232
            int theType = iterator.currentSegment(theData);
233
            switch (theType) {
234
                case PathIterator.SEG_MOVETO:
235
                    startPoint = new Point2D.Double(theData[0], theData[1]);
236

    
237
                    endPoint = null;
238
                    iterator.next();
239

    
240
                    continue;
241

    
242
                case PathIterator.SEG_LINETO:
243
                case PathIterator.SEG_QUADTO:
244
                case PathIterator.SEG_CUBICTO:
245
                    endPoint = new Point2D.Double(theData[0], theData[1]);
246

    
247
                    break;
248
                case PathIterator.SEG_CLOSE:
249
                    endPoint = startPoint;
250
                    startPoint = firstPoint;
251
                    break;
252
            }
253

    
254
            double a = endPoint.getX() - startPoint.getX();
255
            double b = endPoint.getY() - startPoint.getY();
256
            double theta = pl.angleAtLength(currentPathLength);
257
            if(this.getEfectiveRotationInRadians(f) != 0.0){
258
                theta += this.getEfectiveRotationInRadians(f);
259
            }
260

    
261
            double x = startPoint.getX();
262
            double y = startPoint.getY();
263

    
264
            // Theorem of Pythagoras
265
            float segmentLength = (float) Math.sqrt(a * a + b * b);
266

    
267
            // compute how many times the image has to be drawn
268
            // to completely cover this segment's length
269
            int count = (int) Math.ceil(segmentLength / imageWidth);
270

    
271
            for (int i = 0; (cancel == null || !cancel.isCanceled()) && i < count; i++) {
272
                g.translate(x, y);
273
                g.rotate(theta);
274

    
275
                double xOffsetTranslation = imageWidth * i;
276
                g.translate(xOffsetTranslation, -csWidth);
277

    
278
                rect.setBounds(0, (int) Math.round(height * .5), (int) Math.ceil(imageWidth), height);
279
                Dimension rectSize = rect.getSize();
280
                if(rectSize.getHeight() > 0 && rectSize.getWidth() > 0) {
281
                    try {
282
                        bg.drawInsideRectangle(g, rect, false);
283
                    } catch (SymbolDrawingException e) {
284
                        logger.warn(Messages.getText("label_style_could_not_be_painted"), e);
285
                    }
286
                }
287
                g.translate(-xOffsetTranslation, csWidth);
288

    
289
                g.rotate(-theta);
290
                g.translate(-x, -y);
291
            }
292

    
293
            startPoint = endPoint;
294
            currentPathLength += segmentLength;
295
            iterator.next();
296
        }
297
        g.setClip(null);
298
    }
299
    
300
    protected double getAdjustedSize(Rectangle r, double size) {
301
        if (r == null) {
302
            return size;
303
        }
304
        double min = Math.min(r.getHeight(), r.getWidth());
305
        if (size > min) {
306
            size = min;
307
        }
308
        return size;
309
    }
310

    
311
        public String getClassName() {
312
                return getClass().getName();
313
        }
314

    
315
        /**
316
         * Returns the URL of the image that is used as a picture line symbol (when it
317
         * is selected in the map)
318
         * @return selimagePath,URL
319
         */
320
        @Override
321
        public URL getSelectedSource(){
322
                return bgSelImage.getSource();
323
        }
324
        /**
325
         * Returns the URL of the image that is used as a picture line symbol
326
         * @return imagePath,URL
327
         */
328
        @Override
329
        public URL getSource() {
330
                return bgImage.getSource();
331
        }
332

    
333
        /**
334
         * Returns the yscale for the picture line symbol
335
         * @param yScale
336
         */
337
        private double getScale(double size) {
338
            BackgroundFileStyle image;
339
            if(selected){
340
                image = bgSelImage;
341
            } else {
342
                image = bgImage;
343
            }
344
            return size/image.getBounds().getHeight();
345
        }
346

    
347
        @Override
348
    public Object clone() throws CloneNotSupportedException {
349
        PictureLineSymbol copy = (PictureLineSymbol) super.clone();
350

    
351
        // clone selection
352
        if (selectionSym != null) {
353
                //to avoid an infinite loop
354
                if (this == selectionSym){
355
                        copy.selectionSym = copy;
356
                } else {
357
                        copy.selectionSym = (PictureLineSymbol) selectionSym.clone();
358
                }
359
        }
360

    
361
        // clone brackground image
362
        if (bgImage != null) {
363
            copy.bgImage = (BackgroundFileStyle) bgImage.clone();
364
        }
365

    
366
        // clone selection brackground image
367
        if (bgSelImage != null) {
368
            copy.bgSelImage = (BackgroundFileStyle) bgSelImage.clone();
369
        }
370

    
371
        // FIXME: clone properties
372

    
373
        return copy;
374
    }
375

    
376
        @Override
377
    public void loadFromState(PersistentState state) throws PersistenceException {
378
        // Set parent style properties
379
        super.loadFromState(state);
380

    
381
        this.selected = (Boolean) state.get(SELECTED);
382
        this.selectionSym = (PictureLineSymbol) state.get(SELECTION_SYMBOL);
383
        this.bgImage = (BackgroundFileStyle) state.get(BACKGROUND_IMAGE);
384
        this.bgSelImage =
385
            (BackgroundFileStyle) state.get(BACKGROUND_SELECTION_IMAGE);
386
        this.setLineWidth(state.getDouble(WIDTH));
387
        this.setLineWidth(state.getDouble(WIDTH));
388
        this.setSizeExpression(state.getString(FIELD_SIZE_EXPRESSION));
389
    }
390

    
391
        @Override
392
    public void saveToState(PersistentState state) throws PersistenceException {
393
        // Save parent fill symbol properties
394
        super.saveToState(state);
395

    
396
        // Save own properties
397
        state.set(SELECTED, this.selected);
398
        state.set(SELECTION_SYMBOL, this.getSymbolForSelection());
399
        state.set(BACKGROUND_IMAGE, this.bgImage);
400
        state.set(BACKGROUND_SELECTION_IMAGE, this.bgSelImage);
401
        state.set(WIDTH, width);
402
        state.set(FIELD_SIZE_EXPRESSION, this.getSizeExpression());
403
    }
404
    
405
    private FeatureSymbolTable symbolTable = null;
406

    
407
    protected SymbolTable getSymbolTable(Feature f) {
408
        if (symbolTable == null) {
409
            this.symbolTable = DALLocator.getManager().createFeatureSymbolTable();
410
            this.symbolTable.addSymbolTable(ExpressionUtils.createSymbolTable());
411
        }
412
        symbolTable.setFeature(f);
413
        return symbolTable;
414
    }
415

    
416

    
417
    @Override
418
    public Color getEfectiveLineToOffsetColor(Feature f) {
419
        if (f == null) {
420
            f = this.getFeature();
421
        }
422
        if (f == null || StringUtils.isBlank(this.lineToOffsetColorExpression)) {
423
            return this.getLineToOffsetColor();
424
        }
425
        Color theColor = ExpressionUtils.parseColor(
426
                this.getSymbolTable(f),
427
                this.lineToOffsetColorExpression,
428
                this.getLineToOffsetColor()
429
        );
430
        return theColor;
431
    }
432

    
433
    @Override
434
    public Point2D getEfectiveOffset(Feature f) {
435
        if (f == null) {
436
            f = this.getFeature();
437
        }
438
        Point2D p;
439
        if (f == null || StringUtils.isBlank(this.offsetXExpression) || StringUtils.isBlank(this.offsetYExpression)) {
440
            p = this.getOffset();
441
            p = new Point2D.Double(
442
                    toCartographicUnits(p.getX()),
443
                    toCartographicUnits(p.getY())
444
            );
445
        } else {
446
            double offsetX = toCartographicUnits(ExpressionUtils.parseDouble(
447
                    this.getSymbolTable(f),
448
                    offsetXExpression,
449
                    (int) this.getOffset().getX()
450
            ));
451
            double offsetY = toCartographicUnits(ExpressionUtils.parseDouble(
452
                    this.getSymbolTable(f),
453
                    offsetYExpression,
454
                    (int) this.getOffset().getY()
455
            ));
456
            p = new Point2D.Double(offsetX, offsetY);
457
        }
458
        return p;
459
    }
460

    
461
    @Override
462
    public double getEfectiveRotationInDegres(Feature f) {
463
        if (StringUtils.isBlank(this.rotationExpression)) {
464
            return Math.toDegrees(this.getRotation());
465
        }
466
        // Por defecto vedra en grados.
467
        if (f == null) {
468
            f = this.getFeature();
469
        }
470
        if (f == null) {
471
            return Math.toDegrees(this.getRotation());
472
        }
473
        double r = ExpressionUtils.parseDouble(
474
                this.getSymbolTable(f),
475
                rotationExpression,
476
                this.getRotation()
477
        );
478
        return r;
479
    }
480

    
481
    @Override
482
    public double getEfectiveRotationInRadians(Feature f) {
483
        // Pillamos el valor por defecto que es en grados y lo transformamos a radianes.
484
        if (StringUtils.isBlank(this.rotationExpression)) {
485
            return this.getRotation();
486
        }
487
        double r = this.getEfectiveRotationInDegres(f);
488
        if (r == 0) {
489
            return 0;
490
        }
491
        r = Math.toRadians(r);
492
        return r;
493
    }
494

    
495
    private double getCartographicSize() {
496
        return toCartographicUnits(getSize());
497
    }
498

    
499
    @Override
500
    public double getEfectiveSize(Feature f) {
501
        if (StringUtils.isBlank(this.sizeExpression)) {
502
            return this.getCartographicSize();
503
        }
504
        if (f == null) {
505
            f = this.getFeature();
506
        }
507
        if (f == null) {
508
            return this.getCartographicSize();
509
        }
510
        double sz = ExpressionUtils.parseDouble(
511
                this.getSymbolTable(f),
512
                this.sizeExpression,
513
                -1
514
        );
515
        if (sz < 0) {
516
            return this.getCartographicSize();
517
        }
518
        return toCartographicUnits(sz);
519
    }
520

    
521
    @Override
522
    public Color getLineToOffsetColor() {
523
        return this.lineToOffsetColor;
524
    }
525

    
526
    @Override
527
    public String getLineToOffsetColorExpression() {
528
        return this.lineToOffsetColorExpression;
529
    }
530

    
531
    @Override
532
    public String getOffsetXExpression() {
533
        return offsetXExpression;
534
    }
535

    
536
    @Override
537
    public String getOffsetYExpression() {
538
        return offsetYExpression;
539
    }
540

    
541
    @Override
542
    public String getRotationExpression() {
543
        return rotationExpression;
544
    }
545

    
546
    @Override
547
    public String getSizeExpression() {
548
        return sizeExpression;
549
    }
550

    
551
    @Override
552
    public boolean isDrawLineToOffset() {
553
        return this.drawLineToOffset;
554
    }
555

    
556
    @Override
557
    public void setDrawLineToOffset(boolean drawLineToOffset) {
558
        this.drawLineToOffset = drawLineToOffset;
559
    }
560

    
561
    @Override
562
    public void setLineToOffsetColor(Color color) {
563
        this.lineToOffsetColor = color;
564
    }
565

    
566
    @Override
567
    public void setLineToOffsetColorExpression(String lineToOffsetColorExpression) {
568
        this.lineToOffsetColorExpression = StringUtils.trimToNull(lineToOffsetColorExpression);
569
    }
570

    
571
    @Override
572
    public void setOffsetXExpression(String offsetXExpression) {
573
        this.offsetXExpression = StringUtils.trimToNull(offsetXExpression);
574
    }
575

    
576
    @Override
577
    public void setOffsetYExpression(String offsetYExpression) {
578
        this.offsetYExpression = StringUtils.trimToNull(offsetYExpression);
579
    }
580

    
581
    @Override
582
    public void setRotationExpression(String rotationExpression) {
583
        this.rotationExpression = StringUtils.trimToNull(rotationExpression);
584
    }
585

    
586
    @Override
587
    public void setSizeExpression(String sizeExpression) {
588
        this.sizeExpression = StringUtils.trimToNull(sizeExpression);
589
    }
590

    
591
    @Override
592
    public double getRotation() {
593
        return rotation;
594
    }
595

    
596
    @Override
597
    public void setRotation(double r) {
598
        this.rotation = r;
599
        this.setRotationExpression(null);
600
    }
601

    
602
    @Override
603
    public Point2D getOffset() {
604
        if (offset == null) {
605
            offset = new Point();
606
        }
607
        return offset;
608
    }
609

    
610
    @Override
611
    public void setOffset(Point2D offset) {
612
        this.offset = offset;
613
    }
614

    
615
    @Override
616
    public double getSize() {
617
        return getLineWidth();
618
    }
619

    
620
    @Override
621
    public void setSize(double size) {
622
        this.setSizeExpression(null);
623
        this.setLineWidth(size);
624
    }
625

    
626
    @Override
627
    public IMask getMask() {
628
        return mask;
629
    }
630

    
631
    @Override
632
    public void setMask(IMask mask) {
633
        this.mask = mask;
634
    }
635
        
636
    @Override
637
    public String[] getRequiredFeatureAttributeNames(FeatureStore featureStore) throws DataException {
638
        // By default only need the default Geometry
639
        FeatureType ftype = featureStore.getDefaultFeatureTypeQuietly();
640
        String[] res = new String[ftype.size()];
641
        int cont = 0;
642
        for (FeatureAttributeDescriptor attr : ftype) {
643
            res[cont++]=attr.getName();
644
        }
645
        return res;
646
    }
647

    
648
    public static class RegisterPersistence implements Callable {
649

    
650
        @Override
651
        public Object call() throws Exception {
652
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
653
            if (manager.getDefinition(PICTURE_LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME) == null) {
654
                DynStruct definition =
655
                    manager.addDefinition(PictureLineSymbol.class,
656
                                    PICTURE_LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME,
657
                                    PICTURE_LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME
658
                            + " Persistence definition",
659
                        null,
660
                        null);
661

    
662
                // Extend the Style base definition
663
                definition.extend(manager.getDefinition(LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME));
664

    
665
                definition.addDynFieldBoolean(SELECTED).setMandatory(false);
666
                definition.addDynFieldObject(SELECTION_SYMBOL)
667
                    .setClassOfValue(PictureLineSymbol.class).setMandatory(false);
668
                definition.addDynFieldObject(BACKGROUND_IMAGE)
669
                    .setClassOfValue(BackgroundFileStyle.class).setMandatory(false);
670
                definition.addDynFieldObject(BACKGROUND_SELECTION_IMAGE)
671
                    .setClassOfValue(BackgroundFileStyle.class).setMandatory(false);
672

    
673
                definition.addDynFieldObject(WIDTH)
674
                    .setClassOfValue(Double.class).setMandatory(true);
675
                definition.addDynFieldString(FIELD_SIZE_EXPRESSION)
676
                    .setMandatory(false);
677
            }
678
            return Boolean.TRUE;
679
        }
680
    }
681

    
682
        public static class RegisterSymbol implements Callable {
683

    
684
                @Override
685
                public Object call() throws Exception {
686
                        SymbolManager manager = MapContextLocator.getSymbolManager();
687

    
688
                        manager.registerSymbol(PICTURE_LINE_SYMBOL_PERSISTENCE_DEFINITION_NAME,
689
                            PictureLineSymbol.class);
690

    
691
                        return Boolean.TRUE;
692
                }
693
        }
694

    
695
//    @Override
696
//    public void getPixExtentPlus(Geometry geom, float[] distances, ViewPort viewPort, int dpi) {
697
//        super.getPixExtentPlus(geom, distances, viewPort, dpi);
698
//            double pixWidth = toCartographicUnits(width);
699
//            distances[0] += pixWidth/2;
700
//            distances[1] += pixWidth/2;
701
//    }
702
        
703
        
704
}