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
CheckBoundssul proprioWidth()/Height()delGraphproprietario, 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 ilGraphaPage.Paragraphs()— la costruzione di unCircle,EllipseoLinenon ha alcun effetto visibile finché non viene sia aggiunta al suoGraphproprietario sia quelGraphviene aggiunto a una pagina. - Raggruppa le forme correlate sotto un unico
Graphinvece di unGraphper forma;Left()/Top()/Width()/Height()posizionano l’intero contenitore una sola volta, e ogni forma inShapes()viene disegnata rispetto a esso. - Imposta
Shape.GraphInfo()esplicitamente per le forme che richiedono un riempimento visibile o un tratto non predefinito — ilGraphInfopredefinito ha uno spessore di linea1.0f, nessun riempimento e unDashArray()vuoto. - Costruisci
Line.PositionArray()come coppiex0, y0, x1, y1, …nell’ordine in cui il percorso dovrebbe essere tracciato — un vettore di lunghezza dispari descrive un punto incompleto.
Problemi comuni
| Problema | Cause | Correzione |
|---|---|---|
Un Circle, Ellipse o Line non appare mai nella pagina salvata | La forma è stata costruita ma non è mai stata aggiunta al Shapes() del suo Graph, oppure il Graph non è mai stato aggiunto alla pagina | Inserisci la forma su graph->Shapes() e chiama page.Paragraphs().Add(graph) |
| La forma viene disegnata con un tratto nero sottile predefinito | Shape.GraphInfo() non è mai stato impostato | Chiama shape->GraphInfo(customGraphInfo) prima di aggiungere la forma a Shapes() |
Line è mancante o sembra un punto singolo | PositionArray() ha meno di due coppie (x, y) o un numero dispari di valori | Fornisci almeno quattro valori come x0, y0, x1, y1 |
| Solo alcuni bordi del contenitore sono stilizzati | BorderInfo è stato costruito con una maschera BorderSide che esclude alcuni bordi | Usa BorderSide::All, oppure combina con OR tutti i flag BorderSide necessari |
CheckBounds restituisce inaspettatamente false | Le dimensioni passate a CheckBounds non corrispondono al contenitore in cui la forma è effettivamente disegnata | Passa 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/Metodo | Descrizione |
|---|---|
Graph | Contenitore 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 |
Shape | Base 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 |
Circle | Forma circolare: PosX(), PosY(), Radius() |
Ellipse | Forma ellittica: riquadro di delimitazione tramite Left(), Bottom(), Width(), Height() |
Line | Forma linea/percorso: PositionArray(), un std::vector<float> piatto di coordinate x, y |
GraphInfo | Stile tratto/pieno: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() |
BorderInfo | Bordo contenitore per lato: Left(), Right(), Top(), Bottom() (ognuno un GraphInfo), più RoundedBorderRadius() |
BorderSide | Enum che seleziona i bordi durante la costruzione di un BorderInfo: None, Left, Top, Right, Bottom, All, Box |