You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ga...@apache.org on 2014/08/03 06:40:35 UTC
svn commit: r1615385 [1/2] - in /xmlgraphics/fop/trunk: ./ lib/
src/java/org/apache/fop/complexscripts/fonts/
src/java/org/apache/fop/complexscripts/scripts/
src/java/org/apache/fop/complexscripts/util/ src/java/org/apache/fop/fonts/
src/java/org/apach...
Author: gadams
Date: Sun Aug 3 04:40:34 2014
New Revision: 1615385
URL: http://svn.apache.org/r1615385
Log:
FOP-2391: preliminary (but incomplete) support for complex script text nodes in svg foreign object
Added:
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/ComplexGlyphVector.java (with props)
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/text/ComplexGlyphLayout.java (with props)
Modified:
xmlgraphics/fop/trunk/findbugs-exclude.xml
xmlgraphics/fop/trunk/lib/batik-all-trunk.jar
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/GlyphMapping.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTFont.java
xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/font/FOPGVTGlyphVector.java
xmlgraphics/fop/trunk/test/java/org/apache/fop/svg/font/GlyphLayoutTestCase.java
Modified: xmlgraphics/fop/trunk/findbugs-exclude.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/findbugs-exclude.xml?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/findbugs-exclude.xml (original)
+++ xmlgraphics/fop/trunk/findbugs-exclude.xml Sun Aug 3 04:40:34 2014
@@ -142,6 +142,16 @@
</Or>
</Match>
<Match>
+ <Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
+ <And>
+ <Class name="org.apache.fop.svg.font.FOPGVTGlyphVector"/>
+ <Or>
+ <Field name="glyphTransforms"/>
+ <Field name="glyphVisibilities"/>
+ </Or>
+ </And>
+ </Match>
+ <Match>
<Bug pattern="DM_DEFAULT_ENCODING"/>
<Or>
<And>
@@ -5463,7 +5473,7 @@
<Bug pattern="EI_EXPOSE_REP"/>
</Match>
<Match>
- <Class name="org.apache.fop.complexscripts.util.GlyphSequence$CharAssociation"/>
+ <Class name="org.apache.fop.complexscripts.util.CharAssociation"/>
<Method name="getSubIntervals"/>
<Bug pattern="EI_EXPOSE_REP"/>
</Match>
Modified: xmlgraphics/fop/trunk/lib/batik-all-trunk.jar
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/lib/batik-all-trunk.jar?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
Binary files - no diff available.
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphProcessingState.java Sun Aug 3 04:40:34 2014
@@ -23,6 +23,7 @@ import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphContextTester;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.GlyphTester;
@@ -417,7 +418,7 @@ public class GlyphProcessingState {
* @return character association of glyph at current position
* @throws IndexOutOfBoundsException if offset results in an invalid index into input glyph sequence
*/
- public GlyphSequence.CharAssociation getAssociation(int offset) throws IndexOutOfBoundsException {
+ public CharAssociation getAssociation(int offset) throws IndexOutOfBoundsException {
int i = index + offset;
if ((i >= 0) && (i < indexLast)) {
return igs.getAssociation(i);
@@ -431,7 +432,7 @@ public class GlyphProcessingState {
* @return character association of glyph at current position
* @throws IndexOutOfBoundsException if no glyph available
*/
- public GlyphSequence.CharAssociation getAssociation() throws IndexOutOfBoundsException {
+ public CharAssociation getAssociation() throws IndexOutOfBoundsException {
return getAssociation(0);
}
@@ -722,7 +723,7 @@ public class GlyphProcessingState {
* @throws IndexOutOfBoundsException if offset or count results in an
* invalid index into input glyph sequence
*/
- public GlyphSequence.CharAssociation[] getAssociations(int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts)
+ public CharAssociation[] getAssociations(int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, CharAssociation[] associations, int[] counts)
throws IndexOutOfBoundsException {
if (count < 0) {
count = getGlyphsAvailable(offset, reverseOrder, ignoreTester) [ 0 ];
@@ -736,7 +737,7 @@ public class GlyphProcessingState {
throw new IndexOutOfBoundsException("will attempt index at " + (start - count));
}
if (associations == null) {
- associations = new GlyphSequence.CharAssociation [ count ];
+ associations = new CharAssociation [ count ];
} else if (associations.length != count) {
throw new IllegalArgumentException("associations array is non-null, but its length (" + associations.length + "), is not equal to count (" + count + ")");
}
@@ -747,7 +748,7 @@ public class GlyphProcessingState {
}
}
- private GlyphSequence.CharAssociation[] getAssociationsForward(int start, int count, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts)
+ private CharAssociation[] getAssociationsForward(int start, int count, GlyphTester ignoreTester, CharAssociation[] associations, int[] counts)
throws IndexOutOfBoundsException {
int counted = 0;
int ignored = 0;
@@ -775,7 +776,7 @@ public class GlyphProcessingState {
return associations;
}
- private GlyphSequence.CharAssociation[] getAssociationsReverse(int start, int count, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts)
+ private CharAssociation[] getAssociationsReverse(int start, int count, GlyphTester ignoreTester, CharAssociation[] associations, int[] counts)
throws IndexOutOfBoundsException {
int counted = 0;
int ignored = 0;
@@ -813,7 +814,7 @@ public class GlyphProcessingState {
* @throws IndexOutOfBoundsException if offset or count results in an
* invalid index into input glyph sequence
*/
- public GlyphSequence.CharAssociation[] getAssociations(int offset, int count) throws IndexOutOfBoundsException {
+ public CharAssociation[] getAssociations(int offset, int count) throws IndexOutOfBoundsException {
return getAssociations(offset, count, offset < 0, ignoreDefault, null, null);
}
@@ -833,7 +834,7 @@ public class GlyphProcessingState {
* @throws IndexOutOfBoundsException if offset or count results in an
* invalid index into input glyph sequence
*/
- public GlyphSequence.CharAssociation[] getIgnoredAssociations(int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, GlyphSequence.CharAssociation[] associations, int[] counts)
+ public CharAssociation[] getIgnoredAssociations(int offset, int count, boolean reverseOrder, GlyphTester ignoreTester, CharAssociation[] associations, int[] counts)
throws IndexOutOfBoundsException {
return getAssociations(offset, count, reverseOrder, new NotGlyphTester(ignoreTester), associations, counts);
}
@@ -848,7 +849,7 @@ public class GlyphProcessingState {
* @throws IndexOutOfBoundsException if offset or count results in an
* invalid index into input glyph sequence
*/
- public GlyphSequence.CharAssociation[] getIgnoredAssociations(int offset, int count) throws IndexOutOfBoundsException {
+ public CharAssociation[] getIgnoredAssociations(int offset, int count) throws IndexOutOfBoundsException {
return getIgnoredAssociations(offset, count, offset < 0, ignoreDefault, null, null);
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionState.java Sun Aug 3 04:40:34 2014
@@ -23,6 +23,7 @@ import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester;
@@ -128,7 +129,7 @@ public class GlyphSubstitutionState exte
* @param a character association that applies to glyph
* @param predication a predication value to add to association A if predications enabled
*/
- public void putGlyph(int glyph, GlyphSequence.CharAssociation a, Object predication) {
+ public void putGlyph(int glyph, CharAssociation a, Object predication) {
if (!ogb.hasRemaining()) {
ogb = growBuffer(ogb);
}
@@ -145,7 +146,7 @@ public class GlyphSubstitutionState exte
* @param associations array of character associations that apply to glyphs
* @param predication optional predicaion object to be associated with glyphs' associations
*/
- public void putGlyphs(int[] glyphs, GlyphSequence.CharAssociation[] associations, Object predication) {
+ public void putGlyphs(int[] glyphs, CharAssociation[] associations, Object predication) {
assert glyphs != null;
assert associations != null;
assert associations.length >= glyphs.length;
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/GlyphSubstitutionTable.java Sun Aug 3 04:40:34 2014
@@ -28,6 +28,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.complexscripts.scripts.ScriptProcessor;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.GlyphTester;
@@ -382,7 +383,7 @@ public class GlyphSubstitutionTable exte
} else {
int[] ga = getGlyphsForCoverageIndex(ci, gi);
if (ga != null) {
- ss.putGlyphs(ga, GlyphSequence.CharAssociation.replicate(ss.getAssociation(), ga.length), Boolean.TRUE);
+ ss.putGlyphs(ga, CharAssociation.replicate(ss.getAssociation(), ga.length), Boolean.TRUE);
ss.consume(1);
}
return true;
@@ -581,9 +582,9 @@ public class GlyphSubstitutionTable exte
nga = counts[0];
ngi = counts[1];
// fetch associations of matched component glyphs
- GlyphSequence.CharAssociation[] laa = ss.getAssociations(0, nga);
+ CharAssociation[] laa = ss.getAssociations(0, nga);
// output ligature glyph and its association
- ss.putGlyph(go, GlyphSequence.CharAssociation.join(laa), Boolean.TRUE);
+ ss.putGlyph(go, CharAssociation.join(laa), Boolean.TRUE);
// fetch and output ignored glyphs (if necessary)
if (ngi > 0) {
ss.putGlyphs(ss.getIgnoredGlyphs(0, ngi), ss.getIgnoredAssociations(0, ngi), null);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/fonts/Substitutable.java Sun Aug 3 04:40:34 2014
@@ -19,6 +19,8 @@
package org.apache.fop.complexscripts.fonts;
+import java.util.List;
+
// CSOFF: LineLengthCheck
/**
@@ -43,10 +45,11 @@ public interface Substitutable {
* @param cs character sequence to map to output font encoding character sequence
* @param script a script identifier
* @param language a language identifier
+ * @param associations optional list to receive list of character associations
* @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
*/
- CharSequence performSubstitution(CharSequence cs, String script, String language);
+ CharSequence performSubstitution(CharSequence cs, String script, String language, List associations);
/**
* Reorder combining marks in character sequence so that they precede (within the sequence) the base
@@ -57,8 +60,9 @@ public interface Substitutable {
* @param gpa associated glyph position adjustments (also reordered)
* @param script a script identifier
* @param language a language identifier
+ * @param associations optional list of associations to be reordered
* @return output sequence containing reordered "font characters"
*/
- CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa, String script, String language);
+ CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa, String script, String language, List associations);
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/ArabicScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFac
import org.apache.fop.complexscripts.bidi.BidiClass;
import org.apache.fop.complexscripts.bidi.BidiConstants;
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphContextTester;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester;
@@ -147,7 +148,7 @@ public class ArabicScriptProcessor exten
}
private static boolean inFinalContext(String script, String language, String feature, GlyphSequence gs, int index, int flags) {
- GlyphSequence.CharAssociation a = gs.getAssociation(index);
+ CharAssociation a = gs.getAssociation(index);
int[] ca = gs.getCharacterArray(false);
int nc = gs.getCharacterCount();
if (nc == 0) {
@@ -168,7 +169,7 @@ public class ArabicScriptProcessor exten
}
private static boolean inInitialContext(String script, String language, String feature, GlyphSequence gs, int index, int flags) {
- GlyphSequence.CharAssociation a = gs.getAssociation(index);
+ CharAssociation a = gs.getAssociation(index);
int[] ca = gs.getCharacterArray(false);
int nc = gs.getCharacterCount();
if (nc == 0) {
@@ -187,7 +188,7 @@ public class ArabicScriptProcessor exten
}
private static boolean inIsolateContext(String script, String language, String feature, GlyphSequence gs, int index, int flags) {
- GlyphSequence.CharAssociation a = gs.getAssociation(index);
+ CharAssociation a = gs.getAssociation(index);
int nc = gs.getCharacterCount();
if (nc == 0) {
return false;
@@ -199,7 +200,7 @@ public class ArabicScriptProcessor exten
}
private static boolean inLigatureContext(String script, String language, String feature, GlyphSequence gs, int index, int flags) {
- GlyphSequence.CharAssociation a = gs.getAssociation(index);
+ CharAssociation a = gs.getAssociation(index);
int[] ca = gs.getCharacterArray(false);
int nc = gs.getCharacterCount();
if (nc == 0) {
@@ -218,7 +219,7 @@ public class ArabicScriptProcessor exten
}
private static boolean inMedialContext(String script, String language, String feature, GlyphSequence gs, int index, int flags) {
- GlyphSequence.CharAssociation a = gs.getAssociation(index);
+ CharAssociation a = gs.getAssociation(index);
int[] ca = gs.getCharacterArray(false);
int nc = gs.getCharacterCount();
if (nc == 0) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DefaultScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -20,6 +20,7 @@
package org.apache.fop.complexscripts.scripts;
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
import org.apache.fop.complexscripts.util.ScriptContextTester;
@@ -92,18 +93,18 @@ public class DefaultScriptProcessor exte
}
// only reorder if there is at least one mark and at least one non-mark glyph
if ((nm > 0) && ((ng - nm) > 0)) {
- GlyphSequence.CharAssociation[] aa = gs.getAssociations(0, -1);
+ CharAssociation[] aa = gs.getAssociations(0, -1);
int[] nga = new int [ ng ];
int[][] npa = (gpa != null) ? new int [ ng ][] : null;
- GlyphSequence.CharAssociation[] naa = new GlyphSequence.CharAssociation [ ng ];
+ CharAssociation[] naa = new CharAssociation [ ng ];
int k = 0;
- GlyphSequence.CharAssociation ba = null;
+ CharAssociation ba = null;
int bg = -1;
int[] bpa = null;
for (int i = 0; i < ng; i++) {
int gid = ga [ i ];
int[] pa = (gpa != null) ? gpa [ i ] : null;
- GlyphSequence.CharAssociation ca = aa [ i ];
+ CharAssociation ca = aa [ i ];
if (gdef.isGlyphClass(gid, GlyphDefinitionTable.GLYPH_CLASS_MARK)) {
nga [ k ] = gid;
naa [ k ] = ca;
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/DevanagariScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -22,6 +22,7 @@ package org.apache.fop.complexscripts.sc
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
// CSOFF: LineLengthCheck
@@ -82,7 +83,7 @@ public class DevanagariScriptProcessor e
}
private static boolean containsPreBaseMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isPreM(ca [ i ])) {
@@ -93,7 +94,7 @@ public class DevanagariScriptProcessor e
}
private static boolean containsConsonant(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isC(ca [ i ])) {
@@ -159,7 +160,7 @@ public class DevanagariScriptProcessor e
}
private static boolean containsMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isM(ca [ i ])) {
@@ -170,7 +171,7 @@ public class DevanagariScriptProcessor e
}
private static boolean containsOtherMark(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
switch (typeOf(ca [ i ])) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GujaratiScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -22,6 +22,7 @@ package org.apache.fop.complexscripts.sc
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
// CSOFF: LineLengthCheck
@@ -82,7 +83,7 @@ public class GujaratiScriptProcessor ext
}
private static boolean containsPreBaseMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isPreM(ca [ i ])) {
@@ -93,7 +94,7 @@ public class GujaratiScriptProcessor ext
}
private static boolean containsConsonant(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isC(ca [ i ])) {
@@ -159,7 +160,7 @@ public class GujaratiScriptProcessor ext
}
private static boolean containsMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isM(ca [ i ])) {
@@ -170,7 +171,7 @@ public class GujaratiScriptProcessor ext
}
private static boolean containsOtherMark(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
switch (typeOf(ca [ i ])) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/GurmukhiScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.complexscripts.fonts.GlyphDefinitionTable;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.GlyphSequence;
// CSOFF: LineLengthCheck
@@ -83,7 +84,7 @@ public class GurmukhiScriptProcessor ext
}
private static boolean containsPreBaseMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isPreM(ca [ i ])) {
@@ -94,7 +95,7 @@ public class GurmukhiScriptProcessor ext
}
private static boolean containsConsonant(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isC(ca [ i ])) {
@@ -160,7 +161,7 @@ public class GurmukhiScriptProcessor ext
}
private static boolean containsMatra(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
if (isM(ca [ i ])) {
@@ -171,7 +172,7 @@ public class GurmukhiScriptProcessor ext
}
private static boolean containsOtherMark(GlyphSequence gs, int k) {
- GlyphSequence.CharAssociation a = gs.getAssociation(k);
+ CharAssociation a = gs.getAssociation(k);
int[] ca = gs.getCharacterArray(false);
for (int i = a.getStart(), e = a.getEnd(); i < e; i++) {
switch (typeOf(ca [ i ])) {
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/scripts/IndicScriptProcessor.java Sun Aug 3 04:40:34 2014
@@ -31,6 +31,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.complexscripts.fonts.GlyphTable;
+import org.apache.fop.complexscripts.util.CharAssociation;
import org.apache.fop.complexscripts.util.CharScript;
import org.apache.fop.complexscripts.util.GlyphContextTester;
import org.apache.fop.complexscripts.util.GlyphSequence;
@@ -488,21 +489,21 @@ public class IndicScriptProcessor extend
protected GlyphSequence[] segmentize(GlyphSequence gs, Segment[] sa) {
int ng = gs.getGlyphCount();
int[] ga = gs.getGlyphArray(false);
- GlyphSequence.CharAssociation[] aa = gs.getAssociations(0, -1);
+ CharAssociation[] aa = gs.getAssociations(0, -1);
Vector<GlyphSequence> nsv = new Vector<GlyphSequence>();
for (int i = 0, ns = sa.length; i < ns; i++) {
Segment s = sa [ i ];
Vector<Integer> ngv = new Vector<Integer>(ng);
- Vector<GlyphSequence.CharAssociation> nav = new Vector<GlyphSequence.CharAssociation>(ng);
+ Vector<CharAssociation> nav = new Vector<CharAssociation>(ng);
for (int j = 0; j < ng; j++) {
- GlyphSequence.CharAssociation ca = aa [ j ];
+ CharAssociation ca = aa [ j ];
if (ca.contained(s.getOffset(), s.getCount())) {
ngv.add(ga [ j ]);
nav.add(ca);
}
}
if (ngv.size() > 0) {
- nsv.add(new GlyphSequence(gs, null, toIntArray(ngv), null, null, nav.toArray(new GlyphSequence.CharAssociation [ nav.size() ]), null));
+ nsv.add(new GlyphSequence(gs, null, toIntArray(ngv), null, null, nav.toArray(new CharAssociation [ nav.size() ]), null));
}
}
if (nsv.size() > 0) {
Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java?rev=1615385&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java Sun Aug 3 04:40:34 2014
@@ -0,0 +1,490 @@
+/*
+ * 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.complexscripts.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A structure class encapsulating an interval of characters expressed as an offset and count of
+ * Unicode scalar values (in an IntBuffer). A <code>CharAssociation</code> is used to maintain a
+ * backpointer from a glyph to one or more character intervals from which the glyph was derived.
+ *
+ * Each glyph in a glyph sequence is associated with a single <code>CharAssociation</code> instance.
+ *
+ * A <code>CharAssociation</code> instance is additionally (and optionally) used to record
+ * predication information about the glyph, such as whether the glyph was produced by the
+ * application of a specific substitution table or whether its position was adjusted by a specific
+ * poisitioning table.
+ *
+ * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p>
+ */
+public class CharAssociation implements Cloneable {
+
+ // instance state
+ private final int offset;
+ private final int count;
+ private final int[] subIntervals;
+ private Map<String, Object> predications;
+
+ // class state
+ private static volatile Map<String, PredicationMerger> predicationMergers;
+
+ interface PredicationMerger {
+ Object merge(String key, Object v1, Object v2);
+ }
+
+ /**
+ * Instantiate a character association.
+ * @param offset into array of Unicode scalar values (in associated IntBuffer)
+ * @param count of Unicode scalar values (in associated IntBuffer)
+ * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even
+ * members of array are sub-interval starts, and odd members are sub-interval
+ * ends (exclusive)
+ */
+ public CharAssociation(int offset, int count, int[] subIntervals) {
+ this.offset = offset;
+ this.count = count;
+ this.subIntervals = ((subIntervals != null) && (subIntervals.length > 2)) ? subIntervals : null;
+ }
+
+ /**
+ * Instantiate a non-disjoint character association.
+ * @param offset into array of UTF-16 code elements (in associated CharSequence)
+ * @param count of UTF-16 character code elements (in associated CharSequence)
+ */
+ public CharAssociation(int offset, int count) {
+ this (offset, count, null);
+ }
+
+ /**
+ * Instantiate a non-disjoint character association.
+ * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even
+ * members of array are sub-interval starts, and odd members are sub-interval
+ * ends (exclusive)
+ */
+ public CharAssociation(int[] subIntervals) {
+ this (getSubIntervalsStart(subIntervals), getSubIntervalsLength(subIntervals), subIntervals);
+ }
+
+ /** @return offset (start of association interval) */
+ public int getOffset() {
+ return offset;
+ }
+
+ /** @return count (number of characer codes in association) */
+ public int getCount() {
+ return count;
+ }
+
+ /** @return start of association interval */
+ public int getStart() {
+ return getOffset();
+ }
+
+ /** @return end of association interval */
+ public int getEnd() {
+ return getOffset() + getCount();
+ }
+
+ /** @return true if association is disjoint */
+ public boolean isDisjoint() {
+ return subIntervals != null;
+ }
+
+ /** @return subintervals of disjoint association */
+ public int[] getSubIntervals() {
+ return subIntervals;
+ }
+
+ /** @return count of subintervals of disjoint association */
+ public int getSubIntervalCount() {
+ return (subIntervals != null) ? (subIntervals.length / 2) : 0;
+ }
+
+ /**
+ * @param offset of interval in sequence
+ * @param count length of interval
+ * @return true if this association is contained within [offset,offset+count)
+ */
+ public boolean contained(int offset, int count) {
+ int s = offset;
+ int e = offset + count;
+ if (!isDisjoint()) {
+ int s0 = getStart();
+ int e0 = getEnd();
+ return (s0 >= s) && (e0 <= e);
+ } else {
+ int ns = getSubIntervalCount();
+ for (int i = 0; i < ns; i++) {
+ int s0 = subIntervals [ 2 * i + 0 ];
+ int e0 = subIntervals [ 2 * i + 1 ];
+ if ((s0 >= s) && (e0 <= e)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Set predication <KEY,VALUE>.
+ * @param key predication key
+ * @param value predication value
+ */
+ public void setPredication(String key, Object value) {
+ if (predications == null) {
+ predications = new HashMap<String, Object>();
+ }
+ if (predications != null) {
+ predications.put(key, value);
+ }
+ }
+
+ /**
+ * Get predication KEY.
+ * @param key predication key
+ * @return predication KEY at OFFSET or null if none exists
+ */
+ public Object getPredication(String key) {
+ if (predications != null) {
+ return predications.get(key);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Merge predication <KEY,VALUE>.
+ * @param key predication key
+ * @param value predication value
+ */
+ public void mergePredication(String key, Object value) {
+ if (predications == null) {
+ predications = new HashMap<String, Object>();
+ }
+ if (predications != null) {
+ if (predications.containsKey(key)) {
+ Object v1 = predications.get(key);
+ Object v2 = value;
+ predications.put(key, mergePredicationValues(key, v1, v2));
+ } else {
+ predications.put(key, value);
+ }
+ }
+ }
+
+ /**
+ * Merge predication values V1 and V2 on KEY. Uses registered <code>PredicationMerger</code>
+ * if one exists, otherwise uses V2 if non-null, otherwise uses V1.
+ * @param key predication key
+ * @param v1 first (original) predication value
+ * @param v2 second (to be merged) predication value
+ * @return merged value
+ */
+ public static Object mergePredicationValues(String key, Object v1, Object v2) {
+ PredicationMerger pm = getPredicationMerger(key);
+ if (pm != null) {
+ return pm.merge(key, v1, v2);
+ } else if (v2 != null) {
+ return v2;
+ } else {
+ return v1;
+ }
+ }
+
+ /**
+ * Merge predications from another CA.
+ * @param ca from which to merge
+ */
+ public void mergePredications(CharAssociation ca) {
+ if (ca.predications != null) {
+ for (Map.Entry<String, Object> e : ca.predications.entrySet()) {
+ mergePredication(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() {
+ try {
+ CharAssociation ca = (CharAssociation) super.clone();
+ if (predications != null) {
+ ca.predications = new HashMap<String, Object>(predications);
+ }
+ return ca;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Register predication merger PM for KEY.
+ * @param key for predication merger
+ * @param pm predication merger
+ */
+ public static void setPredicationMerger(String key, PredicationMerger pm) {
+ if (predicationMergers == null) {
+ predicationMergers = new HashMap<String, PredicationMerger>();
+ }
+ if (predicationMergers != null) {
+ predicationMergers.put(key, pm);
+ }
+ }
+
+ /**
+ * Obtain predication merger for KEY.
+ * @param key for predication merger
+ * @return predication merger or null if none exists
+ */
+ public static PredicationMerger getPredicationMerger(String key) {
+ if (predicationMergers != null) {
+ return predicationMergers.get(key);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Replicate association to form <code>repeat</code> new associations.
+ * @param a association to replicate
+ * @param repeat count
+ * @return array of replicated associations
+ */
+ public static CharAssociation[] replicate(CharAssociation a, int repeat) {
+ CharAssociation[] aa = new CharAssociation [ repeat ];
+ for (int i = 0, n = aa.length; i < n; i++) {
+ aa [ i ] = (CharAssociation) a.clone();
+ }
+ return aa;
+ }
+
+ /**
+ * Join (merge) multiple associations into a single, potentially disjoint
+ * association.
+ * @param aa array of associations to join
+ * @return (possibly disjoint) association containing joined associations
+ */
+ public static CharAssociation join(CharAssociation[] aa) {
+ CharAssociation ca;
+ // extract sorted intervals
+ int[] ia = extractIntervals(aa);
+ if ((ia == null) || (ia.length == 0)) {
+ ca = new CharAssociation(0, 0);
+ } else if (ia.length == 2) {
+ int s = ia[0];
+ int e = ia[1];
+ ca = new CharAssociation(s, e - s);
+ } else {
+ ca = new CharAssociation(mergeIntervals(ia));
+ }
+ return mergePredicates(ca, aa);
+ }
+
+ private static CharAssociation mergePredicates(CharAssociation ca, CharAssociation[] aa) {
+ for (CharAssociation a : aa) {
+ ca.mergePredications(a);
+ }
+ return ca;
+ }
+
+ private static int getSubIntervalsStart(int[] ia) {
+ int us = Integer.MAX_VALUE;
+ int ue = Integer.MIN_VALUE;
+ if (ia != null) {
+ for (int i = 0, n = ia.length; i < n; i += 2) {
+ int s = ia [ i + 0 ];
+ int e = ia [ i + 1 ];
+ if (s < us) {
+ us = s;
+ }
+ if (e > ue) {
+ ue = e;
+ }
+ }
+ if (ue < 0) {
+ ue = 0;
+ }
+ if (us > ue) {
+ us = ue;
+ }
+ }
+ return us;
+ }
+
+ private static int getSubIntervalsLength(int[] ia) {
+ int us = Integer.MAX_VALUE;
+ int ue = Integer.MIN_VALUE;
+ if (ia != null) {
+ for (int i = 0, n = ia.length; i < n; i += 2) {
+ int s = ia [ i + 0 ];
+ int e = ia [ i + 1 ];
+ if (s < us) {
+ us = s;
+ }
+ if (e > ue) {
+ ue = e;
+ }
+ }
+ if (ue < 0) {
+ ue = 0;
+ }
+ if (us > ue) {
+ us = ue;
+ }
+ }
+ return ue - us;
+ }
+
+ /**
+ * Extract sorted sub-intervals.
+ */
+ private static int[] extractIntervals(CharAssociation[] aa) {
+ int ni = 0;
+ for (int i = 0, n = aa.length; i < n; i++) {
+ CharAssociation a = aa [ i ];
+ if (a.isDisjoint()) {
+ ni += a.getSubIntervalCount();
+ } else {
+ ni += 1;
+ }
+ }
+ int[] sa = new int [ ni ];
+ int[] ea = new int [ ni ];
+ for (int i = 0, k = 0; i < aa.length; i++) {
+ CharAssociation a = aa [ i ];
+ if (a.isDisjoint()) {
+ int[] da = a.getSubIntervals();
+ for (int j = 0; j < da.length; j += 2) {
+ sa [ k ] = da [ j + 0 ];
+ ea [ k ] = da [ j + 1 ];
+ k++;
+ }
+ } else {
+ sa [ k ] = a.getStart();
+ ea [ k ] = a.getEnd();
+ k++;
+ }
+ }
+ return sortIntervals(sa, ea);
+ }
+
+ private static final int[] SORT_INCREMENTS_16
+ = { 1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1 };
+
+ private static final int[] SORT_INCREMENTS_03
+ = { 7, 3, 1 };
+
+ /**
+ * Sort sub-intervals using modified Shell Sort.
+ */
+ private static int[] sortIntervals(int[] sa, int[] ea) {
+ assert sa != null;
+ assert ea != null;
+ assert sa.length == ea.length;
+ int ni = sa.length;
+ int[] incr = (ni < 21) ? SORT_INCREMENTS_03 : SORT_INCREMENTS_16;
+ for (int k = 0; k < incr.length; k++) {
+ for (int h = incr [ k ], i = h, n = ni, j; i < n; i++) {
+ int s1 = sa [ i ];
+ int e1 = ea [ i ];
+ for (j = i; j >= h; j -= h) {
+ int s2 = sa [ j - h ];
+ int e2 = ea [ j - h ];
+ if (s2 > s1) {
+ sa [ j ] = s2;
+ ea [ j ] = e2;
+ } else if ((s2 == s1) && (e2 > e1)) {
+ sa [ j ] = s2;
+ ea [ j ] = e2;
+ } else {
+ break;
+ }
+ }
+ sa [ j ] = s1;
+ ea [ j ] = e1;
+ }
+ }
+ int[] ia = new int [ ni * 2 ];
+ for (int i = 0; i < ni; i++) {
+ ia [ (i * 2) + 0 ] = sa [ i ];
+ ia [ (i * 2) + 1 ] = ea [ i ];
+ }
+ return ia;
+ }
+
+ /**
+ * Merge overlapping and abutting sub-intervals.
+ */
+ private static int[] mergeIntervals(int[] ia) {
+ int ni = ia.length;
+ int i;
+ int n;
+ int nm;
+ int is;
+ int ie;
+ // count merged sub-intervals
+ for (i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2) {
+ int s = ia [ i + 0 ];
+ int e = ia [ i + 1 ];
+ if ((ie < 0) || (s > ie)) {
+ is = s;
+ ie = e;
+ nm++;
+ } else if (s >= is) {
+ if (e > ie) {
+ ie = e;
+ }
+ }
+ }
+ int[] mi = new int [ nm * 2 ];
+ // populate merged sub-intervals
+ for (i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2) {
+ int s = ia [ i + 0 ];
+ int e = ia [ i + 1 ];
+ int k = nm * 2;
+ if ((ie < 0) || (s > ie)) {
+ is = s;
+ ie = e;
+ mi [ k + 0 ] = is;
+ mi [ k + 1 ] = ie;
+ nm++;
+ } else if (s >= is) {
+ if (e > ie) {
+ ie = e;
+ }
+ mi [ k - 1 ] = ie;
+ }
+ }
+ return mi;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append('[');
+ sb.append(offset);
+ sb.append(',');
+ sb.append(count);
+ sb.append(']');
+ return sb.toString();
+ }
+
+}
Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/CharAssociation.java
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/complexscripts/util/GlyphSequence.java Sun Aug 3 04:40:34 2014
@@ -22,9 +22,7 @@ package org.apache.fop.complexscripts.ut
import java.nio.IntBuffer;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
// CSOFF: LineLengthCheck
@@ -527,8 +525,8 @@ public class GlyphSequence implements Cl
int ng = gs.getGlyphCount();
int[] ga = gs.getGlyphArray(false);
int[] nga = new int [ ng ];
- GlyphSequence.CharAssociation[] aa = gs.getAssociations(0, ng);
- GlyphSequence.CharAssociation[] naa = new GlyphSequence.CharAssociation [ ng ];
+ CharAssociation[] aa = gs.getAssociations(0, ng);
+ CharAssociation[] naa = new CharAssociation [ ng ];
if (source < target) {
int t = 0;
for (int s = 0, e = source; s < e; s++, t++) {
@@ -614,462 +612,4 @@ public class GlyphSequence implements Cl
}
}
- /**
- * A structure class encapsulating an interval of characters
- * expressed as an offset and count of Unicode scalar values (in
- * an IntBuffer). A <code>CharAssociation</code> is used to
- * maintain a backpointer from a glyph to one or more character
- * intervals from which the glyph was derived.
- *
- * Each glyph in a glyph sequence is associated with a single
- * <code>CharAssociation</code> instance.
- *
- * A <code>CharAssociation</code> instance is additionally (and
- * optionally) used to record predication information about the
- * glyph, such as whether the glyph was produced by the
- * application of a specific substitution table or whether its
- * position was adjusted by a specific poisitioning table.
- */
- public static class CharAssociation implements Cloneable {
-
- // instance state
- private final int offset;
- private final int count;
- private final int[] subIntervals;
- private Map<String, Object> predications;
-
- // class state
- private static volatile Map<String, PredicationMerger> predicationMergers;
-
- interface PredicationMerger {
- Object merge(String key, Object v1, Object v2);
- }
-
- /**
- * Instantiate a character association.
- * @param offset into array of Unicode scalar values (in associated IntBuffer)
- * @param count of Unicode scalar values (in associated IntBuffer)
- * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even
- * members of array are sub-interval starts, and odd members are sub-interval
- * ends (exclusive)
- */
- public CharAssociation(int offset, int count, int[] subIntervals) {
- this.offset = offset;
- this.count = count;
- this.subIntervals = ((subIntervals != null) && (subIntervals.length > 2)) ? subIntervals : null;
- }
-
- /**
- * Instantiate a non-disjoint character association.
- * @param offset into array of UTF-16 code elements (in associated CharSequence)
- * @param count of UTF-16 character code elements (in associated CharSequence)
- */
- public CharAssociation(int offset, int count) {
- this (offset, count, null);
- }
-
- /**
- * Instantiate a non-disjoint character association.
- * @param subIntervals if disjoint, then array of sub-intervals, otherwise null; even
- * members of array are sub-interval starts, and odd members are sub-interval
- * ends (exclusive)
- */
- public CharAssociation(int[] subIntervals) {
- this (getSubIntervalsStart(subIntervals), getSubIntervalsLength(subIntervals), subIntervals);
- }
-
- /** @return offset (start of association interval) */
- public int getOffset() {
- return offset;
- }
-
- /** @return count (number of characer codes in association) */
- public int getCount() {
- return count;
- }
-
- /** @return start of association interval */
- public int getStart() {
- return getOffset();
- }
-
- /** @return end of association interval */
- public int getEnd() {
- return getOffset() + getCount();
- }
-
- /** @return true if association is disjoint */
- public boolean isDisjoint() {
- return subIntervals != null;
- }
-
- /** @return subintervals of disjoint association */
- public int[] getSubIntervals() {
- return subIntervals;
- }
-
- /** @return count of subintervals of disjoint association */
- public int getSubIntervalCount() {
- return (subIntervals != null) ? (subIntervals.length / 2) : 0;
- }
-
- /**
- * @param offset of interval in sequence
- * @param count length of interval
- * @return true if this association is contained within [offset,offset+count)
- */
- public boolean contained(int offset, int count) {
- int s = offset;
- int e = offset + count;
- if (!isDisjoint()) {
- int s0 = getStart();
- int e0 = getEnd();
- return (s0 >= s) && (e0 <= e);
- } else {
- int ns = getSubIntervalCount();
- for (int i = 0; i < ns; i++) {
- int s0 = subIntervals [ 2 * i + 0 ];
- int e0 = subIntervals [ 2 * i + 1 ];
- if ((s0 >= s) && (e0 <= e)) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Set predication <KEY,VALUE>.
- * @param key predication key
- * @param value predication value
- */
- public void setPredication(String key, Object value) {
- if (predications == null) {
- predications = new HashMap<String, Object>();
- }
- if (predications != null) {
- predications.put(key, value);
- }
- }
-
- /**
- * Get predication KEY.
- * @param key predication key
- * @return predication KEY at OFFSET or null if none exists
- */
- public Object getPredication(String key) {
- if (predications != null) {
- return predications.get(key);
- } else {
- return null;
- }
- }
-
- /**
- * Merge predication <KEY,VALUE>.
- * @param key predication key
- * @param value predication value
- */
- public void mergePredication(String key, Object value) {
- if (predications == null) {
- predications = new HashMap<String, Object>();
- }
- if (predications != null) {
- if (predications.containsKey(key)) {
- Object v1 = predications.get(key);
- Object v2 = value;
- predications.put(key, mergePredicationValues(key, v1, v2));
- } else {
- predications.put(key, value);
- }
- }
- }
-
- /**
- * Merge predication values V1 and V2 on KEY. Uses registered <code>PredicationMerger</code>
- * if one exists, otherwise uses V2 if non-null, otherwise uses V1.
- * @param key predication key
- * @param v1 first (original) predication value
- * @param v2 second (to be merged) predication value
- * @return merged value
- */
- public static Object mergePredicationValues(String key, Object v1, Object v2) {
- PredicationMerger pm = getPredicationMerger(key);
- if (pm != null) {
- return pm.merge(key, v1, v2);
- } else if (v2 != null) {
- return v2;
- } else {
- return v1;
- }
- }
-
- /**
- * Merge predications from another CA.
- * @param ca from which to merge
- */
- public void mergePredications(CharAssociation ca) {
- if (ca.predications != null) {
- for (Map.Entry<String, Object> e : ca.predications.entrySet()) {
- mergePredication(e.getKey(), e.getValue());
- }
- }
- }
-
- /** {@inheritDoc} */
- public Object clone() {
- try {
- CharAssociation ca = (CharAssociation) super.clone();
- if (predications != null) {
- ca.predications = new HashMap<String, Object>(predications);
- }
- return ca;
- } catch (CloneNotSupportedException e) {
- return null;
- }
- }
-
- /**
- * Register predication merger PM for KEY.
- * @param key for predication merger
- * @param pm predication merger
- */
- public static void setPredicationMerger(String key, PredicationMerger pm) {
- if (predicationMergers == null) {
- predicationMergers = new HashMap<String, PredicationMerger>();
- }
- if (predicationMergers != null) {
- predicationMergers.put(key, pm);
- }
- }
-
- /**
- * Obtain predication merger for KEY.
- * @param key for predication merger
- * @return predication merger or null if none exists
- */
- public static PredicationMerger getPredicationMerger(String key) {
- if (predicationMergers != null) {
- return predicationMergers.get(key);
- } else {
- return null;
- }
- }
-
- /**
- * Replicate association to form <code>repeat</code> new associations.
- * @param a association to replicate
- * @param repeat count
- * @return array of replicated associations
- */
- public static CharAssociation[] replicate(CharAssociation a, int repeat) {
- CharAssociation[] aa = new CharAssociation [ repeat ];
- for (int i = 0, n = aa.length; i < n; i++) {
- aa [ i ] = (CharAssociation) a.clone();
- }
- return aa;
- }
-
- /**
- * Join (merge) multiple associations into a single, potentially disjoint
- * association.
- * @param aa array of associations to join
- * @return (possibly disjoint) association containing joined associations
- */
- public static CharAssociation join(CharAssociation[] aa) {
- CharAssociation ca;
- // extract sorted intervals
- int[] ia = extractIntervals(aa);
- if ((ia == null) || (ia.length == 0)) {
- ca = new CharAssociation(0, 0);
- } else if (ia.length == 2) {
- int s = ia[0];
- int e = ia[1];
- ca = new CharAssociation(s, e - s);
- } else {
- ca = new CharAssociation(mergeIntervals(ia));
- }
- return mergePredicates(ca, aa);
- }
-
- private static CharAssociation mergePredicates(CharAssociation ca, CharAssociation[] aa) {
- for (CharAssociation a : aa) {
- ca.mergePredications(a);
- }
- return ca;
- }
-
- private static int getSubIntervalsStart(int[] ia) {
- int us = Integer.MAX_VALUE;
- int ue = Integer.MIN_VALUE;
- if (ia != null) {
- for (int i = 0, n = ia.length; i < n; i += 2) {
- int s = ia [ i + 0 ];
- int e = ia [ i + 1 ];
- if (s < us) {
- us = s;
- }
- if (e > ue) {
- ue = e;
- }
- }
- if (ue < 0) {
- ue = 0;
- }
- if (us > ue) {
- us = ue;
- }
- }
- return us;
- }
-
- private static int getSubIntervalsLength(int[] ia) {
- int us = Integer.MAX_VALUE;
- int ue = Integer.MIN_VALUE;
- if (ia != null) {
- for (int i = 0, n = ia.length; i < n; i += 2) {
- int s = ia [ i + 0 ];
- int e = ia [ i + 1 ];
- if (s < us) {
- us = s;
- }
- if (e > ue) {
- ue = e;
- }
- }
- if (ue < 0) {
- ue = 0;
- }
- if (us > ue) {
- us = ue;
- }
- }
- return ue - us;
- }
-
- /**
- * Extract sorted sub-intervals.
- */
- private static int[] extractIntervals(CharAssociation[] aa) {
- int ni = 0;
- for (int i = 0, n = aa.length; i < n; i++) {
- CharAssociation a = aa [ i ];
- if (a.isDisjoint()) {
- ni += a.getSubIntervalCount();
- } else {
- ni += 1;
- }
- }
- int[] sa = new int [ ni ];
- int[] ea = new int [ ni ];
- for (int i = 0, k = 0; i < aa.length; i++) {
- CharAssociation a = aa [ i ];
- if (a.isDisjoint()) {
- int[] da = a.getSubIntervals();
- for (int j = 0; j < da.length; j += 2) {
- sa [ k ] = da [ j + 0 ];
- ea [ k ] = da [ j + 1 ];
- k++;
- }
- } else {
- sa [ k ] = a.getStart();
- ea [ k ] = a.getEnd();
- k++;
- }
- }
- return sortIntervals(sa, ea);
- }
-
- private static final int[] SORT_INCREMENTS_16
- = { 1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1 };
-
- private static final int[] SORT_INCREMENTS_03
- = { 7, 3, 1 };
-
- /**
- * Sort sub-intervals using modified Shell Sort.
- */
- private static int[] sortIntervals(int[] sa, int[] ea) {
- assert sa != null;
- assert ea != null;
- assert sa.length == ea.length;
- int ni = sa.length;
- int[] incr = (ni < 21) ? SORT_INCREMENTS_03 : SORT_INCREMENTS_16;
- for (int k = 0; k < incr.length; k++) {
- for (int h = incr [ k ], i = h, n = ni, j; i < n; i++) {
- int s1 = sa [ i ];
- int e1 = ea [ i ];
- for (j = i; j >= h; j -= h) {
- int s2 = sa [ j - h ];
- int e2 = ea [ j - h ];
- if (s2 > s1) {
- sa [ j ] = s2;
- ea [ j ] = e2;
- } else if ((s2 == s1) && (e2 > e1)) {
- sa [ j ] = s2;
- ea [ j ] = e2;
- } else {
- break;
- }
- }
- sa [ j ] = s1;
- ea [ j ] = e1;
- }
- }
- int[] ia = new int [ ni * 2 ];
- for (int i = 0; i < ni; i++) {
- ia [ (i * 2) + 0 ] = sa [ i ];
- ia [ (i * 2) + 1 ] = ea [ i ];
- }
- return ia;
- }
-
- /**
- * Merge overlapping and abutting sub-intervals.
- */
- private static int[] mergeIntervals(int[] ia) {
- int ni = ia.length;
- int i;
- int n;
- int nm;
- int is;
- int ie;
- // count merged sub-intervals
- for (i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2) {
- int s = ia [ i + 0 ];
- int e = ia [ i + 1 ];
- if ((ie < 0) || (s > ie)) {
- is = s;
- ie = e;
- nm++;
- } else if (s >= is) {
- if (e > ie) {
- ie = e;
- }
- }
- }
- int[] mi = new int [ nm * 2 ];
- // populate merged sub-intervals
- for (i = 0, n = ni, nm = 0, is = ie = -1; i < n; i += 2) {
- int s = ia [ i + 0 ];
- int e = ia [ i + 1 ];
- int k = nm * 2;
- if ((ie < 0) || (s > ie)) {
- is = s;
- ie = e;
- mi [ k + 0 ] = is;
- mi [ k + 1 ] = ie;
- nm++;
- } else if (s >= is) {
- if (e > ie) {
- ie = e;
- }
- mi [ k - 1 ] = ie;
- }
- }
- return mi;
- }
-
- }
-
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/Font.java Sun Aug 3 04:40:34 2014
@@ -20,6 +20,7 @@
package org.apache.fop.fonts;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -402,20 +403,22 @@ public class Font implements Substitutab
}
/** {@inheritDoc} */
- public CharSequence performSubstitution(CharSequence cs, String script, String language) {
+ public CharSequence performSubstitution(CharSequence cs,
+ String script, String language, List associations) {
if (metric instanceof Substitutable) {
Substitutable s = (Substitutable) metric;
- return s.performSubstitution(cs, script, language);
+ return s.performSubstitution(cs, script, language, associations);
} else {
throw new UnsupportedOperationException();
}
}
/** {@inheritDoc} */
- public CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa, String script, String language) {
+ public CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa,
+ String script, String language, List associations) {
if (metric instanceof Substitutable) {
Substitutable s = (Substitutable) metric;
- return s.reorderCombiningMarks(cs, gpa, script, language);
+ return s.reorderCombiningMarks(cs, gpa, script, language, associations);
} else {
throw new UnsupportedOperationException();
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/GlyphMapping.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/GlyphMapping.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/GlyphMapping.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/GlyphMapping.java Sun Aug 3 04:40:34 2014
@@ -19,6 +19,9 @@
package org.apache.fop.fonts;
+import java.util.Collections;
+import java.util.List;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -47,18 +50,19 @@ public class GlyphMapping {
public final Font font;
public final int level;
public final int[][] gposAdjustments;
- public final String mapping;
+ public String mapping;
+ public List associations;
public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount,
MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter,
Font font, int level, int[][] gposAdjustments) {
this(startIndex, endIndex, wordSpaceCount, letterSpaceCount, areaIPD, isHyphenated,
- isSpace, breakOppAfter, font, level, gposAdjustments, null);
+ isSpace, breakOppAfter, font, level, gposAdjustments, null, null);
}
public GlyphMapping(int startIndex, int endIndex, int wordSpaceCount, int letterSpaceCount,
MinOptMax areaIPD, boolean isHyphenated, boolean isSpace, boolean breakOppAfter,
- Font font, int level, int[][] gposAdjustments, String mapping) {
+ Font font, int level, int[][] gposAdjustments, String mapping, List associations) {
assert startIndex <= endIndex;
this.startIndex = startIndex;
this.endIndex = endIndex;
@@ -73,15 +77,17 @@ public class GlyphMapping {
this.level = level;
this.gposAdjustments = gposAdjustments;
this.mapping = mapping;
+ this.associations = associations;
}
public static GlyphMapping doGlyphMapping(TextFragment text, int startIndex, int endIndex,
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 retainAssociations) {
GlyphMapping mapping;
if (font.performsSubstitution() || font.performsPositioning()) {
mapping = processWordMapping(text, startIndex, endIndex, font,
- breakOpportunityChar, endsWithHyphen, level);
+ breakOpportunityChar, endsWithHyphen, level, retainAssociations);
} else {
mapping = processWordNoMapping(text, startIndex, endIndex, font,
letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen,
@@ -92,7 +98,7 @@ public class GlyphMapping {
private static GlyphMapping processWordMapping(TextFragment text, int startIndex,
int endIndex, final Font font, final char breakOpportunityChar,
- final boolean endsWithHyphen, int level) {
+ final boolean endsWithHyphen, int level, boolean retainAssociations) {
int e = endIndex; // end index of word in FOText character buffer
int nLS = 0; // # of letter spaces
String script = text.getScript();
@@ -105,11 +111,11 @@ public class GlyphMapping {
+ " }");
}
- // 1. extract unmapped character sequence
+ // 1. extract unmapped character sequence.
CharSequence ics = text.subSequence(startIndex, e);
// 2. if script is not specified (by FO property) or it is specified as 'auto',
- // then compute dominant script
+ // then compute dominant script.
if ((script == null) || "auto".equals(script)) {
script = CharScript.scriptTagFromCode(CharScript.dominantScript(ics));
}
@@ -117,10 +123,12 @@ public class GlyphMapping {
language = "dflt";
}
- // 3. perform mapping of chars to glyphs ... to glyphs ... to chars
- CharSequence mcs = font.performSubstitution(ics, script, language);
+ // 3. perform mapping of chars to glyphs ... to glyphs ... to chars, retaining
+ // associations if requested.
+ List associations = retainAssociations ? new java.util.ArrayList() : null;
+ CharSequence mcs = font.performSubstitution(ics, script, language, associations);
- // 4. compute glyph position adjustments on (substituted) characters
+ // 4. compute glyph position adjustments on (substituted) characters.
int[][] gpa;
if (font.performsPositioning()) {
// handle GPOS adjustments
@@ -133,10 +141,10 @@ public class GlyphMapping {
}
// 5. reorder combining marks so that they precede (within the mapped char sequence) the
- // base to which they are applied; N.B. position adjustments (gpa) are reordered in place
- mcs = font.reorderCombiningMarks(mcs, gpa, script, language);
+ // base to which they are applied; N.B. position adjustments (gpa) are reordered in place.
+ mcs = font.reorderCombiningMarks(mcs, gpa, script, language, associations);
- // 6. compute word ipd based on final position adjustments
+ // 6. compute word ipd based on final position adjustments.
MinOptMax ipd = MinOptMax.ZERO;
for (int i = 0, n = mcs.length(); i < n; i++) {
int c = mcs.charAt(i);
@@ -155,7 +163,7 @@ public class GlyphMapping {
return new GlyphMapping(startIndex, e, 0, nLS, ipd, endsWithHyphen, false,
breakOpportunityChar != 0, font, level, gpa,
- CharUtilities.isSameSequence(mcs, ics) ? null : mcs.toString());
+ CharUtilities.isSameSequence(mcs, ics) ? null : mcs.toString(), associations);
}
/**
@@ -311,6 +319,27 @@ public class GlyphMapping {
areaIPD = areaIPD.plus(idp);
}
+ public void reverse() {
+ if (mapping.length() > 0) {
+ mapping = new StringBuffer(mapping).reverse().toString();
+ }
+ if (associations != null) {
+ Collections.reverse(associations);
+ }
+ if (gposAdjustments != null) {
+ reverse(gposAdjustments);
+ }
+ }
+
+ private static void reverse(int[][] aa) {
+ for (int i = 0, n = aa.length, m = n / 2; i < m; i++) {
+ int k = n - i - 1;
+ int[] t = aa [ k ];
+ aa [ k ] = aa [ i ];
+ aa [ i ] = t;
+ }
+ }
+
public String toString() {
return super.toString() + "{"
+ "interval = [" + startIndex + "," + endIndex + "]"
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/LazyFont.java Sun Aug 3 04:40:34 2014
@@ -22,6 +22,7 @@ import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -402,10 +403,10 @@ public class LazyFont extends Typeface i
/**
* {@inheritDoc}
*/
- public CharSequence performSubstitution(CharSequence cs, String script, String language) {
+ public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
load(true);
if (realFontDescriptor instanceof Substitutable) {
- return ((Substitutable)realFontDescriptor).performSubstitution(cs, script, language);
+ return ((Substitutable)realFontDescriptor).performSubstitution(cs, script, language, associations);
} else {
return cs;
}
@@ -415,13 +416,13 @@ public class LazyFont extends Typeface i
* {@inheritDoc}
*/
public CharSequence reorderCombiningMarks(
- CharSequence cs, int[][] gpa, String script, String language) {
+ CharSequence cs, int[][] gpa, String script, String language, List associations) {
if (!isMetricsLoaded) {
load(true);
}
if (realFontDescriptor instanceof Substitutable) {
return ((Substitutable)realFontDescriptor)
- .reorderCombiningMarks(cs, gpa, script, language);
+ .reorderCombiningMarks(cs, gpa, script, language, associations);
} else {
return cs;
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fonts/MultiByteFont.java Sun Aug 3 04:40:34 2014
@@ -25,6 +25,7 @@ import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.util.BitSet;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -487,10 +488,14 @@ public class MultiByteFont extends CIDFo
}
/** {@inheritDoc} */
- public CharSequence performSubstitution(CharSequence cs, String script, String language) {
+ public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
if (gsub != null) {
- GlyphSequence igs = mapCharsToGlyphs(cs);
+ GlyphSequence igs = mapCharsToGlyphs(cs, associations);
GlyphSequence ogs = gsub.substitute(igs, script, language);
+ if (associations != null) {
+ associations.clear();
+ associations.addAll(ogs.getAssociations());
+ }
CharSequence ocs = mapGlyphsToChars(ogs);
return ocs;
} else {
@@ -500,10 +505,14 @@ public class MultiByteFont extends CIDFo
/** {@inheritDoc} */
public CharSequence reorderCombiningMarks(
- CharSequence cs, int[][] gpa, String script, String language) {
+ CharSequence cs, int[][] gpa, String script, String language, List associations) {
if (gdef != null) {
- GlyphSequence igs = mapCharsToGlyphs(cs);
+ GlyphSequence igs = mapCharsToGlyphs(cs, associations);
GlyphSequence ogs = gdef.reorderCombiningMarks(igs, gpa, script, language);
+ if (associations != null) {
+ associations.clear();
+ associations.addAll(ogs.getAssociations());
+ }
CharSequence ocs = mapGlyphsToChars(ogs);
return ocs;
} else {
@@ -520,7 +529,7 @@ public class MultiByteFont extends CIDFo
public int[][]
performPositioning(CharSequence cs, String script, String language, int fontSize) {
if (gpos != null) {
- GlyphSequence gs = mapCharsToGlyphs(cs);
+ GlyphSequence gs = mapCharsToGlyphs(cs, null);
int[][] adjustments = new int [ gs.getGlyphCount() ] [ 4 ];
if (gpos.position(gs, script, language, fontSize, this.width, adjustments)) {
return scaleAdjustments(adjustments, fontSize);
@@ -559,7 +568,7 @@ public class MultiByteFont extends CIDFo
* @param cs a CharSequence containing UTF-16 encoded Unicode characters
* @returns a CharSequence containing glyph indices
*/
- private GlyphSequence mapCharsToGlyphs(CharSequence cs) {
+ private GlyphSequence mapCharsToGlyphs(CharSequence cs, List associations) {
IntBuffer cb = IntBuffer.allocate(cs.length());
IntBuffer gb = IntBuffer.allocate(cs.length());
int gi;
@@ -598,7 +607,12 @@ public class MultiByteFont extends CIDFo
}
cb.flip();
gb.flip();
- return new GlyphSequence(cb, gb, null);
+ if ((associations != null) && (associations.size() == cs.length())) {
+ associations = new java.util.ArrayList(associations);
+ } else {
+ associations = null;
+ }
+ return new GlyphSequence(cb, gb, associations);
}
/**
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java Sun Aug 3 04:40:34 2014
@@ -933,7 +933,8 @@ public class TextLayoutManager extends L
char precedingChar = prevMapping != null && !prevMapping.isSpace
&& prevMapping.endIndex > 0 ? foText.charAt(prevMapping.endIndex - 1) : 0;
GlyphMapping mapping = GlyphMapping.doGlyphMapping(foText, thisStart, lastIndex, font,
- letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar, endsWithHyphen, level);
+ letterSpaceIPD, letterSpaceAdjustArray, precedingChar, breakOpportunityChar,
+ endsWithHyphen, level, false);
prevMapping = mapping;
addGlyphMapping(mapping);
tempStart = nextStart;
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java Sun Aug 3 04:40:34 2014
@@ -24,6 +24,7 @@ import java.awt.FontFormatException;
import java.awt.Rectangle;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -261,9 +262,9 @@ public class CustomFontMetricsMapper ext
/**
* {@inheritDoc}
*/
- public CharSequence performSubstitution(CharSequence cs, String script, String language) {
+ public CharSequence performSubstitution(CharSequence cs, String script, String language, List associations) {
if (typeface instanceof Substitutable) {
- return ((Substitutable) typeface).performSubstitution(cs, script, language);
+ return ((Substitutable) typeface).performSubstitution(cs, script, language, associations);
} else {
return cs;
}
@@ -272,9 +273,10 @@ public class CustomFontMetricsMapper ext
/**
* {@inheritDoc}
*/
- public CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa, String script, String language) {
+ public CharSequence reorderCombiningMarks(CharSequence cs, int[][] gpa,
+ String script, String language, List associations) {
if (typeface instanceof Substitutable) {
- return ((Substitutable) typeface).reorderCombiningMarks(cs, gpa, script, language);
+ return ((Substitutable) typeface).reorderCombiningMarks(cs, gpa, script, language, associations);
} else {
return cs;
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/NativeTextPainter.java Sun Aug 3 04:40:34 2014
@@ -23,6 +23,7 @@ import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
+import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
@@ -38,6 +39,8 @@ import org.apache.batik.bridge.SVGGVTFon
import org.apache.batik.gvt.font.FontFamilyResolver;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
+import org.apache.batik.gvt.text.GlyphLayout;
+import org.apache.batik.gvt.text.TextLayoutFactory;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.text.TextSpanLayout;
@@ -45,6 +48,7 @@ import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.font.FOPFontFamilyResolverImpl;
import org.apache.fop.svg.font.FOPGVTFont;
+import org.apache.fop.svg.text.ComplexGlyphLayout;
import org.apache.fop.util.CharUtilities;
/**
@@ -273,4 +277,21 @@ public abstract class NativeTextPainter
return this.fontFamilyResolver;
}
+ private static final TextLayoutFactory COMPLEX_SCRIPT_TEXT_LAYOUT_FACTORY =
+ new TextLayoutFactory() {
+ public TextSpanLayout createTextLayout(AttributedCharacterIterator aci,
+ int [] charMap, Point2D offset, FontRenderContext frc) {
+ if (ComplexGlyphLayout.mayRequireComplexLayout(aci)) {
+ return new ComplexGlyphLayout(aci, charMap, offset, frc);
+ } else {
+ return new GlyphLayout(aci, charMap, offset, frc);
+ }
+ }
+ };
+
+ @Override
+ protected TextLayoutFactory getTextLayoutFactory() {
+ return COMPLEX_SCRIPT_TEXT_LAYOUT_FACTORY;
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java?rev=1615385&r1=1615384&r2=1615385&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java Sun Aug 3 04:40:34 2014
@@ -26,7 +26,10 @@ import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
+import java.text.AttributedCharacterIterator;
+import java.util.List;
+import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.fop.fonts.FontInfo;
@@ -182,4 +185,12 @@ class PDFTextPainter extends NativeTextP
textUtil.writeTJMappedChar(glyph);
}
+ @Override
+ public List computeTextRuns(TextNode node,
+ AttributedCharacterIterator nodeACI,
+ AttributedCharacterIterator [] chunkACIs) {
+ // skip Batik's bidi reordering and use identity character index maps
+ return super.computeTextRuns(node, nodeACI, chunkACIs, (int[][]) null);
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org