You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by ga...@apache.org on 2014/08/23 05:38:55 UTC
svn commit: r1619958 - in
/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt: font/ renderer/ text/
Author: gadams
Date: Sat Aug 23 03:38:55 2014
New Revision: 1619958
URL: http://svn.apache.org/r1619958
Log:
Improve support for external text painters for dealing with Bidi text.
Modified:
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java
xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/AWTGVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -815,6 +815,15 @@ public class AWTGVTGlyphVector implement
return charCount;
}
+ @Override
+ public boolean isReversed() {
+ return false;
+ }
+
+ @Override
+ public void maybeReverse(boolean mirror) {
+ }
+
/**
* Draws this glyph vector.
*/
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/GVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -184,6 +184,17 @@ public interface GVTGlyphVector {
int getCharacterCount(int startGlyphIndex, int endGlyphIndex);
/**
+ * Return true if glyphs have been reversed.
+ */
+ boolean isReversed();
+
+ /**
+ * Reverse (and optionally mirror) glyphs if not
+ * already reversed.
+ */
+ void maybeReverse(boolean mirror);
+
+ /**
* Draws the glyph vector.
*/
void draw(Graphics2D graphics2D,
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/MultiGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -387,6 +387,15 @@ public class MultiGlyphVector implements
return ret;
}
+ @Override
+ public boolean isReversed() {
+ return false;
+ }
+
+ @Override
+ public void maybeReverse(boolean mirror) {
+ }
+
/**
* Draws the glyph vector.
*/
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/font/SVGGVTGlyphVector.java Sat Aug 23 03:38:55 2014
@@ -707,6 +707,15 @@ public final class SVGGVTGlyphVector imp
return numChars;
}
+ @Override
+ public boolean isReversed() {
+ return false;
+ }
+
+ @Override
+ public void maybeReverse(boolean mirror) {
+ }
+
/**
* Draws this glyph vector.
*/
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java Sat Aug 23 03:38:55 2014
@@ -232,8 +232,8 @@ public class StrokingTextPainter extends
chunkStart += (chunkACIs[i].getEndIndex() - chunkACIs[i].getBeginIndex());
}
- // create text runs for each chunk and add them to the list
- List textRuns = new ArrayList();
+ // Create text runs for each chunk and add them to the list.
+ List perNodeRuns = new ArrayList();
TextChunk chunk, prevChunk=null;
int currentChunk = 0;
@@ -243,23 +243,46 @@ public class StrokingTextPainter extends
// create from the ACI.
chunkACIs[currentChunk].first();
+ List perChunkRuns = new ArrayList();
chunk = getTextChunk(node,
chunkACIs[currentChunk],
chunkCharMaps != null ? chunkCharMaps[currentChunk] : null,
- textRuns,
+ perChunkRuns,
prevChunk);
- // Adjust according to text-anchor property value
+ // Perform bidi reordering on chunk's runs. Must be performed before
+ // adjusting chunk offsets.
+ perChunkRuns = reorderTextRuns(chunk, perChunkRuns);
+
+ // Adjust according to text-anchor property value.
chunkACIs[currentChunk].first();
if (chunk != null) {
- location = adjustChunkOffsets(location, textRuns, chunk);
+ location = adjustChunkOffsets(location, perChunkRuns, chunk);
}
+
+ // Append per chunk runs to overall node runs.
+ perNodeRuns.addAll(perChunkRuns);
+
prevChunk = chunk;
currentChunk++;
} while (chunk != null && currentChunk < chunkACIs.length);
- return textRuns;
+ return perNodeRuns;
+ }
+
+ /**
+ * Reorder text runs as required by bidi algorithm.
+ * @param runs - unordered runs
+ * @return reordered runs
+ */
+ protected List reorderTextRuns(TextChunk chunk, List runs) {
+ // NOP here since they were previous reordered (by batik's
+ // BidiAttributedCharacterIterator); derived painters (e.g., FOP) may
+ // use a different strategy.
+ // N.B. batik doesn't sub-divide a text chunk at bidi level
+ // boundaries; however, derived painters may do so.
+ return runs;
}
/**
@@ -577,6 +600,10 @@ public class StrokingTextPainter extends
return DefaultFontFamilyResolver.SINGLETON;
}
+ protected Set getTextRunBoundaryAttributes() {
+ return extendedAtts;
+ }
+
protected TextChunk getTextChunk(TextNode node,
AttributedCharacterIterator aci,
int [] charMap,
@@ -596,9 +623,10 @@ public class StrokingTextPainter extends
Point2D.Float advance = new Point2D.Float(0,0);
boolean isChunkStart = true;
TextSpanLayout layout = null;
+ Set textRunBoundaryAttributes = getTextRunBoundaryAttributes();
do {
- int start = aci.getRunStart(extendedAtts);
- int end = aci.getRunLimit(extendedAtts);
+ int start = aci.getRunStart(textRunBoundaryAttributes);
+ int end = aci.getRunLimit(textRunBoundaryAttributes);
AttributedCharacterIterator runaci;
runaci = new AttributedCharacterSpanIterator(aci, start, end);
@@ -691,8 +719,8 @@ public class StrokingTextPainter extends
visualAdvance = new Point2D.Float
((float)(chunk.advance.getX() + lastW -
lastMetrics.getHorizontalAdvance()),
- (float)(chunk.advance.getY() - lastMetrics.getVerticalAdvance() +
- lastH));
+ (float)(chunk.advance.getY() + lastH -
+ lastMetrics.getVerticalAdvance()));
} else {
Point2D advance = chunk.advance;
@@ -702,19 +730,19 @@ public class StrokingTextPainter extends
if (layout.isVertical()) {
if (lengthAdj == ADJUST_SPACING) {
yScale = (float)
- ((length.floatValue()-lastH)/
- (advance.getY()-lastMetrics.getVerticalAdvance()));
+ ((length.floatValue() - lastH) /
+ (advance.getY() - lastMetrics.getVerticalAdvance()));
} else {
- double adv =(advance.getY()-
- lastMetrics.getVerticalAdvance() + lastH);
+ double adv =(advance.getY() + lastH -
+ lastMetrics.getVerticalAdvance());
yScale = (float)(length.floatValue()/adv);
}
visualAdvance = new Point2D.Float(0, length.floatValue());
} else {
if (lengthAdj == ADJUST_SPACING) {
xScale = (float)
- ((length.floatValue()-lastW)/
- (advance.getX()-lastMetrics.getHorizontalAdvance()));
+ ((length.floatValue() - lastW) /
+ (advance.getX() - lastMetrics.getHorizontalAdvance()));
} else {
double adv = (advance.getX() + lastW -
lastMetrics.getHorizontalAdvance());
@@ -1587,11 +1615,16 @@ public class StrokingTextPainter extends
// inner classes
- class TextChunk {
+ public class TextChunk {
+ // the following denote indices of text runs over all chunks of text node,
+ // where index 0 is first run of first chunk of text node; the begin index
+ // of the first chunk is 0; for subsequent chunks, the begin index is the
+ // end index of its immediately previous chunk; the end index is exclusive
public int begin;
public int end;
- public Point2D advance;
+
+ public Point2D advance; // sum of advances of runs in chunk
public TextChunk(int begin, int end, Point2D advance) {
this.begin = begin;
@@ -1608,12 +1641,14 @@ public class StrokingTextPainter extends
*/
public class TextRun {
- protected AttributedCharacterIterator aci;
- protected TextSpanLayout layout;
- protected int anchorType;
- protected boolean firstRunInChunk;
- protected Float length;
- protected Integer lengthAdjust;
+ protected AttributedCharacterIterator aci; // source aci
+ protected TextSpanLayout layout; // layout object
+ protected int anchorType; // text-anchor attribute
+ protected boolean firstRunInChunk; // first run in chunk flag
+ protected Float length; // textLength attribute
+ protected Integer lengthAdjust; // lengthAdjust attribute
+ private int level; // resolved bidi level of run
+ private int reversals; // reversal count
public TextRun(TextSpanLayout layout,
AttributedCharacterIterator aci,
@@ -1646,6 +1681,13 @@ public class StrokingTextPainter extends
(GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH);
lengthAdjust = (Integer) aci.getAttribute
(GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
+
+ Integer level = (Integer) aci.getAttribute(BIDI_LEVEL);
+ if (level != null) {
+ this.level = level.intValue();
+ } else {
+ this.level = -1;
+ }
}
public AttributedCharacterIterator getACI() {
@@ -1672,5 +1714,19 @@ public class StrokingTextPainter extends
return firstRunInChunk;
}
+ public int getBidiLevel() {
+ return level;
+ }
+
+ public void reverse() {
+ reversals++;
+ }
+
+ public void maybeReverseGlyphs(boolean mirror) {
+ if ((reversals & 1) == 1) {
+ layout.maybeReverse(mirror);
+ }
+ }
+
}
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/GlyphLayout.java Sat Aug 23 03:38:55 2014
@@ -2030,4 +2030,14 @@ public class GlyphLayout implements Text
public boolean isAltGlyph(){
return this.isAltGlyph;
}
+
+ @Override
+ public boolean isReversed(){
+ return gv.isReversed();
+ }
+
+ @Override
+ public void maybeReverse(boolean mirror){
+ gv.maybeReverse(mirror);
+ }
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java?rev=1619958&r1=1619957&r2=1619958&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/text/TextSpanLayout.java Sat Aug 23 03:38:55 2014
@@ -227,4 +227,15 @@ public interface TextSpanLayout {
* an alt glyph.
*/
boolean isAltGlyph();
+
+ /**
+ * Return true if this text has been reversed.
+ */
+ boolean isReversed();
+
+ /**
+ * Reverse (and optionally mirror) glyphs if not
+ * already reversed.
+ */
+ void maybeReverse(boolean mirror);
}