下面列出了怎么用java.awt.font.TextLayout的API类实例代码及写法,或者点击链接到github查看源代码。
static void measureText() {
Font font = new Font(FONT, Font.PLAIN, 36);
if (!font.getFamily(Locale.ENGLISH).equals(FONT)) {
return;
}
FontRenderContext frc = new FontRenderContext(null, false, false);
TextLayout tl1 = new TextLayout(STR1, font, frc);
TextLayout tl2 = new TextLayout(STR2, font, frc);
Rectangle r1 = tl1.getPixelBounds(frc, 0f, 0f);
Rectangle r2 = tl2.getPixelBounds(frc, 0f, 0f);
if (r1.height > r2.height) {
System.out.println(font);
System.out.println(r1);
System.out.println(r2);
throw new RuntimeException("BAD BOUNDS");
}
}
public void paintObject(Graphics2D g, double scale) {
Rectangle bounds = getBounds(scale);
if (style != null) style.setStyle(g);
Style[] styles = context.flagger.getStyles(element);
for (int i = 0; i < styles.length; i++) {
styles[i].setStyle(g);
}
if (style.isFilled()) {
Color c = g.getColor();
g.setColor(style.getBackground());
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
g.setColor(c);
}
Point[] tp = getTextPositions(scale);
TextLayout[] tl = getTextLines(scale);
for (int i = 0; i < tp.length; i++) {
tl[i].draw(g, tp[i].x, tp[i].y);
}
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
int len = tlctx.text.length();
Rectangle2D lb = tlctx.lb;
Shape s;
if (len < 3) {
do {
s = tl.getLogicalHighlightShape(0, len, lb);
} while (--numReps >= 0);
} else {
do {
for (int i = 3; i < len; ++i) {
s = tl.getLogicalHighlightShape(i-3, i, lb);
}
} while (--numReps >= 0);
}
}
private void paintWord (WordInter word,
FontInfo lineMeanFont)
{
if (lineMeanFont != null) {
Font font = new TextFont(lineMeanFont);
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout(word.getValue(), font, frc);
setColor(word);
if (word.getValue().length() > 2) {
paint(layout, word.getLocation(), BASELINE_LEFT);
} else {
paint(layout, word.getCenter(), AREA_CENTER);
}
}
}
private Rectangle getCaretRectangle(TextHitInfo caret) {
int caretLocation = 0;
TextLayout layout = composedTextLayout;
if (layout != null) {
caretLocation = Math.round(layout.getCaretInfo(caret)[0]);
}
Graphics g = getGraphics();
FontMetrics metrics = null;
try {
metrics = g.getFontMetrics();
} finally {
g.dispose();
}
return new Rectangle(TEXT_ORIGIN_X + caretLocation,
TEXT_ORIGIN_Y - metrics.getAscent(),
0, metrics.getAscent() + metrics.getDescent());
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
TextHitInfo[] hits = tlctx.hits;
Rectangle2D lb = tlctx.lb;
Shape s;
if (hits.length < 3) {
do {
s = tl.getVisualHighlightShape(hits[0], hits[hits.length - 1], lb);
} while (--numReps >= 0);
} else {
do {
for (int i = 3; i < hits.length; ++i) {
s = tl.getVisualHighlightShape(hits[i-3], hits[i], lb);
}
} while (--numReps >= 0);
}
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(getForeground());
g2.setFont(getFont());
SwingUtilities.calculateInnerArea(this, RECT);
float x = RECT.x;
float y = RECT.y;
int w = RECT.width;
AttributedString as = new AttributedString(getText());
as.addAttribute(TextAttribute.FONT, getFont()); // TEST: .deriveFont(at));
// TEST: as.addAttribute(TextAttribute.TRANSFORM, at);
AttributedCharacterIterator aci = as.getIterator();
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
while (lbm.getPosition() < aci.getEndIndex()) {
TextLayout tl = lbm.nextLayout(w);
tl.draw(g2, x, y + tl.getAscent());
y += tl.getDescent() + tl.getLeading() + tl.getAscent();
}
g2.dispose();
}
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(Color.WHITE);
g.fillRect(0, 0, w, h);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext frc = g2.getFontRenderContext();
Shape shape = new TextLayout(text, getFont(), frc).getOutline(null);
Rectangle2D b = shape.getBounds2D();
double cx = w / 2d - b.getCenterX();
double cy = h / 2d - b.getCenterY();
AffineTransform toCenterAtf = AffineTransform.getTranslateInstance(cx, cy);
Shape s = toCenterAtf.createTransformedShape(shape);
g2.setPaint(Color.BLACK);
g2.fill(s);
Rectangle2D clip = new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth(), b.getHeight() / 2d);
g2.setClip(toCenterAtf.createTransformedShape(clip));
g2.setPaint(Color.RED);
g2.fill(s);
g2.dispose();
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
Font font = getFont();
Insets ins = getInsets();
Dimension d = getSize();
int w = d.width - ins.left - ins.right;
if (w != prevWidth) {
prevWidth = w;
layout = new TextLayout(getText(), font, g2.getFontRenderContext()).getJustifiedLayout((float) w);
}
g2.setPaint(getBackground());
g2.fillRect(0, 0, d.width, d.height);
g2.setPaint(getForeground());
// int baseline = getBaseline(d.width, d.height);
float baseline = ins.top + font.getSize2D();
layout.draw(g2, (float) ins.left, baseline);
g2.dispose();
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
int len = tlctx.text.length();
Rectangle2D lb = tlctx.lb;
Shape s;
if (len < 3) {
do {
s = tl.getLogicalHighlightShape(0, len, lb);
} while (--numReps >= 0);
} else {
do {
for (int i = 3; i < len; ++i) {
s = tl.getLogicalHighlightShape(i-3, i, lb);
}
} while (--numReps >= 0);
}
}
@Override
public Shape getUnclippedOutline() {
TextLayout layout = new TextLayout(getAttributedCharacterIterator(),
getContext().getFontRenderContext());
Rectangle2D bounds = layout.getBounds();
bounds.setFrame(bounds.getX() + getX(), bounds.getY() + getY(),
bounds.getWidth(), bounds.getHeight());
return bounds;
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
TextHitInfo[] hits = tlctx.hits;
do {
for (int i = 0; i < hits.length; ++i) {
tl.getCaretInfo(hits[i]);
}
} while (--numReps >= 0);
}
@Override protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.WHITE);
g2.fillRect(0, 0, getWidth(), getHeight());
String str = getCharacterString();
FontRenderContext frc = g2.getFontRenderContext();
Shape exShape = new TextLayout(str, ipaEx, frc).getOutline(null);
Shape mjShape = new TextLayout(str, ipaMj, frc).getOutline(null);
Rectangle2D b = exShape.getBounds2D();
double cx = getWidth() / 2d - b.getCenterX();
double cy = getHeight() / 2d - b.getCenterY();
AffineTransform toCenterAtf = AffineTransform.getTranslateInstance(cx, cy);
g2.setPaint(Color.YELLOW);
g2.draw(toCenterAtf.createTransformedShape(b));
Shape s1 = toCenterAtf.createTransformedShape(exShape);
Shape s2 = toCenterAtf.createTransformedShape(mjShape);
if (fontPaintFlag.contains(FontPaint.IPA_EX_MINCHO)) {
g2.setPaint(Color.CYAN);
g2.fill(s1);
}
if (fontPaintFlag.contains(FontPaint.IPA_MJ_MINCHO)) {
g2.setPaint(Color.MAGENTA);
g2.fill(s2);
}
if (fontPaintFlag.containsAll(EnumSet.allOf(FontPaint.class))) {
g2.setClip(s1);
g2.setPaint(Color.BLACK);
g2.fill(s2);
}
g2.dispose();
}
public void runTest(Object ctx, int numReps) {
TLContext tlctx = (TLContext)ctx;
TextLayout tl = tlctx.tl;
Rectangle2D r;
do {
r = tl.getBounds();
} 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());
}
}
public void drawString(AttributedCharacterIterator attributedcharacteriterator, float x, float y)
{
TextLayout textlayout = new TextLayout(attributedcharacteriterator, getFontRenderContext());
Paint paint1 = getPaint();
setColor(getColor());
fill(textlayout.getOutline(AffineTransform.getTranslateInstance(x, y)));
setPaint(paint1);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(getForeground());
TextLayout layout = composedTextLayout;
if (layout != null) {
layout.draw((Graphics2D) g, TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
}
if (caret != null) {
Rectangle rectangle = getCaretRectangle(caret);
g.setXORMode(getBackground());
g.fillRect(rectangle.x, rectangle.y, 1, rectangle.height);
g.setPaintMode();
}
}
public void drawChars(SunGraphics2D sg2d,
char data[], int offset, int length,
int ix, int iy)
{
FontInfo info = sg2d.getFontInfo();
float x, y;
if (info.pixelHeight > OutlineTextRenderer.THRESHHOLD) {
SurfaceData.outlineTextRenderer.drawChars(
sg2d, data, offset, length, ix, iy);
return;
}
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
double origin[] = {ix + info.originX, iy + info.originY};
sg2d.transform.transform(origin, 0, origin, 0, 1);
x = (float) origin[0];
y = (float) origin[1];
} else {
x = ix + info.originX + sg2d.transX;
y = iy + info.originY + sg2d.transY;
}
GlyphList gl = GlyphList.getInstance();
if (gl.setFromChars(info, data, offset, length, x, y)) {
drawGlyphList(sg2d, gl);
gl.dispose();
} else {
gl.dispose(); // release this asap.
TextLayout tl = new TextLayout(new String(data, offset, length),
sg2d.getFont(),
sg2d.getFontRenderContext());
tl.draw(sg2d, ix, iy);
}
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
TextHitInfo[] hits = tlctx.hits;
TextHitInfo hit;
do {
for (int i = 0; i < hits.length; ++i) {
hit = tl.getNextLeftHit(hits[i]);
}
} 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 a rectangle that encloses the axis label. This is typically
* used for layout purposes (it gives the maximum dimensions of the label).
*
* @param g2 the graphics device.
* @param edge the edge of the plot area along which the axis is measuring.
*
* @return The enclosing rectangle.
*/
protected Rectangle2D getLabelEnclosure(Graphics2D g2, RectangleEdge edge) {
Rectangle2D result = new Rectangle2D.Double();
Rectangle2D bounds = null;
if (this.attributedLabel != null) {
TextLayout layout = new TextLayout(
this.attributedLabel.getIterator(),
g2.getFontRenderContext());
bounds = layout.getBounds();
} else {
String axisLabel = getLabel();
if (axisLabel != null && !axisLabel.equals("")) {
FontMetrics fm = g2.getFontMetrics(getLabelFont());
bounds = TextUtilities.getTextBounds(axisLabel, g2, fm);
}
}
if (bounds != null) {
RectangleInsets insets = getLabelInsets();
bounds = insets.createOutsetRectangle(bounds);
double angle = getLabelAngle();
if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) {
angle = angle - Math.PI / 2.0;
}
double x = bounds.getCenterX();
double y = bounds.getCenterY();
AffineTransform transformer
= AffineTransform.getRotateInstance(angle, x, y);
Shape labelBounds = transformer.createTransformedShape(bounds);
result = labelBounds.getBounds2D();
}
return result;
}
private static long test(String text) {
long start = System.nanoTime();
for (int i = 0; i < 2000; ++i) {
TextLayout tl = new TextLayout(text, font, frc);
}
return System.nanoTime() - start;
}
public void drawString(SunGraphics2D g2d, String str, double x, double y) {
if ("".equals(str)) {
return; // TextLayout constructor throws IAE on "".
}
TextLayout tl = new TextLayout(str, g2d.getFont(),
g2d.getFontRenderContext());
Shape s = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
int textAAHint = g2d.getFontInfo().aaHint;
int prevaaHint = - 1;
if (textAAHint != SunHints.INTVAL_TEXT_ANTIALIAS_OFF &&
g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
prevaaHint = g2d.antialiasHint;
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_ON;
g2d.validatePipe();
} else if (textAAHint == SunHints.INTVAL_TEXT_ANTIALIAS_OFF
&& g2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_OFF) {
prevaaHint = g2d.antialiasHint;
g2d.antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;
g2d.validatePipe();
}
g2d.fill(s);
if (prevaaHint != -1) {
g2d.antialiasHint = prevaaHint;
g2d.validatePipe();
}
}
public void drawString(AttributedCharacterIterator iterator,
float x, float y) {
if (iterator == null) {
throw
new NullPointerException("attributedcharacteriterator is null");
}
TextLayout layout =
new TextLayout(iterator, getFontRenderContext());
layout.draw(this, x, y);
}
public void drawLabel(String text, GraphicInfo graphicInfo, boolean centered){
float interline = 1.0f;
// text
if (text != null && text.length()>0) {
Paint originalPaint = g.getPaint();
Font originalFont = g.getFont();
g.setPaint(LABEL_COLOR);
g.setFont(LABEL_FONT);
int wrapWidth = 100;
int textY = (int) graphicInfo.getY();
// TODO: use drawMultilineText()
AttributedString as = new AttributedString(text);
as.addAttribute(TextAttribute.FOREGROUND, g.getPaint());
as.addAttribute(TextAttribute.FONT, g.getFont());
AttributedCharacterIterator aci = as.getIterator();
FontRenderContext frc = new FontRenderContext(null, true, false);
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
while (lbm.getPosition() < text.length()) {
TextLayout tl = lbm.nextLayout(wrapWidth);
textY += tl.getAscent();
Rectangle2D bb = tl.getBounds();
double tX = graphicInfo.getX();
if (centered) {
tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2);
}
tl.draw(g, (float) tX, textY);
textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent();
}
// restore originals
g.setFont(originalFont);
g.setPaint(originalPaint);
}
}
public static void main(String[] args) {
Font font = new Font("Monospaced", Font.PLAIN, 12);
String text = "\u0601";
FontRenderContext frc = new FontRenderContext(null, false, false);
TextLayout layout = new TextLayout(text, font, frc);
BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
layout.draw(g2d, 50.0f, 50.0f);
layout.getCaretShapes(0);
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
TextHitInfo[] hits = tlctx.hits;
TextHitInfo hit;
do {
for (int i = 0; i < hits.length; ++i) {
hit = tl.getNextLeftHit(hits[i]);
}
} while (--numReps >= 0);
}
@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());
}
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(getForeground());
TextLayout layout = composedTextLayout;
if (layout != null) {
layout.draw((Graphics2D) g, TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
}
if (caret != null) {
Rectangle rectangle = getCaretRectangle(caret);
g.setXORMode(getBackground());
g.fillRect(rectangle.x, rectangle.y, 1, rectangle.height);
g.setPaintMode();
}
}
public void runTest(Object ctx, int numReps) {
TLExContext tlctx = (TLExContext)ctx;
TextLayout tl = tlctx.tl;
TextHitInfo[] hits = tlctx.hits;
Shape s;
do {
for (int i = 0; i < hits.length; ++i) {
s = tl.getCaretShape(hits[i]);
}
} while (--numReps >= 0);
}