Changeset 11722 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2017-03-13T17:04:29+01:00 (7 years ago)
Author:
michael2402
Message:

Do not include text label in area style - use a separate class and start merging code for on-line and in-area drawing.

Location:
trunk/src/org/openstreetmap/josm
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r11719 r11722  
    7575import org.openstreetmap.josm.gui.mappaint.styleelement.MapImage;
    7676import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
     77import org.openstreetmap.josm.gui.mappaint.styleelement.PositionForAreaStrategy;
    7778import org.openstreetmap.josm.gui.mappaint.styleelement.RepeatImageElement.LineImageAlignment;
    7879import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
    7980import org.openstreetmap.josm.gui.mappaint.styleelement.Symbol;
     81import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
    8082import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel;
    8183import org.openstreetmap.josm.tools.CompositeList;
     
    400402    protected void drawArea(OsmPrimitive osm, Path2D.Double path, Color color,
    401403            MapImage fillImage, Float extent, Path2D.Double pfClip, boolean disabled, TextLabel text) {
    402 
    403         Shape area = path.createTransformedShape(mapState.getAffineTransform());
    404 
    405         if (color.getAlpha() == 0) {
    406             // skip drawing
    407         } else if (!isOutlineOnly) {
     404        if (!isOutlineOnly && color.getAlpha() != 0) {
     405            Shape area = path.createTransformedShape(mapState.getAffineTransform());
    408406            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    409407            if (fillImage == null) {
     
    451449        }
    452450
    453         drawAreaText(osm, text, area);
    454     }
    455 
    456     private void drawAreaText(OsmPrimitive osm, TextLabel text, Shape area) {
    457         if (text != null && isShowNames()) {
     451        drawAreaText(osm, text, path);
     452    }
     453
     454    private void drawAreaText(OsmPrimitive osm, TextLabel text, Path2D.Double path) {
     455        if (text != null && isShowNames() && isAreaVisible(path)) {
    458456            // abort if we can't compose the label to be rendered
    459457            if (text.labelCompositionStrategy == null) return;
     
    461459            if (name == null || name.isEmpty()) return;
    462460
     461            Shape area = path.createTransformedShape(mapState.getAffineTransform());
    463462            FontMetrics fontMetrics = g.getFontMetrics(orderFont); // if slow, use cache
    464463            Rectangle2D nb = fontMetrics.getStringBounds(name, g); // if slow, approximate by strlen()*maxcharbounds(font)
    465464
    466             Rectangle centeredNBounds = findLabelPlacement(area, nb);
     465            Rectangle2D centeredNBounds = text.getLabelPositionSteategy().findLabelPlacement(area, nb);
    467466            if (centeredNBounds != null) {
    468467                Font defaultFont = g.getFont();
     
    475474            }
    476475        }
    477     }
    478 
    479     /**
    480      * Finds the correct position of a label / icon inside the area.
    481      * @param area The area to search in
    482      * @param nb The bounding box of the thing we are searching a place for.
    483      * @return The position as rectangle with the same dimension as nb. <code>null</code> if none was found.
    484      */
    485     private Rectangle findLabelPlacement(Shape area, Rectangle2D nb) {
    486         // Using the Centroid is Nicer for buildings like: +--------+
    487         // but this needs to be fast.  As most houses are  |   42   |
    488         // boxes anyway, the center of the bounding box    +---++---+
    489         // will have to do.                                    ++
    490         // Centroids are not optimal either, just imagine a U-shaped house.
    491 
    492         Rectangle pb = area.getBounds();
    493 
    494         // quick check to see if label box is smaller than primitive box
    495         if (pb.width < nb.getWidth() || pb.height < nb.getHeight()) {
    496             return null;
    497         }
    498 
    499         final double w = pb.width - nb.getWidth();
    500         final double h = pb.height - nb.getHeight();
    501 
    502         final int x2 = pb.x + (int) (w/2.0);
    503         final int y2 = pb.y + (int) (h/2.0);
    504 
    505         final int nbw = (int) nb.getWidth();
    506         final int nbh = (int) nb.getHeight();
    507 
    508         Rectangle centeredNBounds = new Rectangle(x2, y2, nbw, nbh);
    509 
    510         // slower check to see if label is displayed inside primitive shape
    511         if (area.contains(centeredNBounds)) {
    512             return centeredNBounds;
    513         }
    514 
    515         // if center position (C) is not inside osm shape, try naively some other positions as follows:
    516         // CHECKSTYLE.OFF: SingleSpaceSeparator
    517         final int x1 = pb.x + (int)   (w/4.0);
    518         final int x3 = pb.x + (int) (3*w/4.0);
    519         final int y1 = pb.y + (int)   (h/4.0);
    520         final int y3 = pb.y + (int) (3*h/4.0);
    521         // CHECKSTYLE.ON: SingleSpaceSeparator
    522         // +-----------+
    523         // |  5  1  6  |
    524         // |  4  C  2  |
    525         // |  8  3  7  |
    526         // +-----------+
    527         Rectangle[] candidates = new Rectangle[] {
    528                 new Rectangle(x2, y1, nbw, nbh),
    529                 new Rectangle(x3, y2, nbw, nbh),
    530                 new Rectangle(x2, y3, nbw, nbh),
    531                 new Rectangle(x1, y2, nbw, nbh),
    532                 new Rectangle(x1, y1, nbw, nbh),
    533                 new Rectangle(x3, y1, nbw, nbh),
    534                 new Rectangle(x3, y3, nbw, nbh),
    535                 new Rectangle(x1, y3, nbw, nbh)
    536         };
    537         // Dumb algorithm to find a better placement. We could surely find a smarter one but it should
    538         // solve most of building issues with only few calculations (8 at most)
    539         for (int i = 0; i < candidates.length; i++) {
    540             centeredNBounds = candidates[i];
    541             if (area.contains(centeredNBounds)) {
    542                 return centeredNBounds;
    543             }
    544         }
    545 
    546         // none found
    547         return null;
    548476    }
    549477
     
    11811109
    11821110    /**
     1111     * Draws a text for the given primitive
     1112     * @param osm The primitive to draw the text for
     1113     * @param text The text definition (font/position/.../text content) to draw.
     1114     * @since 11722
     1115     */
     1116    public void drawText(OsmPrimitive osm, TextLabel text) {
     1117        PositionForAreaStrategy position = text.getLabelPositionSteategy();
     1118        if (position.supportsGlyphVector()) {
     1119            if (osm instanceof Way) {
     1120                // we might allow this for the outline of relations as well.
     1121                drawTextOnPath((Way) osm, text);
     1122            }
     1123        } else {
     1124            if (osm instanceof Way) {
     1125                drawAreaText(osm, text, getPath((Way) osm));
     1126            } else if (osm instanceof Relation) {
     1127                Multipolygon multipolygon = MultipolygonCache.getInstance().get(nc, (Relation) osm);
     1128                if (!multipolygon.getOuterWays().isEmpty()) {
     1129                    for (PolyData pd : multipolygon.getCombinedPolygons()) {
     1130                        drawAreaText(osm, text, pd.get());
     1131                    }
     1132                }
     1133            }
     1134        }
     1135    }
     1136
     1137    /**
    11831138     * Draws a text along a given way.
    11841139     * @param way The way to draw the text on.
     
    18221777                if (drawMultipolygon && drawArea && s instanceof AreaElement && (flags & FLAG_DISABLED) == 0) {
    18231778                    output.add(new StyleRecord(s, osm, flags));
     1779                } else if (drawMultipolygon && drawArea && s instanceof TextElement) {
     1780                    output.add(new StyleRecord(s, osm, flags));
    18241781                } else if (drawRestriction && s instanceof NodeElement) {
    18251782                    output.add(new StyleRecord(s, osm, flags));
  • trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java

    r11608 r11722  
    2626import org.openstreetmap.josm.gui.mappaint.styleelement.BoxTextElement;
    2727import org.openstreetmap.josm.gui.mappaint.styleelement.LineElement;
    28 import org.openstreetmap.josm.gui.mappaint.styleelement.LineTextElement;
    2928import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
    3029import org.openstreetmap.josm.gui.mappaint.styleelement.RepeatImageElement;
    3130import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
     31import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
    3232import org.openstreetmap.josm.gui.mappaint.styleelement.TextLabel;
    3333import org.openstreetmap.josm.gui.util.GuiHelper;
     
    366366            env.layer = e.getKey();
    367367            if (osm instanceof Way) {
    368                 addIfNotNull(sl, AreaElement.create(env));
     368                AreaElement areaStyle = AreaElement.create(env);
     369                addIfNotNull(sl, areaStyle);
    369370                addIfNotNull(sl, RepeatImageElement.create(env));
    370371                addIfNotNull(sl, LineElement.createLine(env));
     
    372373                addIfNotNull(sl, LineElement.createRightCasing(env));
    373374                addIfNotNull(sl, LineElement.createCasing(env));
    374                 addIfNotNull(sl, LineTextElement.create(env));
     375                addIfNotNull(sl, TextElement.create(env));
     376                if (areaStyle != null) {
     377                    //TODO: Warn about this, or even remove it completely
     378                    addIfNotNull(sl, TextElement.createForContent(env));
     379                }
    375380            } else if (osm instanceof Node) {
    376381                NodeElement nodeStyle = NodeElement.create(env);
     
    383388            } else if (osm instanceof Relation) {
    384389                if (((Relation) osm).isMultipolygon()) {
    385                     addIfNotNull(sl, AreaElement.create(env));
     390                    AreaElement areaStyle = AreaElement.create(env);
     391                    addIfNotNull(sl, areaStyle);
    386392                    addIfNotNull(sl, RepeatImageElement.create(env));
    387393                    addIfNotNull(sl, LineElement.createLine(env));
    388394                    addIfNotNull(sl, LineElement.createCasing(env));
    389                     addIfNotNull(sl, LineTextElement.create(env));
     395                    addIfNotNull(sl, TextElement.create(env));
     396                    if (areaStyle != null) {
     397                        //TODO: Warn about this, or even remove it completely
     398                        addIfNotNull(sl, TextElement.createForContent(env));
     399                    }
    390400                } else if (osm.hasTag("type", "restriction")) {
    391401                    addIfNotNull(sl, NodeElement.create(env));
  • trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/AreaElement.java

    r11720 r11722  
    1010import org.openstreetmap.josm.data.osm.Way;
    1111import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
    12 import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
    1312import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
    1413import org.openstreetmap.josm.data.preferences.IntegerProperty;
    1514import org.openstreetmap.josm.gui.mappaint.Cascade;
    1615import org.openstreetmap.josm.gui.mappaint.Environment;
    17 import org.openstreetmap.josm.gui.mappaint.Keyword;
    1816import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
    1917import org.openstreetmap.josm.gui.util.RotationAngle;
     
    120118        }
    121119
    122         TextLabel text = null;
    123         Keyword textPos = c.get(TEXT_POSITION, null, Keyword.class);
    124         if (textPos == null || "center".equals(textPos.val)) {
    125             text = TextLabel.create(env, PaintColors.AREA_TEXT.get(), true);
    126         }
     120        TextLabel text = null; // <- text is handled by TextElement
    127121        MapImage iconImage = NodeElement.createIcon(env);
    128122        RotationAngle rotationAngle = NodeElement.createRotationAngle(env);
    129123
    130         if (iconImage != null || text != null) {
     124        if (iconImage != null) {
    131125            // fake a transparent color.
    132126            color = new Color(0, 0, 0, 0);
  • trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LineTextElement.java

    r9371 r11722  
    1313import org.openstreetmap.josm.gui.mappaint.Keyword;
    1414
     15/**
     16 * A text that is only on the line
     17 * @deprecated since 11722. To be removed summer 2017
     18 */
     19@Deprecated
    1520public class LineTextElement extends StyleElement {
    1621
  • trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java

    r11717 r11722  
    1515import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.StaticLabelCompositionStrategy;
    1616import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.TagLookupCompositionStrategy;
     17import org.openstreetmap.josm.gui.mappaint.styleelement.PositionForAreaStrategy.CompletelyInsideAreaStrategy;
    1718import org.openstreetmap.josm.tools.CheckParameterUtil;
    1819import org.openstreetmap.josm.tools.Utils;
     
    5455     */
    5556    public Color haloColor;
     57
     58    /**
     59     * The position strategy for this text label.
     60     */
     61    private final PositionForAreaStrategy labelPositionSteategy;
    5662
    5763    /**
     
    6672     * @param haloRadius halo radius
    6773     * @param haloColor halo color
    68      */
     74     * @deprecated since 11722, To be removed in mid-2017
     75     */
     76    @Deprecated
    6977    public TextLabel(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor) {
    70         CheckParameterUtil.ensureParameterNotNull(font);
    71         CheckParameterUtil.ensureParameterNotNull(color);
    72         labelCompositionStrategy = strategy;
    73         this.font = font;
     78        this(strategy, font, xOffset, yOffset, color, haloRadius, haloColor, new CompletelyInsideAreaStrategy());
     79    }
     80
     81    /**
     82     * Creates a new text element
     83     *
     84     * @param strategy the strategy indicating how the text is composed for a specific {@link OsmPrimitive} to be rendered.
     85     * If null, no label is rendered.
     86     * @param font the font to be used. Must not be null.
     87     * @param xOffset x offset
     88     * @param yOffset y offset
     89     * @param color the color to be used. Must not be null
     90     * @param haloRadius halo radius
     91     * @param haloColor halo color
     92     * @param labelPositionSteategy The position in the area.
     93     */
     94    protected TextLabel(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius, Color haloColor, PositionForAreaStrategy labelPositionSteategy) {
     95        this.labelCompositionStrategy = strategy;
     96        this.font = Objects.requireNonNull(font, "font");
    7497        this.xOffset = xOffset;
    7598        this.yOffset = yOffset;
    76         this.color = color;
     99        this.color = Objects.requireNonNull(color, "color");
    77100        this.haloRadius = haloRadius;
    78101        this.haloColor = haloColor;
     102        this.labelPositionSteategy = Objects.requireNonNull(labelPositionSteategy, "labelPositionSteategy");
    79103    }
    80104
     
    92116        this.haloColor = other.haloColor;
    93117        this.haloRadius = other.haloRadius;
     118        this.labelPositionSteategy = other.labelPositionSteategy;
     119    }
     120
     121    /**
     122     * Copy constructor that changes the position strategy.
     123     *
     124     * @param other the other element.
     125     * @param labelPositionSteategy the position
     126     */
     127    private TextLabel(TextLabel other, PositionForAreaStrategy labelPositionSteategy) {
     128        this.labelCompositionStrategy = other.labelCompositionStrategy;
     129        this.font = other.font;
     130        this.xOffset = other.xOffset;
     131        this.yOffset = other.yOffset;
     132        this.color = other.color;
     133        this.haloColor = other.haloColor;
     134        this.haloRadius = other.haloRadius;
     135        this.labelPositionSteategy = labelPositionSteategy;
    94136    }
    95137
     
    177219        }
    178220
    179         return new TextLabel(strategy, font, (int) xOffset, -(int) yOffset, color, haloRadius, haloColor);
     221        Keyword positionKeyword = c.get(AreaElement.TEXT_POSITION, null, Keyword.class);
     222        PositionForAreaStrategy position = PositionForAreaStrategy.forKeyword(positionKeyword);
     223
     224        return new TextLabel(strategy, font, (int) xOffset, -(int) yOffset, color, haloRadius, haloColor, position);
    180225    }
    181226
     
    190235        if (labelCompositionStrategy == null) return null;
    191236        return labelCompositionStrategy.compose(osm);
     237    }
     238
     239    /**
     240     * Gets the strategy that defines where to place the label.
     241     * @return The strategy. Never null.
     242     * @since 11722
     243     */
     244    public PositionForAreaStrategy getLabelPositionSteategy() {
     245        return labelPositionSteategy;
     246    }
     247
     248    public TextLabel withPosition(PositionForAreaStrategy labelPositionSteategy) {
     249        return new TextLabel(this, labelPositionSteategy);
    192250    }
    193251
Note: See TracChangeset for help on using the changeset viewer.