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

org.docx4j.spring.boot.event.linstener.ApplicationReadyFontMapperistener Maven / Gradle / Ivy

There is a newer version: 2.7.x.20241003.RELEASE
Show newest version
package org.docx4j.spring.boot.event.linstener;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.docx4j.fonts.BestMatchingMapper;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFont;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.spring.boot.Docx4jAutoConfiguration;
import org.docx4j.spring.boot.Docx4jProperties;
import org.docx4j.spring.boot.utils.StringUtils;
import org.docx4j.template.fonts.FontMapperHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.CollectionUtils;

public class ApplicationReadyFontMapperistener
		implements ApplicationListener, ResourceLoaderAware {

	protected static Logger LOG = LoggerFactory.getLogger(Docx4jAutoConfiguration.class);
	protected ResourceLoader resourceLoader;
	protected final Docx4jProperties docx4jProperties;
	
	public ApplicationReadyFontMapperistener(Docx4jProperties docx4jProperties) {
		this.docx4jProperties  = docx4jProperties;
	}

	@Override
	public void onApplicationEvent(ApplicationReadyEvent event) {
		if(docx4jProperties.isDiscoverFonts()) {
			// 使用独立线程初始化字体信息
			new Thread() {
				
				@Override
				public void run() {
					try {

						// Set up font mapper (optional)

						// example of mapping font Times New Roman which doesn't have certain Arabic
						// glyphs
						// eg Glyph "ي" (0x64a, afii57450) not available in font
						// "TimesNewRomanPS-ItalicMT".
						// eg Glyph "ج" (0x62c, afii57420) not available in font
						// "TimesNewRomanPS-ItalicMT".
						// to a font which does
						PhysicalFonts.get("Arial Unicode MS");

						final String osName = System.getProperty("os.name");
						if (osName.startsWith("Windows")) {
							/*
							 * 
							 * This mapper automatically maps document fonts for which the exact font is
							 * physically available. Think of this as an identity mapping. For this reason,
							 * it will work best on Windows, or a system on which Microsoft fonts have been
							 * installed. (此映射器自动映射确切可用的文档字体,将此视为标识映射;基于这个原因,它在Windows系统或安装了微软字体库的系统运行的更好。)
							 * You can manually add your own additional mappings if you wish.
							 * 如果需要,你可以手动添加自己的字体映射
							 * 
							 * 1、 自动检测系统上可用的字体 PhysicalFonts.discoverPhysicalFonts();
							 * 
							 */
							Mapper fontMapper = new IdentityPlusMapper();
							defaultFontMapper(fontMapper);
							customFontMapper(fontMapper, docx4jProperties.getFontMapper());
							FontMapperHolder.setFontMapper(fontMapper);
						} else {
							/*
							 * This mapper uses Panose to guess the physical font which is a closest fit for
							 * the font used in the document. (这个映射器使用Panose算法猜测最适合这个文档使用的物理字体。)
							 * 
							 * Panose是一种依照字体外观来进行分类的方法。我们可以通过PANOSE体系将字体的外观特征进行整理,并且与其它字体归类比较。
							 * Panose的原形在1985年由Benjamin
							 * Bauermeister开发,当时一种字体由7位16进制数字定义,现在则发展为10位,也就是字体的十种特征。这每一位数字都给出了它定义的一种视觉外观的量度
							 * ,如笔划的粗细或是字体衬线的样式等。 Panose定义的范围:Latin Text,Latin Script,Latin
							 * Decorative,Iconographic,Japanese Text,Cyrillic Text,Hebrew。
							 * 
							 * It is most likely to be suitable on Linux or OSX systems which don't have
							 * Microsoft's fonts installed. (它很可能适用于没有安装Microsoft字体的Linux或OSX系统。)
							 * 
							 * 1、获取Microsoft字体我们需要这些:a.在Microsoft平台上,嵌入PDF输出; b. docx4all - 所有平台 - 填充字体下拉列表
							 * setupMicrosoftFontFilenames(); 2、 自动检测系统上可用的字体
							 * PhysicalFonts.discoverPhysicalFonts();
							 * 
							 */
							Mapper fontMapper = new BestMatchingMapper();
							defaultFontMapper(fontMapper);
							customFontMapper(fontMapper, docx4jProperties.getFontMapper());
							FontMapperHolder.setFontMapper(fontMapper);
						}

					} catch (Exception e) {
					}
				};
			}.start();
		}
	}

	protected void customFontMapper(Mapper fontMapper, Map fontMap) {
		if (CollectionUtils.isEmpty(fontMap)) {
			return;
		}
		// 遍历自定义的字体库信息
		Iterator> ite = fontMap.entrySet().iterator();
		while (ite.hasNext()) {

			Entry entry = ite.next();

			try {
				// 获取字体库
				PhysicalFont physicalFont = PhysicalFonts.get(entry.getKey());
				if (physicalFont == null) {
					// 加载字体文件(解决linux环境下无中文字体问题)
					Resource resource = resourceLoader.getResource(entry.getValue());
					if (resource.exists()) {
						PhysicalFonts.addPhysicalFonts(entry.getKey(), resource.getURI());
					}
					LOG.debug("Add PhysicalFont " + entry.getKey());
				}

				// 设置字体名对应的字体库
				fontMapper.put(entry.getKey(), physicalFont);
				// 设置字体别名对应的字体库,支持多个别名
				String fontAliasArr = docx4jProperties.getFontAliasMapper().get(entry.getKey());
				if (StringUtils.hasText(fontAliasArr)) {
					for (String fontAlias : StringUtils.tokenizeToStringArray(fontAliasArr)) {
						fontMapper.put(fontAlias, physicalFont);
					}
				}

			} catch (Exception e) {
				LOG.debug("Add PhysicalFont Fail : Ingore");
			}

		}

	}

	protected void defaultFontMapper(Mapper fontMapper) {

		// 进行中文字体兼容处理
		fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
		fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
		fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
		fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
		fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
		fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
		fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
		fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
		fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
		fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
		fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
		fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
		fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
		fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
		
	}

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy