/* * 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$ */ package org.apache.fop.area.inline; /** * Abstract base class for both TextArea and Character. */ public abstract class AbstractTextArea extends InlineParent { private static final long serialVersionUID = -1246306443569094371L; /** * this class stores information about spaces and potential adjustments * that can be used in order to re-compute adjustments when a * page-number or a page-number-citation is resolved */ // @SuppressFBWarnings("SE_INNER_CLASS") protected class TextAdjustingInfo extends InlineAdjustingInfo { private static final long serialVersionUID = -2412095162983479947L; /** difference between the optimal width of a space * and the default width of a space according to the font * (this is equivalent to the property word-spacing.optimum) */ protected int spaceDifference; /** * Constructor * * @param stretch the available space for stretching * @param shrink the available space for shrinking * @param adj space adjustment type */ protected TextAdjustingInfo(int stretch, int shrink, int adj) { super(stretch, shrink, adj); } } private int textWordSpaceAdjust; private int textLetterSpaceAdjust; private TextAdjustingInfo textAdjustingInfo; private int baselineOffset; /** * Default constructor */ public AbstractTextArea() { } /** * Constructor with extra parameters: * create a TextAdjustingInfo object * @param stretch the available stretch of the text * @param shrink the available shrink of the text * @param adj the current adjustment of the area */ public AbstractTextArea(int stretch, int shrink, int adj) { textAdjustingInfo = new TextAdjustingInfo(stretch, shrink, adj); } /** * Get text word space adjust. * * @return the text word space adjustment */ public int getTextWordSpaceAdjust() { return textWordSpaceAdjust; } /** * Set text word space adjust. * * @param textWordSpaceAdjust the text word space adjustment */ public void setTextWordSpaceAdjust(int textWordSpaceAdjust) { this.textWordSpaceAdjust = textWordSpaceAdjust; } /** * Get text letter space adjust. * * @return the text letter space adjustment */ public int getTextLetterSpaceAdjust() { return textLetterSpaceAdjust; } /** * Set text letter space adjust. * * @param textLetterSpaceAdjust the text letter space adjustment */ public void setTextLetterSpaceAdjust(int textLetterSpaceAdjust) { this.textLetterSpaceAdjust = textLetterSpaceAdjust; } /** * Set the difference between optimal width of a space and * default width of a space according to the font; this part * of the space adjustment is fixed and must not be * multiplied by the variation factor. * @param spaceDiff the space difference */ public void setSpaceDifference(int spaceDiff) { textAdjustingInfo.spaceDifference = spaceDiff; } /** * recursively apply the variation factor to all descendant areas * @param variationFactor the variation factor that must be applied to adjustments * @param lineStretch the total stretch of the line * @param lineShrink the total shrink of the line * @return true if there is an UnresolvedArea descendant */ public boolean applyVariationFactor(double variationFactor, int lineStretch, int lineShrink) { if (textAdjustingInfo != null) { // compute the new adjustments: // if the variation factor is negative, it means that before // the ipd variation the line had to stretch and now it has // to shrink (or vice versa); // in this case, if the stretch and shrink are not equally // divided among the inline areas, we must compute a // balancing factor double balancingFactor = 1.0; if (variationFactor < 0) { if (textWordSpaceAdjust < 0) { // from a negative adjustment to a positive one balancingFactor = ((double) textAdjustingInfo.availableStretch / textAdjustingInfo.availableShrink) * ((double) lineShrink / lineStretch); } else { // from a positive adjustment to a negative one balancingFactor = ((double) textAdjustingInfo.availableShrink / textAdjustingInfo.availableStretch) * ((double) lineStretch / lineShrink); } } textWordSpaceAdjust = (int) ((textWordSpaceAdjust - textAdjustingInfo.spaceDifference) * variationFactor * balancingFactor) + textAdjustingInfo.spaceDifference; textLetterSpaceAdjust *= variationFactor; // update the ipd of the area int oldAdjustment = textAdjustingInfo.adjustment; textAdjustingInfo.adjustment *= balancingFactor * variationFactor; ipd += textAdjustingInfo.adjustment - oldAdjustment; } return false; } /** * Get baseline offset, i.e. the distance from the before edge * of this area to the nominal baseline. * * @return the baseline offset */ public int getBaselineOffset() { return baselineOffset; } /** * Set the baseline offset. * * @param baselineOffset the baseline offset */ public void setBaselineOffset(int baselineOffset) { this.baselineOffset = baselineOffset; } @Override int getVirtualOffset() { return getBlockProgressionOffset(); } @Override int getVirtualBPD() { /* Word and space areas don't have a properly set bpd; return this area's bpd instead. */ return getBPD(); } }