چگونه با گرافیک PDF در C++ کار کنیم

چگونه با گرافیک PDF در C++ کار کنیم

Aspose.PDF FOSS برای C++ شامل یک API گرافیک‌های برداری کوچک برای رسم اشکال آزاد مستقیماً روی صفحه PDF است — جدا از دستگاه‌های رندرینگ رستری کتابخانه (BmpDevice, JpegDevice, TiffDevice) که محتوای موجود صفحه را به تصویر تبدیل می‌کنند. این راهنما نحوه ایجاد یک کانتینر Graph، افزودن اشکال Circle، Ellipse و Line به آن، استایل‌دهی به این اشکال با GraphInfo، و قرار دادن Graph نهایی بر روی یک صفحه را قدم به قدم توضیح می‌دهد. کتابخانه از طریق CMake به پروژه اضافه می‌شود.

راهنمای گام به گام

مرحله ۱: نصب بسته

کتابخانه را به‌عنوان زیرپوشه CMake اضافه کنید و در برابر هدف aspose_pdf_foss لینک کنید:

add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)

با کامپایل یک برنامهٔ حداقل، زنجیره ابزار و هدرها را بررسی کنید که به درستی حل می‌شوند:

#include <aspose/pdf/document.hpp>
#include <iostream>

int main() {
    Aspose::Pdf::Document doc;
    std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}

یک ساخت موفق که pages: 0 را چاپ می‌کند، تأیید می‌کند که کتابخانه به‌درستی لینک شده است.


مرحله ۲: وارد کردن کلاس‌های مورد نیاز

سرآیندهای سند، مخزن شکل، سه شکل خاص و انواع استایل آن‌ها را شامل کنید:

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/drawing/graph.hpp>
#include <aspose/pdf/drawing/circle.hpp>
#include <aspose/pdf/drawing/ellipse.hpp>
#include <aspose/pdf/drawing/line.hpp>
#include <aspose/pdf/graph_info.hpp>
#include <aspose/pdf/border_info.hpp>
#include <aspose/pdf/color.hpp>

using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Drawing;

Graph، Shape، Circle، Ellipse و Line در فضای نام Aspose::Pdf::Drawing قرار دارند؛ GraphInfo، BorderInfo و Color مستقیماً زیر Aspose::Pdf قرار دارند.


مرحله ۳: ایجاد یک گراف و افزودن آن به یک صفحه

Graph یک مخزن است که خود را بر روی صفحه از طریق Left()، Top()، Width() و Height() موقعیت‌دهی می‌کند و اشکالی که داخل آن رسم می‌شوند را از طریق Shapes() نگه می‌دارد. پس از پیکربندی، از طریق Page.Paragraphs().Add() بر روی صفحه قرار می‌گیرد، همان مجموعه‌ای که برای سایر محتوای صفحه استفاده می‌شود:

Document doc;
Page page = doc.Pages().Add();

auto graph = std::make_shared<Graph>();
graph->Left(50.0);
graph->Top(50.0);
graph->Width(400.0);
graph->Height(400.0);

page.Paragraphs().Add(graph);

مرحله ۴: رسم یک دایره و یک بیضی

Circle هندسه خود را با PosX()، PosY() و Radius() توصیف می‌کند. Ellipse به‌جای آن از یک جعبه محدود‌کننده استفاده می‌کند — Left()، Bottom()، Width() و Height(). هر دو با افزودن آنها به عنوان اشاره‌گرهای Shape به وکتور بازگشتی توسط Shapes()، به Graph اضافه می‌شوند:

auto circle = std::make_unique<Circle>();
circle->PosX(150.0);
circle->PosY(150.0);
circle->Radius(75.0);
graph->Shapes().push_back(std::move(circle));

auto ellipse = std::make_unique<Ellipse>();
ellipse->Left(20.0);
ellipse->Bottom(20.0);
ellipse->Width(120.0);
ellipse->Height(60.0);
graph->Shapes().push_back(std::move(ellipse));

هر دو شکل CheckBounds(containerWidth, containerHeight) را از Shape به ارث می‌برند، که گزارش می‌دهد آیا هندسه فعلی شکل در یک مخزن با اندازهٔ داده شده جا می‌گیرد یا نه:

bool circleFits = circle->CheckBounds(graph->Width(), graph->Height());

مرحله 5: رسم یک خط

Line geometry را به شکل متفاوتی ذخیره می‌کند: PositionArray() یک std::vector<float> مسطح از مختصات را نگه می‌دارد — یک جفت x, y برای هر نقطه — به‌جای ویژگی‌های نامگذاری شده. یک قطعه دو نقطه‌ای به چهار مقدار نیاز دارد: start x, start y, end x, end y.

auto line = std::make_unique<Line>();
line->PositionArray({0.0f, 0.0f, 400.0f, 400.0f});
graph->Shapes().push_back(std::move(line));

مرحله 6: استایل‌دهی به اشکال با GraphInfo و Container Border

خط‌کشی و پر کردن هر شکل از یک GraphInfo می‌آید، که از طریق Shape.GraphInfo() / GraphInfo(value) خوانده و تنظیم می‌شود. این مورد عرض خط‌کشی (LineWidth(), پیش‌فرض 1.0f)، رنگ خط‌کشی و پر کردن (Color(), FillColor())، و یک الگوی خط‌چین (DashArray(), DashPhase()) را نشان می‌دهد:

GraphInfo stroke;
stroke.LineWidth(2.0f);
stroke.Color(Color::FromRgb(1.0, 0.0, 0.0));
stroke.FillColor(Color::FromRgb(1.0, 0.9, 0.9));

خود کانتینر Graph یک BorderInfo را حمل می‌کند، که از طریق Border() تنظیم می‌شود و یک GraphInfo برای هر لبه (Left(), Right(), Top(), Bottom()) به‌علاوه یک RoundedBorderRadius() برای قاب خود کانتینر گروه‌بندی می‌کند:

BorderInfo border{BorderSide::All, 1.5f, Color::Black()};
border.RoundedBorderRadius(6.0);
graph->Border(border);

مرحله 7: ذخیره سند

doc.Save("graphics.pdf");

مسائل رایج و راه‌حل‌ها

شکلی که من ساختم هرگز در صفحه ظاهر نمی‌شود

ساختن یک Circle، Ellipse یا Line به تنهایی هیچ‌گونه اثری ندارد تا زمانی که به برداری که توسط Shapes() متعلق به Graph بازگردانده می‌شود، اضافه نشود و آن Graph از طریق Page.Paragraphs().Add() به صفحه افزوده شود. هر سه مرحله — ساخت، افزودن، افزودن Graph به صفحه — الزامی هستند.

شکل‌ها در موقعیت نادرست رندر می‌شوند

Graph.Left() و Graph.Top() موقعیت محفظه را در صفحه تعیین می‌کنند؛ ویژگی‌های شکل (Circle.PosX()/PosY()، Ellipse.Left()/Bottom()، مختصات Line.PositionArray()) هندسه داخل آن محفظه را توصیف می‌کنند. هنگامیکه خروجی جابجا به نظر می‌رسد، هر دو موقعیت محفظه و مختصات خود شکل را بررسی کنید.

CheckBounds returns false unexpectedly

CheckBounds(containerWidth, containerHeight) هندسهٔ خود شکل را در مقابل ابعادی که عبور داده می‌شود بررسی می‌کند — معمولاً Width()/Height() متعلق به Graph، نه جعبهٔ رسانه‌ای کامل صفحه. ارسال ابعاد اشتباه حتی وقتی که شکل در واقع داخل Graph قرار می‌گیرد، منجر به نتیجهٔ منفی نادرست می‌شود.

A Line ظاهر نمی‌شود، یا به‌عنوان یک نقطهٔ تک ظاهر می‌شود

PositionArray() برای توصیف یک قطعهٔ قابل مشاهده حداقل به دو جفت (x, y) — یعنی چهار مقدار float — نیاز دارد. یک بردار کوتاه‌تر خطی ایجاد نمی‌کند.

Confusing Circle with AnnotationType::Circle or CircleAnnotation

کتابخانه همچنین یک API جداگانه برای حاشیه‌نویسی PDF دارد، جایی که AnnotationType::Circle و CircleAnnotation نشانگر حاشیه‌نویسی‌های دایره‌شکل هستند. کلاس Circle که در این راهنما پوشش داده شده است، نامرتبط است — در Aspose::Pdf::Drawing قرار دارد و به‌جای افزودن شیء حاشیه‌نویسی، مستقیماً در محتوای صفحه رسم می‌کند.

سوالات متداول

تفاوت بین GraphInfo و BorderInfo چیست؟

GraphInfo یک قلم‌خط منفرد را استایل می‌دهد — عرض خط، رنگ، رنگ پر، و الگوی خط — و هم بر روی شکل‌های تک‌تکه (از طریق Shape.GraphInfo()) و هم برای هر لبه داخل یک BorderInfo استفاده می‌شود. BorderInfo چهار مقدار GraphInfo (Left()، Right()، Top()، Bottom()) به‌همراه یک RoundedBorderRadius() را گروه‌بندی می‌کند تا چارچوب مرزی خود یک محفظه Graph را توصیف کند.

آیا می‌توانم یک شکل را با رنگ جامد پر کنم؟

بله. GraphInfo.FillColor() رنگ پر کردن را تنظیم می‌کند که هنگام رسم شکل از طریق Graph مالک آن استفاده می‌شود.

آیا Circle یک جعبه محدود کننده مشابه Ellipse ذخیره می‌کند؟

خیر. Circle PosX()، PosY() و Radius() را در دسترس می‌گذارد؛ Ellipse Left()، Bottom()، Width() و Height() را در دسترس می‌گذارد. آن‌ها نمایهٔ هندسی مشترکی جز پایهٔ انتزاعی Shape و استایل GraphInfo ندارند.

آیا یک Graph می‌تواند بیش از یک شکل را در خود داشته باشد؟

بله. Graph.Shapes() مجموعهٔ کامل اشیاء Shape که در آن Graph قرار گرفته‌اند را برمی‌گرداند — دایره‌ها، بیضی‌ها و خطوط می‌توانند همگی به همان مخزن افزوده شوند.

آیا این همانند رندر کردن یک صفحه به تصویر است؟

خیر. BmpDevice، JpegDevice و TiffDevice محتوای موجود صفحه را به فرمت‌های تصویر تبدیل (رستر) می‌کنند. Graph، Shape، Circle، Ellipse و Line هندسهٔ برداری جدید را مستقیماً در محتوای PDF می‌سازند در حالی که سند در حال ساخت یا ویرایش است.

همچنین ببینید:

 فارسی