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.

File:
1 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));
Note: See TracChangeset for help on using the changeset viewer.