123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /*
- * 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;
-
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
-
- import org.apache.fop.area.inline.InlineArea;
-
- import static org.apache.fop.fo.Constants.EN_CENTER;
- import static org.apache.fop.fo.Constants.EN_END;
- import static org.apache.fop.fo.Constants.EN_JUSTIFY;
- import static org.apache.fop.fo.Constants.EN_START;
-
- /**
- * The line area.
- * This is a line area that contains inline areas.
- */
- public class LineArea extends Area {
-
- private static final long serialVersionUID = 7670235908329290684L;
-
- /**
- * this class stores information about line width and potential adjustments
- * that can be used in order to re-compute adjustement and / or indents when a
- * page-number or a page-number-citation is resolved
- */
- private final class LineAdjustingInfo implements Serializable {
-
- private static final long serialVersionUID = -6103629976229458273L;
-
- private int lineAlignment;
- private int difference;
- private int availableStretch;
- private int availableShrink;
- private double variationFactor;
- private boolean bAddedToAreaTree;
-
- private LineAdjustingInfo(int alignment, int diff,
- int stretch, int shrink) {
- lineAlignment = alignment;
- difference = diff;
- availableStretch = stretch;
- availableShrink = shrink;
- variationFactor = 1.0;
- bAddedToAreaTree = false;
- }
-
- /** {@inheritDoc} */
- public String toString() {
- return getClass().getSimpleName()
- + ": diff=" + difference
- + ", variation=" + variationFactor
- + ", stretch=" + availableStretch
- + ", shrink=" + availableShrink;
- }
- }
-
- private LineAdjustingInfo adjustingInfo;
-
- // this class can contain the dominant char styling info
- // this means that many renderers can optimise a bit
-
- private List<InlineArea> inlineAreas = new ArrayList<InlineArea>();
-
- /**
- * default constructor:
- * nothing to do
- */
- public LineArea() {
- }
-
- /**
- * constructor with extra parameters:
- * a new LineAdjustingInfo object is created
- * @param alignment alignment of this line
- * @param diff difference between content width and line width
- * @param stretch the available stretch for any adjustments
- * @param shrink the available shrink for any adjustments
- */
- public LineArea(int alignment, int diff,
- int stretch, int shrink) {
- adjustingInfo = new LineAdjustingInfo(alignment, diff, stretch, shrink);
- }
-
- /**
- * Add a child area to this line area.
- *
- * @param childArea the inline child area to add
- */
- @Override
- public void addChildArea(Area childArea) {
- if (childArea instanceof InlineArea) {
- addInlineArea((InlineArea)childArea);
- // set the parent area for the child area
- ((InlineArea)childArea).setParentArea(this);
- }
- }
-
- /**
- * Add an inline child area to this line area.
- *
- * @param area the inline child area to add
- */
- public void addInlineArea(InlineArea area) {
- inlineAreas.add(area);
- }
-
- /**
- * <p>Set (en masse) the inline child areas of this line area.</p>
- * <p> Used by bidirectional processing after line area consituent reordering.</p>
- * @param inlineAreas the list of inline areas
- */
- public void setInlineAreas(List inlineAreas) {
- for (Iterator<InlineArea> it = inlineAreas.iterator(); it.hasNext();) {
- InlineArea ia = it.next();
- Area pa = ia.getParentArea();
- if (pa == null) {
- ia.setParentArea(this);
- } else {
- assert pa == this;
- }
- }
- this.inlineAreas = inlineAreas;
- }
-
- /**
- * Get the inline child areas of this line area.
- *
- * @return the list of inline areas
- */
- public List getInlineAreas() {
- return inlineAreas;
- }
-
- /**
- * Get the start indent of this line area.
- * The start indent is used for offsetting the start of
- * the inline areas for alignment or other indents.
- *
- * @return the start indent value
- */
- public int getStartIndent() {
- if (hasTrait(Trait.START_INDENT)) {
- return getTraitAsInteger(Trait.START_INDENT);
- } else {
- return 0;
- }
- }
-
- /**
- * Get the end indent of this line area.
- * The end indent is used for offsetting the end of
- * the inline areas for alignment or other indents.
- *
- * @return the end indent value
- */
- public int getEndIndent() {
- if (hasTrait(Trait.END_INDENT)) {
- return getTraitAsInteger(Trait.END_INDENT);
- } else {
- return 0;
- }
- }
-
- /**
- * Updates the extents of the line area from its children.
- */
- public void updateExtentsFromChildren() {
- int ipd = 0;
- int bpd = 0;
- for (int i = 0, len = inlineAreas.size(); i < len; i++) {
- ipd = Math.max(ipd, inlineAreas.get(i).getAllocIPD());
- bpd += inlineAreas.get(i).getAllocBPD();
- }
- setIPD(ipd);
- setBPD(bpd);
- }
-
- /**
- * receive notification about the ipd variation of a descendant area
- * and perform the needed adjustment, according to the alignment;
- * in particular:
- * <ul>
- * <li>left-aligned text needs no adjustement;</li>
- * <li>right-aligned text and centered text are handled locally,
- * adjusting the indent of this LineArea;</li>
- * <li>justified text requires a more complex adjustment, as the
- * variation factor computed on the basis of the total
- * stretch and shrink of the line must be applied in every
- * descendant leaf areas (text areas and leader areas).</li>
- * </ul>
- * @param ipdVariation the difference between old and new ipd
- */
- public void handleIPDVariation(int ipdVariation) {
- int si = getStartIndent();
- int ei = getEndIndent();
- switch (adjustingInfo.lineAlignment) {
- case EN_START:
- // adjust end indent
- addTrait(Trait.END_INDENT, ei - ipdVariation);
- break;
- case EN_CENTER:
- // adjust start and end indents
- addTrait(Trait.START_INDENT, si - ipdVariation / 2);
- addTrait(Trait.END_INDENT, ei - ipdVariation / 2);
- break;
- case EN_END:
- // adjust start indent
- addTrait(Trait.START_INDENT, si - ipdVariation);
- break;
- case EN_JUSTIFY:
- // compute variation factor
- adjustingInfo.variationFactor *= (float) (adjustingInfo.difference - ipdVariation)
- / adjustingInfo.difference;
- adjustingInfo.difference -= ipdVariation;
- // if the LineArea has already been added to the area tree,
- // call finalize(); otherwise, wait for the LineLM to call it
- if (adjustingInfo.bAddedToAreaTree) {
- finish();
- }
- break;
- default:
- throw new RuntimeException();
- }
- }
-
- /**
- * apply the variation factor to all descendant areas
- * and destroy the AdjustingInfo object if there are
- * no UnresolvedAreas left
- */
- public void finish() {
- if (adjustingInfo.lineAlignment == EN_JUSTIFY) {
- if (log.isTraceEnabled()) {
- log.trace("Applying variation factor to justified line: " + adjustingInfo);
- }
- // justified line: apply the variation factor
- boolean bUnresolvedAreasPresent = false;
- // recursively apply variation factor to descendant areas
- for (int i = 0, len = inlineAreas.size(); i < len; i++) {
- bUnresolvedAreasPresent |= inlineAreas.get(i)
- .applyVariationFactor(adjustingInfo.variationFactor,
- adjustingInfo.availableStretch,
- adjustingInfo.availableShrink);
- }
- if (!bUnresolvedAreasPresent) {
- // there are no more UnresolvedAreas:
- // destroy the AdjustingInfo instance
- adjustingInfo = null;
- } else {
- // this method will be called again later:
- // the first time, it is called by the LineLM,
- // afterwards it must be called by the LineArea itself
- if (!adjustingInfo.bAddedToAreaTree) {
- adjustingInfo.bAddedToAreaTree = true;
- }
- // reset the variation factor
- adjustingInfo.variationFactor = 1.0;
- }
- } else {
- // the line is not justified: the ipd variation has already
- // been handled, modifying the line indent
- }
- }
- }
|