/*
 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.font;

import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;

/* These are font metrics: they are in user space, not device space.
 * Hence they are not truly "strike" metrics. However it is convenient to
 * treat them as such since we need to have a scaler context to obtain them
 * and also to cache them. The old implementation obtained a C++ strike object
 * that matched the Font TX + pt size only. It was wasteful of strike objects.
 * This new implementation still has separate StrikeMetrics for 2 fonts that
 * are really the same but are used in different device transforms, but at
 * least it doesn't create a whole new strike just to get the metrics for
 * a strike in a transformed graphics.
 * So these metrics do not take into account the device transform. They
 * are considered inherent properties of the font. Hence it may be that we
 * should use the device transform to obtain the most accurate metrics, but
 * typically 1.1 APIs do not provide for this. So some APIs may want to
 * ignore the dev. tx and others may want to use it, and then apply an
 * inverse transform. For now we ignore the dev. tx.
 * "Font" metrics are representative of a typical glyph in the font.
 * Generally speaking these values are the choice of the font designer and
 * are stored in the font, from which we retrieve the values. They do
 * not necessarily equate to the maximum bounds of all glyphs in the font.
 * Note that the ascent fields are typically a -ve value as we use a top-left
 * origin user space, and text is positioned relative to its baseline.
 */
public final class StrikeMetrics {

    public float ascentX;
    public float ascentY;
    public float descentX;
    public float descentY;
    public float baselineX;
    public float baselineY;
    public float leadingX;
    public float leadingY;
    public float maxAdvanceX;
    public float maxAdvanceY;


    /* The no-args constructor is used by CompositeStrike, which then
     * merges in the metrics of physical fonts.
     * The approach here is the same as earlier releases but it is flawed
     * take for example the following which ignores leading for simplicity.
     * Say we have a composite with an element asc=-9, dsc=2, and another with
     * asc=-7, dsc=3.  The merged font is (-9,3) for height of -(-9)+3=12.
     * Suppose this same font has been derived with a 180% rotation
     * Now its signs for ascent/descent are reversed. Its (9,-2) and (7,-3)
     * Its merged values are (using the code in this class) (7,-2) for
     * a height of -(7)+-2 = =-9!
     * We need to have a more intelligent merging algorithm,
     * which so far as I can see needs to apply an inverse of the font
     * tx, do its merging, and then reapply the font tx.
     * This wouldn't often be a problem as there rarely is a font TX, and
     * the tricky part is getting the information. Probably the no-args
     * constructor needs to pass a TX in to be applied to all merges.
     * CompositeStrike would be left with the problem of figuring out what
     * tx to use.
     * But at least for now we are probably no worse than 1.4 ...
     * REMIND: FIX THIS.
     */
    StrikeMetrics() {
        ascentX = ascentY = Integer.MAX_VALUE;
        descentX = descentY = leadingX = leadingY = Integer.MIN_VALUE;
        baselineX = baselineX = maxAdvanceX = maxAdvanceY = Integer.MIN_VALUE;
    }

    StrikeMetrics(float ax, float ay, float dx, float dy, float bx, float by,
                  float lx, float ly, float mx, float my) {
       ascentX = ax;
       ascentY = ay;
       descentX = dx;
       descentY = dy;
       baselineX = bx;
       baselineY = by;
       leadingX = lx;
       leadingY = ly;
       maxAdvanceX = mx;
       maxAdvanceY = my;
    }

    public float getAscent() {
        return -ascentY;
    }

    public float getDescent() {
        return descentY;
    }

    public float getLeading() {
        return leadingY;
    }

    public float getMaxAdvance() {
        return maxAdvanceX;
    }

    /*
     * Currently only used to merge together slot metrics to create
     * the metrics for a composite font.
     */
     void merge(StrikeMetrics other) {
         if (other == null) {
             return;
         }
         if (other.ascentX < ascentX) {
             ascentX = other.ascentX;
         }
         if (other.ascentY < ascentY) {
             ascentY = other.ascentY;
         }
         if (other.descentX > descentX) {
             descentX = other.descentX;
         }
         if (other.descentY > descentY) {
             descentY = other.descentY;
         }
         if (other.baselineX > baselineX) {
             baselineX = other.baselineX;
         }
         if (other.baselineY > baselineY) {
             baselineY = other.baselineY;
         }
         if (other.leadingX > leadingX) {
             leadingX = other.leadingX;
         }
         if (other.leadingY > leadingY) {
             leadingY = other.leadingY;
         }
         if (other.maxAdvanceX > maxAdvanceX) {
             maxAdvanceX = other.maxAdvanceX;
         }
         if (other.maxAdvanceY > maxAdvanceY) {
             maxAdvanceY = other.maxAdvanceY;
         }
    }

    /* Used to transform the values back into user space.
     * This is done ONCE by the strike so clients should not need
     * to worry about this
     */
    void convertToUserSpace(AffineTransform invTx) {
        Point2D.Float pt2D = new Point2D.Float();

        pt2D.x = ascentX; pt2D.y = ascentY;
        invTx.deltaTransform(pt2D, pt2D);
        ascentX = pt2D.x; ascentY = pt2D.y;

        pt2D.x = descentX; pt2D.y = descentY;
        invTx.deltaTransform(pt2D, pt2D);
        descentX = pt2D.x; descentY = pt2D.y;

        pt2D.x = baselineX; pt2D.y = baselineY;
        invTx.deltaTransform(pt2D, pt2D);
        baselineX = pt2D.x; baselineY = pt2D.y;

        pt2D.x = leadingX; pt2D.y = leadingY;
        invTx.deltaTransform(pt2D, pt2D);
        leadingX = pt2D.x; leadingY = pt2D.y;

        pt2D.x = maxAdvanceX; pt2D.y = maxAdvanceY;
        invTx.deltaTransform(pt2D, pt2D);
        maxAdvanceX = pt2D.x; maxAdvanceY = pt2D.y;
    }

    public String toString() {
        return "ascent:x="      + ascentX +     " y=" + ascentY +
               " descent:x="    + descentX +    " y=" + descentY +
               " baseline:x="   + baselineX +   " y=" + baselineY +
               " leading:x="    + leadingX +    " y=" + leadingY +
               " maxAdvance:x=" + maxAdvanceX + " y=" + maxAdvanceY;
    }
}
