org.ofdrw.layout.element.canvas.TextMeasureTool Maven / Gradle / Ivy
The newest version!
package org.ofdrw.layout.element.canvas;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
/**
* 字体测量工具
*
* @author 权观宇
* @since 2020-05-08 21:30:59
*/
public final class TextMeasureTool {
/**
* 分析字间距偏移量并计算文字宽度
*
* @param text 文本
* @param fontSetting 文字设置
* @return 测量结果
*/
public static MeasureBody measureWithWith(String text, FontSetting fontSetting) {
MeasureBody body = new MeasureBody();
if (text.length() == 0) {
return body;
}
int readDirection = fontSetting.getReadDirection();
int charDirection = fontSetting.getCharDirection();
char firstChar = text.charAt(0);
char lastChar = text.charAt(text.length() - 1);
final Double fontSize = fontSetting.getFontSize();
if (readDirection == 0) {
if (charDirection == 0) {
body.offset = offset(text, fontSetting, 0, "W", 1);
body.with(fontSetting.charWidth(lastChar));
} else if (charDirection == 180) {
body.offset = offset(text, fontSetting, 1, "W", 1);
body.with(fontSetting.charWidth(firstChar));
body.firstCharOffsetX = fontSetting.charWidth(firstChar);
body.firstCharOffsetY = -fontSize;
} else if (charDirection == 90 || charDirection == 270) {
body.offset = offset(text, fontSetting, 0, "H", 1);
body.with(fontSize);
if (charDirection == 90) {
body.firstCharOffsetY = -fontSize;
} else {
body.firstCharOffsetX = fontSize;
}
}
} else if (readDirection == 180) {
if (charDirection == 0) {
body.offset = offset(text, fontSetting, 1, "W", -1);
body.with(fontSetting.charWidth(firstChar));
body.firstCharOffsetX = -fontSetting.charWidth(firstChar);
} else if (charDirection == 180) {
body.offset = offset(text, fontSetting, 0, "W", -1);
body.with(fontSetting.charWidth(lastChar));
body.firstCharOffsetY = -fontSize;
} else if (charDirection == 90 || charDirection == 270) {
body.offset = offset(text, fontSetting, 0, "H", -1);
body.with(fontSize);
if (charDirection == 90) {
body.firstCharOffsetX = -fontSize;
body.firstCharOffsetY = -fontSize;
}
}
} else if (readDirection == 90) {
if (charDirection == 0 || charDirection == 180) {
body.offset = offset(text, fontSetting, 0, "H", 1);
body.with(fontSize);
if (charDirection == 0) {
body.firstCharOffsetY = fontSize;
} else {
body.firstCharOffsetX = fontSize;
}
} else if (charDirection == 90) {
body.offset = offset(text, fontSetting, 0, "W", 1);
body.with(fontSetting.charWidth(lastChar));
} else if (charDirection == 270) {
body.offset = offset(text, fontSetting, 1, "W", 1);
body.with(fontSetting.charWidth(firstChar));
body.firstCharOffsetX = fontSize;
body.firstCharOffsetY = fontSetting.charWidth(firstChar);
}
} else if (readDirection == 270) {
if (charDirection == 0 || charDirection == 180) {
body.offset = offset(text, fontSetting, 0, "H", -1);
body.with(fontSize);
if (charDirection == 180) {
body.firstCharOffsetX = fontSize;
body.firstCharOffsetY = -fontSize;
}
} else if (charDirection == 90) {
body.offset = offset(text, fontSetting, 1, "W", -1);
body.with(fontSetting.charWidth(firstChar));
body.firstCharOffsetY = -fontSetting.charWidth(firstChar);
} else if (charDirection == 270) {
body.offset = offset(text, fontSetting, 0, "W", -1);
body.with(fontSetting.charWidth(lastChar));
body.firstCharOffsetX = fontSize;
}
}
return body;
}
/**
* 测量文本各个字符在特定排列方式下的偏移量数组
*
* @param text 需要测试文本
* @param fontSetting 文字配置
* @return 偏移量数组
*/
public static Double[] measure(String text, FontSetting fontSetting) {
return measureWithWith(text, fontSetting).offset;
}
/**
* 计算文本所占空间大小
*
* @param text 文本
* @param fontSetting 文字设置
* @return 文档所占区域大小
*/
public static TextMetricsArea measureArea(String text, FontSetting fontSetting) {
TextMetricsArea area = new TextMetricsArea();
area.charAreas = new ArrayList<>(text.length());
area.width = 0d;
area.height = 0d;
int readDirection = fontSetting.getReadDirection();
int charDirection = fontSetting.getCharDirection();
double width = 0d;
double height = 0d;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
Rectangle2D box = fontSetting.box(c);
if (readDirection == 0 || readDirection == 180) {
if (charDirection == 0 || charDirection == 180) {
if (i != 0) {
width += fontSetting.getLetterSpacing();
}
width += box.getWidth();
height = Math.max(height, box.getHeight());
area.charAreas.add(new Rectangle2D.Double(0, 0, box.getWidth(), box.getHeight()));
} else if (charDirection == 90 || charDirection == 270) {
if (i != 0) {
width += fontSetting.getLetterSpacing();
}
width += box.getHeight();
height = Math.max(height, box.getWidth());
area.charAreas.add(new Rectangle2D.Double(0, 0, box.getHeight(), box.getWidth()));
}
} else if (readDirection == 90 || readDirection == 270) {
if (charDirection == 0 || charDirection == 180) {
if (i != 0) {
height += fontSetting.getLetterSpacing();
}
height += box.getHeight();
width = Math.max(width, box.getWidth());
area.charAreas.add(new Rectangle2D.Double(0, 0, box.getWidth(), box.getHeight()));
} else if (charDirection == 90 || charDirection == 270) {
if (i != 0) {
height += fontSetting.getLetterSpacing();
}
height += box.getWidth();
width = Math.max(width, box.getHeight());
area.charAreas.add(new Rectangle2D.Double(0, 0, box.getHeight(), box.getWidth()));
}
}
}
area.height = height;
area.width = width;
area.letterSpacing = fontSetting.getLetterSpacing();
return area;
}
/**
* 获取字符偏移量
*
* @param text 文字
* @param fontSetting 文字设置
* @param indexOffset 相对偏移
* @param wOrH 宽度或高度作为偏移量,W 或 H
* @param direction 文字排列方向:1 正序递增,-1 逆序递减。
* @return 偏移数组
*/
private static Double[] offset(String text,
FontSetting fontSetting,
int indexOffset,
String wOrH,
int direction) {
if (text.length() == 1) {
return new Double[0];
}
Double fontSize = fontSetting.getFontSize();
Double letterSpacing = fontSetting.getLetterSpacing();
Double[] offsetArray = new Double[text.length() - 1];
for (int i = indexOffset, len = indexOffset + text.length() - 1; i < len; i++) {
int index = indexOffset == 0 ? i : i - 1;
if ("w".equalsIgnoreCase(wOrH)) {
offsetArray[index] = fontSetting.charWidth(text.charAt(i)) + letterSpacing;
} else {
offsetArray[index] = fontSize + letterSpacing;
}
// read direction 180 或 270
offsetArray[index] = direction * offsetArray[index];
}
return offsetArray;
}
}