JavaFX字库精简项目开发(四)—— 装配LocalServer
概述
JavaFX是用于构建富互联网应用程序的Java库。使用JavaFX开发的应用程序可以在各种设备上运行,如台式计算机,手机,物联网设备,平板电脑等。最近为了巩固一下JavaFX学习成果,准备利用整个技术开发一个工具软件能够对字库进行裁剪,可以根据用户的设置自动生成精简字库,简化手动裁剪的麻烦。
技术实现
在上一篇文章我在程序中增加了WebView组件,可以引入Web前端技术。但是javaFX的WebView组件仅仅适用于web页面的显示场景,对于文件下载支持不好。网上虽然有下载文件的例子,我实验没有成功。因此我决定将前端生成的json文件内容通过post请求发送到javaFX创建的服务器中,再完成文件创建写入操作。
涉及技术
- JavaFX8中的WebView,jfoenix8
- html js css 基本的web技术
- SimpleServer
功能编码
后端服务创建
使用hutool工具类创建简单服务器
import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.SimpleServer;
import cn.hutool.json.JSONUtil;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
public class LocalServer {
public static void startLocalServer() throws Exception {
SimpleServer server = HttpUtil.createServer(8082);
server.addAction("/font/convert", (request, res) -> {
FileInputStream fis = null;
BufferedOutputStream bos = null;
try {
fis = new FileInputStream(MainController.fileDes);
byte[] tmp = new byte[fis.available()];
fis.read(tmp);
res.setContentType("application/octet-stream");
res.setHeader("Content-Disposition",
"attachment;fileName=" + new String("msyh_simplify.ttf".getBytes("utf-8"), "iso8859-1"));
res.setHeader("Content-Length", String.valueOf(tmp.length));
bos = new BufferedOutputStream(res.getOut());
bos.write(tmp, 0, tmp.length);
bos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis!=null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (bos!=null) {
try {
bos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
//用来处理前端传来的数据
server.addAction("/push/json", (request, res) -> {
String output = (String) JSONUtil.parseArray(request.getParams().get("res")).get(0);
String fileName = (String) JSONUtil.parseArray(request.getParams().get("name")).get(0);
System.out.println(res+"----"+fileName);
String filePath = MainController.getBasicFilePath()+ File.separator+fileName;
Files.write(Paths.get(filePath),output.getBytes(Charset.defaultCharset()));
});
server.start();
}
}
前端调用接口
//调用简化后ttf字库,转换为json字库
function convertTTFtoJson() {
opentype.load('http://127.0.0.1:8082/font/convert', function(err, font) {
if (err)
throw err;
var result = convert(font);
exportString(result, font.familyName + "_" + font.styleName + ".json");
});
}
restrictCharactersCheck.onchange = function() {
restrictCharacterSetInput.disabled = !restrictCharactersCheck.checked;
};
//导出字符串
var exportString = function(output, filename) {
var blob = new Blob([output], {
type: 'text/plain'
});
var objectURL = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = objectURL;
link.download = filename || 'data.json';
link.target = '_blank';
// link.click();
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false,
false, false, false, 0, null);
link.dispatchEvent(event);
//将json传回cs端的服务器
var res = {"res":output,"name":filename}
$.ajax({
url:'http://127.0.0.1:8082/push/json',
type: 'POST',
data: res,
dataType: 'JSON',
success: function (data) {
}
});
};
//字体库简化
var convert = function(font) {
console.log(font);
var scale = (1000 * 100) / ((font.unitsPerEm || 2048) * 72);
var result = {};
result.glyphs = {};
var restriction = {
range: null,
set: null
};
if (restrictCharactersCheck.checked) {
var restrictContent = restrictCharacterSetInput.value;
var rangeSeparator = '-';
if (restrictContent.indexOf(rangeSeparator) != -1) {
var rangeParts = restrictContent.split(rangeSeparator);
if (rangeParts.length === 2 && !isNaN(rangeParts[0]) &&
!isNaN(rangeParts[1])) {
restriction.range = [parseInt(rangeParts[0]),
parseInt(rangeParts[1])
];
}
}
if (restriction.range === null) {
restriction.set = restrictContent;
}
}
font.glyphs
.forEach(function(glyph) {
if (glyph.unicode !== undefined) {
var glyphCharacter = String.fromCharCode(glyph.unicode);
var needToExport = true;
if (restriction.range !== null) {
needToExport = (glyph.unicode >= restriction.range[0] && glyph.unicode <= restriction.range[1]);
} else if (restriction.set !== null) {
needToExport = (restrictCharacterSetInput.value
.indexOf(glyphCharacter) != -1);
}
if (needToExport) {
var token = {};
token.ha = Math.round(glyph.advanceWidth * scale);
token.x_min = Math.round(glyph.xMin * scale);
token.x_max = Math.round(glyph.xMax * scale);
token.o = ""
glyph.path.commands.forEach(function(command, i) {
if (command.type.toLowerCase() === "c") {
command.type = "b";
}
token.o += command.type.toLowerCase();
token.o += " "
if (command.x !== undefined &&
command.y !== undefined) {
token.o += Math.round(command.x * scale);
token.o += " "
token.o += Math.round(command.y * scale);
token.o += " "
}
if (command.x1 !== undefined &&
command.y1 !== undefined) {
token.o += Math.round(command.x1 * scale);
token.o += " "
token.o += Math.round(command.y1 * scale);
token.o += " "
}
if (command.x2 !== undefined &&
command.y2 !== undefined) {
token.o += Math.round(command.x2 * scale);
token.o += " "
token.o += Math.round(command.y2 * scale);
token.o += " "
}
});
result.glyphs[String.fromCharCode(glyph.unicode)] = token;
}
};
});
result.familyName = font.familyName;
result.ascender = Math.round(font.ascender * scale);
result.descender = Math.round(font.descender * scale);
result.underlinePosition = Math.round(font.tables.post.underlinePosition *
scale);
result.underlineThickness = Math.round(font.tables.post.underlineThickness *
scale);
result.boundingBox = {
"yMin": Math.round(font.tables.head.yMin * scale),
"xMin": Math.round(font.tables.head.xMin * scale),
"yMax": Math.round(font.tables.head.yMax * scale),
"xMax": Math.round(font.tables.head.xMax * scale)
};
result.resolution = 1000;
result.original_font_information = font.tables.name;
if (font.styleName.toLowerCase().indexOf("bold") > -1) {
result.cssFontWeight = "bold";
} else {
result.cssFontWeight = "normal";
};
if (font.styleName.toLowerCase().indexOf("italic") > -1) {
result.cssFontStyle = "italic";
} else {
result.cssFontStyle = "normal";
};
return JSON.stringify(result);
};
总结
以上已经完成全后端的简单交互,实现了文件文件的下载。通过javaFX中打开相应的文件路径,就可以做到下载功能。