C++ PDF PoDoFo库使用教程

cpp 复制代码
#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博客


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

相关推荐
ULTRA??19 分钟前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者1 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者1 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可2 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
白子寰2 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
小芒果_013 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
gkdpjj3 小时前
C++优选算法十 哈希表
c++·算法·散列表
王俊山IT3 小时前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
-Even-3 小时前
【第六章】分支语句和逻辑运算符
c++·c++ primer plus