Vektorgrafiken auf einer PDF-Seite zeichnen

Vektorgrafiken auf einer PDF-Seite zeichnen

Vektorgrafiken auf einer PDF-Seite zeichnen

Aspose.PDF FOSS für C++ enthält ein kleines Vektorgrafik-API zum direkten Zeichnen von Formen auf einer PDF-Seite, während ein Dokument erstellt wird. Der Einstiegspunkt ist Graph, ein Container, der auf einer Seite platziert wird und eine Sammlung von Shape-Objekten hält; drei konkrete Formen — Circle, Ellipse und Line — leiten von Shape ab und geben jeweils ihre Geometrie unterschiedlich wieder. Die Strich- und Füllstilistik pro Form stammt von GraphInfo, und der Graph-Container selbst trägt ein BorderInfo zum Rahmen. Dies ist nicht verwandt mit der Seitenrasterisierung (BmpDevice, JpegDevice, TiffDevice), die vorhandenen Seiteninhalt in Rasterbildformate konvertiert, anstatt neue Geometrie zu zeichnen.


Der Graph-Container und das Hinzufügen von Formen zu einer Seite

Graph positioniert und skaliert sich selbst auf der Seite über Left(), Top(), Width() und Height(), und sein IsChangePosition()-Flag steuert, ob diese Position relativ zu anderem Seiteninhalt verschoben werden kann. Die Formen, die es zeichnet, befinden sich im Vektor, der von Shapes() zurückgegeben wird — std::vector<std::unique_ptr<Shape>> — und werden gefüllt, indem man eine Form konstruiert, konfiguriert und auf diesen Vektor verschiebt. Sobald sie gebaut ist, wird der Graph selbst über Page.Paragraphs().Add() auf der Seite platziert, dieselbe Sammlung, die für anderen Seiteninhalt verwendet wird.

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

Kreise und Ellipsen zeichnen

Circle und Ellipse geben jeweils die Geometrie als einfache numerische Eigenschaften wieder, anstatt einen gemeinsamen Punkt- oder Rechtecktyp zu verwenden. Circle ist ein Mittelpunkt und ein Radius — PosX(), PosY(), Radius() —, während Ellipse ein Begrenzungsrahmen ist — Left(), Bottom(), Width(), Height(). Beide erben CheckBounds(containerWidth, containerHeight) von Shape, das meldet, ob die aktuelle Geometrie der Form in einen Container der angegebenen Größe passt, ohne die Form selbst zu verändern.

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

Linien zeichnen mit PositionArray

Line speichert seine Geometrie anders als Circle und Ellipse: PositionArray() liefert ein flaches std::vector<float>, das ein x-y-Paar für jeden Punkt enthält, den die Linie durchläuft, anstatt einer festen Menge benannter Eigenschaften. Zwei Punkte (vier Werte) erzeugen ein gerades Segment; zusätzliche Paare erzeugen einen mehrsegmentigen Pfad durch diese Punkte in der Reihenfolge. Wie die anderen Formen überschreibt Line CheckBounds(containerWidth, containerHeight) von 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);

Gestalten von Formen mit GraphInfo und BorderInfo

Jede Form liest und schreibt ihr Strich- und Füll-Styling über Shape.GraphInfo() / GraphInfo(value). GraphInfo verwendet standardmäßig ein LineWidth() von 1.0f mit einem leeren DashArray() und stellt außerdem Color(), FillColor(), DashArray()/DashPhase() für gestrichelte Striche, IsDoubled() für eine doppelte Linie sowie SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() und RotationAngle() für die Transformation des Strichs bereit. Graph selbst enthält ein BorderInfo, das über Border() gesetzt wird und ein GraphInfo pro Kante gruppiert – Left(), Right(), Top(), Bottom() – plus ein RoundedBorderRadius(), und kann erstellt werden, indem man angibt, welche Kanten mit einem BorderSide-Flag zu stylen sind (BorderSide::Left | BorderSide::Right oder BorderSide::All für jede Kante).

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

Tipps und bewährte Verfahren

  • Rufen Sie CheckBounds gegenüber dem eigenen Width()/Height() des besitzenden Graph auf, nicht gegenüber der gesamten Medienbox der Seite — die Prüfung validiert die Geometrie einer Form gegen die von Ihnen übergebene Containergröße und betrachtet die Seite nicht automatisch.
  • Fügen Sie Formen zu Shapes() hinzu, bevor Sie das Graph zu Page.Paragraphs() hinzufügen — das Erstellen eines Circle, Ellipse oder Line hat keine sichtbare Wirkung, bis es sowohl an sein besitzendes Graph angehängt wurde als auch dieses Graph einer Seite hinzugefügt wird.
  • Gruppieren Sie verwandte Formen unter einem einzigen Graph statt je einem Graph pro Form; Left()/Top()/Width()/Height() positionieren den gesamten Container einmal, und jede Form in Shapes() wird relativ zu ihm gezeichnet.
  • Setzen Sie Shape.GraphInfo() explizit für Formen, die eine sichtbare Füllung oder einen nicht-Standard-Strich benötigen — das Standard-GraphInfo hat eine 1.0f Linienbreite, keine Füllung und ein leeres DashArray().
  • Erstelle Line.PositionArray() als x0, y0, x1, y1, …-Paare in der Reihenfolge, in der der Pfad gezeichnet werden soll — ein Vektor ungerader Länge beschreibt einen unvollständigen Punkt.

Häufige Probleme

ProblemUrsacheLösung
Ein Circle, Ellipse oder Line erscheint nie auf der gespeicherten SeiteDie Form wurde konstruiert, wurde aber nie an das Graphs Shapes() angehängt, oder das Graph wurde nie zur Seite hinzugefügtFüge die Form zu graph->Shapes() hinzu und rufe page.Paragraphs().Add(graph) auf
Form wird mit einem standardmäßigen dünnen schwarzen Strich gezeichnetShape.GraphInfo() wurde nie gesetztRufen Sie shape->GraphInfo(customGraphInfo) auf, bevor Sie die Form an Shapes() anhängen
Line fehlt oder sieht aus wie ein einzelner PunktPositionArray() hat weniger als zwei (x, y)-Paare oder eine ungerade Anzahl von WertenGeben Sie mindestens vier Werte als x0, y0, x1, y1 an
Nur einige Kanten des Containerrahmens sind gestyltBorderInfo wurde mit einer BorderSide-Maske konstruiert, die einige Kanten ausschließtVerwenden Sie BorderSide::All, oder ORen Sie alle benötigten BorderSide-Flags
CheckBounds gibt unerwartet false zurückDie an CheckBounds übergebenen Dimensionen stimmen nicht mit dem Container überein, in dem die Form tatsächlich gezeichnet wirdÜbergib das aktuelle Width()/Height() des besitzenden Graph

FAQ

Was ist der Unterschied zwischen Circle und AnnotationType::Circle?

Circle (dieser Leitfaden) ist eine Zeichenform, die direkt in den Seiteninhalt über ein Graph zeichnet. AnnotationType::Circle und CircleAnnotation gehören zu einem separaten Annotations API und stellen stattdessen eine kreisförmige Markup-Annotation dar — die beiden sind trotz des gemeinsamen Namens nicht miteinander verbunden.

Kann ein einzelner Graph mehr als eine Form enthalten?

Ja. Graph.Shapes() gibt das vollständige std::vector<std::unique_ptr<Shape>> für diesen Container zurück, und jede Mischung aus Circle, Ellipse und Line-Instanzen kann angehängt werden, bevor Graph zur Seite hinzugefügt wird.

Teilen Circle und Ellipse einen Geometrietyp?

Nr. Circle ist ein Mittelpunkt und Radius (PosX, PosY, Radius); Ellipse ist ein Begrenzungsrahmen (Left, Bottom, Width, Height). Beide leiten sich von Shape ab, aber keiner teilt einen gemeinsamen Punkt- oder Rechtecktyp mit dem anderen.

Ist das Zeichnen von Formen mit Graph dasselbe wie das Rendern einer Seite zu einem Bild?

Nein. Graph, Shape, Circle, Ellipse und Line erzeugen neue Vektorgeometrie im Seiteninhalt, während das Dokument erstellt wird. Das Konvertieren einer bestehenden Seite in ein Rasterbild ist eine separate Fähigkeit, die von BmpDevice, JpegDevice und TiffDevice übernommen wird.

Was macht GraphInfo.IsDoubled()?

Es markiert den Strich als doppelte Linie, anstatt irgendeine andere Strich-Eigenschaft zu ändern. Es ist ein boolesches Flag, das über IsDoubled() / IsDoubled(value) ausgelesen und gesetzt wird, zusammen mit den anderen GraphInfo Strich-Eigenschaften.


API Reference Zusammenfassung

Klasse/MethodeBeschreibung
GraphForm-Container, der auf einer Seite platziert wird; positioniert sich mit Left(), Top(), Width(), Height()
Graph.Shapes()Gibt das von diesem Container gezeichnete std::vector<std::unique_ptr<Shape>> zurück
Graph.GraphInfo() / GraphInfo(value)Liest/Setzt das eigene Strich- und Füllstyling des Containers
Graph.Border() / Border(value)Liest/Setzt die BorderInfo, die den Container umrahmt
ShapeAbstrakte Basisklasse für Circle, Ellipse und Line; stellt GraphInfo() und CheckBounds() bereit
Shape.CheckBounds(w, h)Gibt an, ob die Geometrie der Form in einen Container der angegebenen Breite/Höhe passt
CircleKreisform: PosX(), PosY(), Radius()
EllipseEllipse-Form: Begrenzungsrahmen via Left(), Bottom(), Width(), Height()
LineLinien-/Pfadform: PositionArray(), ein flaches std::vector<float> aus x-, y-Koordinaten
GraphInfoStrich-/Füllstil: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY()
BorderInfoPro-Kanten-Container-Rand: Left(), Right(), Top(), Bottom() (je ein GraphInfo), plus RoundedBorderRadius()
BorderSideEnum, das Kanten auswählt beim Erstellen eines BorderInfo: None, Left, Top, Right, Bottom, All, Box

Siehe auch

 Deutsch