package com.ks.tools;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
/**
* @author 李英夫
* @ClassName CreateImg
* @date 2010-6-18 上午2:51:47
* @description
* 1.在生成的图片上输出文字
* 2.算法Scare和Node类提供,某吉大研究生,嘿嘿
*/
public class CreateImg {
private static final int INIT_X = 5; //初始X坐标
private static final int INIT_Y = 5; //初始Y坐标
private static final int LINE_HEIGHT = 5; //行高
private static final int PAINT_INIT_X = 0; //打印默认X坐标
private static final int PAINT_INIT_Y = 0; //打印默认Y坐标
private static final String FONT_FAMILY = "宋体"; //字体
private static final int FONT_WEIGHT = Font.PLAIN; //字体粗细
private static final Color FONT_COLOR = Color.BLACK; //字体颜色
private static final Color BACKGROUND = Color.WHITE; //背景颜色
private static final int IMAGE_COLOR_WEIGHT = BufferedImage.TYPE_INT_RGB; //表示一个图像,它具有合成整数像素的 8 位 RGB 颜色分量。
private static final String IMG_TYPE = "png"; //图片类型
/**
* 创建一个图片,在图片上写字
* @author 李英夫(2009-12-29 下午07:35:29)
* @param path 生成图片的路径
* @param texts 文字的集合
* @param fontSize 文字的大小
* @param textNum 每行文字的数量
* @throws Exception void
*/
public static void createIMG(String path, List<String> texts, int fontSize, int textNum)throws Exception{
int x = INIT_X;//文字显示的x轴坐标
int y = INIT_Y;//文字显示的y轴坐标
//行数
int lineNum = 0;
//先计算整张图片的高度和宽度
for (int i = 0; i < texts.size(); i++) {
lineNum += (int)Math.ceil(removeMark(texts.get(i)).length()*1.0/textNum*1.0);
}
int width = 2*x + fontSize*(textNum+2); //两个x的补白
//int height = (lineNum+1)*(fontSize+LINE_HEIGHT) + 2*y + LINE_HEIGHT; //两个y的补白
int height = lineNum*(fontSize+LINE_HEIGHT) + 2*y; //两个y的补白
File file = new File(path);
//设置字体和样式
Font font = new Font(FONT_FAMILY, FONT_WEIGHT, fontSize);
BufferedImage bi = new BufferedImage(width, height, IMAGE_COLOR_WEIGHT);
Graphics2D g2 = (Graphics2D) bi.getGraphics();
g2.setBackground(BACKGROUND);
g2.clearRect(PAINT_INIT_X, PAINT_INIT_Y, width, height);
g2.setPaint(FONT_COLOR);
g2.setFont(font);
FontRenderContext context = g2.getFontRenderContext();
for (int i = 0; i < texts.size(); i++) {
//行数
int linesPreTest = (int)Math.ceil(removeMark(texts.get(i)).length()*1.0/textNum*1.0) ;
for (int j = 0; j < linesPreTest; j++) {
String tempString = "";
//每次计算折行
if(j == linesPreTest-1)
tempString = texts.get(i).substring(j*textNum);
else
tempString = texts.get(i).substring(j*textNum, (j+1)*textNum);
//判断当前行有没有上、下标
double baseY = 0.0;
Rectangle2D bounds = font.getStringBounds(tempString, context);
double ascent = -bounds.getY();
baseY = y + ascent;
if(!isMark(tempString)){
g2.drawString(tempString, x, (int) baseY);
}else{
Scare s = new Scare();
s.parse(tempString);
List<Node> list = s.getList();
int xRay = x;
for (int k = 0; k < list.size(); k++) {
Node node = list.get(k);
float baseF = 0f;
if(null == node.getTag())baseF = 1f;
else if("sub".equals(node.getTag()))baseF = 1.2f;
else baseF = 1f/1.2f;
g2.drawString(node.getText(), (float)xRay*1.0f, (float)baseY*baseF);
xRay += getTxtLen(node.getText())*fontSize;
}
}
//纵坐标
y += fontSize+LINE_HEIGHT;
//横坐标
//x = INIT_X + fontSize + DOT;
x = INIT_X;
}
x = INIT_X;
}
ImageIO.write(bi, IMG_TYPE, file);
}
/**
* 是否存在上、下标的标签,存在返回true
* @param s
* @return
*/
private static boolean isMark(String s){
return (s.indexOf("<sub>") == -1) && (s.indexOf("<sup>") == -1) ? false : true;
}
/**
* 将标记替换掉
* @param s
* @return
*/
private static String removeMark(String s){
return s.replaceAll("<.*?>","");
}
/**
* 获得字符串真正的长度,分为双字节和单字节
* @param s
* @return
*/
private static double getTxtLen(String s){
return s.replaceAll("[^\\x00-\\xff]", "").length()/2.0 + s.replaceAll("[\\x00-\\xff]", "").length()*1.0;
}
public static void main(String[] args) throws Exception {
List<String> s = new ArrayList<String>();
s.add("A.a<sup>2</sup>+b<sup>2</sup>=c<sup>2</sup>===========H<sub>2</sub>O");
s.add("B.一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一!");
s.add("C.九十!");
s.add("D.一!");
createIMG("C:\\a.jpg",s,14,40);
String ssss = "Aaaa在aa工a";
System.out.println(getTxtLen(ssss));
}
}
package com.ks.tools;
import java.util.ArrayList;
import java.util.List;
public class Scare {
private int state = 0;
private int count = 0;
private boolean flag = true;
private String startTag = null;
private String endTag = null;
private List<Node> list = new ArrayList<Node>();
public boolean parse(String input) {
int length = input.length();
StringBuffer sb = new StringBuffer();
Node node = null;
for (int i = 0; i < length; i++) {
String str = input.substring(i, i + 1);
switch (state) {
case 0:
if (str.equals("<")) {
state = 2;
count++;
} else if (str.equals(">")) {
return false;
} else {
state = 1;
sb.append(str);
}
break;
case 1:
if (str.equals("<")) {
state = 2;
node = new Node();
node.setText(sb.toString());
list.add(node);
count++;
sb.delete(0, sb.length());
} else if (str.equals(">")) {
return false;
} else {
sb.append(str);
}
break;
case 2:
if (str.equals("<") || str.equals(">")) {
return false;
} else {
if (str.equals("/")) {
if (flag == true)
return false;
else {
state = 3;
}
} else {
if (flag == false)
return false;
else {
state = 3;
sb.append(str);
}
}
}
break;
case 3:
if (str.equals("<")) {
return false;
} else if (str.equals(">")) {
state = 4;
if (flag == true) {
startTag = sb.toString();
flag = false;
} else {
endTag = sb.toString();
flag = true;
if (check())
node.setTag(sb.toString());
else
return false;
}
count--;
sb.delete(0, sb.length());
} else {
sb.append(str);
}
break;
case 4:
if (str.equals("<") || str.equals(">")) {
return false;
} else {
state = 1;
sb.append(str);
}
break;
}
}
if ((flag == true) && check() && count == 0) {
node = new Node();
node.setText(sb.toString());
list.add(node);
sb.delete(0, sb.length());
return true;
}
return false;
}
private boolean check() {
return startTag.equals(endTag);
}
public List<Node> getList() {
return list;
}
public static void main(String args[]) {
Scare scare = new Scare();
String input = "ab<sub>c</sub>def<sup>g</sup>hi";
System.out.println(scare.parse(input));
List<Node> list = scare.getList();
for (Node node : list) {
System.out.println(node.getTag() + " " + node.getText());
}
}
}
package com.ks.tools;
public class Node {
private String tag = null;
private String text = null;
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}