Package org.apache.fop.layoutmgr.inline

Source Code of org.apache.fop.layoutmgr.inline.AlignmentContext

/*
* 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.
*/

/* $Id: AlignmentContext.java 679326 2008-07-24 09:35:34Z vhennebert $ */

package org.apache.fop.layoutmgr.inline;

import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.Font;

/**
* The alignment context is carried within a LayoutContext and as
* part of the Knuth Inline elements to facilitate proper line building.
* All measurements are in mpt.
*/
public class AlignmentContext implements Constants {

    /** The height or BPD of this context */
    private int areaHeight;
    /** The computed line-height property value applicable */
    private int lineHeight;
    /** The distance in BPD from the top of the box to the alignmentPoint */
    private int alignmentPoint;
    /** The baseline shift value in effect */
    private int baselineShiftValue;
    /** The computed alignment baseline identifier */
    private int alignmentBaselineIdentifier;
    /** The x height */
    private int xHeight;
    private ScaledBaselineTable scaledBaselineTable = null;
    private ScaledBaselineTable actualBaselineTable = null;
    private AlignmentContext parentAlignmentContext = null;

    /**
     * Creates a new instance of AlignmentContext
     * for graphics areas.
     * @param height the total height of the area
     * @param alignmentAdjust the alignment-adjust property
     * @param alignmentBaseline the alignment-baseline property
     * @param baselineShift the baseline-shift property
     * @param dominantBaseline the dominant-baseline property
     * @param parentAlignmentContext the parent alignment context
     */
    public AlignmentContext(int height
                            , Length alignmentAdjust
                            , int alignmentBaseline
                            , Length baselineShift
                            , int dominantBaseline
                            , AlignmentContext parentAlignmentContext) {

        this.areaHeight = height;
        this.lineHeight = height;
        this.xHeight = height;
        this.parentAlignmentContext = parentAlignmentContext;
        this.scaledBaselineTable = parentAlignmentContext.getScaledBaselineTable();
        setAlignmentBaselineIdentifier(alignmentBaseline
                                       , parentAlignmentContext.getDominantBaselineIdentifier());
        setBaselineShift(baselineShift);
        int dominantBaselineIdentifier = parentAlignmentContext.getDominantBaselineIdentifier();
        boolean newScaledBaselineTableRequired = false;
        if (baselineShiftValue != 0) {
            newScaledBaselineTableRequired = true;
        }
        switch (dominantBaseline) {
            case EN_AUTO:
                newScaledBaselineTableRequired = baselineShiftValue != 0;
                break;
            case EN_USE_SCRIPT: // TODO
                break;
            case EN_NO_CHANGE:
                break;
            case EN_RESET_SIZE:
                newScaledBaselineTableRequired = true;
                break;
            default:
                newScaledBaselineTableRequired = true;
                dominantBaselineIdentifier = dominantBaseline;
                break;
        }
        actualBaselineTable = ScaledBaselineTableFactory.makeGraphicsScaledBaselineTable(
                                                            height,
                                                            dominantBaselineIdentifier,
                                                            scaledBaselineTable.getWritingMode());
        if (newScaledBaselineTableRequired) {
            scaledBaselineTable = ScaledBaselineTableFactory.makeGraphicsScaledBaselineTable(
                                                            height,
                                                            dominantBaselineIdentifier,
                                                            scaledBaselineTable.getWritingMode());
        }
        setAlignmentAdjust(alignmentAdjust);
    }

    /**
     * Creates a new instance of AlignmentContext
     * @param font the font
     * @param lineHeight the computed value of the lineHeight property
     * @param alignmentAdjust the alignment-adjust property
     * @param alignmentBaseline the alignment-baseline property
     * @param baselineShift the baseline-shift property
     * @param dominantBaseline the dominant-baseline property
     * @param parentAlignmentContext the parent alignment context
     */
    public AlignmentContext(Font font
                            , int lineHeight
                            , Length alignmentAdjust
                            , int alignmentBaseline
                            , Length baselineShift
                            , int dominantBaseline
                            , AlignmentContext parentAlignmentContext) {
        this.areaHeight = font.getAscender() - font.getDescender();
        this.lineHeight = lineHeight;
        this.parentAlignmentContext = parentAlignmentContext;
        this.scaledBaselineTable = parentAlignmentContext.getScaledBaselineTable();
        this.xHeight = font.getXHeight();
        setAlignmentBaselineIdentifier(alignmentBaseline
                                       , parentAlignmentContext.getDominantBaselineIdentifier());
        setBaselineShift(baselineShift);
        int dominantBaselineIdentifier = parentAlignmentContext.getDominantBaselineIdentifier();
        boolean newScaledBaselineTableRequired = false;
        if (baselineShiftValue != 0) {
            newScaledBaselineTableRequired = true;
        }
        switch (dominantBaseline) {
            case EN_AUTO:
                newScaledBaselineTableRequired = baselineShiftValue != 0;
                break;
            case EN_USE_SCRIPT: // TODO
                break;
            case EN_NO_CHANGE:
                break;
            case EN_RESET_SIZE:
                newScaledBaselineTableRequired = true;
                break;
            default:
                newScaledBaselineTableRequired = true;
                dominantBaselineIdentifier = dominantBaseline;
                break;
        }
        actualBaselineTable = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font,
                                                            dominantBaselineIdentifier,
                                                            scaledBaselineTable.getWritingMode());
        if (newScaledBaselineTableRequired) {
            scaledBaselineTable = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font,
                                    dominantBaselineIdentifier,
                                    scaledBaselineTable.getWritingMode());
        }
        setAlignmentAdjust(alignmentAdjust);
    }

    /**
     * Creates a new instance of AlignmentContext based simply
     * on the font and the writing mode.
     * @param font the font
     * @param lineHeight the computed value of the lineHeight property
     * @param writingMode the current writing mode
     */
    public AlignmentContext(Font font, int lineHeight, int writingMode) {
        this.areaHeight = font.getAscender() - font.getDescender();
        this.lineHeight = lineHeight;
        this.xHeight = font.getXHeight();
        this.parentAlignmentContext = null;
        this.scaledBaselineTable
                    = ScaledBaselineTableFactory.makeFontScaledBaselineTable(font, writingMode);
        this.actualBaselineTable = scaledBaselineTable;
        this.alignmentBaselineIdentifier = getDominantBaselineIdentifier();
        this.alignmentPoint = font.getAscender();
        this.baselineShiftValue = 0;
    }

    /**
     * Returns the alignment point for this context.
     * This is the point on the start edge of the area this context
     * applies to measured from the before edge of the area.
     * @return the default alignment point
     */
    public int getAlignmentPoint() {
        return alignmentPoint;
    }

    /**
     * Returns the current value of baseline shift in effect.
     * @return the baseline shift
     */
    public int getBaselineShiftValue() {
        return baselineShiftValue;
    }

    /**
     * Returns the current alignment baseline identifier
     * @return the alignment baseline identifier
     */
    public int getAlignmentBaselineIdentifier() {
        return alignmentBaselineIdentifier;
    }

    /**
     * Sets the current alignment baseline identifer. For
     * alignment-baseline values of "auto" and "baseline" this
     * method does the conversion into the appropriate computed
     * value assuming script is "auto" and the fo is not fo:character.
     * @param alignmentBaseline the alignment-baseline property
     * @param parentDominantBaselineIdentifier the dominant baseline of the parent fo
     */
    private void setAlignmentBaselineIdentifier(int alignmentBaseline
                                               , int parentDominantBaselineIdentifier) {
        switch (alignmentBaseline) {
            case EN_AUTO: // fall through
            case EN_BASELINE:
                this.alignmentBaselineIdentifier = parentDominantBaselineIdentifier;
                break;
            case EN_BEFORE_EDGE:
            case EN_TEXT_BEFORE_EDGE:
            case EN_CENTRAL:
            case EN_MIDDLE:
            case EN_AFTER_EDGE:
            case EN_TEXT_AFTER_EDGE:
            case EN_IDEOGRAPHIC:
            case EN_ALPHABETIC:
            case EN_HANGING:
            case EN_MATHEMATICAL:
                this.alignmentBaselineIdentifier = alignmentBaseline;
                break;
        }
    }

    /**
     * Sets the current alignment baseline identifer. For
     * alignment-baseline values of "auto" and "baseline" this
     * method does the conversion into the appropriate computed
     * value assuming script is "auto" and the fo is not fo:character.
     * @param alignmentAdjust the alignment-adjust property
     */
    private void setAlignmentAdjust(Length alignmentAdjust) {
        int beforeEdge = actualBaselineTable.getBaseline(EN_BEFORE_EDGE);
        switch (alignmentAdjust.getEnum()) {
            case EN_AUTO:
                alignmentPoint = beforeEdge
                                    - actualBaselineTable.getBaseline(alignmentBaselineIdentifier);
                break;
            case EN_BASELINE:
                alignmentPoint = beforeEdge;
                break;
            case EN_BEFORE_EDGE:
            case EN_TEXT_BEFORE_EDGE:
            case EN_CENTRAL:
            case EN_MIDDLE:
            case EN_AFTER_EDGE:
            case EN_TEXT_AFTER_EDGE:
            case EN_IDEOGRAPHIC:
            case EN_ALPHABETIC:
            case EN_HANGING:
            case EN_MATHEMATICAL:
                alignmentPoint = beforeEdge
                                    - actualBaselineTable.getBaseline(alignmentAdjust.getEnum());
                break;
            default:
                alignmentPoint = beforeEdge
                    + alignmentAdjust.getValue(new SimplePercentBaseContext(null
                                                        , LengthBase.ALIGNMENT_ADJUST
                                                        , lineHeight));
                break;
        }
    }

    /**
     * Return the scaled baseline table for this context.
     * @return the scaled baseline table
     */
    public ScaledBaselineTable getScaledBaselineTable() {
        return this.scaledBaselineTable;
    }

    /**
     * Return the dominant baseline identifier.
     * @return the dominant baseline identifier
     */
    public int getDominantBaselineIdentifier() {
        return scaledBaselineTable.getDominantBaselineIdentifier();
    }

    /**
     * Return the writing mode.
     * @return the writing mode
     */
    public int getWritingMode() {
        return scaledBaselineTable.getWritingMode();
    }

    /**
     * Calculates the baseline shift value based on the baseline-shift
     * property value.
     * @param baselineShift the baseline shift property value
     * @return the computed baseline shift value
     */
    private void setBaselineShift(Length baselineShift) {
        baselineShiftValue = 0;
        ScaledBaselineTable sbt = null;
        switch (baselineShift.getEnum()) {
            case EN_BASELINE: //Nothing to do
                break;
            case EN_SUB:
                baselineShiftValue = Math.round(-(xHeight / 2)
                                + parentAlignmentContext.getActualBaselineOffset(EN_ALPHABETIC)
                                );
                break;
            case EN_SUPER:
                baselineShiftValue = Math.round(parentAlignmentContext.getXHeight()
                                + parentAlignmentContext.getActualBaselineOffset(EN_ALPHABETIC)
                                );
                break;
            case 0: // A <length> or <percentage> value
                baselineShiftValue = baselineShift.getValue(
                    new SimplePercentBaseContext(null
                                                , LengthBase.CUSTOM_BASE
                                                , parentAlignmentContext.getLineHeight()));
                break;
        }
    }

    /**
     * Return the parent alignment context.
     * @return the parent alignment context
     */
    public AlignmentContext getParentAlignmentContext() {
        return parentAlignmentContext;
    }

    /**
     * Return the offset between the current dominant baseline and
     * the parent dominant baseline.
     * @return the offset in shift direction
     */
    public int getBaselineOffset() {
        if (parentAlignmentContext == null) {
            return 0;
        }
        return parentAlignmentContext.getScaledBaselineTable()
                                    .getBaseline(alignmentBaselineIdentifier)
                - scaledBaselineTable
                    .deriveScaledBaselineTable(parentAlignmentContext.getDominantBaselineIdentifier())
                    .getBaseline(alignmentBaselineIdentifier)
                - scaledBaselineTable
                    .getBaseline(parentAlignmentContext.getDominantBaselineIdentifier())
                + baselineShiftValue;
    }

    /**
     * Return the offset between the current dominant baseline and
     * the outermost parent dominant baseline.
     * @return the offet in shift direction
     */
    public int getTotalBaselineOffset() {
        int offset = 0;
        if (parentAlignmentContext != null) {
            offset = getBaselineOffset() + parentAlignmentContext.getTotalBaselineOffset();
        }
        return offset;
    }

    /**
     * Return the offset between the alignment baseline and
     * the outermost parent dominant baseline.
     * @return the offset in shift direction
     */
    public int getTotalAlignmentBaselineOffset() {
        return getTotalAlignmentBaselineOffset(alignmentBaselineIdentifier);
    }

    /**
     * Return the offset between the given alignment baseline and
     * the outermost parent dominant baseline.
     * @param alignmentBaselineId the alignment baseline
     * @return the offset
     */
    public int getTotalAlignmentBaselineOffset(int alignmentBaselineId) {
        int offset = baselineShiftValue;
        if (parentAlignmentContext != null) {
            offset = parentAlignmentContext.getTotalBaselineOffset()
                    + parentAlignmentContext.getScaledBaselineTable()
                        .getBaseline(alignmentBaselineId)
                    + baselineShiftValue;
        }
        return offset;
    }

    /**
     * Return the offset between the dominant baseline and
     * the given actual baseline
     * @param baselineIdentifier the baseline
     * @return the offset
     */
    public int getActualBaselineOffset(int baselineIdentifier) {
        // This is the offset from the dominant baseline to the alignment baseline
        int offset = getTotalAlignmentBaselineOffset() - getTotalBaselineOffset();
        // Add the offset to the actual baseline we want
        offset += actualBaselineTable.deriveScaledBaselineTable(alignmentBaselineIdentifier)
                    .getBaseline(baselineIdentifier);
        return offset;
    }

    /**
     * Return the offset the outermost parent dominant baseline
     * and the top of this box.
     * @return the offset
     */
    private int getTotalTopOffset() {
        int offset = getTotalAlignmentBaselineOffset() + getAltitude();
        return offset;
    }

    /**
     * Return the total height of the context.
     * @return the height
     */
    public int getHeight() {
        return areaHeight;
    }

    /**
     * Return the line height of the context.
     * @return the height
     */
    public int getLineHeight() {
        return lineHeight;
    }

    /**
     * The altitude of the context that is the height above the
     * alignment point.
     * @return the altitude
     */
    public int getAltitude() {
        return alignmentPoint;
    }

    /**
     * The depth of the context that is the height below
     * alignment point.
     * @return the altitude
     */
    public int getDepth() {
        return getHeight() - alignmentPoint;
    }

    /**
     * The x height of the context.
     * @return the x height
     */
    public int getXHeight() {
        return this.xHeight;
    }

    /**
     * Resizes the line as specified. Assumes that the new alignment point
     * is on the dominant baseline, that is this function should be called for
     * line areas only.
     * @param newLineHeight the new height of the line
     * @param newAlignmentPoint the new alignment point
     */
    public void resizeLine(int newLineHeight, int newAlignmentPoint) {
        areaHeight = newLineHeight;
        alignmentPoint = newAlignmentPoint;
        scaledBaselineTable.setBeforeAndAfterBaselines(alignmentPoint
                                                        , alignmentPoint - areaHeight);
    }

    /**
     * Returns the offset from the before-edge of the parent to
     * this context.
     * @return the offset for rendering
     */
    public int getOffset() {
        int offset = 0;
        if (parentAlignmentContext != null) {
            offset = parentAlignmentContext.getTotalTopOffset() - getTotalTopOffset();
        } else {
            offset = getAltitude() - scaledBaselineTable.getBaseline(EN_TEXT_BEFORE_EDGE);
        }
        return offset;
    }

    /**
     * Returns an indication if we still use the initial baseline table.
     * The initial baseline table is the table generated by the Line LM.
     * @return true if this is still the initial baseline table
     */
    public boolean usesInitialBaselineTable() {
        return parentAlignmentContext == null
               || (scaledBaselineTable == parentAlignmentContext.getScaledBaselineTable()
                    && parentAlignmentContext.usesInitialBaselineTable());
    }

    private boolean isHorizontalWritingMode() {
        return (getWritingMode() == EN_LR_TB || getWritingMode() == EN_RL_TB);
    }

    /** {@inheritDoc} */
    public String toString() {
        StringBuffer sb = new StringBuffer(64);
        sb.append("ah=" + areaHeight);
        sb.append(" lp=" + lineHeight);
        sb.append(" ap=" + alignmentPoint);
        sb.append(" ab=" + alignmentBaselineIdentifier);
        sb.append(" bs=" + baselineShiftValue);
        return sb.toString();
    }

}
TOP

Related Classes of org.apache.fop.layoutmgr.inline.AlignmentContext

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.