blob: 1b38b9d8faaa00d0f1925150fc4d379e40e78abd [file] [log] [blame]
/*
* 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.layoutmgr;
import java.util.LinkedList;
import java.util.List;
import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
import org.apache.fop.layoutmgr.inline.KnuthInlineBox;
/**
* Represents a list of inline Knuth elements.
* If closed, it represents all elements of a Knuth paragraph.
*/
public class InlineKnuthSequence extends KnuthSequence {
private static final long serialVersionUID = 1354774188859946549L;
private boolean isClosed;
/**
* Creates a new and empty list.
*/
public InlineKnuthSequence() {
super();
}
/**
* Creates a new list from an existing list.
* @param list The list from which to create the new list.
*/
public InlineKnuthSequence(List list) {
super(list);
}
/**
* Is this an inline or a block sequence?
* @return false
*/
public boolean isInlineSequence() {
return true;
}
/** {@inheritDoc} */
public boolean canAppendSequence(KnuthSequence sequence) {
return sequence.isInlineSequence() && !isClosed;
}
/** {@inheritDoc} */
public boolean appendSequence(KnuthSequence sequence) {
if (!canAppendSequence(sequence)) {
return false;
}
// does the first element of the first paragraph add to an existing word?
ListElement lastOldElement;
ListElement firstNewElement;
lastOldElement = getLast();
firstNewElement = sequence.getElement(0);
if (firstNewElement.isBox() && !((KnuthElement) firstNewElement).isAuxiliary()
&& lastOldElement.isBox() && ((KnuthElement) lastOldElement).getWidth() != 0) {
addALetterSpace();
}
addAll(sequence);
return true;
}
/** {@inheritDoc} */
public boolean appendSequence(KnuthSequence sequence, boolean keepTogether,
BreakElement breakElement) {
return appendSequence(sequence);
}
/** {@inheritDoc} */
public KnuthSequence endSequence() {
if (!isClosed) {
add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false));
isClosed = true;
}
return this;
}
/**
* Add letter space.
*/
public void addALetterSpace() {
KnuthBox prevBox = (KnuthBox) getLast();
if (prevBox.isAuxiliary()
&& (size() < 4
|| !getElement(size() - 2).isGlue()
|| !getElement(size() - 3).isPenalty()
|| !getElement(size() - 4).isBox()
)
) {
// Not the sequence we are expecting
return;
}
removeLast();
LinkedList oldList = new LinkedList();
// if there are two consecutive KnuthBoxes the
// first one does not represent a whole word,
// so it must be given one more letter space
if (!prevBox.isAuxiliary()) {
// if letter spacing is constant,
// only prevBox needs to be replaced;
oldList.add(prevBox);
} else {
// prevBox is the last element
// in the sub-sequence
// <box> <aux penalty> <aux glue> <aux box>
// the letter space is added to <aux glue>,
// while the other elements are not changed
oldList.add(prevBox);
oldList.addFirst((KnuthGlue) removeLast());
oldList.addFirst((KnuthPenalty) removeLast());
oldList.addFirst((KnuthBox) removeLast());
}
// adding a letter space could involve, according to the text
// represented by oldList, replacing a glue element or adding
// new elements
addAll(((InlineLevelLayoutManager)
prevBox.getLayoutManager())
.addALetterSpaceTo(oldList));
// prevBox may not be a KnuthInlineBox;
// this may happen if it is a padding box; see bug 39571.
if (prevBox instanceof KnuthInlineBox && ((KnuthInlineBox) prevBox).isAnchor()) {
// prevBox represents a footnote citation: copy footnote info
// from prevBox to the new box
KnuthInlineBox newBox = (KnuthInlineBox) getLast();
newBox.setFootnoteBodyLM(((KnuthInlineBox) prevBox).getFootnoteBodyLM());
}
}
}