You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by be...@apache.org on 2001/07/05 08:37:47 UTC
cvs commit: xml-batik/sources/org/apache/batik/gvt/renderer StrokingTextPainter.java
bella 01/07/04 23:37:47
Modified: sources/org/apache/batik/gvt/renderer
StrokingTextPainter.java
Log:
tidied up textDecoration code, fixed problem with caching the textRuns
Revision Changes Path
1.8 +316 -151 xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
Index: StrokingTextPainter.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- StrokingTextPainter.java 2001/06/12 23:49:45 1.7
+++ StrokingTextPainter.java 2001/07/05 06:37:46 1.8
@@ -11,6 +11,7 @@
import java.awt.Graphics2D;
import java.awt.Paint;
+import java.awt.Color;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.Composite;
@@ -51,7 +52,7 @@
* @see org.apache.batik.gvt.text.GVTAttributedCharacterIterator
*
* @author <a href="bill.haneman@ireland.sun.com>Bill Haneman</a>
- * @version $Id: StrokingTextPainter.java,v 1.7 2001/06/12 23:49:45 bella Exp $
+ * @version $Id: StrokingTextPainter.java,v 1.8 2001/07/05 06:37:46 bella Exp $
*/
public class StrokingTextPainter extends BasicTextPainter {
@@ -87,6 +88,7 @@
paintDecorations(textRuns, g2d, TextSpanLayout.DECORATION_OVERLINE);
paintTextRuns(textRuns, g2d, context);
paintDecorations(textRuns, g2d, TextSpanLayout.DECORATION_STRIKETHROUGH);
+
}
@@ -98,7 +100,6 @@
if (textRuns != null) {
return textRuns;
}
-
AttributedCharacterIterator[] chunkACIs = node.getChunkACIs();
if (chunkACIs == null) {
@@ -112,16 +113,13 @@
aci = as.getIterator();
node.setAttributedCharacterIterator(aci);
- // add font attributed to the aci
- AttributedCharacterIterator fontaci = createModifiedACIForFontMatching(node, aci);
- fontaci.first();
-
// break the aci up into text chunks
- chunkACIs = getTextChunkACIs(fontaci);
+ chunkACIs = getTextChunkACIs(aci);
// reorder each chunk ACI for bidi text
for (int i = 0; i < chunkACIs.length; i++) {
chunkACIs[i] = new BidiAttributedCharacterIterator(chunkACIs[i], frc);
+ chunkACIs[i] = createModifiedACIForFontMatching(node, chunkACIs[i]);
}
node.setChunkACIs(chunkACIs);
}
@@ -142,15 +140,19 @@
beginChunk, lastChunkAdvance, frc);
/* Adjust according to text-anchor property value */
-
+ chunkACIs[currentChunk].first();
if (chunk != null) {
adjustChunkOffsets(textRuns, chunk.advance, chunk.begin, chunk.end);
beginChunk = chunk.end;
lastChunkAdvance = chunk.advance;
}
+ chunkACIs[currentChunk].first();
currentChunk++;
} while (chunk != null && currentChunk < chunkACIs.length);
+
+ // cache the textRuns so don't need to recalculate
+ node.setTextRuns(textRuns);
return textRuns;
}
@@ -181,6 +183,8 @@
AttributedCharacterIterator runaci =
new AttributedCharacterSpanIterator(aci, start, end);
+ runaci.first();
+
Float runX = (Float) runaci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.X);
Float runY = (Float) runaci.getAttribute(
@@ -264,6 +268,8 @@
runaci =
new AttributedCharacterSpanIterator(aci, start, end);
+ runaci.first();
+
Float runX = (Float) runaci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.X);
Float runY = (Float) runaci.getAttribute(
@@ -480,7 +486,6 @@
TextRun r = (TextRun) textRuns.get(n);
int anchorType = r.getAnchorType();
-
float dx = 0f;
float dy = 0f;
@@ -512,6 +517,11 @@
}
}
+
+
+
+
+
/**
* Paints decorations of the specified type.
*/
@@ -528,6 +538,13 @@
AttributedCharacterIterator runaci = textRun.getACI();
runaci.first();
+ Composite opacity = (Composite)
+ runaci.getAttribute(GVTAttributedCharacterIterator.
+ TextAttribute.OPACITY);
+ if (opacity != null) {
+ g2d.setComposite(opacity);
+ }
+
Paint paint = null;
Stroke stroke = null;
Paint strokePaint = null;
@@ -594,7 +611,6 @@
prevPaint = paint;
prevStroke = stroke;
prevStrokePaint = strokePaint;
-
}
// if there is a decoration rect that hasn't been drawn yet, draw it now
@@ -676,7 +692,7 @@
protected Shape getOutline(TextNode node, FontRenderContext frc,
boolean includeDecoration) {
- Shape outline = null;
+ GeneralPath outline = null;
AttributedCharacterIterator aci = node.getAttributedCharacterIterator();
// get the list of text runs
@@ -686,46 +702,48 @@
for (int i = 0; i < textRuns.size(); ++i) {
TextRun textRun = (TextRun)textRuns.get(i);
TextSpanLayout textRunLayout = textRun.getLayout();
- Shape textRunOutline = textRunLayout.getOutline();
+ GeneralPath textRunOutline = new GeneralPath(textRunLayout.getOutline());
+ if (outline == null) {
+ outline = textRunOutline;
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(textRunOutline, false);
+ }
+ }
- if (includeDecoration && !textRunLayout.isVertical() && !textRunLayout.isOnATextPath()) {
- AttributedCharacterIterator textRunACI = textRun.getACI();
- int decorationTypes = 0;
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.UNDERLINE) != null) {
- decorationTypes |= TextSpanLayout.DECORATION_UNDERLINE;
- }
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.OVERLINE) != null) {
- decorationTypes |= TextSpanLayout.DECORATION_OVERLINE;
- }
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.STRIKETHROUGH) != null) {
- decorationTypes |= TextSpanLayout.DECORATION_STRIKETHROUGH;
+ // append any decoration outlines
+ if (includeDecoration) {
+
+ Shape underline = getDecorationOutline(textRuns, TextSpanLayout.DECORATION_UNDERLINE);
+ Shape strikeThrough = getDecorationOutline(textRuns, TextSpanLayout.DECORATION_STRIKETHROUGH);
+ Shape overline = getDecorationOutline(textRuns, TextSpanLayout.DECORATION_OVERLINE);
+
+ if (underline != null) {
+ if (outline == null) {
+ outline = new GeneralPath(underline);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(underline, false);
}
- if (decorationTypes != 0) {
- if (!(textRunOutline instanceof GeneralPath)) {
- textRunOutline = new GeneralPath(textRunOutline);
- }
- ((GeneralPath) textRunOutline).setWindingRule(
- GeneralPath.WIND_NON_ZERO);
- ((GeneralPath) textRunOutline).append(
- textRunLayout.getDecorationOutline(decorationTypes), false);
+ }
+ if (strikeThrough != null) {
+ if (outline == null) {
+ outline = new GeneralPath(strikeThrough);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(strikeThrough, false);
}
}
-
- if (outline == null) {
- outline = textRunOutline;
- } else {
- if (!(outline instanceof GeneralPath)) {
- outline = new GeneralPath(outline);
+ if (overline != null) {
+ if (outline == null) {
+ outline = new GeneralPath(overline);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(overline, false);
}
- ((GeneralPath) outline).setWindingRule(
- GeneralPath.WIND_NON_ZERO);
- ((GeneralPath) outline).append(textRunOutline, false);
}
-
}
+
return outline;
}
@@ -740,7 +758,7 @@
protected Shape getStrokeOutline(TextNode node, FontRenderContext frc,
boolean includeDecoration) {
- Shape outline = null;
+ GeneralPath outline = null;
AttributedCharacterIterator aci = node.getAttributedCharacterIterator();
// get the list of text runs
@@ -752,6 +770,8 @@
TextRun textRun = (TextRun)textRuns.get(i);
AttributedCharacterIterator textRunACI = textRun.getACI();
+ textRunACI.first();
+
TextSpanLayout textRunLayout = textRun.getLayout();
Stroke stroke = (Stroke) textRunACI.getAttribute(
@@ -765,102 +785,247 @@
textRunStrokeOutline = stroke.createStrokedShape(textRunOutline);
}
- if (includeDecoration && !textRunLayout.isVertical() && !textRunLayout.isOnATextPath()) {
- Shape decorationStrokeOutline = null;
-
- // look for stroked underline
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.UNDERLINE) != null) {
- Stroke decorationStroke = (Stroke) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE);
- Paint decorationStrokePaint = (Paint) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE_PAINT);
- if (decorationStroke != null && decorationStrokePaint != null) {
- Shape textRunUnderlineOutline = textRunLayout.getDecorationOutline(
- TextSpanLayout.DECORATION_UNDERLINE);
- decorationStrokeOutline
- = decorationStroke.createStrokedShape(textRunUnderlineOutline);
- }
+ if (textRunStrokeOutline != null) {
+ if (outline == null) {
+ outline = new GeneralPath(textRunStrokeOutline);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(textRunStrokeOutline, false);
}
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.OVERLINE) != null) {
- Stroke decorationStroke = (Stroke) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE);
- Paint decorationStrokePaint = (Paint) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE_PAINT);
- if (decorationStroke != null && decorationStrokePaint != null) {
- Shape textRunOverlineOutline = textRunLayout.getDecorationOutline(
- TextSpanLayout.DECORATION_OVERLINE);
- if (decorationStrokeOutline == null) {
- decorationStrokeOutline
- = decorationStroke.createStrokedShape(textRunOverlineOutline);
- } else {
- if (!(decorationStrokeOutline instanceof GeneralPath)) {
- decorationStrokeOutline = new GeneralPath(decorationStrokeOutline);
- }
- ((GeneralPath)decorationStrokeOutline).append(
- decorationStroke.createStrokedShape(textRunOverlineOutline), false);
- }
- }
+ }
+ }
+
+ // append any stroked decoration outlines
+ if (includeDecoration) {
+
+ Shape underline = getDecorationStrokeOutline(textRuns, TextSpanLayout.DECORATION_UNDERLINE);
+ Shape strikeThrough = getDecorationStrokeOutline(textRuns, TextSpanLayout.DECORATION_STRIKETHROUGH);
+ Shape overline = getDecorationStrokeOutline(textRuns, TextSpanLayout.DECORATION_OVERLINE);
+ if (underline != null) {
+ if (outline == null) {
+ outline = new GeneralPath(underline);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(underline, false);
}
- if (textRunACI.getAttribute(GVTAttributedCharacterIterator.
- TextAttribute.STRIKETHROUGH) != null) {
- Stroke decorationStroke = (Stroke) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE);
- Paint decorationStrokePaint = (Paint) textRunACI.getAttribute(
- GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE_PAINT);
- if (decorationStroke != null && decorationStrokePaint != null) {
- Shape textRunStrikethroughOutline = textRunLayout.getDecorationOutline(
- TextSpanLayout.DECORATION_STRIKETHROUGH);
- if (decorationStrokeOutline == null) {
- decorationStrokeOutline
- = decorationStroke.createStrokedShape(textRunStrikethroughOutline);
- } else {
- if (!(decorationStrokeOutline instanceof GeneralPath)) {
- decorationStrokeOutline = new GeneralPath(decorationStrokeOutline);
- }
- ((GeneralPath)decorationStrokeOutline).append(
- decorationStroke.createStrokedShape(textRunStrikethroughOutline), false);
- }
- }
+ }
+ if (strikeThrough != null) {
+ if (outline == null) {
+ outline = new GeneralPath(strikeThrough);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(strikeThrough, false);
}
- if (decorationStrokeOutline != null) {
- if (textRunStrokeOutline != null) {
- if (!(textRunStrokeOutline instanceof GeneralPath)) {
- textRunStrokeOutline = new GeneralPath(textRunStrokeOutline);
- }
- ((GeneralPath) textRunStrokeOutline).setWindingRule(
- GeneralPath.WIND_NON_ZERO);
- ((GeneralPath) textRunStrokeOutline).append(decorationStrokeOutline, false);
+ }
+ if (overline != null) {
+ if (outline == null) {
+ outline = new GeneralPath(overline);
+ } else {
+ outline.setWindingRule(GeneralPath.WIND_NON_ZERO);
+ outline.append(overline, false);
+ }
+ }
+ }
+
+ return outline;
+ }
+
+
+ /**
+ * Returns the outline of the specified decoration type.
+ *
+ * @param textRuns The list of text runs to get the decoration outline for.
+ * @param decoratonType Indicates the type of decoration required.
+ * eg. underline, overline or strikethrough.
+ *
+ * @return The decoration outline or null if the text is not decorated.
+ */
+ private Shape getDecorationOutline(List textRuns, int decorationType) {
+
+ GeneralPath outline = null;
+
+ Paint prevPaint = null;
+ Paint prevStrokePaint = null;
+ Stroke prevStroke = null;
+ Rectangle2D decorationRect = null;
+
+ for (int i = 0; i < textRuns.size(); i++) {
+ TextRun textRun = (TextRun)textRuns.get(i);
+ AttributedCharacterIterator runaci = textRun.getACI();
+ runaci.first();
+
+ Paint paint = null;
+ Stroke stroke = null;
+ Paint strokePaint = null;
+ switch (decorationType) {
+ case TextSpanLayout.DECORATION_UNDERLINE :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE_PAINT);
+ break;
+ case TextSpanLayout.DECORATION_OVERLINE :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE_PAINT);
+ break;
+ case TextSpanLayout.DECORATION_STRIKETHROUGH :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE_PAINT);
+ break;
+ default:
+ // should never get here
+ return null;
+ }
+
+ if (textRun.isFirstRunInChunk() || paint != prevPaint
+ || stroke != prevStroke || strokePaint != prevStrokePaint) {
+
+ // if there is a current decoration, added it to the overall outline
+ if (decorationRect != null) {
+ if (outline == null) {
+ outline = new GeneralPath(decorationRect);
} else {
- textRunStrokeOutline = decorationStrokeOutline;
+ outline.append(decorationRect, false);
}
+ decorationRect = null;
}
}
- if (textRunStrokeOutline != null) {
- if (outline == null) {
- outline = textRunStrokeOutline;
+ if ((paint != null || strokePaint != null)
+ && !textRun.getLayout().isVertical()
+ && !textRun.getLayout().isOnATextPath()) {
+
+ // this text run should be decorated with the specified decoration type
+ // note: decorations are only supported for plain horizontal layouts
+
+ Shape decorationShape = textRun.getLayout().getDecorationOutline(decorationType);
+ if (decorationRect == null) {
+ // create a new one
+ decorationRect = decorationShape.getBounds2D();
} else {
- if (!(outline instanceof GeneralPath)) {
- outline = new GeneralPath(outline);
- }
- ((GeneralPath) outline).setWindingRule(
- GeneralPath.WIND_NON_ZERO);
- ((GeneralPath) outline).append(textRunStrokeOutline, false);
+ // extend the current one
+ Rectangle2D bounds = decorationShape.getBounds2D();
+ decorationRect.setRect(decorationRect.getMinX(), decorationRect.getMinY(),
+ bounds.getMaxX() - decorationRect.getMinX(), decorationRect.getHeight());
}
}
+ prevPaint = paint;
+ prevStroke = stroke;
+ prevStrokePaint = strokePaint;
+ }
+ // if there is a decoration rect that hasn't been added to the overall outline
+ if (decorationRect != null) {
+ if (outline == null) {
+ outline = new GeneralPath(decorationRect);
+ } else {
+ outline.append(decorationRect, false);
+ }
}
return outline;
}
+ /**
+ * Returns the stroke outline of the specified decoration type.
+ *
+ * @param textRuns The list of text runs to get the decoration outline for.
+ * @param decoratonType Indicates the type of decoration required.
+ * eg. underline, overline or strikethrough.
+ *
+ * @return The decoration outline or null if the text is not decorated.
+ */
+ private Shape getDecorationStrokeOutline(List textRuns, int decorationType) {
+
+ GeneralPath outline = null;
+
+ Paint prevPaint = null;
+ Paint prevStrokePaint = null;
+ Stroke prevStroke = null;
+ Rectangle2D decorationRect = null;
+
+ for (int i = 0; i < textRuns.size(); i++) {
+ TextRun textRun = (TextRun)textRuns.get(i);
+ AttributedCharacterIterator runaci = textRun.getACI();
+ runaci.first();
+
+ Paint paint = null;
+ Stroke stroke = null;
+ Paint strokePaint = null;
+ switch (decorationType) {
+ case TextSpanLayout.DECORATION_UNDERLINE :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.UNDERLINE_STROKE_PAINT);
+ break;
+ case TextSpanLayout.DECORATION_OVERLINE :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.OVERLINE_STROKE_PAINT);
+ break;
+ case TextSpanLayout.DECORATION_STRIKETHROUGH :
+ paint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_PAINT);
+ stroke = (Stroke) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE);
+ strokePaint = (Paint) runaci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.STRIKETHROUGH_STROKE_PAINT);
+ break;
+ default:
+ // should never get here
+ return null;
+ }
+
+ if (textRun.isFirstRunInChunk() || paint != prevPaint
+ || stroke != prevStroke || strokePaint != prevStrokePaint) {
+
+ // if there is a current decoration, added it to the overall outline
+ if (decorationRect != null && prevStroke != null && prevStrokePaint != null) {
+ if (outline == null) {
+ outline = new GeneralPath(prevStroke.createStrokedShape(decorationRect));
+ } else {
+ outline.append(prevStroke.createStrokedShape(decorationRect), false);
+ }
+ decorationRect = null;
+ }
+ }
+ if ((paint != null || strokePaint != null)
+ && !textRun.getLayout().isVertical()
+ && !textRun.getLayout().isOnATextPath()) {
+ // this text run should be decorated with the specified decoration type
+ // note: decorations are only supported for plain horizontal layouts
+ Shape decorationShape = textRun.getLayout().getDecorationOutline(decorationType);
+ if (decorationRect == null) {
+ // create a new one
+ decorationRect = decorationShape.getBounds2D();
+ } else {
+ // extend the current one
+ Rectangle2D bounds = decorationShape.getBounds2D();
+ decorationRect.setRect(decorationRect.getMinX(), decorationRect.getMinY(),
+ bounds.getMaxX() - decorationRect.getMinX(), decorationRect.getHeight());
+ }
+ }
+ prevPaint = paint;
+ prevStroke = stroke;
+ prevStrokePaint = strokePaint;
+ }
+ // if there is a decoration rect that hasn't been added to the overall outline
+ if (decorationRect != null && prevStroke != null && prevStrokePaint != null) {
+ if (outline == null) {
+ outline = new GeneralPath(prevStroke.createStrokedShape(decorationRect));
+ } else {
+ outline.append(prevStroke.createStrokedShape(decorationRect), false);
+ }
+ }
+ return outline;
+ }
+
+
+
+
TextNode cachedNode;
protected org.apache.batik.gvt.text.Mark hitTest(
@@ -873,12 +1038,6 @@
// get the list of text runs
List textRuns = getTextRuns(node, aci, frc);
- // store the textRuns in the textNode for much quicker highlighting
- // note that we can't set this earlier because of problems with
- // caching the info
- node.setTextRuns(textRuns);
-
-
// for each text run, see if its been hit
for (int i = 0; i < textRuns.size(); ++i) {
TextRun textRun = (TextRun)textRuns.get(i);
@@ -918,11 +1077,6 @@
// get the list of text runs
List textRuns = getTextRuns(node, aci, frc);
- // store the textRuns in the textNode for much quicker highlighting
- // note that we can't set this earlier because of problems with
- // caching the info
- node.setTextRuns(textRuns);
-
aci.first();
int charIndex = ((Integer)aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.CHAR_INDEX)).intValue();
@@ -947,11 +1101,6 @@
// get the list of text runs
List textRuns = getTextRuns(node, aci, frc);
- // store the textRuns in the textNode for much quicker highlighting
- // note that we can't set this earlier because of problems with
- // caching the info
- node.setTextRuns(textRuns);
-
TextSpanLayout lastLayout = ((TextRun)textRuns.get(textRuns.size()-1)).getLayout();
int lastGlyphIndex = lastLayout.getGlyphCount()-1;
aci.last();
@@ -976,6 +1125,9 @@
org.apache.batik.gvt.text.Mark startMark,
org.apache.batik.gvt.text.Mark finishMark) {
+ if (startMark == null || finishMark == null) {
+ return null;
+ }
BasicTextPainter.Mark start;
BasicTextPainter.Mark finish;
try {
@@ -988,6 +1140,30 @@
int[] result = new int[2];
result[0] = start.getHit().getCharIndex();
result[1] = finish.getHit().getCharIndex();
+
+ // this next bit is to make sure that ligatures are selected properly
+ TextSpanLayout startLayout = start.getLayout();
+ TextSpanLayout finishLayout = finish.getLayout();
+
+ int startGlyphIndex = startLayout.getGlyphIndex(result[0]);
+ int finishGlyphIndex = finishLayout.getGlyphIndex(result[1]);
+ int startCharCount = startLayout.getCharacterCount(startGlyphIndex, startGlyphIndex);
+ int finishCharCount = finishLayout.getCharacterCount(finishGlyphIndex, finishGlyphIndex);
+ if (startCharCount > 1) {
+ if (result[0] > result[1] && startLayout.isLeftToRight()) {
+ result[0] += startCharCount-1;
+ } else if (result[1] > result[0] && !startLayout.isLeftToRight()) {
+ result[0] -= startCharCount-1;
+ }
+ }
+ if (finishCharCount > 1) {
+ if (result[1] > result[0] && finishLayout.isLeftToRight()) {
+ result[1] += finishCharCount-1;
+ } else if (result[0] > result[1] && !finishLayout.isLeftToRight()) {
+ result[1] -= finishCharCount-1;
+ }
+ }
+
return result;
}
@@ -1000,6 +1176,10 @@
public Shape getHighlightShape(org.apache.batik.gvt.text.Mark beginMark,
org.apache.batik.gvt.text.Mark endMark) {
+ if (beginMark == null || endMark == null) {
+ return null;
+ }
+
BasicTextPainter.Mark begin;
BasicTextPainter.Mark end;
try {
@@ -1028,21 +1208,6 @@
FontRenderContext frc = begin.getHit().getFontRenderContext();
List textRuns = getTextRuns(textNode, textNode.getAttributedCharacterIterator(), frc);
- // determine whether selection is right to left or not, ie. whether
- // beginLayout is before endLayout or not
- boolean leftToRight = true;
- for (int i = 0; i < textRuns.size(); ++i) {
- TextRun textRun = (TextRun)textRuns.get(i);
- TextSpanLayout layout = textRun.getLayout();
- if (layout == beginLayout) {
- break;
- }
- if (layout == endLayout) {
- leftToRight = false;
- break;
- }
- }
-
GeneralPath highlightedShape = new GeneralPath();
// for each text run, append any highlight it may contain for the current selection
@@ -1050,7 +1215,7 @@
TextRun textRun = (TextRun)textRuns.get(i);
TextSpanLayout layout = textRun.getLayout();
- Shape layoutHighlightedShape = layout.getHighlightShape(beginIndex, endIndex, leftToRight);
+ Shape layoutHighlightedShape = layout.getHighlightShape(beginIndex, endIndex);
// append the highlighted shape of this layout to the
// overall hightlighted shape
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org