Малювання векторної графіки на сторінці PDF

Малювання векторної графіки на сторінці PDF

Малювання векторної графіки на сторінці PDF

Aspose.PDF FOSS для C++ включає невеликий векторний графічний API для малювання фігур безпосередньо на сторінці PDF під час створення документа. Точкою входу є Graph, контейнер, розташований на сторінці, який містить колекцію об’єктів Shape; три конкретні форми — Circle, Ellipse та Line — успадковують Shape і кожна виражає свою геометрію по-різному. Стиль обведення та заповнення для кожної форми береться з GraphInfo, а сам контейнер Graph містить BorderInfo для обрамлення. Це не пов’язано з растеризацією сторінки (BmpDevice, JpegDevice, TiffDevice), яка перетворює існуючий вміст сторінки у растрові формати зображень, а не малює нову геометрію.


Контейнер графа та додавання форм на сторінку

Graph позиціонує та розмірює себе на сторінці за допомогою Left(), Top(), Width() та Height(), а його прапорець IsChangePosition() контролює, чи може ця позиція зміщуватись щодо іншого вмісту сторінки. Форми, які він малює, знаходяться у векторі, що повертається Shapes() — std::vector<std::unique_ptr<Shape>> — заповненому шляхом створення форми, її налаштування та переміщення у цей вектор. Після створення сам Graph розміщується на сторінці через Page.Paragraphs().Add(), ту ж колекцію, що використовується для іншого вмісту рівня сторінки.

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

Малювання кіл та еліпсів

Circle і Ellipse кожен виражає геометрію як прості числові властивості, а не як спільний тип точки або прямокутника. Circle — це центр і радіус — PosX(), PosY(), Radius() — тоді як Ellipse — це обмежувальний прямокутник — Left(), Bottom(), Width(), Height(). Обидва успадковують CheckBounds(containerWidth, containerHeight) від Shape, який повідомляє, чи поточна геометрія форми поміщається у контейнер заданого розміру без зміни самої форми.

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

Малювання ліній за допомогою PositionArray

Line зберігає свою геометрію інакше, ніж Circle і Ellipse: PositionArray() повертає плоский std::vector<float>, що містить пару x, y для кожної точки, через яку проходить лінія, замість фіксованого набору іменованих властивостей. Дві точки (чотири значення) малюють прямий сегмент; додаткові пари малюють багатосегментний шлях через ці точки у порядку. Як і інші форми, Line перевизначає CheckBounds(containerWidth, containerHeight) з 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);

Стилізація форм за допомогою GraphInfo і BorderInfo

Кожна форма читає і записує стиль обводки та заповнення через Shape.GraphInfo() / GraphInfo(value). GraphInfo за замовчуванням має LineWidth() 1.0f з порожнім DashArray(), і також надає Color(), FillColor(), DashArray()/DashPhase() для пунктирних обводок, IsDoubled() для подвоєної лінії, та SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY() і RotationAngle() для трансформації обводки. Graph сам по собі містить BorderInfo, встановлюваний через Border(), який групує один GraphInfo на кожному краю — Left(), Right(), Top(), Bottom() — плюс RoundedBorderRadius(), і може бути створений шляхом вказання, які краї стилізувати за допомогою прапорця BorderSide (BorderSide::Left | BorderSide::Right або BorderSide::All для всіх країв).

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

Поради та найкращі практики

  • Викликайте CheckBounds проти власного Width()/Height() у Graph, а не проти повного медіа-боксу сторінки — перевірка валідовує геометрію форми щодо розміру контейнера, який ви передаєте, і не переглядає сторінку автоматично.
  • Додавайте форми до Shapes() перед тим, як додавати Graph у Page.Paragraphs() — створення Circle, Ellipse або Line не має видимого ефекту, доки воно не буде додане до свого власника Graph і цей Graph не буде доданий до сторінки.
  • Групуйте пов’язані форми під одним Graph, а не по одному Graph на форму; Left()/Top()/Width()/Height() позиціонують весь контейнер один раз, і кожна форма в Shapes() малюється відносно нього.
  • Встановіть Shape.GraphInfo() явно для форм, яким потрібне видиме заповнення або нестандартна обводка — за замовчуванням GraphInfo має ширину лінії 1.0f, без заповнення і порожній DashArray().
  • Створіть Line.PositionArray() як пари x0, y0, x1, y1, … у порядку, в якому має малюватись шлях — вектор непарної довжини описує неповну точку.

Типові проблеми

ПроблемаПричинаВиправлення
Circle, Ellipse або Line ніколи не з’являються на збереженій сторінціФорма була створена, але її ніколи не додали до Graph’s Shapes(), або Graph ніколи не було додано на сторінкуДодайте форму до graph->Shapes() і викличте page.Paragraphs().Add(graph)
Форма малюється з тонким чорним контуром за замовчуваннямShape.GraphInfo() ніколи не було встановленоВикличте shape->GraphInfo(customGraphInfo) перед додаванням форми до Shapes()
Line відсутній або виглядає як одна точкаPositionArray() має менше двох пар (x, y) або непарну кількість значеньНадайте принаймні чотири значення як x0, y0, x1, y1
Тільки деякі краї межі контейнера стилізованіBorderInfo був створений за допомогою маски BorderSide, яка виключає деякі країВикористайте BorderSide::All, або OR разом усі потрібні прапорці BorderSide
CheckBounds неочікувано повертає falseРозміри, передані до CheckBounds, не відповідають контейнеру, у якому фактично намальовано формуПередайте поточний Width()/Height() власника Graph

FAQ

У чому різниця між Circle і AnnotationType::Circle?

Circle (цей посібник) — це форма малювання, яка малює безпосередньо вміст сторінки через Graph. AnnotationType::Circle і CircleAnnotation належать до окремого набору анотацій API і представляють анотацію розмітки у формі кола — ці два поняття не пов’язані, незважаючи на спільну назву.

Чи може один Graph містити більше однієї форми?

Так. Graph.Shapes() повертає повний std::vector<std::unique_ptr<Shape>> для цього контейнера, і будь-яка комбінація екземплярів Circle, Ellipse та Line може бути додана до нього перед тим, як Graph буде додано на сторінку.

Чи мають Circle і Ellipse спільний тип геометрії?

№ Circle є центральною точкою та радіусом (PosX, PosY, Radius); Ellipse — це обмежувальний прямокутник (Left, Bottom, Width, Height). Обидва походять від Shape, але жоден не має спільної точки або типу прямокутника з іншим.

Чи є малювання форм за допомогою Graph таким же, як рендеринг сторінки у зображення?

Ні. Graph, Shape, Circle, Ellipse та Line створюють нову векторну геометрію вмісту сторінки під час генерації документа. Перетворення існуючої сторінки у растрове зображення — окрема можливість, яку обробляють BmpDevice, JpegDevice та TiffDevice.

Що робить GraphInfo.IsDoubled()?

Воно позначає штрих як подвійну лінію, а не змінює інші властивості штриха. Це булевий прапорець, який читається та встановлюється через IsDoubled() / IsDoubled(value) разом з іншими властивостями штриха GraphInfo.


API Reference Підсумок

Клас/МетодОпис
GraphКонтейнер форми, розташований на сторінці; позиціонує себе за допомогою Left(), Top(), Width(), Height()
Graph.Shapes()Повертає std::vector<std::unique_ptr<Shape>>, намальований цим контейнером
Graph.GraphInfo() / GraphInfo(value)Отримує/встановлює власний стиль обведення та заповнення контейнера
Graph.Border() / Border(value)Отримує/встановлює BorderInfo, що обрамлює контейнер
ShapeАбстрактна база для Circle, Ellipse та Line; надає GraphInfo() і CheckBounds()
Shape.CheckBounds(w, h)Повідомляє, чи геометрія форми поміщається в контейнер заданої ширини/висоти
CircleКругова форма: PosX(), PosY(), Radius()
EllipseФорма еліпса: обмежувальна рамка за допомогою Left(), Bottom(), Width(), Height()
LineФорма лінії/шляху: PositionArray(), плоска std::vector<float> координат x, y
GraphInfoСтилізація обведення/заповнення: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY()
BorderInfoКонтур контейнера по кожному краю: Left(), Right(), Top(), Bottom() (кожен – GraphInfo), плюс RoundedBorderRadius()
BorderSideПерелічення, що вибирає ребра при побудові BorderInfo: None, Left, Top, Right, Bottom, All, Box

Дивіться також

 Українська