首页 > 编程语言 >C++ PDF PoDoFo库使用教程

C++ PDF PoDoFo库使用教程

时间:2024-07-21 15:27:52浏览次数:13  
标签:0.0 text PoDoFo C++ height path PDF font painter


#include <podofo/podofo.h>
#include <iostream>


// All PoDoFo classes are member of the PoDoFo namespace.
//using namespace std;
using namespace PoDoFo;

PdfFont* getFont(PdfDocument& doc);

// Base14 + other non-Base14 fonts for comparison

static const char* s_base14fonts[] =
{
    "Times-Roman",
    "Times-Italic",
    "Times-Bold",
    "Times-BoldItalic",
    "Helvetica",
    "Helvetica-Oblique",
    "Helvetica-Bold",
    "Helvetica-BoldOblique",
    "Courier",
    "Courier-Oblique",
    "Courier-Bold",
    "Courier-BoldOblique",
    "Symbol",
    "ZapfDingbats",
    "Arial",
    "Verdana"
};

const char* GetBase14FontName(unsigned i)
{
    if (i >= std::size(s_base14fonts))
        return nullptr;

    return s_base14fonts[i];
}

void DrawRedFrame(PdfPainter& painter, double x, double y, double width, double height)
{
    // draw red box
    painter.GraphicsState.SetFillColor(PdfColor(1.0f, 0.0f, 0.0f));
    painter.GraphicsState.SetStrokeColor(PdfColor(1.0f, 0.0f, 0.0f));
    painter.DrawLine(x, y, x + width, y);
    if (height > 0.0f)
    {
        painter.DrawLine(x, y, x, y + height);
        painter.DrawLine(x + width, y, x + width, y + height);
        painter.DrawLine(x, y + height, x + width, y + height);
    }
    // restore to black
    painter.GraphicsState.SetFillColor(PdfColor(0.0f, 0.0f, 0.0f));
    painter.GraphicsState.SetStrokeColor(PdfColor(0.0f, 0.0f, 0.0f));
}

void DemoBase14Fonts(PdfPainter& painter, PdfPage& page, PdfDocument& document)
{
    PdfFontSearchParams params;
    params.AutoSelect = PdfFontAutoSelectBehavior::Standard14;

    double x = 56, y = page.GetRect().Height - 56.69;
    std::string_view demo_text = "abcdefgABCDEFG12345!#$%&+-@?        ";
    double height = 0.0f, width = 0.0f;

    // draw sample of all types
    for (unsigned i = 0; i < std::size(s_base14fonts); i++)
    {
        x = 56; y = y - 25;
        std::string text;
        if (i == 12)
        {
            // Or u8"♠♣♥♦": Symbol font doesn't support regular characters
            text = u8"\\u2660\\u2663\\u2665\\u2666";
        }
        else if (i == 13)
        {
            // Or u8"❏❑▲▼": ZapfDingbats font doesn't support regular characters
            text = u8"\\u274f\\u2751\\u25b2\\u25bc";
        }
        else
        {
            text = demo_text;
            text.append(GetBase14FontName(i));
        }

        PdfFont* font = document.GetFonts().SearchFont(GetBase14FontName(i), params);        
        font = &document.GetFonts().GetStandard14Font(PdfStandard14FontType::Helvetica);
        font = getFont(document);
        if (font == nullptr)
            throw std::runtime_error("Font not found");

        painter.TextState.SetFont(*font, 12.0);

        width = font->GetStringLength(text, painter.TextState);
        height = font->GetLineSpacing(painter.TextState);

        std::cout << GetBase14FontName(i) << " Width = " << width << " Height = " << height << std::endl;

        // draw red box
        DrawRedFrame(painter, x, y, width, height);

        // draw text
        painter.DrawText(text, x, y);
    }

    // draw some individual characters:
    std::string_view demo_text2 = " @_1jiPlg .;";

    auto helveticaStd14 = document.GetFonts().SearchFont("Helvetica", params);
    auto arialImported = document.GetFonts().SearchFont("Arial");
    helveticaStd14 = getFont(document);
    arialImported = getFont(document);
    auto& metrics = arialImported->GetMetrics();
    std::cout << "Non base 14 font characteristics" << std::endl;
    std::cout << "Font name: " << metrics.GetFontName() << std::endl;
    std::cout << "Family font name: " << metrics.GetFontFamilyName() << std::endl;
    std::cout << "Font file path: " << metrics.GetFilePath() << std::endl;
    std::cout << "Font face index: " << metrics.GetFaceIndex() << std::endl;

    // draw  individuals
    for (unsigned i = 0; i < demo_text2.length(); i++)
    {
        x = 56; y = y - 25;
        std::string text;
        if (i == 0)
            text = "Helvetica / Arial Comparison:";
        else
            text = (std::string)demo_text2.substr(i, 1);


        painter.TextState.SetFont(*helveticaStd14, 12);
        height = helveticaStd14->GetLineSpacing(painter.TextState);
        width = helveticaStd14->GetStringLength(text, painter.TextState);

        // draw red box
        DrawRedFrame(painter, x, y, width, height);

        // draw text
        painter.DrawText(text, x, y);

        if (i > 0)
        {
            // draw again, with non-Base14 font
            painter.TextState.SetFont(*arialImported, 12);
            height = arialImported->GetLineSpacing(painter.TextState);
            width = arialImported->GetStringLength((std::string_view)text, painter.TextState);

            // draw red box
            DrawRedFrame(painter, x + 100, y, width, height);

            // draw text
            painter.DrawText(text, x + 100, y);
        }
    }
}

void drawSquareWithCross(PdfPainter& painter, double x, double y)
{
    painter.Save();
    const double SquareSize = 6;
    painter.GraphicsState.SetLineWidth(0.6);
    painter.DrawRectangle(x - SquareSize / 2, y - SquareSize / 2, SquareSize, SquareSize);

    painter.GraphicsState.SetLineWidth(0);
    painter.DrawLine(x, y - SquareSize / 2, x, y + SquareSize / 2);
    painter.DrawLine(x - SquareSize / 2, y, x + SquareSize / 2, y);
    painter.Restore();
}


void createDocument2(const char* filename)
{
    PdfMemDocument doc;
    auto& page = doc.GetPages().CreatePage(PdfPage::CreateStandardPageSize(PdfPageSize::A4));

    PdfFontCreateParams params;
    params.Encoding = PdfEncodingMapFactory::WinAnsiEncodingInstance();
    auto& font = doc.GetFonts().GetStandard14Font(PdfStandard14FontType::Helvetica, params);

    PdfPainter painter;
    auto& operators = static_cast<PdfContentStreamOperators&>(painter);
    painter.SetCanvas(page);
    painter.TextState.SetFont(font, 15);
    painter.TextObject.Begin();
    painter.TextObject.MoveTo(100, 500);
    painter.TextObject.AddText("Test1");
    // Some low level operations
    operators.TJ_Operator_Begin();
    operators.TJ_Operator_Glyphs("_W", false);
    operators.TJ_Operator_Delta(-500);
    operators.TJ_Operator_Glyphs("orld", false);
    operators.TJ_Operator_End();
    painter.TextObject.End();
    painter.DrawText("Test2", 100, 600, PdfDrawTextStyle::StrikeThrough);

    PdfPainterPath path;
    path.MoveTo(20, 20);
    path.AddArcTo(150, 20, 150, 70, 50);
    path.AddLineTo(150, 120);
    path.AddArc(200, 120, 50, 3.14159, 3.14159 / 8, true);

    auto currPoint1 = path.GetCurrentPoint();

    PdfPainterPath path2;
    path2.MoveTo(250, 120);
    path2.AddLineTo(250, 80);
    path.AddPath(path2, true);

    auto currPoint2 = path.GetCurrentPoint();
    painter.DrawPath(path, PdfPathDrawMode::Stroke);
    path.Reset();
    path.MoveTo(40, 40);
    path.AddLineTo(100, 40);
    path.AddLineTo(70, 80);
    path.AddLineTo(40, 40);
    path.AddCircle(200, 300, 60);
    painter.DrawPath(path, PdfPathDrawMode::Fill);

    drawSquareWithCross(painter, 100, 20);
    drawSquareWithCross(painter, 100, 70);
    drawSquareWithCross(painter, 150, 70);
    drawSquareWithCross(painter, currPoint1.X, currPoint1.Y);
    drawSquareWithCross(painter, currPoint2.X, currPoint2.Y);

    painter.FinishDrawing();
    doc.Save(filename);
}

// 创建一个PDF文件
void testCreatePDF(const char* filename) {
	PdfMemDocument document;
	PdfPainter painter;

	PdfFont* font;

	try
	{
		auto& page = document.GetPages().CreatePage(PdfPage::CreateStandardPageSize(PdfPageSize::A4));
		painter.SetCanvas(page);
		font = document.GetFonts().SearchFont("Microsoft YaHei");
        //font = &document.GetFonts().GetStandard14Font(PdfStandard14FontType::Helvetica);
        font = getFont(document);
		if (font == nullptr)
			throw std::runtime_error("Invalid handle");

		auto& metrics = font->GetMetrics();
		std::cout << "The font name is " << metrics.GetFontName() << std::endl;
		std::cout << "The family font name is " << metrics.GetFontFamilyName() << std::endl;
		std::cout << "The font file path is " << metrics.GetFilePath() << std::endl;
		std::cout << "The font face index is " << metrics.GetFaceIndex() << std::endl;

		painter.TextState.SetFont(*font, 18);
		// painter.SetColor(1.0, 0.0, 0.0);
		painter.DrawText("ABCDEFGHIKLMNOPQRSTVXYZ", 56.69, page.GetRect().Height - 56.69);

		try
		{
			// Add also some non-ASCII characters (Cyrillic alphabet)
			painter.DrawText("АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЫЭЮЯ", 56.69, page.GetRect().Height - 80);
		}
		catch (PdfError& err)
		{
			if (err.GetCode() == PdfErrorCode::InvalidFontData)
				std::cout << "WARNING: The matched font " << metrics.GetFontName() << " doesn't support cyrillic" << std::endl;
		}

		//DemoBase14Fonts(painter, page, document);

		painter.FinishDrawing();

		// Set some additional information on the PDF file.
		document.GetMetadata().SetCreator(PdfString("examplahelloworld - A PoDoFo test application"));
		document.GetMetadata().SetAuthor(PdfString("Dominik Seichter"));
		document.GetMetadata().SetTitle(PdfString("Hello World"));
		document.GetMetadata().SetSubject(PdfString("Testing the PoDoFo PDF Library"));
		document.GetMetadata().SetKeywords(std::vector<std::string>({ "Test", "PDF", "Hello World" }));

		// The last step is to close the document.
		document.Save(filename);
	}
	catch (PdfError& e)
	{
		// All PoDoFo methods may throw exceptions
		// make sure that painter.FinishPage() is called
		// or who will get an assert in its destructor
		try
		{
			painter.FinishDrawing();
		}
		catch (...)
		{
			// Ignore errors this time
		}

		throw e;
	}
}

#include <windows.h>
HFONT createWinFont() {
    return CreateFont(
        -15/*高度*/, -7.5/*宽度*/, 0/*不用管*/, 0/*不用管*/, 400 /*一般这个值设为400*/,
        FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
        DEFAULT_CHARSET, //这里我们使用默认字符集,还有其他以 _CHARSET 结尾的常量可用
        OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, //这行参数不用管
        DEFAULT_QUALITY, //默认输出质量
        FF_DONTCARE, //不指定字体族*/
        "微软雅黑" //字体名
    );
}

PdfFont* getFont(PdfDocument& doc) {
    return &doc.GetFonts().GetOrCreateFont(createWinFont());
}

void testFonts() {
}

void test() {
    //auto& fc = GetFontConfigWrapper();
    //fc.AddFontDirectory("C://fonts");
    //PdfCommon::AddFontDirectory("C:\\Users\\ws\Downloads\\podofo\\extern\\resources\\Fonts\\");
    PdfCommon::SetMaxLoggingSeverity(PdfLogSeverity::Warning);
	testCreatePDF("./test.pdf");
	createDocument2("./test2.pdf");
}

输出

/*
The font name is MicrosoftYaHei
The family font name is Microsoft YaHei
The font file path is
The font face index is 0
*/

 

参考

GitHub - podofo/podofo: A C++17 PDF manipulation library

C++ pdf库总结-CSDN博客

C++ PDF转图片-CSDN博客


创作不易,小小的支持一下吧!

标签:0.0,text,PoDoFo,C++,height,path,PDF,font,painter
From: https://blog.csdn.net/qq_30220519/article/details/140559445

相关文章

  • C++字体库开发之fontconfig使用五
    代码 #include<cassert>#include<algorithm>#include"fontconfig/fontconfig.h"#include<stdexcept>#include<iostream>#defineHAS_FALLBACK_CONFIGURATIONenumFontStyle:uint16_t{Regular=0,Italic=0x01......
  • c++中的文件操作
    前言hello,大家好啊,这里是文宇,不是文字,是文宇哦。C++中的文件操作是用于在程序中读取、写入和操作文件的一种重要功能。文件操作允许程序直接与外部文件进行交互,这对于数据的存储和读取非常有用。在C++中,文件操作主要通过iostream库中的fstream类来实现。fstream类提供了一种......
  • Linux下C++静态链接库的生成以及使用
    目录一.前言二.生成静态链接库三.使用静态链接库一.前言这篇文章简单讨论一下Linux下如何使用gcc/g++生成和使用C++静态链接库(.a文件)。二.生成静态链接库先看下目录结构然后看下代码//demo.h#ifndefDEMO_H#defineDEMO_H#include<string>classDemo{p......
  • C++文件操作-文本文件-读文件
    第一种#include<iostream>//1、包含头文件fstream#include<fstream>usingnamespacestd;voidtest01(){ //2、创建流对象 ifstreamifs; //3、打开文件并且判断是否打开成功 ifs.open("test.txt",ios::in); if(!ifs.is_open()) { cout<<"文件打开失......
  • C++ 鼠标轨迹API【神诺科技SDK】
    一.鼠标轨迹模拟简介传统的鼠标轨迹模拟依赖于简单的数学模型,如直线或曲线路径。然而,这种方法难以捕捉到人类操作的复杂性和多样性。AI大模型的出现,使得神诺科技 能够通过深度学习技术,学习并模拟更自然的鼠标移动行为。二.鼠标轨迹算法实现AI大模型通过学习大量的人类鼠标操......
  • C++鼠标轨迹API - 神诺科技SDK
    一.鼠标轨迹模拟简介传统的鼠标轨迹模拟依赖于简单的数学模型,如直线或曲线路径。然而,这种方法难以捕捉到人类操作的复杂性和多样性。AI大模型的出现,使得神诺科技 能够通过深度学习技术,学习并模拟更自然的鼠标移动行为。二.鼠标轨迹算法实现AI大模型通过学习大量的人类鼠标操......
  • C++之函数
    1概述作用:将一段经常使用的代码封装起来,减少重复代码一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。2函数的定义函数定义一般主要有5个步骤:返回值类型函数名参数列表函数体语句return表达式语法:返回值类型函数名(参数列表){函数体语句......
  • 【C++】类和对象(中篇)
    类和对象一.类的默认成员函数二.构造函数三.析构函数四.拷贝构造函数五.运算符重载六.赋值运算符重载七.日期类的实现1.Date.h2.Date.cpp2.test.cpp八.取地址运算符重载1.const成员函数2.取地址运算符重载一.类的默认成员函数  默认成员函数就是用户不用实现的函......
  • 使用Python读取PDF文件,部分内容显示为一串乱码。我应该如何恢复它?
    使用Python读取PDF文件,部分内容显示为一串乱码。我该如何恢复它?importfitzdoc=fitz.open("2303.11366v4.pdf")#downloadfromhttps://arxiv.org/pdf/2303.11366print(doc[2].get_text().split('Figure1')[0])我得到了这样的文字:<RXDUHLQWKHPLGGOHRIDURRP>@7DVN......
  • C++自学笔记1(c++原理)
    Why学习C++?因为C++直接控制硬件。C++的工作原理是:C++代码,代码交给编译器来编译,编译器将代码转换成目标平台的机器码。(机器码:你操作的设备上CPU实际执行的二进制命令)所以我们使用C++可以控制CPU上每条进程的指令。C++可以运用在哪些平台上?几乎任何平台,只要你找到对应的编译器......