package com.yeechart.dotMatrix.font; import com.yeechart.dotMatrix.font.bean.FontObject; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * 自定义字体库 XZP */ @Component public class XZPFontLoaderUtil { private List fontObjects = new ArrayList<>(); private Map> fontMap = new HashMap<>(); @PostConstruct public void init() { String filePath = "fonts/font_2024_03_15.DAT"; // 获取资源文件的输入流 InputStream inputStream = XZPFontLoaderUtil.class.getClassLoader().getResourceAsStream(filePath); if (inputStream == null) { throw new RuntimeException("文件未找到!"); } try { fontObjects = parseFontFile(inputStream); fontMap = fontlistToMap(fontObjects); } catch (Exception e) { throw new RuntimeException(e); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 得到 字符串 指定的编码集 编号 * * @param text * @return */ public String getEncoding(String text, String charsetName) { String encoding = ""; try { byte[] bytes = String.valueOf(text).getBytes(charsetName); StringBuilder hex = new StringBuilder(); if (bytes != null && bytes.length > 0) { // 将字节转换为16进制字符串 for (byte b : bytes) { hex.append(String.format("%02x", b)); } // System.out.println(text+" GB2312编码: " + hex.toString()); } encoding = hex.toString(); } catch (Exception e) { e.printStackTrace(); } return encoding; } /** * 判断字符串是否仅由英文字母构成 * * @param str * @return */ public boolean isAllLetters(String str) { return str.matches("^[a-zA-Z]+$"); } /** * 判断字符串是否仅由数字组成 * * @param str * @return */ public boolean isAllDigits(String str) { return str.matches("^[0-9]+$"); } /** * 判断字符串是否仅由英文字母和数字组成 * * @param str * @return */ public boolean isAlphanumeric(String str) { return str.matches("^[a-zA-Z0-9]+$"); } /** * 将 字库点阵列表 转换为 map * * @param fontObjectList * @return */ private Map> fontlistToMap(List fontObjectList) { Map> fontMap = new HashMap<>(); for (FontObject fontObject : fontObjectList) { List fontObjects1; if (fontMap.containsKey(fontObject.getEncoding())) { fontObjects1 = fontMap.get(fontObject.getEncoding()); fontObjects1.add(fontObject); } else { fontObjects1 = new ArrayList<>(); fontObjects1.add(fontObject); } fontMap.put(fontObject.getEncoding(), fontObjects1); } return fontMap; } private List parseFontFile(InputStream inputStream) { List fontObjects = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; FontObject fontObject = null; Pattern pattern = null; Matcher matcher = null; //一行行读取 while ((line = reader.readLine()) != null) { //这是第一行 if (line.contains("[Paint_DrawChar] font lib start") || line.contains("[Paint_DrawChar_CN] font lib start")) { fontObject = new FontObject(); fontObjects.add(fontObject); //将字符串去掉头 line = line.replace("[Paint_DrawChar] font lib start", ""); line = line.replace("[Paint_DrawChar_CN] font lib start", ""); //按照逗号隔开 // String[] lineArray = line.split(","); // 解析fontEncoding和encoding pattern = Pattern.compile("\\[(\\S+) = (0x[\\da-fA-F]+(?:\\s+0x[\\da-fA-F]+)*)\\]"); matcher = pattern.matcher(line); if (matcher.find()) { // 解析fontEncoding fontObject.setFontEncoding(matcher.group(1)); // 解析encoding fontObject.setEncoding(matcher.group(2).replace("0x", "").replace(" ", "")); } // 解析type pattern = Pattern.compile("\\[type\\s=\\s(.*?)\\]"); matcher = pattern.matcher(line); if (matcher.find()) { fontObject.setType(matcher.group(1)); } // 解析fontWidth和fontHeight pattern = Pattern.compile("width=\\s(.*?)\\s,\\sheight=\\s(.*?)\\s"); matcher = pattern.matcher(line); if (matcher.find()) { fontObject.setFontWidth(Integer.parseInt(matcher.group(1))); fontObject.setFontHeight(Integer.parseInt(matcher.group(2))); } } else if (line.contains("font lib end!!")) { fontObject = null; } else if (fontObject != null) { // 解析hexArrays pattern = Pattern.compile("(0x[\\da-fA-F]+)\\s"); matcher = pattern.matcher(line); while (matcher.find()) { fontObject.addHexArray(matcher.group(1)); } } } } catch (IOException e) { e.printStackTrace(); } return fontObjects; } /** * 转换为完整的一维的二进制 * * @param hexStrings * @return */ private int[] convertToBinaryArray(List hexStrings) { int numRows = hexStrings.size(); int[] binaryArray = new int[numRows * 8]; for (int i = 0; i < numRows; i++) { String hexString = hexStrings.get(i); int decimalValue = Integer.parseInt(hexString.substring(2), 16); String binaryString = String.format("%8s", Integer.toBinaryString(decimalValue)).replace(' ', '0'); for (int j = 0; j < 8; j++) { binaryArray[i * 8 + j] = Integer.parseInt(String.valueOf(binaryString.charAt(j))); } } return binaryArray; } /** * 转换为指定像素的二进制 * * @param hexStrings * @param fontWidth * @param fontHeight * @return */ private int[][] convertToBinaryArray(List hexStrings, int fontWidth, int fontHeight) { int[] binaryArray1 = convertToBinaryArray(hexStrings); //System.out.println("该字体的完整的2进制点阵: "+ Arrays.toString(binaryArray1)); int[][] binaryArray = new int[fontHeight][fontWidth]; //获取每行的点数 int pooints = fontWidth / 8; if (fontWidth % 8 > 0) { pooints = pooints + 1; } //先转换为完整二进制 for (int i = 0; i < fontHeight; i++) { for (int j = 0; j < fontWidth; j++) { binaryArray[i][j] = binaryArray1[i * pooints * 8 + j]; } } return binaryArray; } /** * 获取单个字体的点阵数组 * * @param encoding 文本编码 * @param font 文本的字体大小 * @return */ public int[][] getSingleFontBinaryArray(String encoding, int font) { try { List myFontList = new ArrayList<>(); List myFontList2 = new ArrayList<>(); List myFontList3 = new ArrayList<>(); if (fontMap.containsKey(encoding)) { myFontList3.addAll(fontMap.get(encoding)); } if (encoding.length() <= 2) { if (fontMap.containsKey("00" + encoding)) { myFontList3.addAll(fontMap.get("00" + encoding)); } } //过滤掉无效的字库 即内容为空的 if (!"20".equals(encoding)) { myFontList2 = myFontList3.stream().filter( value -> !value.getHexArrays().stream().allMatch(s -> s.equals("0x00")) ).collect(Collectors.toList()); } else { myFontList2 = myFontList3; } myFontList = myFontList2; if (myFontList.isEmpty()) { System.out.println("没有找到对应的字库编码 : " + encoding); return null; } //获取第一个 FontObject fontObject = null; FontObject miniFontObject = myFontList.get(0);//最小字体 FontObject multipleFontObject = null;//适合的倍数字体 for (FontObject fontObject1 : myFontList) { if (fontObject1.getFontWidth() == font) { fontObject = fontObject1; break; } if (fontObject1.getFontWidth() < miniFontObject.getFontWidth()) { miniFontObject = fontObject1; } if (font % fontObject1.getFontWidth() == 0) { //使用最大的放大 if (multipleFontObject == null || multipleFontObject.getFontHeight() <= fontObject1.getFontWidth()) { multipleFontObject = fontObject1; } } } if (fontObject == null) { if (multipleFontObject != null) { fontObject = multipleFontObject; } else { fontObject = miniFontObject; } } List hexArrays = fontObject.getHexArrays(); return convertToBinaryArray(hexArrays, fontObject.getFontWidth(), fontObject.getFontHeight()); } catch (Exception e) { e.printStackTrace(); } return null; } }