Малювання векторної графіки на сторінці 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 |