OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 83 | Rev 180 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 83 Rev 93
Line 21... Line 21...
21
import org.openconcerto.utils.CollectionUtils;
21
import org.openconcerto.utils.CollectionUtils;
22
import org.openconcerto.utils.cc.IPredicate;
22
import org.openconcerto.utils.cc.IPredicate;
23
import org.openconcerto.xml.JDOMUtils;
23
import org.openconcerto.xml.JDOMUtils;
24
import org.openconcerto.xml.Validator;
24
import org.openconcerto.xml.Validator;
25
 
25
 
26
import java.math.BigDecimal;
-
 
27
import java.util.ArrayList;
26
import java.util.ArrayList;
28
import java.util.Collections;
27
import java.util.Collections;
29
import java.util.Deque;
28
import java.util.Deque;
30
import java.util.HashMap;
29
import java.util.HashMap;
31
import java.util.Iterator;
30
import java.util.Iterator;
Line 154... Line 153...
154
    public static synchronized OOXML getDefault() {
153
    public static synchronized OOXML getDefault() {
155
        return defaultInstance;
154
        return defaultInstance;
156
    }
155
    }
157
 
156
 
158
    // from OpenDocument-v1.2-schema.rng : a coordinate is a length
157
    // from OpenDocument-v1.2-schema.rng : a coordinate is a length
159
    static private final BigDecimal parseCoordinate(final Element elem, final String attrName, final Namespace ns, LengthUnit unit) {
158
    static private final Length parseCoordinate(final Element elem, final String attrName, final Namespace ns) {
160
        return parseLength(elem, attrName, ns, unit);
159
        return parseLength(elem, attrName, ns);
161
    }
160
    }
162
 
161
 
163
    static private final BigDecimal parseLength(final Element elem, final String attrName, final Namespace ns, LengthUnit unit) {
162
    static private final Length parseLength(final Element elem, final String attrName, final Namespace ns) {
164
        final String attr = elem.getAttributeValue(attrName, ns);
163
        final String attr = elem.getAttributeValue(attrName, ns);
165
        if (attr == null)
164
        final Length res = LengthUnit.parseLength(attr);
166
            return null;
165
        assert res != null;
167
        return LengthUnit.parseLength(attr, unit);
166
        return res.isNone() ? null : res;
168
    }
167
    }
169
 
168
 
170
    // *** instances
169
    // *** instances
171
 
170
 
172
    private final XMLFormatVersion version;
171
    private final XMLFormatVersion version;
Line 402... Line 401...
402
 
401
 
403
    /**
402
    /**
404
     * Return the coordinates of the top-left and bottom-right of the passed shape.
403
     * Return the coordinates of the top-left and bottom-right of the passed shape.
405
     * 
404
     * 
406
     * @param elem an XML element.
405
     * @param elem an XML element.
407
     * @param unit the unit of the returned numbers.
-
 
408
     * @return an array of 4 numbers, <code>null</code> if <code>elem</code> is not a shape, numbers
406
     * @return an array of 4 lengths, <code>null</code> if <code>elem</code> is not a shape, items
409
     *         themselves are never <code>null</code>.
407
     *         themselves are never <code>null</code>.
410
     */
408
     */
411
    public final BigDecimal[] getCoordinates(Element elem, LengthUnit unit) {
409
    public final Length[] getCoordinates(Element elem) {
412
        return this.getCoordinates(elem, unit, true, true);
410
        return this.getCoordinates(elem, true, true);
413
    }
411
    }
414
 
412
 
415
    /**
413
    /**
416
     * Return the coordinates of the top-left and bottom-right of the passed shape.
414
     * Return the coordinates of the top-left and bottom-right of the passed shape.
417
     * 
415
     * 
418
     * @param elem an XML element.
416
     * @param elem an XML element.
419
     * @param unit the unit of the returned numbers.
-
 
420
     * @param horizontal <code>true</code> if the x coordinates should be computed,
417
     * @param horizontal <code>true</code> if the x coordinates should be computed,
421
     *        <code>false</code> meaning items 0 and 2 of the result are <code>null</code>.
418
     *        <code>false</code> meaning items 0 and 2 of the result are <code>null</code>.
422
     * @param vertical <code>true</code> if the y coordinates should be computed, <code>false</code>
419
     * @param vertical <code>true</code> if the y coordinates should be computed, <code>false</code>
423
     *        meaning items 1 and 3 of the result are <code>null</code>.
420
     *        meaning items 1 and 3 of the result are <code>null</code>.
424
     * @return an array of 4 numbers, <code>null</code> if <code>elem</code> is not a shape, numbers
421
     * @return an array of 4 lengths, <code>null</code> if <code>elem</code> is not a shape, items
425
     *         themselves are only <code>null</code> if requested with <code>horizontal</code> or
422
     *         themselves are only <code>null</code> if requested with <code>horizontal</code> or
426
     *         <code>vertical</code>.
423
     *         <code>vertical</code>.
427
     */
424
     */
428
    public final BigDecimal[] getCoordinates(Element elem, LengthUnit unit, final boolean horizontal, final boolean vertical) {
425
    public final Length[] getCoordinates(Element elem, final boolean horizontal, final boolean vertical) {
429
        return getCoordinates(elem, getVersion().getNS("svg"), unit, horizontal, vertical);
426
        return getCoordinates(elem, getVersion().getNS("svg"), horizontal, vertical);
430
    }
427
    }
431
 
428
 
432
    static private final BigDecimal[] getCoordinates(Element elem, final Namespace svgNS, LengthUnit unit, final boolean horizontal, final boolean vertical) {
429
    static private final Length[] getCoordinates(Element elem, final Namespace svgNS, final boolean horizontal, final boolean vertical) {
433
        if (elem.getName().equals("g") && elem.getNamespacePrefix().equals("draw")) {
430
        if (elem.getName().equals("g") && elem.getNamespacePrefix().equals("draw")) {
434
            // put below if to allow null to be returned by getLocalCoordinates() if elem isn't a
431
            // put below if to allow null to be returned by getLocalCoordinates() if elem isn't a
435
            // shape
432
            // shape
436
            if (!horizontal && !vertical)
433
            if (!horizontal && !vertical)
437
                return new BigDecimal[] { null, null, null, null };
434
                return new Length[] { null, null, null, null };
438
 
435
 
439
            // an OpenDocument group (of shapes) doesn't have any coordinates nor any width and
436
            // an OpenDocument group (of shapes) doesn't have any coordinates nor any width and
440
            // height so iterate through its components to find its coordinates
437
            // height so iterate through its components to find its coordinates
441
            BigDecimal minX = null, minY = null;
438
            Length minX = null, minY = null;
442
            BigDecimal maxX = null, maxY = null;
439
            Length maxX = null, maxY = null;
443
            for (final Object c : elem.getChildren()) {
440
            for (final Object c : elem.getChildren()) {
444
                final Element child = (Element) c;
441
                final Element child = (Element) c;
445
                final BigDecimal[] childCoord = getCoordinates(child, svgNS, unit, horizontal, vertical);
442
                final Length[] childCoord = getCoordinates(child, svgNS, horizontal, vertical);
446
                // e.g. <office:event-listeners>, <svg:desc>, <svg:title>
443
                // e.g. <office:event-listeners>, <svg:desc>, <svg:title>
447
                if (childCoord != null) {
444
                if (childCoord != null) {
448
                    {
445
                    {
449
                        final BigDecimal x = childCoord[0];
446
                        final Length x = childCoord[0];
450
                        final BigDecimal x2 = childCoord[2];
447
                        final Length x2 = childCoord[2];
451
                        if (x != null) {
448
                        if (x != null) {
452
                            assert x2 != null;
449
                            assert x2 != null;
453
                            if (minX == null || x.compareTo(minX) < 0)
450
                            if (minX == null || x.compareTo(minX) < 0)
454
                                minX = x;
451
                                minX = x;
455
                            if (maxX == null || x2.compareTo(maxX) > 0)
452
                            if (maxX == null || x2.compareTo(maxX) > 0)
456
                                maxX = x2;
453
                                maxX = x2;
457
                        }
454
                        }
458
                    }
455
                    }
459
                    {
456
                    {
460
                        final BigDecimal y = childCoord[1];
457
                        final Length y = childCoord[1];
461
                        final BigDecimal y2 = childCoord[3];
458
                        final Length y2 = childCoord[3];
462
                        if (y != null) {
459
                        if (y != null) {
463
                            assert y2 != null;
460
                            assert y2 != null;
464
                            if (minY == null || y.compareTo(minY) < 0)
461
                            if (minY == null || y.compareTo(minY) < 0)
465
                                minY = y;
462
                                minY = y;
466
                            if (maxY == null || y2.compareTo(maxY) > 0)
463
                            if (maxY == null || y2.compareTo(maxY) > 0)
Line 470... Line 467...
470
                }
467
                }
471
            }
468
            }
472
            // works because we check above if both horizontal and vertical are false
469
            // works because we check above if both horizontal and vertical are false
473
            if (minX == null && minY == null)
470
            if (minX == null && minY == null)
474
                throw new IllegalArgumentException("Empty group : " + JDOMUtils.output(elem));
471
                throw new IllegalArgumentException("Empty group : " + JDOMUtils.output(elem));
475
            return new BigDecimal[] { minX, minY, maxX, maxY };
472
            return new Length[] { minX, minY, maxX, maxY };
476
        } else {
473
        } else {
477
            return getLocalCoordinates(elem, svgNS, unit, horizontal, vertical);
474
            return getLocalCoordinates(elem, svgNS, horizontal, vertical);
478
        }
475
        }
479
    }
476
    }
480
 
477
 
481
    // return null if elem isn't a shape (no x/y or no width/height)
478
    // return null if elem isn't a shape (no x/y or no width/height)
482
    // BigDecimal null if and only if horizontal/vertical is false
479
    // BigDecimal null if and only if horizontal/vertical is false
483
    static private final BigDecimal[] getLocalCoordinates(Element elem, final Namespace svgNS, LengthUnit unit, final boolean horizontal, final boolean vertical) {
480
    static private final Length[] getLocalCoordinates(Element elem, final Namespace svgNS, final boolean horizontal, final boolean vertical) {
484
        final BigDecimal x = parseCoordinate(elem, "x", svgNS, unit);
481
        final Length x = parseCoordinate(elem, "x", svgNS);
485
        final BigDecimal x1 = parseCoordinate(elem, "x1", svgNS, unit);
482
        final Length x1 = parseCoordinate(elem, "x1", svgNS);
486
        if (x == null && x1 == null)
483
        if (x == null && x1 == null)
487
            return null;
484
            return null;
488
 
485
 
489
        final BigDecimal y = parseCoordinate(elem, "y", svgNS, unit);
486
        final Length y = parseCoordinate(elem, "y", svgNS);
490
        final BigDecimal y1 = parseCoordinate(elem, "y1", svgNS, unit);
487
        final Length y1 = parseCoordinate(elem, "y1", svgNS);
491
        if (y == null && y1 == null)
488
        if (y == null && y1 == null)
492
            throw new IllegalArgumentException("Have x but missing y in " + JDOMUtils.output(elem));
489
            throw new IllegalArgumentException("Have x but missing y in " + JDOMUtils.output(elem));
493
 
490
 
494
        final BigDecimal startX;
491
        final Length startX;
495
        final BigDecimal endX;
492
        final Length endX;
496
        if (horizontal) {
493
        if (horizontal) {
497
            if (x == null) {
494
            if (x == null) {
498
                startX = x1;
495
                startX = x1;
499
                endX = parseCoordinate(elem, "x2", svgNS, unit);
496
                endX = parseCoordinate(elem, "x2", svgNS);
500
            } else {
497
            } else {
501
                startX = x;
498
                startX = x;
502
                final BigDecimal width = parseLength(elem, "width", svgNS, unit);
499
                final Length width = parseLength(elem, "width", svgNS);
503
                endX = width == null ? null : startX.add(width);
500
                endX = width == null ? null : startX.add(width);
504
            }
501
            }
505
            // return null if there's no second coordinate (it's a point)
502
            // return null if there's no second coordinate (it's a point)
506
            if (endX == null)
503
            if (endX == null)
507
                return null;
504
                return null;
508
        } else {
505
        } else {
509
            startX = null;
506
            startX = null;
510
            endX = null;
507
            endX = null;
511
        }
508
        }
512
 
509
 
513
        final BigDecimal startY;
510
        final Length startY;
514
        final BigDecimal endY;
511
        final Length endY;
515
        if (vertical) {
512
        if (vertical) {
516
            if (y == null) {
513
            if (y == null) {
517
                startY = y1;
514
                startY = y1;
518
                endY = parseCoordinate(elem, "y2", svgNS, unit);
515
                endY = parseCoordinate(elem, "y2", svgNS);
519
            } else {
516
            } else {
520
                startY = y;
517
                startY = y;
521
                final BigDecimal height = parseLength(elem, "height", svgNS, unit);
518
                final Length height = parseLength(elem, "height", svgNS);
522
                endY = height == null ? null : startY.add(height);
519
                endY = height == null ? null : startY.add(height);
523
            }
520
            }
524
            // return null if there's no second coordinate (it's a point)
521
            // return null if there's no second coordinate (it's a point)
525
            if (endY == null)
522
            if (endY == null)
526
                return null;
523
                return null;
527
        } else {
524
        } else {
528
            startY = null;
525
            startY = null;
529
            endY = null;
526
            endY = null;
530
        }
527
        }
531
 
528
 
532
        return new BigDecimal[] { startX, startY, endX, endY };
529
        return new Length[] { startX, startY, endX, endY };
533
    }
530
    }
534
 
531
 
535
    @Immutable
532
    @Immutable
536
    private static final class XML_OO extends OOXML {
533
    private static final class XML_OO extends OOXML {
537
        private static final Set<Namespace> NS = XMLVersion.OOo.getNamespaceSet();
534
        private static final Set<Namespace> NS = XMLVersion.OOo.getNamespaceSet();