Disegnare grafica vettoriale su una pagina PDF

Disegnare grafica vettoriale su una pagina PDF

Disegnare grafica vettoriale su una pagina PDF

Aspose.PDF FOSS per C++ include una piccola API di grafica vettoriale per disegnare forme direttamente su una pagina PDF mentre un documento viene costruito. Il punto di ingresso è Graph, un contenitore posizionato su una pagina che contiene una collezione di oggetti Shape; tre forme concrete — Circle, Ellipse e Line — derivano da Shape e ciascuna esprime la propria geometria in modo diverso. Lo stile del tratto e del riempimento per forma proviene da GraphInfo, e il contenitore Graph stesso porta un BorderInfo per l’inquadratura. Questo non è correlato alla rasterizzazione della pagina (BmpDevice, JpegDevice, TiffDevice), che converte il contenuto della pagina esistente in formati di immagine raster piuttosto che disegnare nuova geometria.


Il contenitore grafico e l’aggiunta di forme a una pagina

Graph posiziona e dimensiona se stesso sulla pagina tramite Left(), Top(), Width() e Height(), e il suo flag IsChangePosition() controlla se quella posizione può spostarsi rispetto ad altri contenuti della pagina. Le forme che disegna vivono nel vettore restituito da Shapes() — std::vector<std::unique_ptr<Shape>> — popolato costruendo una forma, configurandola e spostandola su quel vettore. Una volta costruito, il Graph stesso viene posizionato sulla pagina tramite Page.Paragraphs().Add(), la stessa collezione usata per altri contenuti a livello di pagina.

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/drawing/graph.hpp>
#include <aspose/pdf/drawing/circle.hpp>

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

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

auto graph = std::make_shared<Graph>();
graph->Left(36.0);
graph->Top(36.0);
graph->Width(500.0);
graph->Height(300.0);

auto marker = std::make_unique<Circle>();
marker->PosX(60.0);
marker->PosY(60.0);
marker->Radius(30.0);
graph->Shapes().push_back(std::move(marker));

page.Paragraphs().Add(graph);
doc.Save("shapes.pdf");

Disegnare cerchi ed ellissi

Circle e Ellipse esprimono ciascuno la geometria come semplici proprietà numeriche anziché un tipo di punto o rettangolo condiviso. Circle è un punto centrale e raggio — PosX(), PosY(), Radius() — mentre Ellipse è un bounding box — Left(), Bottom(), Width(), Height(). Entrambi ereditano CheckBounds(containerWidth, containerHeight) da Shape, che segnala se la geometria attuale della forma rientra in un contenitore della dimensione data senza alterare la forma stessa.

#include <aspose/pdf/drawing/circle.hpp>
#include <aspose/pdf/drawing/ellipse.hpp>

using namespace Aspose::Pdf::Drawing;

Circle circle;
circle.PosX(120.0);
circle.PosY(120.0);
circle.Radius(60.0);
bool circleFits = circle.CheckBounds(500.0, 300.0);

Ellipse ellipse;
ellipse.Left(220.0);
ellipse.Bottom(20.0);
ellipse.Width(250.0);
ellipse.Height(100.0);
bool ellipseFits = ellipse.CheckBounds(500.0, 300.0);

Disegnare linee con PositionArray

Line memorizza la sua geometria in modo diverso da Circle e Ellipse: PositionArray() restituisce un std::vector<float> piatto che contiene una coppia x, y per ogni punto attraversato dalla linea, invece di un set fisso di proprietà nominate. Due punti (quattro valori) disegnano un segmento rettilineo; coppie aggiuntive disegnano un percorso a più segmenti attraverso quei punti in ordine. Come le altre forme, Line sovrascrive CheckBounds(containerWidth, containerHeight) da Shape.

#include <aspose/pdf/drawing/line.hpp>

using namespace Aspose::Pdf::Drawing;

Line path;
path.PositionArray({0.0f, 0.0f, 250.0f, 0.0f, 125.0f, 200.0f});
bool pathFits = path.CheckBounds(500.0, 300.0);

Stilizzare forme con GraphInfo e BorderInfo

Ogni forma legge e scrive lo stile del tratto e del riempimento tramite Shape.GraphInfo() / GraphInfo(value). GraphInfo predefinito è un LineWidth() di 1.0f con un DashArray() vuoto, e espone anche Color(), FillColor(), DashArray()/DashPhase() per tratti tratteggiati, IsDoubled() per una linea doppia, e SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() e RotationAngle() per trasformare il tratto. Graph stessa contiene un BorderInfo, impostato tramite Border(), che raggruppa un GraphInfo per bordo — Left(), Right(), Top(), Bottom() — più un RoundedBorderRadius(), e può essere costruito specificando quali bordi stilizzare con un flag BorderSide (BorderSide::Left | BorderSide::Right, o BorderSide::All per ogni bordo).

#include <aspose/pdf/graph_info.hpp>
#include <aspose/pdf/border_info.hpp>
#include <aspose/pdf/border_side.hpp>
#include <aspose/pdf/color.hpp>

using namespace Aspose::Pdf;

GraphInfo stroke;
stroke.LineWidth(2.5f);
stroke.Color(Color::FromRgb(1.0, 0.0, 0.0));
stroke.DashArray({3, 2});
stroke.DashPhase(1);
stroke.IsDoubled(true);

// Style only the left and right edges of the container border.
BorderInfo border{BorderSide::Left | BorderSide::Right, 3.0f};
border.RoundedBorderRadius(4.0);

graph->GraphInfo(stroke);
graph->Border(border);

Suggerimenti e buone pratiche

  • Chiama CheckBounds sul proprio Width()/Height() del Graph proprietario, non sul media box completo della pagina — il controllo convalida la geometria di una forma rispetto alla dimensione del contenitore che fornisci, non esamina automaticamente la pagina.
  • Aggiungi le forme a Shapes() prima di aggiungere il Graph a Page.Paragraphs() — la costruzione di un Circle, Ellipse o Line non ha alcun effetto visibile finché non viene sia aggiunta al suo Graph proprietario sia quel Graph viene aggiunto a una pagina.
  • Raggruppa le forme correlate sotto un unico Graph invece di un Graph per forma; Left()/Top()/Width()/Height() posizionano l’intero contenitore una sola volta, e ogni forma in Shapes() viene disegnata rispetto a esso.
  • Imposta Shape.GraphInfo() esplicitamente per le forme che richiedono un riempimento visibile o un tratto non predefinito — il GraphInfo predefinito ha uno spessore di linea 1.0f, nessun riempimento e un DashArray() vuoto.
  • Costruisci Line.PositionArray() come coppie x0, y0, x1, y1, … nell’ordine in cui il percorso dovrebbe essere tracciato — un vettore di lunghezza dispari descrive un punto incompleto.

Problemi comuni

ProblemaCauseCorrezione
Un Circle, Ellipse o Line non appare mai nella pagina salvataLa forma è stata costruita ma non è mai stata aggiunta al Shapes() del suo Graph, oppure il Graph non è mai stato aggiunto alla paginaInserisci la forma su graph->Shapes() e chiama page.Paragraphs().Add(graph)
La forma viene disegnata con un tratto nero sottile predefinitoShape.GraphInfo() non è mai stato impostatoChiama shape->GraphInfo(customGraphInfo) prima di aggiungere la forma a Shapes()
Line è mancante o sembra un punto singoloPositionArray() ha meno di due coppie (x, y) o un numero dispari di valoriFornisci almeno quattro valori come x0, y0, x1, y1
Solo alcuni bordi del contenitore sono stilizzatiBorderInfo è stato costruito con una maschera BorderSide che esclude alcuni bordiUsa BorderSide::All, oppure combina con OR tutti i flag BorderSide necessari
CheckBounds restituisce inaspettatamente falseLe dimensioni passate a CheckBounds non corrispondono al contenitore in cui la forma è effettivamente disegnataPassa l’attuale Width()/Height() del Graph proprietario

FAQ

Qual è la differenza tra Circle e AnnotationType::Circle?

Circle (questa guida) è una forma di disegno che disegna direttamente nel contenuto della pagina tramite un Graph. AnnotationType::Circle e CircleAnnotation appartengono a un API di annotazioni separato e rappresentano invece un’annotazione markup a forma di cerchio — i due non sono correlati nonostante il nome condiviso.

Un singolo Graph può contenere più di una forma?

Sì. Graph.Shapes() restituisce il std::vector<std::unique_ptr<Shape>> completo per quel contenitore, e qualsiasi combinazione di istanze Circle, Ellipse e Line può essere aggiunta ad esso prima che il Graph venga aggiunto alla pagina.

Circle e Ellipse condividono lo stesso tipo di geometria?

No. Circle è un punto centrale e raggio (PosX, PosY, Radius); Ellipse è una bounding box (Left, Bottom, Width, Height). Entrambi derivano da Shape, ma nessuno condivide un punto comune o un tipo di rettangolo con l’altro.

Disegnare forme con Graph è lo stesso di renderizzare una pagina in un’immagine?

No. Graph, Shape, Circle, Ellipse e Line creano nuova geometria vettoriale nel contenuto di una pagina durante la generazione del documento. Convertire una pagina esistente in un’immagine raster è una funzionalità separata, gestita da BmpDevice, JpegDevice e TiffDevice.

Cosa fa GraphInfo.IsDoubled()?

Contrassegna il tratto come una linea doppia anziché modificare altre proprietà del tratto. È un flag booleano letto e impostato tramite IsDoubled() / IsDoubled(value) insieme alle altre proprietà del tratto GraphInfo.


API Reference Riepilogo

Classe/MetodoDescrizione
GraphContenitore di forma posizionato su una pagina; si posiziona con Left(), Top(), Width(), Height()
Graph.Shapes()Restituisce il std::vector<std::unique_ptr<Shape>> disegnato da questo contenitore
Graph.GraphInfo() / GraphInfo(value)Ottiene/imposta lo stile del tratto e del riempimento del contenitore
Graph.Border() / Border(value)Ottiene/imposta il BorderInfo che incornicia il contenitore
ShapeBase astratta per Circle, Ellipse e Line; espone GraphInfo() e CheckBounds()
Shape.CheckBounds(w, h)Riporta se la geometria della forma si adatta a un contenitore con la larghezza/altezza specificata
CircleForma circolare: PosX(), PosY(), Radius()
EllipseForma ellittica: riquadro di delimitazione tramite Left(), Bottom(), Width(), Height()
LineForma linea/percorso: PositionArray(), un std::vector<float> piatto di coordinate x, y
GraphInfoStile tratto/pieno: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY()
BorderInfoBordo contenitore per lato: Left(), Right(), Top(), Bottom() (ognuno un GraphInfo), più RoundedBorderRadius()
BorderSideEnum che seleziona i bordi durante la costruzione di un BorderInfo: None, Left, Top, Right, Bottom, All, Box

Vedi anche

 Italiano