001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.mappaint.styleelement.placement; 003 004import java.awt.font.GlyphVector; 005import java.awt.geom.Point2D; 006import java.awt.geom.Rectangle2D; 007import java.util.List; 008 009import org.openstreetmap.josm.gui.draw.MapViewPath; 010import org.openstreetmap.josm.gui.draw.MapViewPositionAndRotation; 011import org.openstreetmap.josm.gui.mappaint.Keyword; 012 013/** 014 * This strategy defines how to place a label or icon inside the area. 015 * 016 * @author Michael Zangl 017 * @since 11722 018 * @since 11748 moved to own file 019 */ 020public interface PositionForAreaStrategy { 021 /** 022 * Finds the correct position of a label / icon inside the area. 023 * @param path The area to search in 024 * @param nb The bounding box of the thing we are searching a place for. 025 * @return The position as rectangle with the same dimension as nb. <code>null</code> if none was found. 026 */ 027 MapViewPositionAndRotation findLabelPlacement(MapViewPath path, Rectangle2D nb); 028 029 /** 030 * Checks whether this placement strategy supports more detailed (rotation / ...) placement using a glyph vector. 031 * @return <code>true</code> if it is supported. 032 */ 033 boolean supportsGlyphVector(); 034 035 /** 036 * Generates the transformed glyph vectors for the given text. 037 * @param path The path to place the text along 038 * @param nb The bounds of the text 039 * @param gvs The glyph vectors for the text. May be modified 040 * @param isDoubleTranslationBug <code>true</code> to fix a glyph placement bug. 041 * 042 * @return The glyph vectors. 043 * @throws UnsupportedOperationException if {@link #supportsGlyphVector()} returns false 044 */ 045 default List<GlyphVector> generateGlyphVectors( 046 MapViewPath path, Rectangle2D nb, List<GlyphVector> gvs, boolean isDoubleTranslationBug) { 047 throw new UnsupportedOperationException("Single glyph transformation is not supported by this implementation"); 048 } 049 050 /** 051 * Gets a strategy for the given keyword. 052 * @param keyword The text position keyword. 053 * @return The strategy or line if none was specified. 054 * @since 11722 055 */ 056 static PositionForAreaStrategy forKeyword(Keyword keyword) { 057 return forKeyword(keyword, OnLineStrategy.INSTANCE); 058 } 059 060 /** 061 * Gets a strategy for the given keyword. 062 * @param keyword The text position keyword. 063 * @param defaultStrategy The default if no strategy was recognized. 064 * @return The strategy or line if none was specified. 065 * @since 11722 066 */ 067 static PositionForAreaStrategy forKeyword(Keyword keyword, PositionForAreaStrategy defaultStrategy) { 068 if (keyword == null) { 069 return defaultStrategy; 070 } 071 switch (keyword.val) { 072 case "center": 073 return PartiallyInsideAreaStrategy.INSTANCE; 074 case "inside": 075 return CompletelyInsideAreaStrategy.INSTANCE; 076 case "line": 077 return OnLineStrategy.INSTANCE; 078 default: 079 return defaultStrategy; 080 } 081 } 082 083 /** 084 * Create a new instance of the same strategy adding a offset 085 * @param addToOffset The offset to add 086 * @return The new strategy 087 * @since 12476 088 */ 089 PositionForAreaStrategy withAddedOffset(Point2D addToOffset); 090}