字体子集化实践探索
最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试
方案一:node.js做子集化
fontmin 缺点是也需要集成node环境,很多网络下载的字体都不支持
方案二:python做子集化
fontTools库的subset工具,兼容性最好的子集化工具,参数也最丰富
缺点:需要软件集成mini python环境,在低端电脑执行速度特别慢
pip install fonttools
可以直接用命令行执行
pyftsubset 原始字体文件路径 --text=需要保留的字符 --output-file=输出子集字体文件路径
完整的参数使用查看源码
from fontTools.subset import subsetdef create_font_subset(input_font, output_font, characters):subset_options = {'glyphs': characters}subset(input_font, output_font, subset_options)input_font_path = 'path/to/input_font.ttf'
output_font_path = 'path/to/output_font.ttf'
characters_to_include = 'abcdefghijklmnopqrstuvwxyz'create_font_subset(input_font_path, output_font_path, characters_to_include)
方案三:C#做子集化
Microsoft.Extensions.FontSubset 库
using System;
using System.IO;
using Microsoft.Extensions.FontSubset;class Program
{static void Main(string[] args){string fontPath = "path/to/font.ttf"; // 字体文件路径string[] characters = new string[] { "A", "B", "C" }; // 需要包含在子集中的字符列表string outputPath = "output.ttf"; // 输出文件路径using (FileStream outputStream = File.Create(outputPath)){FontSubset.BuildSubset(fontPath, characters, outputStream);}}
}
有一个fontsubset已经编译好可以直接用
fontsubset-console -c <字符集目录> -r <字符集文件匹配规则> -a -s <输入字体文件> <输出的字体文件>
方案四:java做子集化
拷贝了一个韩国人的项目,放到自己的仓库
启动一个java http服务,通过入参生成子集,第一次要400ms左右,后面执行越来越快几十ms
缺点:生成的字体仍然有1.3M;需要集成jre环境;放弃
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.FontSubsetGenerator;import java.io.IOException;public class SubFontByItextPdf {public static boolean subFont(String sourceFontFile, String destFontFile, String text) {long startTime = System.currentTimeMillis();try {String path = FontSubsetGenerator.GEN(sourceFontFile, destFontFile, text);System.out.println("result: "+path);} catch (DocumentException e) {e.printStackTrace();System.out.println("error");return false;} catch (IOException e) {System.out.println("error");e.printStackTrace();return false;}System.out.println("cost" + (System.currentTimeMillis() - startTime) + "ms");System.out.println("done");return true;}
}
方案五:用harfbuzz的工具类hb-subset
调用命令行直接执行,下载地址
hb-subset.exe --output-file=dest.otf C:\source.otf 你好呀
执行速度很快,字体子集化结果也比较理想
参数使用查看源码,也可以hb-subset.exe --help-all
查看所有参数
相关文章:
字体子集化实践探索
最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试 方案一:node.js做子集化 fontmin 缺点是也需要集…...

A1017 基于Java+JSP+SQL Server+servlet的二手购物平台的设计与实现
二手购物平台 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 摘 要 计算机以及网络技术的飞速发展,网络的应用在全国乃至全球日益普及,随着人们的思想水平和生活水平的提高,网络已经是人们必不可少的一部分。人们的…...

Simdroid-EC:液冷仿真新星,助力新能源汽车电机控制器高效散热
近年来,新能源电动车的销量呈现出快速增长的态势。据统计,2024 年1-10月中国新能源汽车销量达728万辆,同比增长37.8%。 电机控制器在新能源汽车中对于保障动力和安全性能扮演着至关重要的角色,其核心部件IGBT(绝缘栅双…...

C语言——实现并求出两个数的最大公约数
问题描述:求出两个数的最大公约数 //求两个数的最大公约数 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<time.h>int main() {int a,b;printf("请您输入两个数 a 和 b\n");scanf…...

今天你学C++了吗?——C++中的类与对象(日期类的实现)——实践与知识的碰撞❤
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...

享元模式的理解和实践
在软件开发中,性能优化是一个永恒的话题。在追求高性能的过程中,减少内存的使用是一项重要的任务。享元模式(Flyweight Pattern)就是一种用于减少内存使用量的设计模式,它特别适用于存在大量重复对象的场景。本文将详细…...
Unreal Engine 中的UI界面开发
推荐的使用方式 轻量级 HUD:使用 Canvas 绘制简单的文本、调试信息或基础 UI(如准星、血量条等)。 复杂 UI:使用 UMG(Unreal Motion Graphics)和 Slate 进行布局和交互,避免手动管理 Canvas 绘制。 避免遮挡场景:仅绘制必要的内容,并利用透明度(如 FLinearColor(1, 1…...

Docker在Ubuntu和CentOS系统下的安装
目录 1. 各版本平台支持情况2. 在Ubuntu系统下安装docker3. 常见报错4. Docker的镜像源修改5. Docker目录修改6. 在CentOS系统下安装docker 1. 各版本平台支持情况 (1)平台支持情况如下: Server 版本 桌面版本 2. 在Ubuntu系统下安装docker…...

EXCEL 关于plot 折线图--频度折线图的一些细节
目录 0 折线图有很多 1 频度折线图 1.1 直接用原始数据做的频度折线图 2 将原始数据生成数据透视表 3 这样可以做出了,频度plot 4 做按某字段汇总,成为累计plot分布 5 修改上面显示效果,做成百分比累计plot频度分布 0 折线图有很多 这…...

Hive操作案例
目录 idea/dg远程连接导入数据建表数据导入 idea/dg远程连接 hive的详细安装不多展示,自行搜索即可。 依次启动zookeeper,hadoop 在zookeeper的节点上启动如下指令(我的是1个主节点和2个备用节点) 启动Hive的metastore࿰…...

C++ 内存管理和模板与STL
此篇目是之后各种C库的基础 目录 内存管理 内存分布 内存管理方式 new和delete operator new 与 operator delete函数 实现原理 定位new表达式(placement-new) 模板基础 泛型编程 模板 函数模板 类模板 STL 组成部分 内存管理 内存分布 int globalVar 1; //全局变量 静…...

JDK8新特性:Stream
JDK8最大的改变: 1. lambda表达式 2. Stream 1. Steam流的入门 什么是Stream? 也叫Stream流,是jdk8开始的一套API,用于操作集合或者数组中的数据 优点: Stream流大量结合了Lambda的语法风格来创建,提…...

前端传入Grule,后端保存到 .grl 文件中
前端传入Grule,后端保存到 .grl 文件中 通过简单的输入框,将Grule的部分拆解成 规则名称 规则描述 规则优先级 规则条件 规则逻辑Grule关键字 when Then 模拟了 if 判断的条件和逻辑部分 类似于 shell 和 ruby 之类的脚本语言,有 then 关键字…...

探索《Crypto Rumble》 游戏:经济模型篇
《Crypto Rumble》是一款基于 Zypher Network 游戏引擎打造的卡牌 RPG三消品类的 Web3 游戏,通过引人入胜的游戏设计以及轻量化的游戏玩法,《Crypto Rumble》不仅能够为玩家带来引人入胜的沉浸式游戏体验,同时基于 AI Bot 的游戏编辑器&#…...

【CSS in Depth 2 精译_072】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(上):究竟该用 em 还是 px
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 ✔️ 12.1.1 使用 em 还是 px ✔️12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 文章目录 第 12 章 排版与间距…...
Elasticsearch对象映射
Spring Data Elasticsearch对象映射是将Java对象(域实体)映射到存储在Elasticsearchs中的JSON表示形式并返回的过程。内部用于此映射的类是MappingElasticsearchConverter。 元模型对象映射 基于元模型的方法使用域类型信息对Elasticsearch进行读写操作…...
Oracle 19c rac 补丁升级,从19.7 to19.22-集群
1. 补丁包概述 数据库环境 角色 数据库 IP地址 数据库版本 主机名 数据库名称 源端 RAC 172.30.21.166/167 19.7 hfcwdb66/hfcwdb67 hfdb 将以下补丁包上传到/soft下 上传到两个节点的soft目录下:p6880880_190000_Linux-x86-64.zip (更新o…...

机器学习--Kaggle的使用
机器学习–Kaggle的使用 打开Kaggle: Your Machine Learning and Data Science Community并点击Sign In登录账号 kaggle中自带了很多的数据集 在点击Datasets之后,单点Notebook,如果有适用的数据集可以单击Copy and Edit复制其Notebook,之后…...

客户服务新突破,天润融通助力电动车企业实现数智化转型
近年来,两轮电动车成为年轻人喜爱的出行新方式,借着这种潮流,许多新兴品牌迅速发展,并跻身行业头部。 但问题也随之而来,由于业务快速发展,各类服务问题也开始增多。 比如天润融通服务的一家头部两轮电动…...
力扣题目 - 2931.购买物品的最大开销
题目 还需要你前往力扣官网查看详细的题目要求 地址 思路 这边需要你去力扣官网详细查看题目看了题目提供的示例 已经有了解法, 先把values转成1维数组,排序之后进行累加即可 代码 var maxSpending function (values) {let list values.flat();list.sort((a, b) > a - …...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...