Package com.jgraph.gaeawt.java.awt.font

Source Code of com.jgraph.gaeawt.java.awt.font.TextLayout

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
/**
* @author Oleg V. Khaschansky
*/

package com.jgraph.gaeawt.java.awt.font;


import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.Map;

import org.apache.harmony.awt.gl.font.BasicMetrics;
import org.apache.harmony.awt.gl.font.TextMetricsCalculator;
import org.apache.harmony.awt.gl.font.TextRunBreaker;
import org.apache.harmony.awt.internal.nls.Messages;

import com.jgraph.gaeawt.java.awt.Font;
import com.jgraph.gaeawt.java.awt.Graphics2D;
import com.jgraph.gaeawt.java.awt.Shape;
import com.jgraph.gaeawt.java.awt.geom.AffineTransform;
import com.jgraph.gaeawt.java.awt.geom.GeneralPath;
import com.jgraph.gaeawt.java.awt.geom.Rectangle2D;

public final class TextLayout implements Cloneable {

    public static class CaretPolicy {

        public CaretPolicy() {
            // Nothing to do
        }

        public TextHitInfo getStrongCaret(TextHitInfo hit1, TextHitInfo hit2, TextLayout layout) {
            // Stronger hit is the one with greater level.
            // If the level is same, leading edge is stronger.

            int level1 = layout.getCharacterLevel(hit1.getCharIndex());
            int level2 = layout.getCharacterLevel(hit2.getCharIndex());

            if (level1 == level2) {
                return (hit2.isLeadingEdge() && (!hit1.isLeadingEdge())) ? hit2 : hit1;
            }
            return level1 > level2 ? hit1 : hit2;
        }

    }

    public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();

    private TextRunBreaker breaker;
    private boolean metricsValid = false;
    private TextMetricsCalculator tmc;
    private BasicMetrics metrics;
    float justificationWidth = -1;

    public TextLayout(String string, Font font, FontRenderContext frc) {
        if (string == null){
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        if (font == null){
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "font")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (string.length() == 0){
            // awt.02='{0}' parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        AttributedString as = new AttributedString(string);
        as.addAttribute(TextAttribute.FONT, font);
        this.breaker = new TextRunBreaker(as.getIterator(), frc);
    }

    public TextLayout(
            String string,
            Map<? extends java.text.AttributedCharacterIterator.Attribute, ?> attributes,
            FontRenderContext frc ) {
        if (string == null){
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        if (attributes == null){
            // awt.01='{0}' parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.01", "attributes")); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        if (string.length() == 0){
            // awt.02='{0}' parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
       
        AttributedString as = new AttributedString(string);
        as.addAttributes(attributes, 0, string.length());
    }

    public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) {
        if (text == null){
            // awt.03='{0}' iterator parameter is null
            throw new IllegalArgumentException(Messages.getString("awt.03", "text")); //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        if (text.getBeginIndex() == text.getEndIndex()){
            // awt.04='{0}' iterator parameter has zero length
            throw new IllegalArgumentException(Messages.getString("awt.04", "text")); //$NON-NLS-1$ //$NON-NLS-2$
        }
    }

    TextLayout(TextRunBreaker breaker) {
        this.breaker = breaker;
    }

    @Override
    public int hashCode() {
        return breaker.hashCode();
    }

    @Override
    protected Object clone() {
        TextLayout res = new TextLayout((TextRunBreaker) breaker.clone());

        if (justificationWidth >= 0) {
            res.handleJustify(justificationWidth);
        }

        return res;
    }

    public boolean equals(TextLayout layout) {
        if (layout == null) {
            return false;
        }
        return this.breaker.equals(layout.breaker);
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof TextLayout ? equals((TextLayout) obj) : false;
    }

    @Override
    public String toString() { // what for?
        return super.toString();
    }

    public void draw(Graphics2D g2d, float x, float y) {
        updateMetrics();
        breaker.drawSegments(g2d, x ,y);
    }

    private void updateMetrics() {
        if (!metricsValid) {
            breaker.createAllSegments();
            tmc = new TextMetricsCalculator(breaker);
            metrics = tmc.createMetrics();
            metricsValid = true;
        }
    }

    public float getAdvance() {
        updateMetrics();
        return metrics.getAdvance();
    }

    public float getAscent() {
        updateMetrics();
        return metrics.getAscent();
    }

    public byte getBaseline() {
        updateMetrics();
        return (byte) metrics.getBaseLineIndex();
    }

    public float[] getBaselineOffsets() {
        updateMetrics();
        return tmc.getBaselineOffsets();
    }

    public Shape getBlackBoxBounds(int firstEndpoint, int secondEndpoint) {
        updateMetrics();
        if (firstEndpoint < secondEndpoint) {
            return breaker.getBlackBoxBounds(firstEndpoint, secondEndpoint);
        }
        return breaker.getBlackBoxBounds(secondEndpoint, firstEndpoint);
    }

    public Rectangle2D getBounds() {
        updateMetrics();
        return breaker.getVisualBounds();
    }

    public int getCharacterCount() {
        return breaker.getCharCount();
    }

    public byte getCharacterLevel(int index) {
        if (index == -1 || index == getCharacterCount()) {
            return (byte) breaker.getBaseLevel();
        }
        return breaker.getLevel(index);
    }

    public float getDescent() {
        updateMetrics();
        return metrics.getDescent();
    }

    public TextLayout getJustifiedLayout(float justificationWidth) throws Error {
        float justification = breaker.getJustification();

        if (justification < 0) {
            // awt.196=Justification impossible, layout already justified
            throw new Error(Messages.getString("awt.196")); //$NON-NLS-1$
        } else if (justification == 0) {
            return this;
        }

        TextLayout justifiedLayout = new TextLayout((TextRunBreaker) breaker.clone());
        justifiedLayout.handleJustify(justificationWidth);
        return justifiedLayout;
    }

    public float getLeading() {
        updateMetrics();
        return metrics.getLeading();
    }

    public Shape getOutline(AffineTransform xform) {
        breaker.createAllSegments();

        GeneralPath outline = breaker.getOutline();

        if (outline != null && xform != null) {
            outline.transform(xform);
        }

        return outline;
    }

    public float getVisibleAdvance() {
        updateMetrics();

        // Trailing whitespace _SHOULD_ be reordered (Unicode spec) to
        // base direction, so it is also trailing
        // in logical representation. We use this fact.
        int lastNonWhitespace = breaker.getLastNonWhitespace();

        if (lastNonWhitespace < 0) {
            return 0;
        } else if (lastNonWhitespace == getCharacterCount()-1) {
            return getAdvance();
        } else if (justificationWidth >= 0) { // Layout is justified
            return justificationWidth;
        } else {
            breaker.pushSegments(
                    breaker.getACI().getBeginIndex(),
                    lastNonWhitespace + breaker.getACI().getBeginIndex() + 1
            );

            breaker.createAllSegments();

            float visAdvance = tmc.createMetrics().getAdvance();

            breaker.popSegments();
            return visAdvance;
        }
    }

    protected void handleJustify(float justificationWidth) {
        float justification = breaker.getJustification();

        if (justification < 0) {
            // awt.196=Justification impossible, layout already justified
            throw new IllegalStateException(Messages.getString("awt.196")); //$NON-NLS-1$
        } else if (justification == 0) {
            return;
        }

        float gap = (justificationWidth - getVisibleAdvance()) * justification;
        breaker.justify(gap);
        this.justificationWidth = justificationWidth;

        // Correct metrics
        tmc = new TextMetricsCalculator(breaker);
        tmc.correctAdvance(metrics);
    }

    public TextHitInfo hitTestChar(float x, float y) {
        return hitTestChar(x, y, getBounds());
    }

    public TextHitInfo hitTestChar(float x, float y, Rectangle2D bounds) {
        if (x > bounds.getMaxX()) {
            return breaker.isLTR() ?
                    TextHitInfo.trailing(breaker.getCharCount() - 1) : TextHitInfo.leading(0);
        }

        if (x < bounds.getMinX()) {
            return breaker.isLTR() ?
                    TextHitInfo.leading(0) : TextHitInfo.trailing(breaker.getCharCount() - 1);
        }

        return breaker.hitTest(x, y);
    }

    public boolean isLeftToRight() {
        return breaker.isLTR();
    }

    public boolean isVertical() {
        return false;
    }
}

TOP

Related Classes of com.jgraph.gaeawt.java.awt.font.TextLayout

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.