FileDocCategorySizeDatePackage
TextMetricsCalculator.javaAPI DocAndroid 1.5 API7475Wed May 06 22:41:54 BST 2009org.apache.harmony.awt.gl.font

TextMetricsCalculator

public class TextMetricsCalculator extends Object
This class operates with an arbitrary text string which can include any number of style, font and direction runs. It is responsible for computation of the text metrics, such as ascent, descent, leading and advance. Actually, each text run segment contains logic which allows it to compute its own metrics and responsibility of this class is to combine metrics for all segments included in the text, managed by the associated TextRunBreaker object.

Fields Summary
TextRunBreaker
breaker
float
ascent
float
descent
float
leading
float
advance
private float[]
baselineOffsets
int
baselineIndex
Constructors Summary
public TextMetricsCalculator(TextRunBreaker breaker)


       
        this.breaker = breaker;
        checkBaselines();
    
Methods Summary
public voidcheckBaselines()
Take baseline offsets from the first font or graphic attribute and normalizes them, than caches the results.

        // Take baseline offsets of the first font and normalize them
        HashMap<Integer, Font> fonts = breaker.fonts;

        Object val = fonts.get(new Integer(0));

        if (val instanceof Font) {
            Font firstFont = (Font) val;
            LineMetrics lm = firstFont.getLineMetrics(breaker.text, 0, 1, breaker.frc);
            baselineOffsets = lm.getBaselineOffsets();
            baselineIndex = lm.getBaselineIndex();
        } else if (val instanceof GraphicAttribute) {
            // Get first graphic attribute and use it
            GraphicAttribute ga = (GraphicAttribute) val;

            int align = ga.getAlignment();

            if (
                    align == GraphicAttribute.TOP_ALIGNMENT ||
                    align == GraphicAttribute.BOTTOM_ALIGNMENT
            ) {
                baselineIndex = GraphicAttribute.ROMAN_BASELINE;
            } else {
                baselineIndex = align;
            }

            baselineOffsets = new float[3];
            baselineOffsets[0] = 0;
            baselineOffsets[1] = (ga.getDescent() - ga.getAscent()) / 2.f;
            baselineOffsets[2] = -ga.getAscent();
        } else { // Use defaults - Roman baseline and zero offsets
            baselineIndex = GraphicAttribute.ROMAN_BASELINE;
            baselineOffsets = new float[3];
        }

        // Normalize offsets if needed
        if (baselineOffsets[baselineIndex] != 0) {
            float baseOffset = baselineOffsets[baselineIndex];
            for (int i = 0; i < baselineOffsets.length; i++) {
                baselineOffsets[i] -= baseOffset;
            }
        }
    
voidcomputeMetrics()
Computes metrics for the text managed by the associated TextRunBreaker


        ArrayList<TextRunSegment> segments = breaker.runSegments;

        float maxHeight = 0;
        float maxHeightLeading = 0;

        for (int i = 0; i < segments.size(); i++) {
            TextRunSegment segment = segments.get(i);
            BasicMetrics metrics = segment.metrics;
            int baseline = metrics.baseLineIndex;

            if (baseline >= 0) {
                float baselineOffset = baselineOffsets[metrics.baseLineIndex];
                float fixedDescent = metrics.descent + baselineOffset;

                ascent = Math.max(ascent, metrics.ascent - baselineOffset);
                descent = Math.max(descent, fixedDescent);
                leading = Math.max(leading, fixedDescent + metrics.leading);
            } else { // Position is not fixed by the baseline, need sum of ascent and descent
                float height = metrics.ascent + metrics.descent;

                maxHeight = Math.max(maxHeight, height);
                maxHeightLeading = Math.max(maxHeightLeading, height + metrics.leading);
            }
        }

        // Need to increase sizes for graphics?
        if (maxHeightLeading != 0) {
            descent = Math.max(descent, maxHeight - ascent);
            leading = Math.max(leading, maxHeightLeading - ascent);
        }

        // Normalize leading
        leading -= descent;

        BasicMetrics currMetrics;
        float currAdvance = 0;

        for (int i = 0; i < segments.size(); i++) {
            TextRunSegment segment = segments.get(breaker.getSegmentFromVisualOrder(i));
            currMetrics = segment.metrics;

            segment.y = getBaselineOffset(currMetrics.baseLineIndex)
                    + currMetrics.superScriptOffset;
            segment.x = currAdvance;

            currAdvance += segment.getAdvance();
        }

        advance = currAdvance;
    
public voidcorrectAdvance(BasicMetrics metrics)
Corrects advance after justification. Gets BasicMetrics object and updates advance stored into it.

param
metrics - metrics with outdated advance which should be corrected

        ArrayList<TextRunSegment> segments = breaker.runSegments;
        TextRunSegment segment = segments.get(breaker
                .getSegmentFromVisualOrder(segments.size() - 1));

        advance = segment.x + segment.getAdvance();
        metrics.advance = advance;
    
public BasicMetricscreateMetrics()
Computes metrics and creates BasicMetrics object from them

return
basic metrics

        computeMetrics();
        return new BasicMetrics(this);
    
floatgetBaselineOffset(int baselineIndex)
Returns either values cached by checkBaselines method or reasonable values for the TOP and BOTTOM alignments.

param
baselineIndex - baseline index
return
baseline offset

        if (baselineIndex >= 0) {
            return baselineOffsets[baselineIndex];
        } else if (baselineIndex == GraphicAttribute.BOTTOM_ALIGNMENT) {
            return descent;
        } else if (baselineIndex == GraphicAttribute.TOP_ALIGNMENT) {
            return -ascent;
        } else {
            // awt.3F=Invalid baseline index
            throw new IllegalArgumentException(Messages.getString("awt.3F")); //$NON-NLS-1$
        }
    
public float[]getBaselineOffsets()

        float ret[] = new float[baselineOffsets.length];
        System.arraycopy(baselineOffsets, 0, ret, 0, baselineOffsets.length);
        return ret;