Преглед на файлове

FOP-2249: elide formatting controls - preliminary

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1631605 13f79535-47bb-0310-9956-ffa450edef68
pull/28/head
Glenn Adams преди 9 години
родител
ревизия
ef1ac97e1f

+ 2
- 1
src/java/org/apache/fop/complexscripts/fonts/Substitutable.java Целия файл

* @param script a script identifier * @param script a script identifier
* @param language a language identifier * @param language a language identifier
* @param associations optional list to receive list of character associations * @param associations optional list to receive list of character associations
* @param retainControls if true, then retain control characters and their glyph mappings, otherwise remove
* @return output sequence (represented as a character sequence, where each character in the returned sequence * @return output sequence (represented as a character sequence, where each character in the returned sequence
* denotes "font characters", i.e., character codes that map directly (1-1) to their associated glyphs * denotes "font characters", i.e., character codes that map directly (1-1) to their associated glyphs
*/ */
CharSequence performSubstitution(CharSequence cs, String script, String language, List associations);
CharSequence performSubstitution(CharSequence cs, String script, String language, List associations, boolean retainControls);


/** /**
* Reorder combining marks in character sequence so that they precede (within the sequence) the base * Reorder combining marks in character sequence so that they precede (within the sequence) the base

+ 2
- 2
src/java/org/apache/fop/fonts/Font.java Целия файл



/** {@inheritDoc} */ /** {@inheritDoc} */
public CharSequence performSubstitution(CharSequence cs, public CharSequence performSubstitution(CharSequence cs,
String script, String language, List associations) {
String script, String language, List associations, boolean retainControls) {
if (metric instanceof Substitutable) { if (metric instanceof Substitutable) {
Substitutable s = (Substitutable) metric; Substitutable s = (Substitutable) metric;
return s.performSubstitution(cs, script, language, associations);
return s.performSubstitution(cs, script, language, associations, retainControls);
} else { } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

+ 5
- 4
src/java/org/apache/fop/fonts/GlyphMapping.java Целия файл

public static GlyphMapping doGlyphMapping(TextFragment text, int startIndex, int endIndex, public static GlyphMapping doGlyphMapping(TextFragment text, int startIndex, int endIndex,
Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray, Font font, MinOptMax letterSpaceIPD, MinOptMax[] letterSpaceAdjustArray,
char precedingChar, char breakOpportunityChar, final boolean endsWithHyphen, int level, char precedingChar, char breakOpportunityChar, final boolean endsWithHyphen, int level,
boolean dontOptimizeForIdentityMapping, boolean retainAssociations) {
boolean dontOptimizeForIdentityMapping, boolean retainAssociations, boolean retainControls) {
GlyphMapping mapping; GlyphMapping mapping;
if (font.performsSubstitution() || font.performsPositioning()) { if (font.performsSubstitution() || font.performsPositioning()) {
mapping = processWordMapping(text, startIndex, endIndex, font, mapping = processWordMapping(text, startIndex, endIndex, font,
breakOpportunityChar, endsWithHyphen, level, dontOptimizeForIdentityMapping, retainAssociations);
breakOpportunityChar, endsWithHyphen, level,
dontOptimizeForIdentityMapping, retainAssociations, retainControls);
} else { } else {
mapping = processWordNoMapping(text, startIndex, endIndex, font, mapping = processWordNoMapping(text, startIndex, endIndex, font,
letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, level); letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, level);
private static GlyphMapping processWordMapping(TextFragment text, int startIndex, private static GlyphMapping processWordMapping(TextFragment text, int startIndex,
int endIndex, final Font font, final char breakOpportunityChar, int endIndex, final Font font, final char breakOpportunityChar,
final boolean endsWithHyphen, int level, final boolean endsWithHyphen, int level,
boolean dontOptimizeForIdentityMapping, boolean retainAssociations) {
boolean dontOptimizeForIdentityMapping, boolean retainAssociations, boolean retainControls) {
int e = endIndex; // end index of word in FOText character buffer int e = endIndex; // end index of word in FOText character buffer
int nLS = 0; // # of letter spaces int nLS = 0; // # of letter spaces
String script = text.getScript(); String script = text.getScript();
// 3. perform mapping of chars to glyphs ... to glyphs ... to chars, retaining // 3. perform mapping of chars to glyphs ... to glyphs ... to chars, retaining
// associations if requested. // associations if requested.
List associations = retainAssociations ? new java.util.ArrayList() : null; List associations = retainAssociations ? new java.util.ArrayList() : null;
CharSequence mcs = font.performSubstitution(ics, script, language, associations);
CharSequence mcs = font.performSubstitution(ics, script, language, associations, retainControls);


// 4. compute glyph position adjustments on (substituted) characters. // 4. compute glyph position adjustments on (substituted) characters.
int[][] gpa = null; int[][] gpa = null;

+ 4
- 2
src/java/org/apache/fop/fonts/LazyFont.java Целия файл

/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations,
boolean retainControls) {
load(true); load(true);
if (realFontDescriptor instanceof Substitutable) { if (realFontDescriptor instanceof Substitutable) {
return ((Substitutable)realFontDescriptor).performSubstitution(cs, script, language, associations);
return ((Substitutable)realFontDescriptor).performSubstitution(cs,
script, language, associations, retainControls);
} else { } else {
return cs; return cs;
} }

+ 66
- 1
src/java/org/apache/fop/fonts/MultiByteFont.java Целия файл

import org.apache.fop.complexscripts.fonts.GlyphTable; import org.apache.fop.complexscripts.fonts.GlyphTable;
import org.apache.fop.complexscripts.fonts.Positionable; import org.apache.fop.complexscripts.fonts.Positionable;
import org.apache.fop.complexscripts.fonts.Substitutable; import org.apache.fop.complexscripts.fonts.Substitutable;
import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.CharNormalize; import org.apache.fop.complexscripts.util.CharNormalize;
import org.apache.fop.complexscripts.util.GlyphSequence; import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;
} }


/** {@inheritDoc} */ /** {@inheritDoc} */
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations,
boolean retainControls) {
if (gsub != null) { if (gsub != null) {
CharSequence ncs = normalize(cs, associations); CharSequence ncs = normalize(cs, associations);
GlyphSequence igs = mapCharsToGlyphs(ncs, associations); GlyphSequence igs = mapCharsToGlyphs(ncs, associations);
associations.clear(); associations.clear();
associations.addAll(ogs.getAssociations()); associations.addAll(ogs.getAssociations());
} }
if (!retainControls) {
ogs = elideControls(ogs);
}
CharSequence ocs = mapGlyphsToChars(ogs); CharSequence ocs = mapGlyphsToChars(ogs);
return ocs; return ocs;
} else { } else {
return sb; return sb;
} }


private static GlyphSequence elideControls(GlyphSequence gs) {
if (hasElidableControl(gs)) {
int[] ca = gs.getCharacterArray(false);
IntBuffer ngb = IntBuffer.allocate(gs.getGlyphCount());
List nal = new java.util.ArrayList(gs.getGlyphCount());
for (int i = 0, n = gs.getGlyphCount(); i < n; ++i) {
CharAssociation a = gs.getAssociation(i);
int s = a.getStart();
int e = a.getEnd();
while (s < e) {
int ch = ca [ s ];
if (isElidableControl(ch)) {
break;
} else {
++s;
}
}
if (s == e) {
ngb.put(gs.getGlyph(i));
nal.add(a);
}
}
ngb.flip();
return new GlyphSequence(gs.getCharacters(), ngb, nal, gs.getPredications());
} else {
return gs;
}
}

private static boolean hasElidableControl(GlyphSequence gs) {
int[] ca = gs.getCharacterArray(false);
for (int i = 0, n = ca.length; i < n; ++i) {
int ch = ca [ i ];
if (isElidableControl(ch)) {
return true;
}
}
return false;
}

private static boolean isElidableControl(int ch) {
if (ch < 0x0020) {
return true;
} else if ((ch >= 0x80) && (ch < 0x00A0)) {
return true;
} else if ((ch >= 0x2000) && (ch <= 0x206F)) {
if ((ch >= 0x200B) && (ch <= 0x200F)) {
return true;
} else if ((ch >= 0x2028) && (ch <= 0x202E)) {
return true;
} else if ((ch >= 0x2066) && (ch <= 0x206F)) {
return true;
} else {
return ch == 0x2060;
}
} else {
return false;
}
}

@Override @Override
public boolean hasFeature(int tableType, String script, String language, String feature) { public boolean hasFeature(int tableType, String script, String language, String feature) {
GlyphTable table; GlyphTable table;

+ 5
- 4
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Целия файл

char ch = 0; char ch = 0;
int level = -1; int level = -1;
int prevLevel = -1; int prevLevel = -1;
boolean retainControls = false;
while (nextStart < foText.length()) { while (nextStart < foText.length()) {
ch = foText.charAt(nextStart); ch = foText.charAt(nextStart);
level = foText.bidiLevelAt(nextStart); level = foText.bidiLevelAt(nextStart);
|| ((prevLevel != -1) && (level != prevLevel))) { || ((prevLevel != -1) && (level != prevLevel))) {
// this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN
prevMapping = processWord(alignment, sequence, prevMapping, ch, prevMapping = processWord(alignment, sequence, prevMapping, ch,
breakOpportunity, true, prevLevel);
breakOpportunity, true, prevLevel, retainControls);
} }
} else if (inWhitespace) { } else if (inWhitespace) {
if (ch != CharUtilities.SPACE || breakOpportunity) { if (ch != CharUtilities.SPACE || breakOpportunity) {


// Process any last elements // Process any last elements
if (inWord) { if (inWord) {
processWord(alignment, sequence, prevMapping, ch, false, false, prevLevel);
processWord(alignment, sequence, prevMapping, ch, false, false, prevLevel, retainControls);
} else if (inWhitespace) { } else if (inWhitespace) {
processWhitespace(alignment, sequence, !keepTogether, prevLevel); processWhitespace(alignment, sequence, !keepTogether, prevLevel);
} else if (mapping != null) { } else if (mapping != null) {


private GlyphMapping processWord(final int alignment, final KnuthSequence sequence, private GlyphMapping processWord(final int alignment, final KnuthSequence sequence,
GlyphMapping prevMapping, final char ch, final boolean breakOpportunity, GlyphMapping prevMapping, final char ch, final boolean breakOpportunity,
final boolean checkEndsWithHyphen, int level) {
final boolean checkEndsWithHyphen, int level, boolean retainControls) {


//Word boundary found, process widths and kerning //Word boundary found, process widths and kerning
int lastIndex = nextStart; int lastIndex = nextStart;
&& prevMapping.endIndex > 0 ? foText.charAt(prevMapping.endIndex - 1) : 0; && prevMapping.endIndex > 0 ? foText.charAt(prevMapping.endIndex - 1) : 0;
GlyphMapping mapping = GlyphMapping.doGlyphMapping(foText, thisStart, lastIndex, font, GlyphMapping mapping = GlyphMapping.doGlyphMapping(foText, thisStart, lastIndex, font,
letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar,
endsWithHyphen, level, false, false);
endsWithHyphen, level, false, false, retainControls);
prevMapping = mapping; prevMapping = mapping;
addGlyphMapping(mapping); addGlyphMapping(mapping);
tempStart = nextStart; tempStart = nextStart;

+ 3
- 2
src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java Целия файл

/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations,
boolean retainControls) {
if (typeface instanceof Substitutable) { if (typeface instanceof Substitutable) {
return ((Substitutable) typeface).performSubstitution(cs, script, language, associations);
return ((Substitutable) typeface).performSubstitution(cs, script, language, associations, retainControls);
} else { } else {
return cs; return cs;
} }

+ 3
- 1
src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java Целия файл

Font f = font.getFont(); Font f = font.getFont();
MinOptMax letterSpaceIPD = MinOptMax.ZERO; MinOptMax letterSpaceIPD = MinOptMax.ZERO;
MinOptMax[] letterSpaceAdjustments = new MinOptMax[text.getEndIndex() - text.getBeginIndex()]; MinOptMax[] letterSpaceAdjustments = new MinOptMax[text.getEndIndex() - text.getBeginIndex()];
boolean retainControls = false;
GlyphMapping mapping = GlyphMapping.doGlyphMapping(text, text.getBeginIndex(), text.getEndIndex(), GlyphMapping mapping = GlyphMapping.doGlyphMapping(text, text.getBeginIndex(), text.getEndIndex(),
f, letterSpaceIPD, letterSpaceAdjustments, '\0', '\0', false, text.getBidiLevel(), true, true);
f, letterSpaceIPD, letterSpaceAdjustments, '\0', '\0',
false, text.getBidiLevel(), true, true, retainControls);
CharacterIterator glyphAsCharIter = CharacterIterator glyphAsCharIter =
mapping.mapping != null ? new StringCharacterIterator(mapping.mapping) : text.getIterator(); mapping.mapping != null ? new StringCharacterIterator(mapping.mapping) : text.getIterator();
this.glyphs = buildGlyphs(f, glyphAsCharIter); this.glyphs = buildGlyphs(f, glyphAsCharIter);

Loading…
Отказ
Запис