GlyphPainter2public class GlyphPainter2 extends GlyphView$GlyphPainter A class to perform rendering of the glyphs.
This can be implemented to be stateless, or
to hold some information as a cache to
facilitate faster rendering and model/view
translation. At a minimum, the GlyphPainter
allows a View implementation to perform its
duties independent of a particular version
of JVM and selection of capabilities (i.e.
shaping for i18n, etc).
This implementation is intended for operation
under the JDK. It uses the
java.awt.font.TextLayout class to do i18n capable
rendering. |
Fields Summary |
---|
TextLayout | layout |
Constructors Summary |
---|
public GlyphPainter2(TextLayout layout)
this.layout = layout;
|
Methods Summary |
---|
public float | getAscent(javax.swing.text.GlyphView v)Fetch the ascent above the baseline for the glyphs
corresponding to the given range in the model.
return layout.getAscent();
| public int | getBoundedPosition(javax.swing.text.GlyphView v, int p0, float x, float len)Determines the model location that represents the
maximum advance that fits within the given span.
This could be used to break the given view. The result
should be a location just shy of the given advance. This
differs from viewToModel which returns the closest
position which might be proud of the maximum advance.
if( len < 0 )
throw new IllegalArgumentException("Length must be >= 0.");
// note: this only works because swing uses TextLayouts that are
// only pure rtl or pure ltr
TextHitInfo hit;
if (layout.isLeftToRight()) {
hit = layout.hitTestChar(len, 0);
} else {
hit = layout.hitTestChar(layout.getAdvance() - len, 0);
}
return v.getStartOffset() + hit.getCharIndex();
| public float | getDescent(javax.swing.text.GlyphView v)Fetch the descent below the baseline for the glyphs
corresponding to the given range in the model.
return layout.getDescent();
| public float | getHeight(javax.swing.text.GlyphView v)
return layout.getAscent() + layout.getDescent() + layout.getLeading();
| public int | getNextVisualPositionFrom(javax.swing.text.GlyphView v, int pos, javax.swing.text.Position$Bias b, java.awt.Shape a, int direction, javax.swing.text.Position$Bias[] biasRet)Provides a way to determine the next visually represented model
location that one might place a caret. Some views may not be
visible, they might not be in the same order found in the model, or
they just might not allow access to some of the locations in the
model.
int startOffset = v.getStartOffset();
int endOffset = v.getEndOffset();
Segment text;
AbstractDocument doc;
boolean viewIsLeftToRight;
TextHitInfo currentHit, nextHit;
switch (direction) {
case View.NORTH:
break;
case View.SOUTH:
break;
case View.EAST:
doc = (AbstractDocument)v.getDocument();
viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset);
if(startOffset == doc.getLength()) {
if(pos == -1) {
biasRet[0] = Position.Bias.Forward;
return startOffset;
}
// End case for bidi text where newline is at beginning
// of line.
return -1;
}
if(pos == -1) {
// Entering view from the left.
if( viewIsLeftToRight ) {
biasRet[0] = Position.Bias.Forward;
return startOffset;
} else {
text = v.getText(endOffset - 1, endOffset);
char c = text.array[text.offset];
SegmentCache.releaseSharedSegment(text);
if(c == '\n") {
biasRet[0] = Position.Bias.Forward;
return endOffset-1;
}
biasRet[0] = Position.Bias.Backward;
return endOffset;
}
}
if( b==Position.Bias.Forward )
currentHit = TextHitInfo.afterOffset(pos-startOffset);
else
currentHit = TextHitInfo.beforeOffset(pos-startOffset);
nextHit = layout.getNextRightHit(currentHit);
if( nextHit == null ) {
return -1;
}
if( viewIsLeftToRight != layout.isLeftToRight() ) {
// If the layout's base direction is different from
// this view's run direction, we need to use the weak
// carrat.
nextHit = layout.getVisualOtherHit(nextHit);
}
pos = nextHit.getInsertionIndex() + startOffset;
if(pos == endOffset) {
// A move to the right from an internal position will
// only take us to the endOffset in a left to right run.
text = v.getText(endOffset - 1, endOffset);
char c = text.array[text.offset];
SegmentCache.releaseSharedSegment(text);
if(c == '\n") {
return -1;
}
biasRet[0] = Position.Bias.Backward;
}
else {
biasRet[0] = Position.Bias.Forward;
}
return pos;
case View.WEST:
doc = (AbstractDocument)v.getDocument();
viewIsLeftToRight = doc.isLeftToRight(startOffset, endOffset);
if(startOffset == doc.getLength()) {
if(pos == -1) {
biasRet[0] = Position.Bias.Forward;
return startOffset;
}
// End case for bidi text where newline is at beginning
// of line.
return -1;
}
if(pos == -1) {
// Entering view from the right
if( viewIsLeftToRight ) {
text = v.getText(endOffset - 1, endOffset);
char c = text.array[text.offset];
SegmentCache.releaseSharedSegment(text);
if(c == '\n") {
biasRet[0] = Position.Bias.Forward;
return endOffset - 1;
}
biasRet[0] = Position.Bias.Backward;
return endOffset;
} else {
biasRet[0] = Position.Bias.Forward;
return startOffset;
}
}
if( b==Position.Bias.Forward )
currentHit = TextHitInfo.afterOffset(pos-startOffset);
else
currentHit = TextHitInfo.beforeOffset(pos-startOffset);
nextHit = layout.getNextLeftHit(currentHit);
if( nextHit == null ) {
return -1;
}
if( viewIsLeftToRight != layout.isLeftToRight() ) {
// If the layout's base direction is different from
// this view's run direction, we need to use the weak
// carrat.
nextHit = layout.getVisualOtherHit(nextHit);
}
pos = nextHit.getInsertionIndex() + startOffset;
if(pos == endOffset) {
// A move to the left from an internal position will
// only take us to the endOffset in a right to left run.
text = v.getText(endOffset - 1, endOffset);
char c = text.array[text.offset];
SegmentCache.releaseSharedSegment(text);
if(c == '\n") {
return -1;
}
biasRet[0] = Position.Bias.Backward;
}
else {
biasRet[0] = Position.Bias.Forward;
}
return pos;
default:
throw new IllegalArgumentException("Bad direction: " + direction);
}
return pos;
| public javax.swing.text.GlyphView$GlyphPainter | getPainter(javax.swing.text.GlyphView v, int p0, int p1)Create a painter to use for the given GlyphView.
return null;
| public float | getSpan(javax.swing.text.GlyphView v, int p0, int p1, javax.swing.text.TabExpander e, float x)Determine the span the glyphs given a start location
(for tab expansion). This implementation assumes it
has no tabs (i.e. TextLayout doesn't deal with tab
expansion).
if ((p0 == v.getStartOffset()) && (p1 == v.getEndOffset())) {
return layout.getAdvance();
}
int p = v.getStartOffset();
int index0 = p0 - p;
int index1 = p1 - p;
TextHitInfo hit0 = TextHitInfo.afterOffset(index0);
TextHitInfo hit1 = TextHitInfo.beforeOffset(index1);
float[] locs = layout.getCaretInfo(hit0);
float x0 = locs[0];
locs = layout.getCaretInfo(hit1);
float x1 = locs[0];
return (x1 > x0) ? x1 - x0 : x0 - x1;
| public java.awt.Shape | modelToView(javax.swing.text.GlyphView v, int pos, javax.swing.text.Position$Bias bias, java.awt.Shape a)
int offs = pos - v.getStartOffset();
Rectangle2D alloc = a.getBounds2D();
TextHitInfo hit = (bias == Position.Bias.Forward) ?
TextHitInfo.afterOffset(offs) : TextHitInfo.beforeOffset(offs);
float[] locs = layout.getCaretInfo(hit);
// vertical at the baseline, should use slope and check if glyphs
// are being rendered vertically.
alloc.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight());
return alloc;
| public void | paint(javax.swing.text.GlyphView v, java.awt.Graphics g, java.awt.Shape a, int p0, int p1)Paint the glyphs for the given view. This is implemented
to only render if the Graphics is of type Graphics2D which
is required by TextLayout (and this should be the case if
running on the JDK).
if (g instanceof Graphics2D) {
Rectangle2D alloc = a.getBounds2D();
Graphics2D g2d = (Graphics2D)g;
float y = (float) alloc.getY() + layout.getAscent() + layout.getLeading();
float x = (float) alloc.getX();
if( p0 > v.getStartOffset() || p1 < v.getEndOffset() ) {
try {
//TextLayout can't render only part of it's range, so if a
//partial range is required, add a clip region.
Shape s = v.modelToView(p0, Position.Bias.Forward,
p1, Position.Bias.Backward, a);
Shape savedClip = g.getClip();
g2d.clip(s);
layout.draw(g2d, x, y);
g.setClip(savedClip);
} catch (BadLocationException e) {}
} else {
layout.draw(g2d, x, y);
}
}
| public int | viewToModel(javax.swing.text.GlyphView v, float x, float y, java.awt.Shape a, javax.swing.text.Position$Bias[] biasReturn)Provides a mapping from the view coordinate space to the logical
coordinate space of the model.
Rectangle2D alloc = (a instanceof Rectangle2D) ? (Rectangle2D)a : a.getBounds2D();
//Move the y co-ord of the hit onto the baseline. This is because TextLayout supports
//italic carets and we do not.
TextHitInfo hit = layout.hitTestChar(x - (float)alloc.getX(), 0);
int pos = hit.getInsertionIndex();
biasReturn[0] = hit.isLeadingEdge() ? Position.Bias.Forward : Position.Bias.Backward;
return pos + v.getStartOffset();
|
|