检验Pdfsharp.dll 支持的语言及对应的字体

文章目录

    • 检验所支持语言的字体
    • 使用字体绘制文本并显示

PdfSharp 语言和字体的支持有限,有时候再本地电脑上能正常显示文本,但在其它电脑上就显示乱码或一个正方体,或??。不同操作系统可能自带的字体本身就不一样,可能中文系统有的,英文系统没有,这就导致文本显示有问题。

检验所支持语言的字体

根据 PdfSharp对中文字体支持及排版格式的调整这篇文章,修改源码,做的一个小工具。

首先是源码的修改

PdfSharp 1.5版本 在github上的源码:https://github.com/empira/PDFsharp-1.5

PdfSharp 1.5版本 在sourceforge上的源码 https://sourceforge.net/projects/pdfsharp/files/pdfsharp/

通过阅读源码,最终在PdfSharp.Fonts.CMapInfo的AddChars方法里找到了解决方案,AddChars方法内部在添加字符的时候会调用OpenTypeDescriptor.CharCodeToGlyphIndex方法将unicode字符映射到相应glyph的索引上,如果映射的索引为0,则说明该字符使用的字体在pdfSharp是不支持的,那么我们就可以通过遍历映射结果字典CharacterToGlyphIndex,只要字典值里有任何一个0值就说明提供的文本在该字体上有不被支持的字符,一旦被打印就会有乱码出现,这时就需要换一种字体来显示了。 (PS, 该段文字来自其他博文的引用)

PdfSharp.Fonts.CMapInfo类中的AddChars方法,源码如下:

        /// <summary>
        /// Adds the characters of the specified string to the hashtable.
        /// </summary>
        public void AddChars(string text)
        {
            if (text != null)
            {
                bool symbol = _descriptor.FontFace.cmap.symbol;
                int length = text.Length;
                for (int idx = 0; idx < length; idx++)
                {
                    char ch = text[idx];
                    if (!CharacterToGlyphIndex.ContainsKey(ch))
                    {
                        char ch2 = ch;
                        if (symbol)
                        {
                            // Remap ch for symbol fonts.
                            ch2 = (char)(ch | (_descriptor.FontFace.os2.usFirstCharIndex & 0xFF00));  // @@@ refactor
                        }

                        //glyphIndex = 0 时说明该字符不被PdfSharp支持
                        int glyphIndex = _descriptor.CharCodeToGlyphIndex(ch2);
                        CharacterToGlyphIndex.Add(ch, glyphIndex);
                        GlyphIndices[glyphIndex] = null;
                        MinChar = (char)Math.Min(MinChar, ch);
                        MaxChar = (char)Math.Max(MaxChar, ch);
                    }
                }
            }
        }

现在我们在PdfSharp.Drawing XFont 类增加一个IsSupport的方法,判断该字体是否支持字符串的绘制。

        /// <summary>
        /// 该字体是否支持字符串的绘制
        /// </summary>
        /// <param name="font"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public  bool IsSupport( XFont font, string text)
        {
            OpenTypeDescriptor descriptor = FontDescriptorCache.GetOrCreateDescriptorFor(font) as
                 OpenTypeDescriptor;
            int count = 1;
            if (descriptor != null)
            {
                var mapInfo = new CMapInfo(descriptor);
                mapInfo.AddChars(text);
                //CharacterToGlyphIndex是AddChars方法映射结果字典
                var maps = mapInfo.CharacterToGlyphIndex;
                foreach (int x in maps.Values)
                {
                    if (x == 0)
                    {
                        count++;
                        break;
                    }
                }
                // return !maps.Values.Any(x => x == 0);
            }

            if (count == 1)
            {
                return true;
            }
            return false;
        }

使用字体绘制文本并显示

在确保字体可以使用时,使用该字体绘制文本并显示出来看看效果。可使用的字体会显示Ok, 不支持该语言文本的字体则显示NG。
先附上效果图:

在这里插入图片描述
在这里插入图片描述
使用的是修改源码编译后的Pdfsharp.dll, 工程源码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

using PdfSharp;
using PdfSharp.Fonts;
using PdfSharp.Drawing;
using PdfSharp.Pdf;


namespace CheckPdfSharpTextFont
{
    public partial class Form1 : Form
    {
        PdfiumViewer.PdfViewer pdfViewer1;

        public Form1()
        {
            InitializeComponent();

            pdfViewer1 = new PdfiumViewer.PdfViewer();
            this.panel1.Controls.Add(pdfViewer1);
            pdfViewer1.Dock = DockStyle.Fill;

            this.btnCheck.Click += btnCheck_Click;
        }


        /// <summary>
        /// 检测
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCheck_Click(object sender, EventArgs e)
        {
            string text = tbText.Text.Trim();
            if(text.Length < 1)
            {
                text = "ABC789def";
            }
            XFont font = BuildFont(text, 20);
            if (font != null && ckbDrawText.Checked)
            {
                // MessageBox.Show(font.Name);
                BuildPdf(font, text);
            }
        }
     
        /// <summary>
        /// 创建检测字体
        /// </summary>
        /// <param name="text"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public XFont BuildFont(string text, double size)
        {
            XFont font = null;

            string str = tbFont.Text;

            var fontFamilies = str.Split(',');
            foreach (var name in fontFamilies)
            {
                try
                {
                    font = new XFont(name, size, XFontStyle.Regular);
                    if (font.IsSupport(font, text))
                    {
                        tbResult.Text = ("Ok: " + name);
                    }
                    else
                    {
                        tbResult.Text = ("NG: " + name);
                    }
                }
                catch { tbResult.Text = ("NG: " + name); }
            }

            return font;
        }


        //创建PDF文档
        private void BuildPdf(XFont font, string text)
        {
            //创建PDF文档
            PdfDocument doc = new PdfDocument();

            //创建空白页
            PdfPage page = doc.AddPage();

            //设置纸张大小
            page.Size = PageSize.A4;

            //设置一个画布
            XGraphics gfx = XGraphics.FromPdfPage(page);

            

            //绘制文本
            for(int i=0; i<5; i++)
            {
                gfx.DrawString(font.Name + ":  " + text, font, XBrushes.DarkSlateGray, 0, 30 + i * 40);
            }
           
            MemoryStream stream = new MemoryStream();
            //将Pdf保存为数据流
            doc.Save(stream);

            //加载PDF文件
            pdfViewer1.Document = PdfiumViewer.PdfDocument.Load(stream);
        }

      
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152694.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode2-两数相加

大佬解法 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val x; }* }*/ class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode pre new ListNode(0);ListNo…

ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION packages field missing or empty

vue执行 pnpm install命令时&#xff0c;报 ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION  packages field missing or empty错&#xff0c;在网上查询了很久&#xff0c;也没有传出来结果&#xff0c;最后发现是pnpm的版本不对引起的。 我先执行的是npm install -g pnpm&…

口袋参谋:如何找竞争小,优势大的蓝海词?

​ 作为淘宝天猫的中小卖家&#xff0c;99.99%的人都知道流量对于店铺的重要性&#xff0c;如果没有流量的话&#xff0c;店铺是肯定没有销量的。 提高流量的方式有很多种&#xff0c;比如优化宝贝图片、标题、关键词等&#xff0c;由于在淘宝天猫上同一宝贝的竞争力太大了…

成果分享丨学生学徒“行业”+大数据模型分享

学生学徒 阶段成果分享 为进一步提升学生学徒制学员的技术水平&#xff0c;增强学员的企业项目应用能力&#xff0c;助力学员全面发展。自学徒制开展以来&#xff0c;泰迪指导学员完成多项企业应用项目&#xff0c;开展多次项目经验分享交流&#xff0c;让学员在实践中不断学…

蘑菇街获得mogujie商品详情 API 返回值说明

速卖通API接口是速卖通平台提供的一种数据交换接口&#xff0c;可以帮助卖家快速获取平台上的商品信息、订单信息、用户信息等数据&#xff0c;以便在自己的应用程序中进行展示、管理或分析。 速卖通API接口可以通过以下步骤进行使用&#xff1a; 注册速卖通账号并获取API密钥…

如何将本地Portainer管理界面结合cpolar内网穿透工具实现远程浏览器访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

内网穿透的应用-通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

软件开发选择个人好?还是公司好?一篇文章带你了解

随着科技的发展&#xff0c;软件开发已成为一个相对复杂的行业&#xff0c;需要专业的技能和经验来保证项目的成功。然而&#xff0c;一些企业或个人可能会选择个人开发者进行软件开发&#xff0c;虽然这种选择可能会带来一些弊端。本文将探讨选择个人开发者进行软件开发的弊端…

分区格式化后的数据恢复指南,从此不再丢失重要数据

在日常生活中&#xff0c;我们使用电脑时&#xff0c;可能会因为种种原因需要对硬盘进行分区格式化。分区格式化是一种对硬盘进行重新划分存储空间的过程&#xff0c;它将删除该分区的所有数据&#xff0c;使其恢复到初始状态。然而&#xff0c;在执行分区格式化操作之后&#…

服务器数据恢复—VMware虚拟化下误操作导致服务器崩溃的数据恢复案例

服务器故障&分析&#xff1a; VMware虚拟化&#xff0c;vmfs文件系统&#xff0c;共3块磁盘。工作人员误操作将VMware虚拟化重装系统&#xff0c;服务器崩溃。 正常情况下&#xff0c;重装系统会导致文件系统元文件被覆盖。要恢复数据须找到重装系统前的文件系统残留信息并…

【EI会议征稿】第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)

第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#…

深入了解域名与SSL证书的关系

在如今数字化的世界里&#xff0c;网络安全成为我们关注的重要议题之一。为了确保数据在网络上传输的安全性&#xff0c;我们通常会采取各种安全措施&#xff0c;其中最常用的就是SSL证书。然而&#xff0c;很多人并不了解SSL证书是如何与域名相互关联的。 首先&#xff0c;我…

CentOS to 浪潮信息 KeyarchOS 迁移体验与优化建议

浪潮信息KeyarchOS简介 KeyarchOS即云峦操作系统(简称KOS), 是浪潮信息研发的一款面向政企、金融等企业级用户的 Linux 服务器操作系统。它基于Linux内核、龙蜥等开源技术&#xff0c;支持x86、ARM 等主流架构处理器&#xff0c;其稳定性、安全性、兼容性和性能等核心能力均已…

elasticsearch+canal增量、全量同步

目录 一、搭建环境&#xff1a; 1.1 下载软件上传到linux目录/data/soft下 1.2 把所有软件解压到/data/es-cluster 二、单节点&#xff08;多节点同理&#xff09;集群部署elasticsearch 2.1 创建es用户 2.2 准备节点通讯证书 2.3 配置elasticsearch&#xff0c;编辑/d…

Flutter应用-使用sqflite升级数据库

文章目录 问题描述具体做法代码示例更多条件限制升级 数据库迁移和备份简介数据库迁移数据库备份 问题描述 使用fluttter开发的应用程序发布后&#xff0c;发现数据库有些设计不合理。如何来更新数据库呢&#xff1f; 使用sqflite来处理数据库&#xff0c;但是第一版软件发布后…

【Vue3 + webStorm】 求助,vite.config.js代理不生效

求助&#xff0c;vite.config.js代理不生效 上面为代理写法 上面为vue组件中,axios跳转写法 网页控制台一直跳转不到8080端口&#xff0c;请问是为什么&#xff1f;

iframe渲染后端接口文件和实现下载功能

一&#xff1a;什么是iframe&#xff1f; 1、介绍 iframe 是HTML 中的一种标签&#xff0c;全称为 Inline Frame&#xff0c;即内联框架。它可以在网页中嵌入其他页面或文档&#xff0c;将其他页面的内容以框架的形式展示在当前页面中。iframe的使用方式是通过在HTML文档中插入…

opencv(2): 视频采集和录制

视频采集 相关API VideoCapture()cap.read()&#xff1a; 返回两个值&#xff0c;第一个参数&#xff0c;如果读到frame&#xff0c;返回 True. 第二个参数为相应的图像帧。cap.release() VideoCapture cv2.VideoCapture(0) 0 表示自动检测&#xff0c;如果在笔记本上运行&…

CCF-C类 | 仅1个月Accept!中科院2区SCI,Elsevier出版社,审稿快易录用!

【SciencePub学术】本期&#xff0c;小编给大家推荐的是一本CCF-C类、审稿快易录用&#xff0c;且对国人相当友好的SCI期刊&#xff0c;其详情及如下&#xff1a; 期刊简介 IMAGE AND VISION COMPUTING ISSN&#xff1a;0262-8856 E-ISSN&#xff1a;1872-8138 IF&#x…

2023亚太杯数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…