Vẽ Đồ Họa Vector trên Trang PDF

Vẽ Đồ Họa Vector trên Trang PDF

Vẽ Đồ Họa Vector trên Trang PDF

Aspose.PDF FOSS cho C++ bao gồm một API đồ họa vector nhỏ để vẽ các hình dạng trực tiếp lên trang PDF trong quá trình xây dựng tài liệu. Điểm vào là Graph, một container đặt trên trang và chứa một tập hợp các đối tượng Shape; ba hình dạng cụ thể — Circle, Ellipse và Line — kế thừa từ Shape và mỗi cái biểu diễn hình học của mình theo cách khác nhau. Kiểu dáng nét và màu nền cho từng hình được lấy từ GraphInfo, và container Graph tự nó mang một BorderInfo để đóng khung. Điều này không liên quan đến raster hóa trang (BmpDevice, JpegDevice, TiffDevice), vốn chuyển đổi nội dung trang hiện có sang các định dạng ảnh raster thay vì vẽ hình học mới.


Container Đồ Thị và Thêm Hình Dạng vào Trang

Graph định vị và xác định kích thước của mình trên trang thông qua Left(), Top(), Width() và Height(), và cờ IsChangePosition() của nó kiểm soát việc vị trí này có thể dịch chuyển so với nội dung trang khác hay không. Các hình dạng mà nó vẽ tồn tại trong vector do Shapes() trả về — std::vector<std::unique_ptr<Shape>> — được lấp đầy bằng cách tạo một hình dạng, cấu hình nó, và đưa nó vào vector đó. Khi đã được xây dựng, Graph tự nó được đặt trên trang qua Page.Paragraphs().Add(), cùng bộ sưu tập được dùng cho các nội dung cấp trang khác.

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

Vẽ Các Hình Tròn và Hình Bầu Dục

Circle và Ellipse mỗi cái biểu diễn hình học dưới dạng các thuộc tính số thuần túy thay vì một kiểu điểm hoặc hình chữ nhật chung. Circle là một điểm trung tâm và bán kính — PosX(), PosY(), Radius() — trong khi Ellipse là một hộp bao — Left(), Bottom(), Width(), Height(). Cả hai đều kế thừa CheckBounds(containerWidth, containerHeight) từ Shape, cái mà báo cáo liệu hình dạng hiện tại có vừa trong một container có kích thước cho trước mà không thay đổi hình dạng đó.

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

Vẽ Đường Thẳng với PositionArray

Line lưu trữ hình học của nó khác với Circle và Ellipse: PositionArray() trả về một std::vector<float> phẳng chứa một cặp x, y cho mỗi điểm mà đường đi qua, thay vì một tập hợp các thuộc tính có tên cố định. Hai điểm (bốn giá trị) vẽ một đoạn thẳng; các cặp bổ sung vẽ một đường đa đoạn qua các điểm đó theo thứ tự. Giống như các hình khác, Line ghi đè CheckBounds(containerWidth, containerHeight) từ 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);

Định dạng các hình dạng với GraphInfo và BorderInfo

Mỗi hình dạng đọc và ghi kiểu dáng nét vẽ và tô đầy thông qua Shape.GraphInfo() / GraphInfo(value). GraphInfo mặc định là một LineWidth() của 1.0f với một DashArray() trống, và cũng cung cấp Color(), FillColor(), DashArray()/DashPhase() cho nét đứt, IsDoubled() cho đường đôi, và SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY(), và RotationAngle() để biến đổi nét vẽ. Graph tự nó chứa một BorderInfo, được đặt qua Border(), nhóm một GraphInfo cho mỗi cạnh — Left(), Right(), Top(), Bottom() — cộng thêm một RoundedBorderRadius(), và có thể được tạo bằng cách chỉ định các cạnh cần định dạng với cờ BorderSide (BorderSide::Left | BorderSide::Right, hoặc BorderSide::All cho mọi cạnh).

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

Mẹo và Thực hành Tốt nhất

  • Gọi CheckBounds trên Width()/Height() của Graph sở hữu, không phải toàn bộ khung media của trang — kiểm tra xác thực hình học của một hình dựa trên kích thước container bạn truyền vào, nó không tự động xem xét trang.
  • Thêm các hình vào Shapes() trước khi thêm Graph vào Page.Paragraphs() — việc tạo một Circle, Ellipse hoặc Line không có hiệu ứng nào cho tới khi nó vừa được nối vào Graph sở hữu và Graph đó được thêm vào một trang.
  • Nhóm các hình liên quan dưới một Graph duy nhất thay vì một Graph cho mỗi hình; Left()/Top()/Width()/Height() định vị toàn bộ container một lần, và mọi hình trong Shapes() được vẽ tương đối so với nó.
  • Thiết lập Shape.GraphInfo() một cách rõ ràng cho các hình cần tô đầy nhìn thấy hoặc nét vẽ không mặc định — GraphInfo mặc định có độ rộng đường 1.0f, không có tô, và một DashArray() trống.
  • Xây dựng Line.PositionArray() dưới dạng các cặp x0, y0, x1, y1, … theo thứ tự đường dẫn cần vẽ — một vector có độ dài lẻ mô tả một điểm không hoàn chỉnh.

Các vấn đề thường gặp

Vấn đềNguyên nhânCách khắc phục
Một Circle, Ellipse, hoặc Line không bao giờ xuất hiện trên trang đã lưuHình dạng đã được tạo nhưng không bao giờ được gắn vào Shapes() của Graph, hoặc Graph không bao giờ được thêm vào trangĐẩy hình dạng lên graph->Shapes() và gọi page.Paragraphs().Add(graph)
Hình dạng được vẽ với đường viền mỏng đen mặc địnhShape.GraphInfo() không bao giờ được đặtGọi shape->GraphInfo(customGraphInfo) trước khi thêm hình vào Shapes()
Line bị thiếu hoặc trông giống một điểm duy nhấtPositionArray() có ít hơn hai cặp (x, y), hoặc số giá trị lẻCung cấp ít nhất bốn giá trị dưới dạng x0, y0, x1, y1
Chỉ một số cạnh của viền container được định kiểuBorderInfo được xây dựng bằng mặt nạ BorderSide loại trừ một số cạnhSử dụng BorderSide::All, hoặc OR tất cả các cờ BorderSide cần thiết
CheckBounds bất ngờ trả về falseKích thước được truyền vào CheckBounds không khớp với container mà hình dạng thực sự được vẽ trong đóChuyển Width()/Height() hiện tại của Graph sở hữu

FAQ

Sự khác nhau giữa Circle và AnnotationType::Circle là gì?

Circle (hướng dẫn này) là một hình vẽ mà vẽ trực tiếp vào nội dung trang thông qua một Graph. AnnotationType::Circle và CircleAnnotation thuộc về một API chú thích riêng biệt và đại diện cho một chú thích dạng vòng tròn — hai thứ này không liên quan mặc dù có cùng tên.

Một Graph duy nhất có thể chứa nhiều hơn một hình không?

Có. Graph.Shapes() trả về toàn bộ std::vector<std::unique_ptr<Shape>> cho container đó, và bất kỳ sự kết hợp nào của các thể hiện Circle, Ellipse và Line đều có thể được thêm vào trước khi Graph được đưa vào trang.

Circle và Ellipse có cùng loại hình học không?

Không. Circle là một điểm trung tâm và bán kính (PosX, PosY, Radius); Ellipse là một hộp bao quanh (Left, Bottom, Width, Height). Cả hai đều xuất phát từ Shape, nhưng không có điểm chung hay loại hình chữ nhật nào chung với nhau.

Việc vẽ các hình dạng bằng Graph có giống như việc render một trang thành hình ảnh không?

Không. Graph, Shape, Circle, Ellipse và Line xây dựng hình học vector mới vào nội dung của trang khi tài liệu được tạo. Việc chuyển đổi một trang hiện có thành hình ảnh raster là một khả năng riêng biệt, được xử lý bởi BmpDevice, JpegDevice và TiffDevice.

Hàm GraphInfo.IsDoubled() làm gì?

Nó đánh dấu nét vẽ là một đường gấp đôi thay vì thay đổi bất kỳ thuộc tính nét vẽ nào khác. Đây là một cờ boolean được đọc và thiết lập qua IsDoubled() / IsDoubled(value) cùng với các thuộc tính nét vẽ GraphInfo khác.


API Reference Tóm tắt

Lớp/Phương thứcMô tả
GraphContainer hình dạng được đặt trên trang; định vị bản thân bằng Left(), Top(), Width(), Height()
Graph.Shapes()Trả về std::vector<std::unique_ptr<Shape>> do container này vẽ
Graph.GraphInfo() / GraphInfo(value)Lấy/đặt kiểu stroke và fill của container
Graph.Border() / Border(value)Lấy/đặt BorderInfo đóng khung container
ShapeCơ sở trừu tượng cho Circle, Ellipse và Line; công khai GraphInfo() và CheckBounds()
Shape.CheckBounds(w, h)Báo cáo liệu hình học của hình dạng có vừa trong một container có độ rộng/chiều cao cho trước hay không
CircleHình tròn: PosX(), PosY(), Radius()
EllipseHình elip: hộp bao qua Left(), Bottom(), Width(), Height()
LineHình đường/đường dẫn: PositionArray(), một std::vector<float> phẳng của các tọa độ x, y
GraphInfoKiểu dáng nét vẽ/lấp đầy: LineWidth(), Color(), FillColor(), DashArray(), DashPhase(), IsDoubled(), RotationAngle(), SkewAngleX()/SkewAngleY(), ScalingRateX()/ScalingRateY()
BorderInfoViền container mỗi cạnh: Left(), Right(), Top(), Bottom() (mỗi là GraphInfo), cộng thêm RoundedBorderRadius()
BorderSideEnum chọn các cạnh khi xây dựng một BorderInfo: None, Left, Top, Right, Bottom, All, Box

Xem thêm

 Tiếng Việt