/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.javase;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.List;
import loon.font.TextFormat;
import loon.font.TextWrap;
import loon.geom.RectBox;
class JavaSETextLayout extends loon.font.TextLayout {
public static JavaSETextLayout layoutText(JavaSEGraphics gfx, String text,
TextFormat format) {
AttributedString astring = new AttributedString(
text.length() == 0 ? " " : text);
if (format.font != null) {
astring.addAttribute(TextAttribute.FONT,
gfx.resolveFont(format.font));
}
FontRenderContext frc = format.antialias ? gfx.aaFontContext
: gfx.aFontContext;
return new JavaSETextLayout(text, format, new TextLayout(
astring.getIterator(), frc));
}
public static JavaSETextLayout[] layoutText(JavaSEGraphics gfx, String text,
TextFormat format, TextWrap wrap) {
text = normalizeEOL(text);
String ltext = text.length() == 0 ? " " : text;
AttributedString astring = new AttributedString(ltext);
if (format.font != null) {
astring.addAttribute(TextAttribute.FONT,
gfx.resolveFont(format.font));
}
List<JavaSETextLayout> layouts = new ArrayList<JavaSETextLayout>();
FontRenderContext frc = format.antialias ? gfx.aaFontContext
: gfx.aFontContext;
LineBreakMeasurer measurer = new LineBreakMeasurer(
astring.getIterator(), frc);
int lastPos = ltext.length(), curPos = 0;
char eol = '\n';
while (curPos < lastPos) {
int nextRet = ltext.indexOf(eol, measurer.getPosition() + 1);
if (nextRet == -1) {
nextRet = lastPos;
}
TextLayout layout = measurer.nextLayout(wrap.width, nextRet, false);
int endPos = measurer.getPosition();
while (curPos < endPos && ltext.charAt(curPos) == eol) {
curPos += 1;
}
layouts.add(new JavaSETextLayout(ltext.substring(curPos, endPos),
format, layout));
curPos = endPos;
}
return layouts.toArray(new JavaSETextLayout[layouts.size()]);
}
private final TextLayout layout;
private final Graphics2D g2d;
private FontMetrics fontMetrics;
JavaSETextLayout(String text, TextFormat format, TextLayout layout) {
super(text, format, computeBounds(layout), layout.getAscent()
+ layout.getDescent());
this.g2d = (Graphics2D) new BufferedImage(1, 1,
BufferedImage.TYPE_INT_ARGB).getGraphics();
this.fontMetrics = g2d.getFontMetrics(new java.awt.Font(
format.font.name, JavaSEGraphics.STYLE_TO_JAVA[format.font.style
.ordinal()], (int) format.font.size));
this.layout = layout;
}
@Override
public float ascent() {
return layout.getAscent();
}
@Override
public float descent() {
return layout.getDescent();
}
@Override
public float leading() {
return layout.getLeading();
}
void stroke(Graphics2D gfx, float x, float y) {
paint(gfx, x, y, true);
}
void fill(Graphics2D gfx, float x, float y) {
paint(gfx, x, y, false);
}
void paint(Graphics2D gfx, float x, float y, boolean stroke) {
Object ohint = gfx.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
try {
gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
format.antialias ? RenderingHints.VALUE_ANTIALIAS_ON
: RenderingHints.VALUE_ANTIALIAS_OFF);
float yoff = y + layout.getAscent();
if (stroke) {
gfx.translate(x, yoff);
gfx.draw(layout.getOutline(null));
gfx.translate(-x, -yoff);
} else {
layout.draw(gfx, x, yoff);
}
} finally {
gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING, ohint);
}
}
private static RectBox computeBounds(TextLayout layout) {
Rectangle2D bounds = layout.getBounds();
return new RectBox((float) bounds.getX(), (float) bounds.getY()
+ layout.getAscent(), (float) bounds.getWidth(),
(float) bounds.getHeight());
}
public int charWidth(char ch){
return fontMetrics.charWidth(ch);
}
@Override
public int stringWidth(String message) {
return fontMetrics.stringWidth(message);
}
@Override
public int getHeight() {
return fontMetrics.getHeight();
}
}