Subject: [PATCH] fix #23654 - improve map imagery attribute padding
---
Index: src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java b/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
--- a/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java	(revision 36509)
+++ b/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java	(date 1789765927263)
@@ -13,6 +13,7 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ImageObserver;
 import java.util.HashMap;
+import java.util.Map;
 
 import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
 import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
@@ -20,6 +21,7 @@
 public class AttributionSupport {
     public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
     public static final Font ATTR_LINK_FONT;
+    private static final int PADDING = 5;
 
     private Attributed source;
 
@@ -32,7 +34,7 @@
     protected Rectangle attrImageBounds;
 
     static {
-        HashMap<TextAttribute, Integer> aUnderline = new HashMap<>();
+        Map<TextAttribute, Integer> aUnderline = new HashMap<>();
         aUnderline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
         ATTR_LINK_FONT = ATTR_FONT.deriveFont(aUnderline);
     }
@@ -66,55 +68,47 @@
         Font font = g.getFont();
         g.setFont(ATTR_LINK_FONT);
 
-        // Draw terms of use text
+        // Draw terms of use text (bottom left corner)
+        final int fontDescent = g.getFontMetrics().getDescent();
         int termsTextHeight = 0;
-        int termsTextY = height;
+        int textY = height - 1 - PADDING; // 1px offset to compensate for the text shadow
 
         if (attrTermsText != null) {
             Rectangle2D termsStringBounds = g.getFontMetrics().getStringBounds(attrTermsText, g);
             int textRealHeight = (int) termsStringBounds.getHeight();
-            termsTextHeight = textRealHeight - 5;
+            termsTextHeight = textRealHeight;
             int termsTextWidth = (int) termsStringBounds.getWidth();
-            termsTextY = height - termsTextHeight;
-            int x = 2;
-            int y = height - termsTextHeight;
-            attrToUBounds = new Rectangle(x, y-termsTextHeight, termsTextWidth, textRealHeight);
-            g.setColor(Color.black);
-            g.drawString(attrTermsText, x + 1, y + 1);
-            g.setColor(Color.white);
-            g.drawString(attrTermsText, x, y);
+            attrToUBounds = new Rectangle(PADDING, textY - termsTextHeight + fontDescent, termsTextWidth, textRealHeight);
+            drawShadedText(g, attrTermsText, PADDING, textY);
         } else {
             attrToUBounds = null;
         }
 
-        // Draw attribution logo
+        // Draw attribution logo (on top of the terms of use text)
         if (attrImage != null) {
-            int x = 2;
             int imgWidth = attrImage.getWidth(observer);
             int imgHeight = attrImage.getHeight(observer);
-            int y = termsTextY - imgHeight - termsTextHeight - 5;
-            attrImageBounds = new Rectangle(x, y, imgWidth, imgHeight);
-            g.drawImage(attrImage, x, y, null);
+            int y = textY - imgHeight - termsTextHeight;
+            attrImageBounds = new Rectangle(PADDING, y, imgWidth, imgHeight);
+            g.drawImage(attrImage, PADDING, y, null);
         } else {
             attrImageBounds = null;
         }
 
+        // Draw attribution (bottom right corner)
         g.setFont(ATTR_FONT);
         String attributionText = source.getAttributionText(zoom, topLeft, bottomRight);
         if (attributionText == null) {
-            // In case attribution text has been forgotte, display URL
+            // In case the attribution text has been forgotten, display URL
             attributionText = source.getAttributionLinkURL();
         }
         if (attributionText != null) {
             Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
-            int textHeight = (int) stringBounds.getHeight() - 5;
-            int x = width - (int) stringBounds.getWidth();
-            int y = height - textHeight;
-            g.setColor(Color.black);
-            g.drawString(attributionText, x + 1, y + 1);
-            g.setColor(Color.white);
-            g.drawString(attributionText, x, y);
-            attrTextBounds = new Rectangle(x, y-textHeight, (int) stringBounds.getWidth(), (int) stringBounds.getHeight());
+            int textWidth = (int) stringBounds.getWidth();
+            int textHeight = (int) stringBounds.getHeight();
+            int x = width - textWidth - PADDING;
+            drawShadedText(g, attributionText, x, textY);
+            attrTextBounds = new Rectangle(x, textY - textHeight + fontDescent, textWidth, textHeight);
         } else {
             attrTextBounds = null;
         }
@@ -122,6 +116,20 @@
         g.setFont(font);
     }
 
+    /**
+     * Draws a string with 1px shadow.
+     * @param g the graphics
+     * @param text the string to be drawn
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    private static void drawShadedText(Graphics g, String text, int x, int y) {
+        g.setColor(Color.black);
+        g.drawString(text, x + 1, y + 1);
+        g.setColor(Color.white);
+        g.drawString(text, x, y);
+    }
+
     public boolean handleAttributionCursor(Point p) {
         if (p == null) return false;
 
