org.apache.fop.layoutmgr.LayoutContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* 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: LayoutContext.java 1610839 2014-07-15 20:25:58Z vhennebert $ */
package org.apache.fop.layoutmgr;
import java.util.Collections;
import java.util.List;
import org.apache.fop.fo.Constants;
import org.apache.fop.layoutmgr.inline.AlignmentContext;
import org.apache.fop.layoutmgr.inline.HyphContext;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.WritingMode;
/**
* This class is used to pass information to the getNextKnuthElements()
* method. It is set up by higher level LM and used by lower level LM.
*/
public final class LayoutContext {
/** Generated break possibility is first in a new area */
public static final int NEW_AREA = 0x01;
/**
* If this flag is set, it indicates that any break-before values other than "auto" should
* not cause a mandatory break as this break was already handled by a parent layout manager.
*/
public static final int SUPPRESS_BREAK_BEFORE = 0x02;
public static final int FIRST_AREA = 0x04;
public static final int LAST_AREA = 0x08;
public static final int RESOLVE_LEADING_SPACE = 0x10;
private static final int TREAT_AS_ARTIFACT = 0x20;
private int flags; // Contains some set of flags defined above
/**
* Total available stacking dimension for a "galley-level" layout
* manager in block-progression-direction. It is passed by the
* parent LM.
* These LM may wish to pass this information down to lower
* level LM to allow them to optimize returned break possibilities.
*/
private MinOptMax stackLimitBP;
/** to keep track of spanning in multi-column layout */
private int currentSpan = Constants.NOT_SET;
private int nextSpan = Constants.NOT_SET;
/** inline-progression-dimension of nearest ancestor reference area */
private int refIPD;
//TODO After the split of stackLimit into stackLimitBP and stackLimitIP there's now some
//overlap with refIPD. Need to investigate how best to refactor that.
/** the writing mode established by the nearest ancestor reference area */
private WritingMode writingMode = WritingMode.LR_TB;
/** Current pending space-after or space-end from preceding area */
private SpaceSpecifier trailingSpace;
/** Current pending space-before or space-start from ancestor areas */
private SpaceSpecifier leadingSpace;
/**
* A list of pending marks (border and padding) on the after edge when a page break occurs.
* May be null.
*/
private List pendingAfterMarks;
/**
* A list of pending marks (border and padding) on the before edge when a page break occurs.
* May be null.
*/
private List pendingBeforeMarks;
/** Current hyphenation context. May be null. */
private HyphContext hyphContext;
/** Alignment in BP direction */
private int bpAlignment = Constants.EN_START;
/** Stretch or shrink value when making areas. */
private double ipdAdjust;
/** Stretch or shrink value when adding spaces. */
private double dSpaceAdjust;
private AlignmentContext alignmentContext;
/** Amount of space before / start */
private int spaceBefore;
/** Amount of space after / end */
private int spaceAfter;
/** Amount of space to reserve at the beginning of each line */
private int lineStartBorderAndPaddingWidth;
/** Amount of space to reserve at the end of each line */
private int lineEndBorderAndPaddingWidth;
private int breakBefore;
private int breakAfter;
private Keep pendingKeepWithNext = Keep.KEEP_AUTO;
private Keep pendingKeepWithPrevious = Keep.KEEP_AUTO;
private int disableColumnBalancing;
public static LayoutContext newInstance() {
return new LayoutContext(0);
}
public static LayoutContext copyOf(LayoutContext copy) {
return new LayoutContext(copy);
}
/**
* Returns a descendant of the given layout context. The new context is the same as
* what would have been created by {@link #newInstance()}, except for inheritable
* properties that are passed on by the parent. At the moment, the only inheritable
* property is the value returned by {@link #treatAsArtifact()}.
*/
public static LayoutContext offspringOf(LayoutContext parent) {
LayoutContext offspring = new LayoutContext(0);
offspring.setTreatAsArtifact(parent.treatAsArtifact());
return offspring;
}
private LayoutContext(LayoutContext parentLC) {
this.flags = parentLC.flags;
this.refIPD = parentLC.refIPD;
this.writingMode = parentLC.writingMode;
setStackLimitBP(parentLC.getStackLimitBP());
this.leadingSpace = parentLC.leadingSpace; //???
this.trailingSpace = parentLC.trailingSpace; //???
this.hyphContext = parentLC.hyphContext;
this.bpAlignment = parentLC.bpAlignment;
this.dSpaceAdjust = parentLC.dSpaceAdjust;
this.ipdAdjust = parentLC.ipdAdjust;
this.alignmentContext = parentLC.alignmentContext;
this.lineStartBorderAndPaddingWidth = parentLC.lineStartBorderAndPaddingWidth;
this.lineEndBorderAndPaddingWidth = parentLC.lineEndBorderAndPaddingWidth;
copyPendingMarksFrom(parentLC);
this.pendingKeepWithNext = parentLC.pendingKeepWithNext;
this.pendingKeepWithPrevious = parentLC.pendingKeepWithPrevious;
// Copy other fields as necessary.
this.disableColumnBalancing = parentLC.disableColumnBalancing;
}
private LayoutContext(int flags) {
this.flags = flags;
this.refIPD = 0;
stackLimitBP = MinOptMax.ZERO;
leadingSpace = null;
trailingSpace = null;
}
/** @param source from which pending marks are copied */
public void copyPendingMarksFrom(LayoutContext source) {
if (source.pendingAfterMarks != null) {
this.pendingAfterMarks = new java.util.ArrayList(source.pendingAfterMarks);
}
if (source.pendingBeforeMarks != null) {
this.pendingBeforeMarks = new java.util.ArrayList(source.pendingBeforeMarks);
}
}
/** @param flags to set */
public void setFlags(int flags) {
setFlags(flags, true);
}
/**
* @param flags to set or clear
* @param bSet true to set, false to clear
*/
public void setFlags(int flags, boolean bSet) {
if (bSet) {
this.flags |= flags;
} else {
this.flags &= ~flags;
}
}
/** @param flags to clear */
public void unsetFlags(int flags) {
setFlags(flags, false);
}
/** @return true if new area is set */
public boolean isStart() {
return ((this.flags & NEW_AREA) != 0);
}
/** @return true if new area is set and leading space is non-null */
public boolean startsNewArea() {
return ((this.flags & NEW_AREA) != 0 && leadingSpace != null);
}
/** @return true if first area is set */
public boolean isFirstArea() {
return ((this.flags & FIRST_AREA) != 0);
}
/** @return true if last area is set */
public boolean isLastArea() {
return ((this.flags & LAST_AREA) != 0);
}
/** @return true if suppress break before is set */
public boolean suppressBreakBefore() {
return ((this.flags & SUPPRESS_BREAK_BEFORE) != 0);
}
/**
* Returns the strength of a keep-with-next currently pending.
* @return the keep-with-next strength
*/
public Keep getKeepWithNextPending() {
return this.pendingKeepWithNext;
}
/**
* Returns the strength of a keep-with-previous currently pending.
* @return the keep-with-previous strength
*/
public Keep getKeepWithPreviousPending() {
return this.pendingKeepWithPrevious;
}
/**
* Clears any pending keep-with-next strength.
*/
public void clearKeepWithNextPending() {
this.pendingKeepWithNext = Keep.KEEP_AUTO;
}
/**
* Clears any pending keep-with-previous strength.
*/
public void clearKeepWithPreviousPending() {
this.pendingKeepWithPrevious = Keep.KEEP_AUTO;
}
/**
* Clears both keep-with-previous and keep-with-next strengths.
*/
public void clearKeepsPending() {
clearKeepWithPreviousPending();
clearKeepWithNextPending();
}
/**
* Updates the currently pending keep-with-next strength.
* @param keep the new strength to consider
*/
public void updateKeepWithNextPending(Keep keep) {
this.pendingKeepWithNext = this.pendingKeepWithNext.compare(keep);
}
/**
* Updates the currently pending keep-with-previous strength.
* @param keep the new strength to consider
*/
public void updateKeepWithPreviousPending(Keep keep) {
this.pendingKeepWithPrevious = this.pendingKeepWithPrevious.compare(keep);
}
/**
* Indicates whether a keep-with-next constraint is pending.
* @return true if a keep-with-next constraint is pending
*/
public boolean isKeepWithNextPending() {
return !getKeepWithNextPending().isAuto();
}
/**
* Indicates whether a keep-with-previous constraint is pending.
* @return true if a keep-with-previous constraint is pending
*/
public boolean isKeepWithPreviousPending() {
return !getKeepWithPreviousPending().isAuto();
}
/** @param space leading space */
public void setLeadingSpace(SpaceSpecifier space) {
leadingSpace = space;
}
/** @return leading space */
public SpaceSpecifier getLeadingSpace() {
return leadingSpace;
}
/** @return true if resolve leading space is set */
public boolean resolveLeadingSpace() {
return ((this.flags & RESOLVE_LEADING_SPACE) != 0);
}
/** @param space trailing space */
public void setTrailingSpace(SpaceSpecifier space) {
trailingSpace = space;
}
/** @return trailing space */
public SpaceSpecifier getTrailingSpace() {
return trailingSpace;
}
/**
* Adds a border or padding element to the pending list which will be used to generate
* the right element list for break possibilities. Conditionality resolution will be done
* elsewhere.
* @param element the border, padding or space element
*/
public void addPendingAfterMark(UnresolvedListElementWithLength element) {
if (this.pendingAfterMarks == null) {
this.pendingAfterMarks = new java.util.ArrayList();
}
this.pendingAfterMarks.add(element);
}
/**
* @return the pending border and padding elements at the after edge
* @see #addPendingAfterMark(UnresolvedListElementWithLength)
*/
public List getPendingAfterMarks() {
if (this.pendingAfterMarks != null) {
return Collections.unmodifiableList(this.pendingAfterMarks);
} else {
return null;
}
}
/**
* Clears all pending marks on the LayoutContext.
*/
public void clearPendingMarks() {
this.pendingBeforeMarks = null;
this.pendingAfterMarks = null;
}
/**
* Adds a border or padding element to the pending list which will be used to generate
* the right element list for break possibilities. Conditionality resolution will be done
* elsewhere.
* @param element the border, padding or space element
*/
public void addPendingBeforeMark(UnresolvedListElementWithLength element) {
if (this.pendingBeforeMarks == null) {
this.pendingBeforeMarks = new java.util.ArrayList();
}
this.pendingBeforeMarks.add(element);
}
/**
* @return the pending border and padding elements at the before edge
* @see #addPendingBeforeMark(UnresolvedListElementWithLength)
*/
public List getPendingBeforeMarks() {
if (this.pendingBeforeMarks != null) {
return Collections.unmodifiableList(this.pendingBeforeMarks);
} else {
return null;
}
}
/**
* Sets the stack limit in block-progression-dimension.
* @param limit the stack limit
*/
public void setStackLimitBP(MinOptMax limit) {
stackLimitBP = limit;
}
/**
* Returns the stack limit in block-progression-dimension.
* @return the stack limit
*/
public MinOptMax getStackLimitBP() {
return stackLimitBP;
}
/**
* Sets the inline-progression-dimension of the nearest ancestor reference area.
* @param ipd of nearest ancestor reference area
*/
public void setRefIPD(int ipd) {
refIPD = ipd;
}
/**
* Returns the inline-progression-dimension of the nearest ancestor reference area.
*
* @return the inline-progression-dimension of the nearest ancestor reference area
*/
public int getRefIPD() {
return refIPD;
}
/** @param hyph a hyphenation context */
public void setHyphContext(HyphContext hyph) {
hyphContext = hyph;
}
/** @return hyphenation context */
public HyphContext getHyphContext() {
return hyphContext;
}
/**
* Sets the currently applicable alignment in BP direction.
* @param alignment one of EN_START, EN_JUSTIFY etc.
*/
public void setBPAlignment(int alignment) {
this.bpAlignment = alignment;
}
/** @return the currently applicable alignment in BP direction (EN_START, EN_JUSTIFY...) */
public int getBPAlignment() {
return this.bpAlignment;
}
/** @param adjust space adjustment */
public void setSpaceAdjust(double adjust) {
dSpaceAdjust = adjust;
}
/** @return space adjustment */
public double getSpaceAdjust() {
return dSpaceAdjust;
}
/** @param ipdA ipd adjustment */
public void setIPDAdjust(double ipdA) {
ipdAdjust = ipdA;
}
/** @return ipd adjustment */
public double getIPDAdjust() {
return ipdAdjust;
}
/** @param alignmentContext alignment context */
public void setAlignmentContext(AlignmentContext alignmentContext) {
this.alignmentContext = alignmentContext;
}
/** @return alignment context */
public AlignmentContext getAlignmentContext() {
return this.alignmentContext;
}
/**
* Reset alignment context.
*/
public void resetAlignmentContext() {
if (this.alignmentContext != null) {
this.alignmentContext = this.alignmentContext.getParentAlignmentContext();
}
}
/**
* Get the width to be reserved for border and padding at the start of the line.
* @return the width to be reserved
*/
public int getLineStartBorderAndPaddingWidth() {
return lineStartBorderAndPaddingWidth;
}
/**
* Set the width to be reserved for border and padding at the start of the line.
* @param lineStartBorderAndPaddingWidth the width to be reserved
*/
public void setLineStartBorderAndPaddingWidth(int lineStartBorderAndPaddingWidth) {
this.lineStartBorderAndPaddingWidth = lineStartBorderAndPaddingWidth;
}
/**
* Get the width to be reserved for border and padding at the end of the line.
* @return the width to be reserved
*/
public int getLineEndBorderAndPaddingWidth() {
return lineEndBorderAndPaddingWidth;
}
/**
* Set the width to be reserved for border and padding at the end of the line.
* @param lineEndBorderAndPaddingWidth the width to be reserved
*/
public void setLineEndBorderAndPaddingWidth(int lineEndBorderAndPaddingWidth) {
this.lineEndBorderAndPaddingWidth = lineEndBorderAndPaddingWidth;
}
/**
* @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE}
* {@link Constants#EN_ALL}
*/
public int getNextSpan() {
return nextSpan;
}
/**
* @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE}
* {@link Constants#EN_ALL}
*/
public int getCurrentSpan() {
return (currentSpan == Constants.NOT_SET)
? Constants.EN_NONE : currentSpan;
}
/**
* Used to signal the PSLM that the element list ends early because of a span change in
* multi-column layout.
* @param span the new span value (legal values: NOT_SET, EN_NONE, EN_ALL)
*/
public void signalSpanChange(int span) {
switch (span) {
case Constants.NOT_SET:
case Constants.EN_NONE:
case Constants.EN_ALL:
this.currentSpan = this.nextSpan;
this.nextSpan = span;
break;
default:
assert false;
throw new IllegalArgumentException("Illegal value on signalSpanChange() for span: "
+ span);
}
}
/**
* Get the writing mode of the relevant reference area.
* @return the applicable writing mode
*/
public WritingMode getWritingMode() {
return writingMode;
}
/**
* Set the writing mode.
* @param writingMode the writing mode
*/
public void setWritingMode(WritingMode writingMode) {
this.writingMode = writingMode;
}
/**
* Get the current amount of space before / start
* @return the space before / start amount
*/
public int getSpaceBefore() {
return spaceBefore;
}
/**
* Set the amount of space before / start
* @param spaceBefore the amount of space before / start
*/
public void setSpaceBefore(int spaceBefore) {
this.spaceBefore = spaceBefore;
}
/**
* Get the current amount of space after / end
* @return the space after / end amount
*/
public int getSpaceAfter() {
return spaceAfter;
}
/**
* Set the amount of space after / end
* @param spaceAfter the amount of space after / end
*/
public void setSpaceAfter(int spaceAfter) {
this.spaceAfter = spaceAfter;
}
/**
* Returns the value of the break before the element whose
* {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been
* called.
*
* @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
* {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
* {@link Constants#EN_ODD_PAGE}
*/
public int getBreakBefore() {
return breakBefore;
}
/**
* Sets the value of the break before the current element.
*
* @param breakBefore the value of the break-before
* @see #getBreakBefore()
*/
public void setBreakBefore(int breakBefore) {
this.breakBefore = breakBefore;
}
/**
* Returns the value of the break after the element whose
* {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been
* called.
*
* @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
* {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
* {@link Constants#EN_ODD_PAGE}
*/
public int getBreakAfter() {
return breakAfter;
}
/**
* Sets the value of the break after the current element.
*
* @param breakAfter the value of the break-after
* @see #getBreakAfter()
*/
public void setBreakAfter(int breakAfter) {
this.breakAfter = breakAfter;
}
/** {@inheritDoc} */
@Override
public String toString() {
return "Layout Context:"
+ "\nStack Limit BPD: \t"
+ (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
+ "\nTrailing Space: \t"
+ (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
+ "\nLeading Space: \t"
+ (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
+ "\nReference IPD: \t" + getRefIPD()
+ "\nSpace Adjust: \t" + getSpaceAdjust()
+ "\nIPD Adjust: \t" + getIPDAdjust()
+ "\nResolve Leading Space: \t" + resolveLeadingSpace()
+ "\nSuppress Break Before: \t" + suppressBreakBefore()
+ "\nIs First Area: \t" + isFirstArea()
+ "\nStarts New Area: \t" + startsNewArea()
+ "\nIs Last Area: \t" + isLastArea()
+ "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
+ "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending"
+ "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
+ (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
}
/**
* Returns whether the column balancer should be disabled before a spanning block
*
* @return one of {@link Constants#EN_TRUE}, {@link Constants#EN_FALSE}
*/
public int getDisableColumnBalancing() {
return disableColumnBalancing;
}
/**
* Sets whether the column balancer should be disabled before a spanning block
*
* @param disableColumnBalancing the value of the fox:disable-column-balancing property
* @see #getDisableColumnBalancing()
*/
public void setDisableColumnBalancing(int disableColumnBalancing) {
this.disableColumnBalancing = disableColumnBalancing;
}
public boolean treatAsArtifact() {
return (flags & TREAT_AS_ARTIFACT) != 0;
}
public void setTreatAsArtifact(boolean treatAsArtifact) {
setFlags(TREAT_AS_ARTIFACT, treatAsArtifact);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy