/**
* 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.android;
import java.util.ArrayList;
import java.util.List;
import loon.font.TextFormat;
import loon.font.TextLayout;
import loon.font.TextWrap;
import loon.geom.RectBox;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
class AndroidTextLayout extends TextLayout {
public final AndroidFont font;
private final Paint.FontMetrics metrics;
public static TextLayout layoutText(AndroidGraphics gfx, String text,
TextFormat format) {
AndroidFont font = gfx.resolveFont(format.font);
Paint paint = new Paint(format.antialias ? Paint.ANTI_ALIAS_FLAG : 0);
paint.setTypeface(font.typeface);
paint.setTextSize(font.size);
paint.setSubpixelText(true);
Paint.FontMetrics metrics = paint.getFontMetrics();
font.paint = paint;
return new AndroidTextLayout(text, format, font, metrics,
paint.measureText(text));
}
public static TextLayout[] layoutText(AndroidGraphics gfx, String text,
TextFormat format, TextWrap wrap) {
AndroidFont font = gfx.resolveFont(format.font);
Paint paint = new Paint(format.antialias ? Paint.ANTI_ALIAS_FLAG : 0);
paint.setTypeface(font.typeface);
paint.setTextSize(font.size);
paint.setSubpixelText(true);
Paint.FontMetrics metrics = paint.getFontMetrics();
font.paint = paint;
List<TextLayout> layouts = new ArrayList<TextLayout>();
float[] measuredWidth = new float[1];
for (String ltext : normalizeEOL(text).split("\\n")) {
if (wrap.width <= 0 || wrap.width == Float.MAX_VALUE) {
layouts.add(new AndroidTextLayout(ltext, format, font, metrics,
paint.measureText(ltext)));
} else {
int start = 0, end = ltext.length();
while (start < end) {
int count = paint.breakText(ltext, start, end, true,
wrap.width, measuredWidth);
int lineEnd = start + count;
if (lineEnd < end && font.resources.length > 0) {
int adjust = accountForLigatures(ltext, start, count,
font.resources);
count += adjust;
lineEnd += adjust;
}
if (lineEnd == end) {
layouts.add(new AndroidTextLayout(ltext.substring(
start, lineEnd), format, font, metrics,
measuredWidth[0]));
start += count;
} else {
if (!Character.isWhitespace(ltext.charAt(lineEnd - 1))
&& !Character.isWhitespace(ltext
.charAt(lineEnd))) {
do {
--lineEnd;
} while (lineEnd > start
&& !Character.isWhitespace(ltext
.charAt(lineEnd)));
}
if (lineEnd == start) {
layouts.add(new AndroidTextLayout(ltext.substring(
start, start + count), format, font,
metrics, measuredWidth[0]));
start += count;
} else {
while (Character.isWhitespace(ltext
.charAt(lineEnd - 1))) {
--lineEnd;
}
String line = ltext.substring(start, lineEnd);
float size = paint.measureText(line);
layouts.add(new AndroidTextLayout(line, format,
font, metrics, size));
start = lineEnd;
}
while (start < end
&& Character.isWhitespace(ltext.charAt(start))) {
start++;
}
}
}
}
}
return layouts.toArray(new TextLayout[layouts.size()]);
}
@Override
public float ascent() {
return -metrics.ascent;
}
@Override
public float descent() {
return metrics.descent;
}
@Override
public float leading() {
return metrics.leading;
}
AndroidTextLayout(String text, TextFormat format, AndroidFont font,
Paint.FontMetrics metrics, float width) {
this(text, format, font, metrics, width, -metrics.ascent
+ metrics.descent);
}
AndroidTextLayout(String text, TextFormat format, AndroidFont font,
Paint.FontMetrics metrics, float width, float height) {
super(text, format, new RectBox(0, 0, width, height), height);
this.font = font;
this.metrics = metrics;
}
void draw(Canvas canvas, float x, float y, Paint paint) {
boolean oldAA = paint.isAntiAlias();
paint.setAntiAlias(format.antialias);
try {
paint.setTypeface(font.typeface);
paint.setTextSize(font.size);
paint.setSubpixelText(true);
if (font.size > 250) {
Path path = new Path();
paint.getTextPath(text, 0, text.length(), x,
y - metrics.ascent, path);
canvas.drawPath(path, paint);
} else {
canvas.drawText(text, x, y - metrics.ascent, paint);
}
} finally {
paint.setAntiAlias(oldAA);
}
}
static int accountForLigatures(String text, int start, int count,
String[] ligatures) {
int adjust = 0;
for (String lig : ligatures) {
int llen = lig.length(), idx = start;
while ((idx = text.indexOf(lig, idx)) != -1) {
if (idx + 1 > start + count){
break;
}
int extra = llen - 1;
adjust += extra;
count += extra;
idx += llen;
}
}
return adjust;
}
@Override
public int stringWidth(String message) {
return (int) this.font.paint.measureText(message);
}
@Override
public int getHeight() {
return this.font.paint.getFontMetricsInt(this.font.paint
.getFontMetricsInt());
}
@Override
public int charWidth(char ch) {
char[] chars = Character.toChars(ch);
int w = (int) this.font.paint.measureText(chars, 0, 1);
return w;
}
}