Cum să lucraţi cu grafice PDF în C++

Cum să lucraţi cu grafice PDF în C++

Aspose.PDF FOSS pentru C++ include un mic API de grafică vectorială pentru desenarea formelor libere direct pe o pagină PDF — separat de dispozitivele de randare raster ale bibliotecii (BmpDevice, JpegDevice, TiffDevice), care convertesc conținutul existent al paginii în imagini. Acest ghid parcurge crearea unui container Graph, adăugarea formelor Circle, Ellipse și Line în acesta, stilizarea acelor forme cu GraphInfo, și plasarea Graph finalizat pe o pagină. Biblioteca este adăugată la un proiect prin CMake.

Ghid pas cu pas

Pasul 1: Instalează pachetul

Adaugă biblioteca ca subdirector CMake și leagă-te de ținta aspose_pdf_foss:

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

Verifică că toolchain-ul și header-ele se rezolvă prin compilarea unui program minimal:

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

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

O compilare reușită care afișează pages: 0 confirmă că biblioteca este legată corect.


Pasul 2: Importă clasele necesare

Include antetele pentru document, containerul de forme, cele trei forme concrete și tipurile lor de stilizare:

#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 și Line se află în spațiul de nume Aspose::Pdf::Drawing; GraphInfo, BorderInfo și Color se află direct sub Aspose::Pdf.


Pasul 3: Creează un grafic și adaugă-l pe o pagină

Graph este un container care se poziționează pe pagină prin Left(), Top(), Width() și Height(), și conține formele desenate în interiorul său prin Shapes(). Odată configurat, este plasat pe pagină prin Page.Paragraphs().Add(), aceeași colecție utilizată pentru alte conținuturi de pagină:

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);

Pasul 4: Desenează un cerc și o elipsă

Circle descrie geometria sa cu PosX(), PosY() și Radius(). Ellipse folosește în schimb o cutie delimitatoare — Left(), Bottom(), Width() și Height(). Ambele sunt adăugate la Graph prin adăugarea lor, ca pointeri Shape, la vectorul returnat de Shapes():

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));

Ambele forme moștenesc CheckBounds(containerWidth, containerHeight) de la Shape, care raportează dacă geometria curentă a formei se încadrează într-un container de dimensiunea specificată:

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

Pasul 5: Desenează o linie

Line își stochează geometria diferit: PositionArray() conține un std::vector<float> plat de coordonate — o pereche x, y pentru fiecare punct — în loc de proprietăți numite. Un segment cu două puncte necesită patru valori: x de început, y de început, x de sfârșit, y de sfârșit.

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

Pasul 6: Stilizează formele cu GraphInfo și marginea containerului

Conturul și umplerea fiecărei forme provin dintr-un GraphInfo, citite și setate prin Shape.GraphInfo() / GraphInfo(value). Acesta expune lățimea conturului (LineWidth(), implicit 1.0f), culoarea conturului și a umplerii (Color(), FillColor()) și un model de liniuțe (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));

Containerul Graph în sine conține un BorderInfo, setat prin Border(), care grupează un GraphInfo pentru fiecare muchie (Left(), Right(), Top(), Bottom()) plus un RoundedBorderRadius() pentru cadrul propriu al containerului:

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

Pasul 7: Salvează documentul

doc.Save("graphics.pdf");

Probleme comune și remedii

O formă pe care am construit-o nu apare niciodată pe pagină

Construirea unui Circle, Ellipse sau Line de unul singur nu are niciun efect până nu este adăugată la vectorul returnat de Shapes() al Graph, iar acel Graph este adăugat la o pagină prin Page.Paragraphs().Add(). Toate cele trei etape — construirea, adăugarea, adăugarea Graph la pagină — sunt necesare.

Formele se redau în poziția greșită

Graph.Left() și Graph.Top() poziționează containerul pe pagină; proprietățile formei (Circle.PosX()/PosY(), Ellipse.Left()/Bottom(), coordonatele Line.PositionArray()) descriu geometria în interiorul acelui container. Verificați atât plasarea containerului, cât și coordonatele proprii ale formei atunci când rezultatul pare decalajat.

CheckBounds returns false unexpectedly

CheckBounds(containerWidth, containerHeight) verifică geometria proprie a formei față de dimensiunile transmise — de obicei Width()/Height() ale Graph deținător, nu caseta media completă a paginii. Transmiterea dimensiunilor incorecte produce un fals negativ chiar și atunci când forma s-ar încadra efectiv în Graph.

A Line nu apare, sau apare ca un singur punct

PositionArray() are nevoie de cel puțin două perechi (x, y) — patru valori float — pentru a descrie un segment vizibil. Un vector mai scurt nu formează o linie.

Confusing Circle with AnnotationType::Circle or CircleAnnotation

Biblioteca are, de asemenea, un API separat pentru adnotări PDF, unde AnnotationType::Circle și CircleAnnotation reprezintă adnotări de tip marcaj în formă de cerc. Clasa Circle acoperită în acest ghid nu are legătură — se află în Aspose::Pdf::Drawing și se desenează direct în conținutul paginii, în loc să adauge un obiect de adnotare.

Întrebări frecvente

Care este diferența dintre GraphInfo și BorderInfo?

GraphInfo stilizează un singur contur — lățimea liniei, culoarea, culoarea de umplere și modelul de puncte — și este folosit atât pe forme individuale (prin Shape.GraphInfo()), cât și pe fiecare margine dintr-un BorderInfo. BorderInfo grupează patru valori GraphInfo (Left(), Right(), Top(), Bottom()) plus un RoundedBorderRadius() pentru a descrie cadrul de bordură al containerului Graph.

Pot umple o formă cu o culoare solidă?

Da. GraphInfo.FillColor() setează culoarea de umplere utilizată când forma este desenată prin Graph propriu.

Circle stochează o cutie delimitatoare așa cum o face Ellipse?

Nu. Circle expune PosX(), PosY() și Radius(); Ellipse expune Left(), Bottom(), Width() și Height(). Nu împărtășesc o reprezentare geometrică comună în afara bazei abstracte Shape și a stilizării GraphInfo.

Poate un Graph să conțină mai mult de o formă?

Da. Graph.Shapes() returnează colecția completă de obiecte Shape plasate în acel Graph — cercuri, elipse și linii pot fi adăugate toate în același container.

Este aceasta același lucru cu redarea unei pagini într-o imagine?

Nu. BmpDevice, JpegDevice și TiffDevice rasterizează conținutul existent al paginii în formate de imagine. Graph, Shape, Circle, Ellipse și Line construiesc geometrie vectorială nouă direct în conținutul PDF în timp ce un document este construit sau editat.

Vezi și:

 Română