src/java.desktop/share/classes/sun/font/FontDesignMetrics.java
author prr
Mon, 11 Dec 2017 15:17:03 -0800
changeset 48285 7e8a0c4ee95e
parent 47216 71c04702a3d5
child 52248 2e330da7cbf4
permissions -rw-r--r--
8189809: Large performance regression in Swing text layout Reviewed-by: serb, pnarayanan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
23288
b7183846db97 8033624: Fix raw and unchecked lint warnings in sun.font
darcy
parents: 5506
diff changeset
     2
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4252
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4252
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4252
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4252
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4252
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.ref.ReferenceQueue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.lang.ref.SoftReference;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.FontMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.Font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.awt.GraphicsEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.awt.geom.AffineTransform;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.awt.geom.NoninvertibleTransformException;
48285
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
    36
import java.awt.geom.Rectangle2D;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.awt.font.FontRenderContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.awt.font.TextLayout;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.io.ObjectInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.io.ObjectOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.concurrent.ConcurrentHashMap;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import sun.java2d.Disposer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import sun.java2d.DisposerRecord;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * This class provides a summary of the glyph measurements  for a Font
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * and a set of hints that guide their display.  It provides more metrics
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * information for the Font than the java.awt.FontMetrics class. There
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * is also some redundancy with that class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * The design metrics for a Font are obtained from Font.getDesignMetrics().
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * The FontDesignMetrics object returned will be independent of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * point size of the Font.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * Most users are familiar with the idea of using <i>point size</i> to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * specify the size of glyphs in a font. This point size defines a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * measurement between the baseline of one line to the baseline of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * following line in a single spaced text document. The point size is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * based on <i>typographic points</i>, approximately 1/72 of an inch.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * The Java2D API adopts the convention that one point is equivalent
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * to one unit in user coordinates.  When using a normalized transform
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * for converting user space coordinates to device space coordinates (see
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * GraphicsConfiguration.getDefaultTransform() and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * GraphicsConfiguration.getNormalizingTransform()), 72 user space units
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * equal 1 inch in device space.  In this case one point is 1/72 of an inch.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * The FontDesignMetrics class expresses font metrics in terms of arbitrary
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * <i>typographic units</i> (not points) chosen by the font supplier
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * and used in the underlying platform font representations.  These units are
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * defined by dividing the em-square into a grid.  The em-sqaure is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * theoretical square whose dimensions are the full body height of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * font.  A typographic unit is the smallest measurable unit in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * em-square.  The number of units-per-em is determined by the font
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * designer.  The greater the units-per-em, the greater the precision
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * in metrics.  For example, Type 1 fonts divide the em-square into a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * 1000 x 1000 grid, while TrueType fonts typically use a 2048 x 2048
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * grid.  The scale of these units can be obtained by calling
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * getUnitsPerEm().
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * Typographic units are relative -- their absolute size changes as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * size of the of the em-square changes.  An em-square is 9 points high
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * in a 9-point font.  Because typographic units are relative to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * em-square, a given location on a glyph will have the same coordinates
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * in typographic units regardless of the point size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * Converting typographic units to pixels requires computing pixels-per-em
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * (ppem).  This can be computed as:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
         ppem = device_resolution * (inches-per-point) * pointSize
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * where device resolution could be measured in pixels/inch and the point
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * size of a font is effectively points/em.  Using a normalized transform
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * from user space to device space (see above), results in 1/72 inch/point.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * In this case, ppem is equal to the point size on a 72 dpi monitor, so
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * that an N point font displays N pixels high.  In general,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
        pixel_units = typographic_units * (ppem / units_per_em)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * @see java.awt.Font
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * @see java.awt.GraphicsConfiguration#getDefaultTransform
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * @see java.awt.GraphicsConfiguration#getNormalizingTransform
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
public final class FontDesignMetrics extends FontMetrics {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    static final long serialVersionUID = 4480069578560887773L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    private static final float UNKNOWN_WIDTH = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    private static final int CURRENT_VERSION = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    // height, ascent, descent, leading are reported to the client
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    // as an integer this value is added to the true fp value to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    // obtain a value which is usually going to result in a round up
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    // to the next integer except for very marginal cases.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    private static float roundingUpValue = 0.95f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    // These fields are all part of the old serialization representation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    private Font  font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    private float ascent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    private float descent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    private float leading;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    private float maxAdvance;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    private double[] matrix;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    private int[] cache; // now unused, still here only for serialization
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    // End legacy serialization fields
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    private int serVersion = 0;  // If 1 in readObject, these fields are on the input stream:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    private boolean isAntiAliased;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    private boolean usesFractionalMetrics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    private AffineTransform frcTx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    private transient float[] advCache; // transient since values could change across runtimes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    private transient int height = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    private transient FontRenderContext frc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    private transient double[] devmatrix = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    private transient FontStrike fontStrike;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    private static FontRenderContext DEFAULT_FRC = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    private static FontRenderContext getDefaultFrc() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        if (DEFAULT_FRC == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            AffineTransform tx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            if (GraphicsEnvironment.isHeadless()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                tx = new AffineTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                tx =  GraphicsEnvironment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                    .getLocalGraphicsEnvironment()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                    .getDefaultScreenDevice()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                    .getDefaultConfiguration()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                    .getDefaultTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            DEFAULT_FRC = new FontRenderContext(tx, false, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        return DEFAULT_FRC;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    /* Strongly cache up to 5 most recently requested FontMetrics objects,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     * and softly cache as many as GC allows. In practice this means we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
     * should keep references around until memory gets low.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
     * We key the cache either by a Font or a combination of the Font and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
     * and FRC. A lot of callers use only the font so although there's code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     * duplication, we allow just a font to be a key implying a default FRC.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
     * Also we put the references on a queue so that if they do get nulled
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * out we can clear the keys from the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
     */
23288
b7183846db97 8033624: Fix raw and unchecked lint warnings in sun.font
darcy
parents: 5506
diff changeset
   174
    private static class KeyReference extends SoftReference<Object>
4252
0e645080f74b 6899078: potential deadlock and performance issue in freeing strike resources with D3D pipeline
prr
parents: 3928
diff changeset
   175
        implements DisposerRecord, Disposer.PollDisposable {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
23288
b7183846db97 8033624: Fix raw and unchecked lint warnings in sun.font
darcy
parents: 5506
diff changeset
   177
        static ReferenceQueue<Object> queue = Disposer.getQueue();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        Object key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        KeyReference(Object key, Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            super(value, queue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            this.key = key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            Disposer.addReference(this, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        /* It is possible that since this reference object has been
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
         * enqueued, that a new metrics has been put into the table
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
         * for the same key value. So we'll test to see if the table maps
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
         * to THIS reference. If its a new one, we'll leave it alone.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
         * It is possible that a new entry comes in after our test, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
         * it is unlikely and if this were a problem we would need to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
         * synchronize all 'put' and 'remove' accesses to the cache which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
         * I would prefer not to do.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        public void dispose() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            if (metricsCache.get(key) == this) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                metricsCache.remove(key);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    private static class MetricsKey {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        Font font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        FontRenderContext frc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        int hash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        MetricsKey() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        MetricsKey(Font font, FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            init(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        void init(Font font, FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            this.font = font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            this.frc = frc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            this.hash = font.hashCode() + frc.hashCode();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        public boolean equals(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            if (!(key instanceof MetricsKey)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                font.equals(((MetricsKey)key).font) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                frc.equals(((MetricsKey)key).frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        public int hashCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            return hash;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        /* Synchronize access to this on the class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        static final MetricsKey key = new MetricsKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    /* All accesses to a CHM do not in general need to be synchronized,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     * as incomplete operations on another thread would just lead to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     * harmless cache misses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
    private static final ConcurrentHashMap<Object, KeyReference>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        metricsCache = new ConcurrentHashMap<Object, KeyReference>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    private static final int MAXRECENT = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    private static final FontDesignMetrics[]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        recentMetrics = new FontDesignMetrics[MAXRECENT];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    private static int recentIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    public static FontDesignMetrics getMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        return getMetrics(font, getDefaultFrc());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    public static FontDesignMetrics getMetrics(Font font,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                                               FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        /* When using alternate composites, can't cache based just on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
         * the java.awt.Font. Since this is rarely used and we can still
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
         * cache the physical fonts, its not a problem to just return a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
         * new instance in this case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
         * Note that currently Swing native L&F composites are not handled
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
         * by this code as they use the metrics of the physical anyway.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
         */
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   265
        SunFontManager fm = SunFontManager.getInstance();
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   266
        if (fm.maybeUsingAlternateCompositeFonts() &&
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   267
            FontUtilities.getFont2D(font) instanceof CompositeFont) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            return new FontDesignMetrics(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        FontDesignMetrics m = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        KeyReference r;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        /* There are 2 possible keys used to perform lookups in metricsCache.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
         * If the FRC is set to all defaults, we just use the font as the key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
         * If the FRC is non-default in any way, we construct a hybrid key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
         * that combines the font and FRC.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        boolean usefontkey = frc.equals(getDefaultFrc());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        if (usefontkey) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
            r = metricsCache.get(font);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        } else /* use hybrid key */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
            // NB synchronization is not needed here because of updates to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            // the metrics cache but is needed for the shared key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            synchronized (MetricsKey.class) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                MetricsKey.key.init(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                r = metricsCache.get(MetricsKey.key);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        if (r != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            m = (FontDesignMetrics)r.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if (m == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            /* either there was no reference, or it was cleared. Need a new
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
             * metrics instance. The key to use in the map is a new
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
             * MetricsKey instance when we've determined the FRC is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
             * non-default. Its constructed from local vars so we are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
             * thread-safe - no need to worry about the shared key changing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            m = new FontDesignMetrics(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            if (usefontkey) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                metricsCache.put(font, new KeyReference(font, m));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            } else /* use hybrid key */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                MetricsKey newKey = new MetricsKey(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                metricsCache.put(newKey, new KeyReference(newKey, m));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        /* Here's where we keep the recent metrics */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        for (int i=0; i<recentMetrics.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            if (recentMetrics[i]==m) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                return m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        synchronized (recentMetrics) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            recentMetrics[recentIndex++] = m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            if (recentIndex == MAXRECENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                recentIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        return m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
  /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
   * Constructs a new FontDesignMetrics object for the given Font.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
   * Its private to enable caching - call getMetrics() instead.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
   * @param font a Font object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
   */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
    private FontDesignMetrics(Font font) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        this(font, getDefaultFrc());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    /* private to enable caching - call getMetrics() instead. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    private FontDesignMetrics(Font font, FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
      super(font);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
      this.font = font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
      this.frc = frc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
      this.isAntiAliased = frc.isAntiAliased();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
      this.usesFractionalMetrics = frc.usesFractionalMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
      frcTx = frc.getTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
      matrix = new double[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
      initMatrixAndMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
      initAdvCache();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    private void initMatrixAndMetrics() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   358
        Font2D font2D = FontUtilities.getFont2D(font);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        fontStrike = font2D.getStrike(font, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        StrikeMetrics metrics = fontStrike.getFontMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        this.ascent = metrics.getAscent();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        this.descent = metrics.getDescent();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        this.leading = metrics.getLeading();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        this.maxAdvance = metrics.getMaxAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        devmatrix = new double[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        frcTx.getMatrix(devmatrix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    private void initAdvCache() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        advCache = new float[256];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        // 0 is a valid metric so force it to -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        for (int i = 0; i < 256; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            advCache[i] = UNKNOWN_WIDTH;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
    private void readObject(ObjectInputStream in) throws IOException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                                                  ClassNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        in.defaultReadObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        if (serVersion != CURRENT_VERSION) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            frc = getDefaultFrc();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            isAntiAliased = frc.isAntiAliased();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            usesFractionalMetrics = frc.usesFractionalMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
            frcTx = frc.getTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            frc = new FontRenderContext(frcTx, isAntiAliased, usesFractionalMetrics);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        // when deserialized, members are set to their default values for their type--
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        // not to the values assigned during initialization before the constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        // body!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        height = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        cache = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        initMatrixAndMetrics();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        initAdvCache();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    private void writeObject(ObjectOutputStream out) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        cache = new int[256];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        for (int i=0; i < 256; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            cache[i] = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        serVersion = CURRENT_VERSION;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        out.defaultWriteObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        cache = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    private float handleCharWidth(int ch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        return fontStrike.getCodePointAdvance(ch); // x-component of result only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    // Uses advCache to get character width
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
    // It is incorrect to call this method for ch > 255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    private float getLatinCharWidth(char ch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        float w = advCache[ch];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        if (w == UNKNOWN_WIDTH) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            w = handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
            advCache[ch] = w;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
        return w;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    /* Override of FontMetrics.getFontRenderContext() */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
    public FontRenderContext getFontRenderContext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        return frc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    public int charWidth(char ch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        // default metrics for compatibility with legacy code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        float w;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        if (ch < 0x100) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            w = getLatinCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            w = handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        return (int)(0.5 + w);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    public int charWidth(int ch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        if (!Character.isValidCodePoint(ch)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
            ch = 0xffff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        float w = handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        return (int)(0.5 + w);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
    public int stringWidth(String str) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        float width = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        if (font.hasLayoutAttributes()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            /* TextLayout throws IAE for null, so throw NPE explicitly */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            if (str == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                throw new NullPointerException("str is null");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            if (str.length() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
            width = new TextLayout(str, font, frc).getAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
            int length = str.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
            for (int i=0; i < length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                char ch = str.charAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                if (ch < 0x100) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                    width += getLatinCharWidth(ch);
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   478
                } else if (FontUtilities.isNonSimpleChar(ch)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                    width = new TextLayout(str, font, frc).getAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                    width += handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        return (int) (0.5 + width);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
    public int charsWidth(char data[], int off, int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        float width = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        if (font.hasLayoutAttributes()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            if (len == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            String str = new String(data, off, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            width = new TextLayout(str, font, frc).getAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            /* Explicit test needed to satisfy superclass spec */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            if (len < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                throw new IndexOutOfBoundsException("len="+len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            int limit = off + len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
            for (int i=off; i < limit; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
                char ch = data[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
                if (ch < 0x100) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                    width += getLatinCharWidth(ch);
3928
be186a33df9b 6795908: Refactor FontManager
rkennke
parents: 2
diff changeset
   509
                } else if (FontUtilities.isNonSimpleChar(ch)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                    String str = new String(data, off, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
                    width = new TextLayout(str, font, frc).getAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
                    width += handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        return (int) (0.5 + width);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    /**
48285
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   523
     * This method is called from java.awt.Font only after verifying
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   524
     * the arguments and that the text is simple and there are no
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   525
     * layout attributes, font transform etc.
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   526
     */
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   527
    public Rectangle2D getSimpleBounds(char data[], int off, int len) {
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   528
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   529
        float width = 0;
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   530
        int limit = off + len;
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   531
        for (int i=off; i < limit; i++) {
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   532
            char ch = data[i];
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   533
            if (ch < 0x100) {
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   534
                width += getLatinCharWidth(ch);
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   535
            } else {
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   536
                width += handleCharWidth(ch);
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   537
            }
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   538
        }
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   539
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   540
        float height = ascent + descent + leading;
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   541
        return new Rectangle2D.Float(0f, -ascent, width, height);
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   542
     }
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   543
7e8a0c4ee95e 8189809: Large performance regression in Swing text layout
prr
parents: 47216
diff changeset
   544
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
     * Gets the advance widths of the first 256 characters in the
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   546
     * {@code Font}.  The advance is the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
     * distance from the leftmost point to the rightmost point on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
     * character's baseline.  Note that the advance of a
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   549
     * {@code String} is not necessarily the sum of the advances
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
     * of its characters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     * @return    an array storing the advance widths of the
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   552
     *                 characters in the {@code Font}
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   553
     *                 described by this {@code FontMetrics} object.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    // More efficient than base class implementation - reuses existing cache
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    public int[] getWidths() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        int[] widths = new int[256];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        for (char ch = 0 ; ch < 256 ; ch++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
            float w = advCache[ch];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            if (w == UNKNOWN_WIDTH) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                w = advCache[ch] = handleCharWidth(ch);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
            widths[ch] = (int) (0.5 + w);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        return widths;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
    public int getMaxAdvance() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        return (int)(0.99f + this.maxAdvance);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
  /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
   * Returns the typographic ascent of the font. This is the maximum distance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
   * glyphs in this font extend above the base line (measured in typographic
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
   * units).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
   */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    public int getAscent() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        return (int)(roundingUpValue + this.ascent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
  /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
   * Returns the typographic descent of the font. This is the maximum distance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
   * glyphs in this font extend below the base line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
   */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    public int getDescent() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        return (int)(roundingUpValue + this.descent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
    public int getLeading() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        // nb this ensures the sum of the results of the public methods
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
        // for leading, ascent & descent sum to height.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
        // if the calculations in any other methods change this needs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        // to be changed too.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        // the 0.95 value used here and in the other methods allows some
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        // tiny fraction of leeway before rouding up. A higher value (0.99)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        // caused some excessive rounding up.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            (int)(roundingUpValue + descent + leading) -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            (int)(roundingUpValue + descent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
    // height is calculated as the sum of two separately rounded up values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
    // because typically clients use ascent to determine the y location to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
    // pass to drawString etc and we need to ensure that the height has enough
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
    // space below the baseline to fully contain any descender.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
    public int getHeight() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        if (height < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            height = getAscent() + (int)(roundingUpValue + descent + leading);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
        return height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
}