Dessiner des graphiques vectoriels sur une page PDF
Dessiner des graphiques vectoriels sur une page PDF
Aspose.PDF FOSS pour C++ inclut un petit API de graphiques vectoriels pour dessiner des formes directement sur une page PDF pendant la construction d’un document. Le point d’entrée est Graph, un conteneur placé sur une page qui contient une collection d’objets Shape ; trois formes concrètes — Circle, Ellipse et Line — dérivent de Shape et chacune exprime sa géométrie différemment. Le style de trait et de remplissage par forme provient de GraphInfo, et le conteneur Graph lui-même possède un BorderInfo pour le cadrage. Cela n’est pas lié à la rasterisation de page (BmpDevice, JpegDevice, TiffDevice), qui convertit le contenu existant d’une page en formats d’images raster plutôt que de dessiner une nouvelle géométrie.
Le conteneur de graphe et l’ajout de formes à une page
Graph se positionne et se dimensionne sur la page via Left(), Top(), Width() et Height(), et son indicateur IsChangePosition() contrôle si cette position peut se déplacer par rapport au reste du contenu de la page. Les formes qu’il dessine résident dans le vecteur renvoyé par Shapes() — std::vector<std::unique_ptr<Shape>> — qui est rempli en construisant une forme, en la configurant, puis en la déplaçant dans ce vecteur. Une fois construite, la Graph elle-même est placée sur la page via Page.Paragraphs().Add(), la même collection utilisée pour les autres contenus au niveau de la page.
#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");Dessiner des cercles et des ellipses
Circle et Ellipse expriment chacun la géométrie sous forme de propriétés numériques simples plutôt qu’un type point ou rectangle partagé. Circle est un point central et un rayon — PosX(), PosY(), Radius() — tandis que Ellipse est une boîte englobante — Left(), Bottom(), Width(), Height(). Les deux héritent de CheckBounds(containerWidth, containerHeight) depuis Shape, qui indique si la géométrie actuelle de la forme tient à l’intérieur d’un conteneur de la taille donnée sans modifier la forme elle-même.
#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);Dessiner des lignes avec PositionArray
Line stocke sa géométrie différemment de Circle et Ellipse: PositionArray() renvoie un std::vector<float> plat contenant une paire x, y pour chaque point traversé par la ligne, plutôt qu’un ensemble fixe de propriétés nommées. Deux points (quatre valeurs) dessinent un segment droit; des paires supplémentaires dessinent un chemin à plusieurs segments à travers ces points dans l’ordre. Comme les autres formes, Line remplace CheckBounds(containerWidth, containerHeight) de 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);Styliser les formes avec GraphInfo et BorderInfo
Chaque forme lit et écrit son style de contour et de remplissage via Shape.GraphInfo() / GraphInfo(value). GraphInfo utilise par défaut un LineWidth() de 1.0f avec un DashArray() vide, et expose également Color(), FillColor(), DashArray()/DashPhase() pour les contours pointillés, IsDoubled() pour une ligne doublée, et SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() et RotationAngle() pour transformer le contour. Graph possède lui-même un BorderInfo, défini via Border(), qui regroupe un GraphInfo par arête — Left(), Right(), Top(), Bottom() — plus un RoundedBorderRadius(), et peut être construit en nommant les arêtes à styliser avec un drapeau BorderSide (BorderSide::Left | BorderSide::Right, ou BorderSide::All pour chaque arête).
#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);Conseils et meilleures pratiques
- Appelez
CheckBoundssur leWidth()/Height()propre duGraphpropriétaire, pas sur la boîte média complète de la page— la vérification valide la géométrie d’une forme par rapport à la taille du conteneur que vous fournissez, elle ne regarde pas automatiquement la page. - Ajoutez les formes à
Shapes()avant d’ajouter leGraphàPage.Paragraphs()— la construction d’unCircle,EllipseouLinen’a aucun effet visible tant qu’elle n’est pas à la fois ajoutée à sonGraphpropriétaire et que ceGraphest ajouté à une page. - Regroupez les formes liées sous un seul
Graphplutôt que sous unGraphpar forme;Left()/Top()/Width()/Height()positionnent l’ensemble du conteneur une fois, et chaque forme dansShapes()est dessinée par rapport à celui-ci. - Définissez
Shape.GraphInfo()explicitement pour les formes qui nécessitent un remplissage visible ou un contour non par défaut— leGraphInfopar défaut a une largeur de ligne de1.0f, aucun remplissage et unDashArray()vide. - Construisez
Line.PositionArray()en tant que pairesx0, y0, x1, y1, …dans l’ordre où le chemin doit être tracé — un vecteur de longueur impaire décrit un point incomplet.
Problèmes courants
| Problème | Cause | Correction |
|---|---|---|
Un Circle, Ellipse ou Line n’apparaît jamais sur la page enregistrée | La forme a été construite mais n’a jamais été ajoutée à son Graph’s Shapes(), ou le Graph n’a jamais été ajouté à la page | Poussez la forme sur graph->Shapes() et appelez page.Paragraphs().Add(graph) |
| La forme se dessine avec un trait noir fin par défaut | Shape.GraphInfo() n’a jamais été défini | Appelez shape->GraphInfo(customGraphInfo) avant d’ajouter la forme à Shapes() |
Line est manquant ou ressemble à un point unique | PositionArray() contient moins de deux paires (x, y), ou un nombre impair de valeurs | Fournissez au moins quatre valeurs en tant que x0, y0, x1, y1 |
| Seules certaines arêtes de la bordure du conteneur sont stylisées | BorderInfo a été construit avec un masque BorderSide qui exclut certaines arêtes | Utilisez BorderSide::All, ou combinez avec OR chaque drapeau BorderSide nécessaire |
CheckBounds renvoie de façon inattendue false | Les dimensions passées à CheckBounds ne correspondent pas au conteneur dans lequel la forme est réellement dessinée | Passez le Width()/Height() actuel du Graph propriétaire |
FAQ
Quelle est la différence entre Circle et AnnotationType::Circle?
Circle (ce guide) est une forme de dessin qui dessine directement dans le contenu de la page via un Graph. AnnotationType::Circle et CircleAnnotation appartiennent à un API d’annotations distinct et représentent une annotation de balisage en forme de cercle — les deux ne sont pas liés malgré le nom commun.
Un seul Graph peut-il contenir plus d’une forme?
Oui. Graph.Shapes() renvoie le std::vector<std::unique_ptr<Shape>> complet pour ce conteneur, et tout mélange d’instances Circle, Ellipse et Line peut être ajouté avant que le Graph ne soit ajouté à la page.
Circle et Ellipse partagent-ils un même type de géométrie?
Non. Circle est un point central et un rayon (PosX, PosY, Radius); Ellipse est une boîte englobante (Left, Bottom, Width, Height). Les deux dérivent de Shape, mais aucun ne partage un point ou un type de rectangle commun avec l’autre.
Le dessin de formes avec Graph est-il identique au rendu d’une page sous forme d’image?
Non. Graph, Shape, Circle, Ellipse et Line créent une nouvelle géométrie vectorielle dans le contenu d’une page lors de la génération du document. Convertir une page existante en image raster est une capacité distincte, gérée par BmpDevice, JpegDevice et TiffDevice.
Que fait GraphInfo.IsDoubled()?
Il marque le trait comme une ligne double plutôt que de modifier une autre propriété du trait. C’est un drapeau booléen lu et défini via IsDoubled()/IsDoubled(value) aux côtés des autres propriétés de trait GraphInfo.
Résumé API Reference
| Classe/Méthode | Description |
|---|---|
Graph | Conteneur de forme placé sur une page ; se positionne avec Left(), Top(), Width(), Height() |
Graph.Shapes() | Renvoie le std::vector<std::unique_ptr<Shape>> dessiné par ce conteneur |
Graph.GraphInfo() / GraphInfo(value) | Obtient/définit le style de contour et de remplissage propre du conteneur |
Graph.Border() / Border(value) | Obtient/définit le BorderInfo encadrant le conteneur |
Shape | Base abstraite pour Circle, Ellipse et Line; expose GraphInfo() et CheckBounds() |
Shape.CheckBounds(w, h) | Rapporte si la géométrie de la forme s’adapte à l’intérieur d’un conteneur de la largeur/hauteur donnée |
Circle | Forme circulaire : PosX(), PosY(), Radius() |
Ellipse | Forme elliptique : boîte englobante via Left(), Bottom(), Width(), Height() |
Line | Forme de ligne/chemin : PositionArray(), un std::vector<float> plat de coordonnées x, y |
GraphInfo | Style du trait/remplissage: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() |
BorderInfo | Bordure du conteneur par arête: Left(), Right(), Top(), Bottom() (chacun étant un GraphInfo), plus RoundedBorderRadius() |
BorderSide | Enum sélectionnant les arêtes lors de la construction d’un BorderInfo: None, Left, Top, Right, Bottom, All, Box |