aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/hyphenation/HyphenationTree.java107
1 files changed, 106 insertions, 1 deletions
diff --git a/src/java/org/apache/fop/hyphenation/HyphenationTree.java b/src/java/org/apache/fop/hyphenation/HyphenationTree.java
index d40daa5cf..1709d204a 100644
--- a/src/java/org/apache/fop/hyphenation/HyphenationTree.java
+++ b/src/java/org/apache/fop/hyphenation/HyphenationTree.java
@@ -30,7 +30,9 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import org.xml.sax.InputSource;
@@ -321,7 +323,109 @@ public class HyphenationTree extends TernaryTree
public Hyphenation hyphenate(String word, int remainCharCount,
int pushCharCount) {
char[] w = word.toCharArray();
- return hyphenate(w, 0, w.length, remainCharCount, pushCharCount);
+ if (isMultiPartWord(w, w.length)) {
+ List<char[]> words = splitOnNonCharacters(w);
+ return new Hyphenation(new String(w),
+ getHyphPointsForWords(words, remainCharCount, pushCharCount));
+ } else {
+ return hyphenate(w, 0, w.length, remainCharCount, pushCharCount);
+ }
+ }
+
+ private boolean isMultiPartWord(char[] w, int len) {
+ int wordParts = 0;
+ for (int i = 0; i < len; i++) {
+ char[] c = new char[2];
+ c[0] = w[i];
+ int nc = classmap.find(c, 0);
+ if (nc > 0) {
+ if (wordParts > 1) {
+ return true;
+ }
+ wordParts = 1;
+ } else {
+ if (wordParts == 1) {
+ wordParts++;
+ }
+ }
+ }
+ return false;
+ }
+
+ private List<char[]> splitOnNonCharacters(char[] word) {
+ List<Integer> breakPoints = getNonLetterBreaks(word);
+ if (breakPoints.size() == 0) {
+ return Collections.emptyList();
+ }
+ List<char[]> words = new ArrayList<char[]>();
+ for (int ibreak = 0; ibreak < breakPoints.size(); ibreak++) {
+ char[] newWord = getWordFromCharArray(word, ((ibreak == 0)
+ ? 0 : breakPoints.get(ibreak - 1)), breakPoints.get(ibreak));
+ words.add(newWord);
+ }
+ if (word.length - breakPoints.get(breakPoints.size() - 1) - 1 > 1) {
+ char[] newWord = getWordFromCharArray(word, breakPoints.get(breakPoints.size() - 1),
+ word.length);
+ words.add(newWord);
+ }
+ return words;
+ }
+
+ private List<Integer> getNonLetterBreaks(char[] word) {
+ char[] c = new char[2];
+ List<Integer> breakPoints = new ArrayList<Integer>();
+ boolean foundLetter = false;
+ for (int i = 0; i < word.length; i++) {
+ c[0] = word[i];
+ if (classmap.find(c, 0) < 0) {
+ if (foundLetter) {
+ breakPoints.add(i);
+ }
+ } else {
+ foundLetter = true;
+ }
+ }
+ return breakPoints;
+ }
+
+ private char[] getWordFromCharArray(char[] word, int startIndex, int endIndex) {
+ char[] newWord = new char[endIndex - ((startIndex == 0) ? startIndex : startIndex + 1)];
+ int iChar = 0;
+ for (int i = (startIndex == 0) ? 0 : startIndex + 1; i < endIndex; i++) {
+ newWord[iChar++] = word[i];
+ }
+ return newWord;
+ }
+
+ private int[] getHyphPointsForWords(List<char[]> nonLetterWords, int remainCharCount,
+ int pushCharCount) {
+ int[] breaks = new int[0];
+ for (int iNonLetterWord = 0; iNonLetterWord < nonLetterWords.size(); iNonLetterWord++) {
+ char[] nonLetterWord = nonLetterWords.get(iNonLetterWord);
+ Hyphenation curHyph = hyphenate(nonLetterWord, 0, nonLetterWord.length,
+ remainCharCount, pushCharCount);
+ if (curHyph == null) {
+ continue;
+ }
+ int[] combined = new int[breaks.length + curHyph.getHyphenationPoints().length];
+ int[] hyphPoints = curHyph.getHyphenationPoints();
+ int foreWordsSize = calcForeWordsSize(nonLetterWords, iNonLetterWord);
+ for (int i = 0; i < hyphPoints.length; i++) {
+ hyphPoints[i] += foreWordsSize;
+ }
+ System.arraycopy(breaks, 0, combined, 0, breaks.length);
+ System.arraycopy(hyphPoints, 0, combined, breaks.length, hyphPoints.length);
+ breaks = combined;
+ }
+ return breaks;
+ }
+
+ private int calcForeWordsSize(List<char[]> nonLetterWords, int iNonLetterWord) {
+ int result = 0;
+ for (int i = 0; i < iNonLetterWord; i++) {
+ result += nonLetterWords.get(i).length + 1;
+ }
+ return result;
}
/**
@@ -389,6 +493,7 @@ public class HyphenationTree extends TernaryTree
}
}
}
+
len = iLength;
if (len < (remainCharCount + pushCharCount)) {
// word is too short to be hyphenated