Hur man arbetar med PDF-grafik i C++

Hur man arbetar med PDF-grafik i C++

Aspose.PDF FOSS för C++ inkluderar ett litet vektor-grafik API för att rita fria former direkt på en PDF-sida — separat från bibliotekets raster-renderingsenheter (BmpDevice, JpegDevice, TiffDevice), som konverterar befintligt sidinnehåll till bilder. Denna guide går igenom att skapa en Graph behållare, lägga till Circle, Ellipse och Line former i den, styla dessa former med GraphInfo, och placera den färdiga Graph på en sida. Biblioteket läggs till i ett projekt via CMake.

Steg-för-steg-guide

Steg 1: Installera paketet

Lägg till biblioteket som en CMake-undermapp och länka mot aspose_pdf_foss-målet:

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

Verifiera att verktygskedjan och header-filerna löses genom att kompilera ett minimalt program:

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

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

En lyckad byggnad som skriver ut pages: 0 bekräftar att biblioteket är korrekt länkat.


Steg 2: Importera nödvändiga klasser

Inkludera rubrikerna för dokumentet, formbehållaren, de tre konkreta formerna och deras stiltyper:

#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 och Line finns i Aspose::Pdf::Drawing-namnutrymmet; GraphInfo, BorderInfo och Color finns direkt under Aspose::Pdf.


Steg 3: Skapa en graf och lägg till den på en sida

Graph är en behållare som placerar sig på sidan via Left(), Top(), Width() och Height(), och håller de former som ritas inuti den via Shapes(). När den är konfigurerad placeras den på sidan via Page.Paragraphs().Add(), samma samling som används för annat sidoinnehåll:

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

Steg 4: Rita en cirkel och en ellips

Circle beskriver sin geometri med PosX(), PosY() och Radius(). Ellipse använder en begränsningsruta istället — Left(), Bottom(), Width() och Height(). Båda läggs till i Graph genom att bifoga dem, som Shape-pekare, till vektorn som returneras av 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));

Båda formerna ärver CheckBounds(containerWidth, containerHeight) från Shape, vilket rapporterar om figurens aktuella geometri får plats i en behållare av given storlek:

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

Steg 5: Rita en linje

Line lagrar sin geometri på ett annat sätt: PositionArray() innehåller en platt std::vector<float> av koordinater — ett x, y-par per punkt — istället för namngivna egenskaper. Ett segment med två punkter kräver fyra värden: start-x, start-y, slut-x, slut-y.

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

Steg 6: Styla former med GraphInfo och behållarens kant

Varje forms kontur och fyllning kommer från en GraphInfo, läses och sätts via Shape.GraphInfo() / GraphInfo(value). Den exponerar konturbredd (LineWidth(), standard 1.0f), kontur- och fyllningsfärg (Color(), FillColor()) samt ett streckmönster (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));

Själva Graph-behållaren har en BorderInfo, satt via Border(), som grupperar en GraphInfo per kant (Left(), Right(), Top(), Bottom()) samt en RoundedBorderRadius() för behållarens egen ram:

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

Steg 7: Spara dokumentet

doc.Save("graphics.pdf");

Vanliga problem och lösningar

En form jag konstruerade visas aldrig på sidan

Att konstruera en Circle, Ellipse eller Line på egen hand har ingen effekt förrän den appenderas till vektorn som returneras av den ägande Graph:s Shapes(), och den Graph läggs till en sida via Page.Paragraphs().Add(). Alla tre stegen — konstruera, appendera, lägg Graph till sidan — krävs.

Former renderas på fel position

Graph.Left() och Graph.Top() placerar containern på sidan; formegenskaper (Circle.PosX()/PosY(), Ellipse.Left()/Bottom(), Line.PositionArray() koordinater) beskriver geometrin inom den containern. Kontrollera både containerns placering och formens egna koordinater när utskriften verkar förskjuten.

CheckBounds returns false unexpectedly

CheckBounds(containerWidth, containerHeight) kontrollerar formens egen geometri mot de angivna dimensionerna — vanligtvis den ägande Graph:s Width()/Height(), inte sidans fullständiga mediabox. Att skicka fel dimensioner ger ett falskt negativt resultat även när formen faktiskt skulle få plats inom Graph.

A Line visas inte, eller visas som en enda punkt

PositionArray() kräver minst två (x, y)-par — fyra float-värden — för att beskriva ett synligt segment. En kortare vektor bildar ingen linje.

Confusing Circle with AnnotationType::Circle or CircleAnnotation

Biblioteket har också en separat PDF-antecknings API, där AnnotationType::Circle och CircleAnnotation representerar cirkelformade markup-anteckningar. Klassen Circle som behandlas i den här guiden är orelaterad — den finns i Aspose::Pdf::Drawing och ritar direkt i sidinnehållet snarare än att lägga till ett annoteringsobjekt.

Vanliga frågor

Vad är skillnaden mellan GraphInfo och BorderInfo?

GraphInfo formaterar ett enskilt streck — linjebredd, färg, fyllnadsfärg och streckmönster — och används både på enskilda former (genom Shape.GraphInfo()) och per kant i en BorderInfo. BorderInfo grupperar fyra GraphInfo-värden (Left(), Right(), Top(), Bottom()) plus en RoundedBorderRadius() för att beskriva en Graph-behållares egen ram.

Kan jag fylla en form med en solid färg?

Ja. GraphInfo.FillColor() anger fyllnadsfärgen som används när formen ritas genom dess ägande Graph.

Lagrar Circle en omgivningsruta som Ellipse gör?

Nej. Circle exponerar PosX(), PosY() och Radius(); Ellipse exponerar Left(), Bottom(), Width() och Height(). De delar inte en gemensam geometrirepresentation utöver den abstrakta Shape basen och GraphInfo stil.

Kan en Graph innehålla mer än en form?

Ja. Graph.Shapes() returnerar hela samlingen av Shape objekt som placerats inom den Graph — cirklar, ellipser och linjer kan alla läggas till i samma behållare.

Är detta samma som att rendera en sida till en bild?

Nej. BmpDevice, JpegDevice och TiffDevice rasteriserar befintligt sidinnehåll till bildformat. Graph, Shape, Circle, Ellipse och Line konstruerar ny vektor-geometri direkt i PDF-innehållet medan ett dokument byggs eller redigeras.

Se även

 Svenska