下面列出了java.awt.font.TextLayout#getAdvance ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public float getPreferredSpan(int axis) {
if (axis == View.X_AXIS) {
String desc = fold.getDescription(); // For empty desc a single-space text layout is returned
float advance = 0;
if (desc.length() > 0) {
TextLayout textLayout = getTextLayout();
if (textLayout == null) {
return 0f;
}
advance = textLayout.getAdvance();
}
return advance + (2 * EXTRA_MARGIN_WIDTH);
} else {
EditorView.Parent parent = (EditorView.Parent) getParent();
return (parent != null) ? parent.getViewRenderContext().getDefaultRowHeight() : 0f;
}
}
/**
* Get width available for display of child views. For non-wrap case it's Integer.MAX_VALUE
* and for wrapping it's a display width or (if display width would become too narrow)
* a width of four chars to not overflow the word wrapping algorithm.
* @return
*/
float getAvailableWidth() {
if (!isAnyStatusBit(AVAILABLE_WIDTH_VALID)) {
// Mark valid and assign early values to prevent stack overflow in getLineContinuationCharTextLayout()
setStatusBits(AVAILABLE_WIDTH_VALID);
availableWidth = Integer.MAX_VALUE;
renderWrapWidth = availableWidth;
if (getLineWrapType() != LineWrapType.NONE) {
final TextLayout lineContTextLayout = getLineContinuationCharTextLayout();
final float lineContTextLayoutAdvance =
lineContTextLayout == null ? 0f : lineContTextLayout.getAdvance();
availableWidth = Math.max(getVisibleRect().width, 4 * getDefaultCharWidth() + lineContTextLayoutAdvance);
renderWrapWidth = availableWidth - lineContTextLayoutAdvance;
}
}
return availableWidth;
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
public void runTest(Object ctx, int numReps) {
TLContext tlctx = (TLContext)ctx;
TextLayout tl = tlctx.tl;
double wid = 0;
do {
wid += tl.getAdvance();
} while (--numReps >= 0);
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
@Override
@Nonnull
public Rectangle2D getStringBounds(@Nonnull final String str) {
if (str.isEmpty()) {
return this.context.getFontMetrics().getStringBounds("", this.context);
} else {
final TextLayout textLayout = new TextLayout(str, this.context.getFont(), this.context.getFontRenderContext());
return new Rectangle2D.Float(0, -textLayout.getAscent(), textLayout.getAdvance(), textLayout.getAscent() + textLayout.getDescent() + textLayout.getLeading());
}
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(this, frc);
return metrics.getSimpleBounds(chars, beginIndex, limit-beginIndex);
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
public float getWidth() {
if (width < 0)
for (TextLayout textLayout : layouts)
if (textLayout.getAdvance() > width)
width = textLayout.getAdvance();
return width;
}
public void runTest(Object ctx, int numReps) {
TLContext tlctx = (TLContext)ctx;
TextLayout tl = tlctx.tl;
double wid = 0;
do {
wid += tl.getAdvance();
} while (--numReps >= 0);
}
void rescale(double scale) {
Rectangle bounds = getBounds(scale);
HashMap settings = new HashMap();
settings.put(TextAttribute.FONT, new Font(style.getFontAttributes(scale)));
AttributedCharacterIterator par = (new AttributedString(element.getAttribute("text"), settings)).getIterator();
LineBreakMeasurer lbm = new LineBreakMeasurer(par, new FontRenderContext(null, false, false));
ArrayList drawList = new ArrayList();
int parEnd = par.getEndIndex();
int positionX;
int positionY = bounds.y;
lbm.setPosition(par.getBeginIndex());
while (lbm.getPosition() < parEnd) {
TextLayout layout = lbm.nextLayout(bounds.width);
positionX = bounds.x;
if (!layout.isLeftToRight()) {
positionX += bounds.width - (int) layout.getAdvance();
}
positionY += layout.getAscent();
if (positionY > bounds.y+bounds.height) break;
drawList.add(new Point(positionX, positionY));
drawList.add(layout);
positionY += layout.getDescent() + layout.getLeading();
}
textPositions = new Point[drawList.size()/2];
textLines = new TextLayout[drawList.size()/2];
textScale = scale;
for (int i = 0; i < textPositions.length; i++) {
textPositions[i] = (Point) drawList.get(i*2);
textLines[i] = (TextLayout) drawList.get(i*2+1);
}
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
/**
* Returns the logical bounds of the specified array of characters
* in the specified <code>FontRenderContext</code>. The logical
* bounds contains the origin, ascent, advance, and height, which
* includes the leading. The logical bounds does not always enclose
* all the text. For example, in some languages and in some fonts,
* accent marks can be positioned above the ascent or below the
* descent. To obtain a visual bounding box, which encloses all the
* text, use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param chars an array of characters
* @param beginIndex the initial offset in the array of
* characters
* @param limit the end offset in the array of characters
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* specified array of characters in the specified
* <code>FontRenderContext</code>.
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than zero, or <code>limit</code> is greater than the
* length of <code>chars</code>, or <code>beginIndex</code>
* is greater than <code>limit</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
*/
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > chars.length) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
// this code should be in textlayout
// quick check for simple text, assume GV ok to use if simple
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
} else {
// need char array constructor on textlayout
String str = new String(chars, beginIndex, limit - beginIndex);
TextLayout tl = new TextLayout(str, this, frc);
return new Rectangle2D.Float(0, -tl.getAscent(), tl.getAdvance(),
tl.getAscent() + tl.getDescent() +
tl.getLeading());
}
}
public void runTest(Object ctx, int numReps) {
TLContext tlctx = (TLContext)ctx;
TextLayout tl = tlctx.tl;
double wid = 0;
do {
wid += tl.getAdvance();
} while (--numReps >= 0);
}
private int computeStringWidth(String text, Font font) {
if (needFontFallback(font, text)) {
TextLayout layout = createTextLayout(text, font, getFontMetrics(font).getFontRenderContext());
return layout != null ? (int)layout.getAdvance() : 0;
}
else {
return getFontMetrics(font).stringWidth(text);
}
}
@Override
public float getPreferredSpan(int axis) {
EditorView.Parent parent = (EditorView.Parent) getParent();
if (axis == View.X_AXIS) {
float advance = 0;
TextLayout textLayout = getTextLayout();
if (textLayout == null) {
return 0f;
}
return textLayout.getAdvance();
} else {
return (parent != null) ? parent.getViewRenderContext().getDefaultRowHeight() : 0f;
}
}
private float computeStringWidth(int fragmentIndex, Font font) {
String text = myFragments.get(fragmentIndex);
if (StringUtil.isEmpty(text)) return 0;
FontRenderContext fontRenderContext = getFontMetrics(font).getFontRenderContext();
TextLayout layout = getTextLayout(fragmentIndex, font, fontRenderContext);
if (layout != null) {
return layout.getAdvance();
}
else {
return (float)font.getStringBounds(text, fontRenderContext).getWidth();
}
}
public void draw(Graphics2D g, int align, int pos, float fRectHeight,
MovingArea area) {
float left = 0;
float fromY = 0;
if (pos == 1)
fromY += fRectHeight / 2 - height / 2;
else if (pos == 2)
fromY += fRectHeight;
if (fromY < 0)
fromY = 0;
int size = layouts.size();
for (int i = 0; i < size; i++) {
TextLayout textLayout = layouts.get(i);
if (align == Line.CENTER_ALIGN)
left = (float) maxWidth / 2f - textLayout.getAdvance() / 2f;
else if (align == Line.RIGHT_ALIGN)
left = (float) maxWidth - textLayout.getAdvance();
fromY += textLayout.getAscent();
if (fromY >= fRectHeight && i + 1 < size)
break;
if (fromY + textLayout.getAscent() + textLayout.getDescent()
// + textLayout.getLeading()
>= fRectHeight
&& i + 1 < size) {
// textLayout= textLayout.getJustifiedLayout(maxWidth-20);
textLayout.draw(g, left, fromY);
/*
* Color color = g.getColor(); g.setColor(new Color(120, 120,
* 120));
*
* g.drawString("(.)", left + textLayout.getAdvance() + (float)
* area.getIDoubleOrdinate(-0.0), fromY); g.setColor(color);
*/
break;
} else
textLayout.draw(g, left, fromY);
fromY += textLayout.getDescent() + textLayout.getLeading();
}
}
public void drawWithSel(Graphics2D g, int align, int pos,
float fRectHeight, MovingArea area, int[][] found) {
float left = 0;
float fromY = 0;
if (pos == 1)
fromY += fRectHeight / 2 - height / 2;
else if (pos == 2)
fromY += fRectHeight;
if (fromY < 0)
fromY = 0;
int size = layouts.size();
in = false;
int selIndex = 0;
for (int i = 0; i < size; i++) {
TextLayout textLayout = layouts.get(i);
if (align == Line.CENTER_ALIGN)
left = (float) maxWidth / 2f - textLayout.getAdvance() / 2f;
else if (align == Line.RIGHT_ALIGN)
left = (float) maxWidth - textLayout.getAdvance();
fromY += textLayout.getAscent();
if (fromY >= fRectHeight && i + 1 < size)
break;
if (fromY + textLayout.getAscent() + textLayout.getDescent() >= fRectHeight
&& i + 1 < size) {
textLayout.draw(g, left, fromY);
selIndex = drawSels(g, found, selIndex, i, textLayout, left,
fromY);
break;
} else {
textLayout.draw(g, left, fromY);
selIndex = drawSels(g, found, selIndex, i, textLayout, left,
fromY);
}
fromY += textLayout.getDescent() + textLayout.getLeading();
}
}
public static String toStringShort(TextLayout textLayout) {
return "[" + textLayout.getCharacterCount() + "]W=" + textLayout.getAdvance(); // NOI18N
}