All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wiki.xsx.core.pdf.handler.XEasyPdfFontMapperHandler Maven / Gradle / Ivy

package wiki.xsx.core.pdf.handler;

import lombok.SneakyThrows;
import org.apache.fontbox.FontBoxFont;
import org.apache.fontbox.ttf.OpenTypeFont;
import org.apache.fontbox.ttf.TTFParser;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.pdfbox.pdmodel.font.*;
import wiki.xsx.core.pdf.doc.XEasyPdfDefaultFontStyle;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * pdf字体映射助手
 *
 * @author xsx
 * @date 2022/6/20
 * @since 1.8
 * 

* Copyright (c) 2020-2023 xsx All Rights Reserved. * x-easypdf is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. * You may obtain a copy of Mulan PSL v1 at: * http://license.coscl.org.cn/MulanPSL * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR * PURPOSE. * See the Mulan PSL v1 for more details. *

*/ public class XEasyPdfFontMapperHandler implements FontMapper { /** * 字体名称映射字典 */ private static final ConcurrentHashMap FONT_NAME_MAPPING = new ConcurrentHashMap<>(16); /** * 字体路径映射字典 */ private static final ConcurrentHashMap FONT_PATH_MAPPING = new ConcurrentHashMap<>(16); /** * 默认字体名称 */ private static final String DEFAULT_FONT_NAME = XEasyPdfDefaultFontStyle.NORMAL.getName(); /** * 字体映射助手实例 */ private static final XEasyPdfFontMapperHandler INSTANCE = new XEasyPdfFontMapperHandler(); /** * 有参构造 */ private XEasyPdfFontMapperHandler() { // 初始化 this.init(XEasyPdfDefaultFontStyle.LIGHT, XEasyPdfDefaultFontStyle.NORMAL, XEasyPdfDefaultFontStyle.BOLD); } /** * 获取字体映射实例 * * @return 返回字体映射实例 */ public static XEasyPdfFontMapperHandler getInstance() { return INSTANCE; } /** * 添加字体 * * @param fontPath 字体路径 * @param font 字体 */ @SneakyThrows public void addFont(String fontPath, TrueTypeFont font) { FONT_NAME_MAPPING.putIfAbsent(font.getName(), font); Optional.ofNullable(this.getFontAliases(font.getName())).ifPresent(name -> FONT_NAME_MAPPING.putIfAbsent(name, font)); FONT_PATH_MAPPING.putIfAbsent(fontPath, font); } /** * 根据字体路径获取字体 * * @param fontPath 字体路径 * @return 返回字体 */ @SneakyThrows public FontBoxFont getFontByPath(String fontPath) { return FONT_PATH_MAPPING.get(fontPath); } /** * 获取ttf字体 * * @param baseFont 字体名称 * @param fontDescriptor 字体描述 * @return 返回ttf字体 */ @Override public FontMapping getTrueTypeFont(String baseFont, PDFontDescriptor fontDescriptor) { // 查找字体 TrueTypeFont ttf = (TrueTypeFont) this.findFont(baseFont); // 如果字体不为空,则返回字体 if (ttf != null) { // 返回字体 return new FontMapping<>(ttf, false); } // 返回默认字体 return new FontMapping<>((TrueTypeFont) FONT_NAME_MAPPING.get(DEFAULT_FONT_NAME), true); } /** * 获取字体 * * @param baseFont 字体名称 * @param fontDescriptor 字体描述 * @return 返回字体 */ @Override public FontMapping getFontBoxFont(String baseFont, PDFontDescriptor fontDescriptor) { // 查找字体 FontBoxFont font = this.findFont(baseFont); // 如果字体不为空,则返回字体 if (font != null) { // 返回字体 return new FontMapping<>(font, false); } // 返回默认字体 return new FontMapping<>(FONT_NAME_MAPPING.get(DEFAULT_FONT_NAME), true); } /** * 获取字体CID信息 * * @param baseFont 字体名称 * @param fontDescriptor 字体描述 * @param cidSystemInfo CID系统信息 * @return 返回字体CID信息 */ @Override public CIDFontMapping getCIDFont(String baseFont, PDFontDescriptor fontDescriptor, PDCIDSystemInfo cidSystemInfo) { // 查找字体 FontBoxFont font = this.findFont(baseFont); // 如果字体为otf类型,则返回otf类型信息 if (font instanceof OpenTypeFont) { // 返回otf类型信息 return new CIDFontMapping((OpenTypeFont) font, null, false); } // 如果字体为ttf类型,则返回ttf类型信息 if (font instanceof TrueTypeFont) { // 返回ttf类型信息 return new CIDFontMapping(null, font, false); } // 返回默认字体类型信息 return new CIDFontMapping(null, FONT_NAME_MAPPING.get(DEFAULT_FONT_NAME), true); } /** * 初始化 * * @param styles 字体样式 */ private void init(XEasyPdfDefaultFontStyle... styles) { // 遍历字体样式 for (XEasyPdfDefaultFontStyle style : styles) { // 初始化输入流(从资源路径读取) try (InputStream inputStream = new BufferedInputStream(XEasyPdfFontMapperHandler.class.getResourceAsStream(style.getPath()))) { // 解析字体 TrueTypeFont font = new TTFParser(true, true).parse(inputStream); // 添加字体 this.addFont(style.getPath(), font); } catch (IOException e) { // 提示异常信息 throw new RuntimeException(e); } } // 初始化字体映射 this.initFontMapper(); } /** * 初始化字体映射 */ private void initFontMapper() { // 获取字体映射策略 String fontMappingPolicy = System.getProperty( XEasyPdfHandler.FontMappingPolicy.key(), XEasyPdfHandler.FontMappingPolicy.DEFAULT.name() ); // 如果字体映射策略为默认,则设置字体映射 if (fontMappingPolicy.equals(XEasyPdfHandler.FontMappingPolicy.DEFAULT.name())) { // 设置字体映射 FontMappers.set(this); } } /** * 查找字体 * * @param postScriptName 字体名称 * @return 返回字体 */ private FontBoxFont findFont(String postScriptName) { // 如果字体名称为空,则返回空 if (postScriptName == null) { // 返回空 return null; } // 获取字体 FontBoxFont info = this.getFont(postScriptName); // 如果字体不为空,则返回字体 if (info != null) { // 返回字体 return info; } // 重新获取字体(替换字体名称,移除“-”) info = this.getFont(postScriptName.replace("-", "")); // 如果字体不为空,则返回字体 if (info != null) { // 返回字体 return info; } // 重新获取字体(替换字体名称,替换“,”为“-”) info = this.getFont(postScriptName.replace(',', '-')); // 如果字体不为空,则返回字体 if (info != null) { // 返回字体 return info; } // 重新获取字体(替换字体名称,添加“-Regular”) info = this.getFont(postScriptName + "-Regular"); // 如果字体不为空,则返回字体 if (info != null) { // 返回字体 return info; } // 替换字体名称,去除空格 String finalName = postScriptName.replaceAll(" ", ""); // 重新获取字体(替换字体名称,去除空格) info = this.getFont(finalName); // 如果字体不为空,则返回字体 if (info != null) { // 返回字体 return info; } String mappedName = Standard14Fonts.getMappedName(finalName); if (mappedName != null) { // 返回字体 return FONT_NAME_MAPPING.get(mappedName); } // 返回字体 return null; } /** * 查找字体名称 * * @param postScriptName 字体名称 * @return 返回字体名称 */ private String getFontAliases(String postScriptName) { // 如果字体名称为空,则返回空 if (postScriptName == null) { // 返回空 return null; } // 返回字体名称 return Standard14Fonts.getMappedName(postScriptName.replaceAll(" ", "")); } /** * 获取字体 * * @param postScriptName 字体名称 * @return 返回字体 */ private FontBoxFont getFont(String postScriptName) { // 如果字体名称包含“+”,则截取子集名称 if (postScriptName.contains("+")) { // 重置字体名称(截取子集名称) postScriptName = postScriptName.substring(postScriptName.indexOf('+') + 1); } // 获取字体 return FONT_NAME_MAPPING.get(postScriptName); } /** * 14种标准字体 */ private static class Standard14Fonts { /** * 别名 */ private static final Map ALIASES = new HashMap<>(100); static { mapName("Courier-Bold"); mapName("Courier-BoldOblique"); mapName("Courier"); mapName("Courier-Oblique"); mapName("Helvetica"); mapName("Helvetica-Bold"); mapName("Helvetica-BoldOblique"); mapName("Helvetica-Oblique"); mapName("Symbol"); mapName("Times-Bold"); mapName("Times-BoldItalic"); mapName("Times-Italic"); mapName("Times-Roman"); mapName("ZapfDingbats"); mapName("CourierCourierNew", "Courier"); mapName("CourierNew", "Courier"); mapName("CourierNewPSMT", "Courier"); mapName("LiberationMono", "Courier"); mapName("NimbusMonL-Regu", "Courier"); mapName("CourierNew,Italic", "Courier-Oblique"); mapName("CourierNewPS-ItalicMT", "Courier-Oblique"); mapName("CourierNew-Italic", "Courier-Oblique"); mapName("LiberationMono-Italic", "Courier-Oblique"); mapName("NimbusMonL-ReguObli", "Courier-Oblique"); mapName("CourierNew,Bold", "Courier-Bold"); mapName("CourierNewPS-BoldMT", "Courier-Bold"); mapName("CourierNew-Bold", "Courier-Bold"); mapName("LiberationMono-Bold", "Courier-Bold"); mapName("NimbusMonL-Bold", "Courier-Bold"); mapName("CourierNew,BoldItalic", "Courier-BoldOblique"); mapName("CourierNewPS-BoldItalicMT", "Courier-BoldOblique"); mapName("LiberationMono-BoldItalic", "Courier-BoldOblique"); mapName("NimbusMonL-BoldObli", "Courier-BoldOblique"); mapName("Arial", "Helvetica"); mapName("ArialMT", "Helvetica"); mapName("LiberationSans", "Helvetica"); mapName("NimbusSanL-Regu", "Helvetica"); mapName("Arial,Italic", "Helvetica-Oblique"); mapName("Arial-ItalicMT", "Helvetica-Oblique"); mapName("Arial-Italic", "Helvetica-Oblique"); mapName("Helvetica-Italic", "Helvetica-Oblique"); mapName("LiberationSans-Italic", "Helvetica-Oblique"); mapName("NimbusSanL-ReguItal", "Helvetica-Oblique"); mapName("Arial,Bold", "Helvetica-Bold"); mapName("Arial-BoldMT", "Helvetica-Bold"); mapName("Arial-Bold", "Helvetica-Bold"); mapName("LiberationSans-Bold", "Helvetica-Bold"); mapName("NimbusSanL-Bold", "Helvetica-Bold"); mapName("Arial,BoldItalic", "Helvetica-BoldOblique"); mapName("Arial-BoldItalicMT", "Helvetica-BoldOblique"); mapName("Helvetica-BoldItalic", "Helvetica-BoldOblique"); mapName("LiberationSans-BoldItalic", "Helvetica-BoldOblique"); mapName("NimbusSanL-BoldItal", "Helvetica-BoldOblique"); mapName("TimesNewRoman", "Times-Roman"); mapName("TimesNewRomanPSMT", "Times-Roman"); mapName("TimesNewRoman", "Times-Roman"); mapName("TimesNewRomanPS", "Times-Roman"); mapName("LiberationSerif", "Times-Roman"); mapName("NimbusRomNo9L-Regu", "Times-Roman"); mapName("TimesNewRoman,Italic", "Times-Italic"); mapName("TimesNewRomanPS-ItalicMT", "Times-Italic"); mapName("TimesNewRomanPS-Italic", "Times-Italic"); mapName("TimesNewRoman-Italic", "Times-Italic"); mapName("LiberationSerif-Italic", "Times-Italic"); mapName("NimbusRomNo9L-ReguItal", "Times-Italic"); mapName("TimesNewRoman,Bold", "Times-Bold"); mapName("TimesNewRomanPS-BoldMT", "Times-Bold"); mapName("TimesNewRomanPS-Bold", "Times-Bold"); mapName("TimesNewRoman-Bold", "Times-Bold"); mapName("LiberationSerif-Bold", "Times-Bold"); mapName("NimbusRomNo9L-Medi", "Times-Bold"); mapName("TimesNewRoman,BoldItalic", "Times-BoldItalic"); mapName("TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic"); mapName("TimesNewRomanPS-BoldItalic", "Times-BoldItalic"); mapName("TimesNewRoman-BoldItalic", "Times-BoldItalic"); mapName("LiberationSerif-BoldItalic", "Times-BoldItalic"); mapName("NimbusRomNo9L-MediItal", "Times-BoldItalic"); mapName("Symbol,Italic", "Symbol"); mapName("Symbol,Bold", "Symbol"); mapName("Symbol,BoldItalic", "Symbol"); mapName("Symbol", "Symbol"); mapName("SymbolMT", "Symbol"); mapName("StandardSymL", "Symbol"); mapName("ZapfDingbatsITCbyBT-Regular", "ZapfDingbats"); mapName("ZapfDingbatsITC", "ZapfDingbats"); mapName("Dingbats", "ZapfDingbats"); mapName("MS-Gothic", "ZapfDingbats"); mapName("Times", "Times-Roman"); mapName("Times,Italic", "Times-Italic"); mapName("Times,Bold", "Times-Bold"); mapName("Times,BoldItalic", "Times-BoldItalic"); mapName("ArialMT", "Helvetica"); mapName("Arial-ItalicMT", "Helvetica-Oblique"); mapName("Arial-BoldMT", "Helvetica-Bold"); mapName("Arial-BoldItalicMT", "Helvetica-BoldOblique"); } /** * 映射名称 * * @param baseName 基础名称 */ private static void mapName(String baseName) { ALIASES.put(baseName, baseName); } /** * 映射名称 * * @param alias 别名 * @param baseName 基础名称 */ private static void mapName(String alias, String baseName) { ALIASES.put(alias, baseName); } /** * 获取映射名称 * * @param fontName 字体名称 * @return 返回映射名称 */ public static String getMappedName(String fontName) { return ALIASES.get(fontName); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy