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