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


Ignore:
Timestamp:
2015-11-07T13:24:20+01:00 (9 years ago)
Author:
bastiK
Message:

fixed #12025 - text along line rendering for bi-directional text

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

Legend:

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

    r8870 r8994  
    2626import java.awt.geom.Point2D;
    2727import java.awt.geom.Rectangle2D;
    28 import java.text.Bidi;
    2928import java.util.ArrayList;
    3029import java.util.Collection;
     
    12481247        }
    12491248
    1250         FontRenderContext frc = g.getFontRenderContext();
    1251         char[] chars = name.toCharArray();
    1252         int dirFlag = Bidi.DIRECTION_LEFT_TO_RIGHT;
    1253         if (Bidi.requiresBidi(chars, 0, chars.length)) {
    1254             Bidi bd = new Bidi(name, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
    1255             if (bd.isRightToLeft()) {
    1256                 dirFlag = Bidi.DIRECTION_RIGHT_TO_LEFT;
    1257             }
    1258         }
    1259         // only works for text that is completely left-to-right or completely right-to-left, not bi-directional text
    1260         GlyphVector gv = text.font.layoutGlyphVector(frc, chars, 0, chars.length, dirFlag);
    1261 
    1262         for (int i = 0; i < gv.getNumGlyphs(); ++i) {
    1263             Rectangle2D rect = gv.getGlyphLogicalBounds(i).getBounds2D();
    1264             double t = tStart + offsetSign * (rect.getX() + rect.getWidth()/2) / pathLength;
    1265             double[] p = pointAt(t, poly, pathLength);
    1266             if (p != null) {
    1267                 AffineTransform trfm = AffineTransform.getTranslateInstance(p[0] - rect.getX(), p[1]);
    1268                 trfm.rotate(p[2]+angleOffset);
    1269                 double off = -rect.getY() - rect.getHeight()/2 + text.yOffset;
    1270                 trfm.translate(-rect.getWidth()/2, off);
    1271                 if (isGlyphVectorDoubleTranslationBug(text.font)) {
    1272                     // scale the translation components by one half
    1273                     AffineTransform tmp = AffineTransform.getTranslateInstance(-0.5 * trfm.getTranslateX(), -0.5 * trfm.getTranslateY());
    1274                     tmp.concatenate(trfm);
    1275                     trfm = tmp;
    1276                 }
    1277                 gv.setGlyphTransform(i, trfm);
    1278             }
    1279         }
    1280         displayText(gv, null, 0, 0, way.isDisabled(), text);
     1249        List<GlyphVector> gvs = Utils.getGlyphVectorsBidi(name, text.font, g.getFontRenderContext());
     1250        double gvOffset = 0;
     1251        for (GlyphVector gv : gvs) {
     1252            double gvWidth = gv.getLogicalBounds().getBounds2D().getWidth();
     1253            for (int i = 0; i < gv.getNumGlyphs(); ++i) {
     1254                Rectangle2D rect = gv.getGlyphLogicalBounds(i).getBounds2D();
     1255                double t = tStart + offsetSign * (gvOffset + rect.getX() + rect.getWidth()/2) / pathLength;
     1256                double[] p = pointAt(t, poly, pathLength);
     1257                if (p != null) {
     1258                    AffineTransform trfm = AffineTransform.getTranslateInstance(p[0] - rect.getX(), p[1]);
     1259                    trfm.rotate(p[2]+angleOffset);
     1260                    double off = -rect.getY() - rect.getHeight()/2 + text.yOffset;
     1261                    trfm.translate(-rect.getWidth()/2, off);
     1262                    if (isGlyphVectorDoubleTranslationBug(text.font)) {
     1263                        // scale the translation components by one half
     1264                        AffineTransform tmp = AffineTransform.getTranslateInstance(-0.5 * trfm.getTranslateX(), -0.5 * trfm.getTranslateY());
     1265                        tmp.concatenate(trfm);
     1266                        trfm = tmp;
     1267                    }
     1268                    gv.setGlyphTransform(i, trfm);
     1269                }
     1270            }
     1271            displayText(gv, null, 0, 0, way.isDisabled(), text);
     1272            gvOffset += gvWidth;
     1273        }
    12811274    }
    12821275
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r8933 r8994  
    66
    77import java.awt.Color;
     8import java.awt.Font;
    89import java.awt.Toolkit;
    910import java.awt.datatransfer.Clipboard;
     
    1314import java.awt.datatransfer.Transferable;
    1415import java.awt.datatransfer.UnsupportedFlavorException;
     16import java.awt.font.FontRenderContext;
     17import java.awt.font.GlyphVector;
    1518import java.io.BufferedReader;
    1619import java.io.ByteArrayOutputStream;
     
    3437import java.security.MessageDigest;
    3538import java.security.NoSuchAlgorithmException;
     39import java.text.Bidi;
    3640import java.text.MessageFormat;
    3741import java.util.AbstractCollection;
     
    14931497        return hashMapInitialCapacity(nEntries, 0.75f);
    14941498    }
     1499
     1500    /**
     1501     * Utility class to save a string along with its rendering direction
     1502     * (left-to-right or right-to-left).
     1503     */
     1504    private static class DirectionString {
     1505        public int direction;
     1506        public String str;
     1507
     1508        public DirectionString(int direction, String str) {
     1509            this.direction = direction;
     1510            this.str = str;
     1511        }
     1512    }
     1513
     1514    /**
     1515     * Convert a string to a list of {@link GlyphVector}s. The string may contain
     1516     * bi-directional text. The result will be in correct visual order.
     1517     * Each element of the resulting list corresponds to one section of the
     1518     * string with consistent writing direction (left-to-right or right-to-left).
     1519     *
     1520     * @param string the string to render
     1521     * @param font the font
     1522     * @param frc a FontRenderContext object
     1523     * @return a list of GlyphVectors
     1524     */
     1525    public static List<GlyphVector> getGlyphVectorsBidi(String string, Font font, FontRenderContext frc) {
     1526        List<GlyphVector> gvs = new ArrayList<>();
     1527        Bidi bidi = new Bidi(string, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
     1528        byte[] levels = new byte[bidi.getRunCount()];
     1529        DirectionString[] dirStrings = new DirectionString[levels.length];
     1530        for (int i = 0; i < levels.length; ++i) {
     1531            levels[i] = (byte) bidi.getRunLevel(i);
     1532            String substr = string.substring(bidi.getRunStart(i), bidi.getRunLimit(i));
     1533            int dir = levels[i] % 2 == 0 ? Bidi.DIRECTION_LEFT_TO_RIGHT : Bidi.DIRECTION_RIGHT_TO_LEFT;
     1534            dirStrings[i] = new DirectionString(dir, substr);
     1535        }
     1536        Bidi.reorderVisually(levels, 0, dirStrings, 0, levels.length);
     1537        for (int i = 0; i < dirStrings.length; ++i) {
     1538            char[] chars = dirStrings[i].str.toCharArray();
     1539            gvs.add(font.layoutGlyphVector(frc, chars, 0, chars.length, dirStrings[i].direction));
     1540        }
     1541        return gvs;
     1542    }
     1543
    14951544}
Note: See TracChangeset for help on using the changeset viewer.