org.apache.fop.area.LineArea Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fop Show documentation
Show all versions of fop Show documentation
Apache FOP (Formatting Objects Processor) is the world's first print formatter driven by XSL formatting objects (XSL-FO) and the world's first output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PCL, PS, AFP, TIFF, PNG, SVG, XML (area tree representation), Print, AWT and TXT. The primary output target is PDF.
/*
* 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: LineArea.java 1761020 2016-09-16 11:17:35Z ssteiner $ */
package org.apache.fop.area;
import java.io.Serializable;
import java.util.ArrayList;
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
*/
// @SuppressFBWarnings("SE_INNER_CLASS")
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 inlineAreas = new ArrayList();
/**
* 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);
}
/**
* Set (en masse) the inline child areas of this line area.
* Used by bidirectional processing after line area consituent reordering.
* @param inlineAreas the list of inline areas
*/
public void setInlineAreas(List inlineAreas) {
for (InlineArea ia : (Iterable) inlineAreas) {
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 (InlineArea inlineArea : inlineAreas) {
ipd = Math.max(ipd, inlineArea.getAllocIPD());
bpd += inlineArea.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:
*
* - left-aligned text needs no adjustement;
* - right-aligned text and centered text are handled locally,
* adjusting the indent of this LineArea;
* - 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).
*
* @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 (InlineArea inlineArea : inlineAreas) {
bUnresolvedAreasPresent |= inlineArea
.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
}
}
public int getEffectiveIPD() {
int maxIPD = 0;
if (inlineAreas != null) {
for (Area area : inlineAreas) {
int effectiveIPD = area.getEffectiveIPD();
if (effectiveIPD > maxIPD) {
maxIPD = effectiveIPD;
}
}
}
return maxIPD;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy