PDF SDK Documentation

Comprehensive Guide for Developers: Features, Integration, and API Reference

Loading...
Searching...
No Matches
graphics.h
1// Copyright (c) 2009-2025 Avanquest Software. All rights reserved.
2
3#ifndef PDFSDK_CXX_GRAPHICS_H_INCLUDED_
4#define PDFSDK_CXX_GRAPHICS_H_INCLUDED_
5
6#include <cstdint>
7#include <filesystem>
8#include <format>
9#include <functional>
10#include <memory>
11#include <optional>
12#include <string>
13#include <string_view>
14#include <vector>
15
16#include <pdfsdk/cxx/bytes.h>
17#include <pdfsdk/cxx/callback.h>
18#include <pdfsdk/cxx/helpers.h>
19#include <pdfsdk/cxx/math.h>
20#include <pdfsdk/cxx/read_stream.h>
21#include <pdfsdk/graphics.h>
22
23#include "wrapper_base.h"
24
25namespace PDF {
26namespace Graphics {
27
32class Palette : public detail::RefCountedHandle<GXPalette> {
33public:
34 static Palette New(const GXColorValue* colors, size_t num_colors) {
35 Palette palette;
36 auto ec = GXCreatePalette(colors, num_colors, &palette);
37 PDF_CHECK_SUCCESS(ec, "Failed to create a palette");
38 return palette;
39 }
40
41 const GXColorValue* GetColorsPtr() const {
42 const GXColorValue* colors = nullptr;
43 auto ec = GXPaletteGetColors(m_handle, &colors);
44 PDF_CHECK_SUCCESS(ec, "Failed to get palette colors");
45 return colors;
46 }
47
48 size_t GetNumColors() const {
49 size_t num_colors = 0;
50 auto ec = GXPaletteGetNumColors(m_handle, &num_colors);
51 PDF_CHECK_SUCCESS(ec, "Failed to get the number of palette colors");
52 return num_colors;
53 }
54
55 GXColorValue GetColor(size_t index) const {
56 GXColorValue color = 0;
57 auto ec = GXPaletteGetColor(m_handle, index, &color);
58 PDF_CHECK_SUCCESS(ec, "Failed to get palette color by index");
59 return color;
60 }
61
62 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Palette, GXPalette)
63};
64
69class Bitmap : public detail::RefCountedHandle<GXBitmap> {
70public:
71 static Bitmap New(const SizeI& size, GXPixelFormat format, float dpiX = 96, float dpiY = 96) {
72 Bitmap bitmap;
73 GXBitmapAttrs attrs = {size, format, dpiX, dpiY};
74 auto ec = GXCreateBitmap(&attrs, &bitmap);
75 PDF_CHECK_SUCCESS(ec, "Failed to create a bitmap");
76 return bitmap;
77 }
78
79 static Bitmap LoadFromFile(const std::filesystem::path& path, uint32_t frame_index = 0, uint32_t* ptotal_frames = nullptr) {
80 Bitmap bitmap;
81 auto path_string = path.wstring();
82 auto ec = GXCreateBitmapFromFileFrame(path_string.c_str(), frame_index, ptotal_frames, &bitmap);
83 PDF_CHECK_SUCCESS(ec, "Failed to load a bitmap from file");
84 return bitmap;
85 }
86
87 static Bitmap LoadFromMemory(std::span<const Byte> data, uint32_t frame_index = 0, uint32_t* ptotal_frames = nullptr) {
88 Bitmap bitmap;
89 auto ec = GXCreateBitmapFromMemoryFrame(data.data(), data.size(), frame_index, ptotal_frames, &bitmap);
90 PDF_CHECK_SUCCESS(ec, "Failed to load a bitmap from memory");
91 return bitmap;
92 }
93
94#if defined(_WIN32)
95 static Bitmap NewFromHBITMAP(void* hbitmap) {
96 Bitmap bitmap;
97 auto ec = GXCreateBitmapFromHBITMAP(hbitmap, &bitmap);
98 PDF_CHECK_SUCCESS(ec, "Failed to create a bitmap from HBITMAP");
99 return bitmap;
100 }
101#endif
102
103 void SaveToFile(const std::filesystem::path& path) const {
104 auto path_string = path.wstring();
105 auto ec = GXBitmapSaveToFile(m_handle, path_string.c_str());
106 PDF_CHECK_SUCCESS(ec, std::format("Failed to save the bitmap to {}", path.string()));
107 }
108
109#if defined(_WIN32)
110 void* SaveToHBITMAP() const {
111 void* hbitmap = NULL;
112 auto ec = GXBitmapSaveToHBITMAP(m_handle, &hbitmap);
113 PDF_CHECK_SUCCESS(ec, "Failed to save the bitmap to HBITMAP");
114 return hbitmap;
115 }
116#endif
117
118 GXPixelFormat GetPixelFormat() const {
120 auto ec = GXBitmapGetPixelFormat(m_handle, &format);
121 PDF_CHECK_SUCCESS(ec, "Failed to get the bitmap pixel format");
122 return format;
123 }
124
125 SizeI GetSize() const {
126 SizeI size;
127 auto ec = GXBitmapGetSize(m_handle, &size);
128 PDF_CHECK_SUCCESS(ec, "Failed to get the bitmap size");
129 return size;
130 }
131
132 float GetDpiX() const {
133 float dpix = 0.f;
134 auto ec = GXBitmapGetDpiX(m_handle, &dpix);
135 PDF_CHECK_SUCCESS(ec, "Failed to get the bitmap horz dpi");
136 return dpix;
137 }
138
139 float GetDpiY() const {
140 float dpiy = 0.f;
141 auto ec = GXBitmapGetDpiY(m_handle, &dpiy);
142 PDF_CHECK_SUCCESS(ec, "Failed to get the bitmap vert dpi");
143 return dpiy;
144 }
145
146 int GetBitsPerPixel() const {
147 GXPixelFormat format = GetPixelFormat();
148
149 switch (format) {
151 return 24;
152
156 return 32;
157
158 case kGXPixelFormatA8:
159 case kGXPixelFormatP8:
160 case kGXPixelFormatL8:
161 return 8;
162
163 case kGXPixelFormatA1:
164 case kGXPixelFormatP1:
165 case kGXPixelFormatL1:
166 return 1;
167
168 default:
169 return 32;
170 }
171 }
172
173 void SetPalette(const Palette& palette) {
174 auto ec = GXBitmapSetPalette(m_handle, palette.get());
175 PDF_CHECK_SUCCESS(ec, "Failed to set the bitmap palette");
176 }
177
178 Palette GetPalette() const {
179 Palette palette;
180 auto ec = GXBitmapGetPalette(m_handle, &palette);
181 PDF_CHECK_SUCCESS(ec, "Failed to get the bitmap palette");
182 return palette;
183 }
184
185 GXLockedData Lock(GXLockMode mode, const RectI* rect = nullptr) {
186 GXLockedData lockdata;
187 auto ec = GXBitmapLock(m_handle, rect, mode, &lockdata);
188 PDF_CHECK_SUCCESS(ec, "Failed to lock the bitmap");
189 return lockdata;
190 }
191
192 void Unlock() {
193 auto ec = GXBitmapUnlock(m_handle);
194 PDF_CHECK_SUCCESS(ec, "Failed to unlock the bitmap");
195 }
196
197 void CopyFromBitmap(const Bitmap& source, const RectI* source_rect = nullptr, const PointI* dest_point = nullptr) {
198 auto ec = GXBitmapCopyFromBitmap(m_handle, dest_point, source.get(), source_rect);
199 PDF_CHECK_SUCCESS(ec, "Failed to copy the bitmap");
200 }
201
202 void CopyFromMemory(const GXLockedData& memory, const RectI* dest_rect = nullptr) {
203 auto ec = GXBitmapCopyFromMemory(m_handle, dest_rect, &memory);
204 PDF_CHECK_SUCCESS(ec, "Failed to copy the bitmap");
205 }
206
207 void CopyToMemory(const GXLockedData& memory, const RectI* source_rect = nullptr) const {
208 auto ec = GXBitmapCopyToMemory(m_handle, source_rect, &memory);
209 PDF_CHECK_SUCCESS(ec, "Failed to copy the bitmap");
210 }
211
212 void ColorFill(GXColorValue color, const RectI* fill_rect = nullptr) {
213 auto ec = GXBitmapColorFill(m_handle, fill_rect, color);
214 PDF_CHECK_SUCCESS(ec, "Failed to fill the bitmap");
215 }
216
217 void NotifyChanged() {
218 auto ec = GXBitmapNotifyChanged(m_handle);
219 PDF_CHECK_SUCCESS(ec, "Failed to notify the bitmap change");
220 }
221
222 void SetOffscreenPainting(bool offscreen) {
223 auto ec = GXBitmapSetOffscreenPainting(m_handle, offscreen);
224 PDF_CHECK_SUCCESS(ec, "Failed to set the bitmap offscreen");
225 }
226
227 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Bitmap, GXBitmap)
228};
229
230struct BitmapScopedLock {
231 BitmapScopedLock(const Bitmap& bm, GXLockMode mode = kGXLockModeRead, const PDF::RectI* rectp = nullptr)
232 : bitmap(bm) {
233 data = bitmap.Lock(mode, rectp);
234 }
235 ~BitmapScopedLock() {
236 try {
237 bitmap.Unlock();
238 } catch (...) {
239 /* ignore */
240 }
241 }
242 Bitmap bitmap;
243 GXLockedData data;
244};
245
250class Geometry : public detail::RefCountedHandle<GXGeometry> {
251public:
252 static Geometry New() {
253 Geometry geom;
254 auto ec = GXCreateGeometry(&geom);
255 PDF_CHECK_SUCCESS(ec, "Failed to create a geometry");
256 return geom;
257 }
258
259 static Geometry NewFromRectangle(const PDF::RectF& rect) {
260 Geometry geom = New();
261 geom.Rectangle(rect);
262 return geom;
263 }
264
265 void SetFillRule(GXFillRule fillrule) {
266 auto ec = GXGeometrySetFillRule(m_handle, fillrule);
267 PDF_CHECK_SUCCESS(ec, "Failed to set the geometry fill rule");
268 }
269
270 GXFillRule GetFillRule() const {
272 auto ec = GXGeometryGetFillRule(m_handle, &fillrule);
273 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry fill rule");
274 return fillrule;
275 }
276
277 bool IsPointsEmpty() const {
278 bool empty = false;
279 auto ec = GXGeometryEmpty(m_handle, &empty);
280 PDF_CHECK_SUCCESS(ec, "Failed to check the geometry points");
281 return empty;
282 }
283
284 bool IsPointsEqual(const Geometry& rhs) const {
285 bool empty = false;
286 auto ec = GXGeometryPointsEqual(m_handle, rhs.get(), &empty);
287 PDF_CHECK_SUCCESS(ec, "Failed to check the geometry points");
288 return empty;
289 }
290
291 bool GetCurrentPoint(PointF* presult) const {
292 auto ec = GXGeometryGetCurrentPoint(m_handle, presult);
293 if (ec == kPDErrNotFound)
294 return false;
295 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry points");
296 return true;
297 }
298
299 RectF GetBound(const Matrix* xform = nullptr) const {
300 RectF bound;
301 auto ec = GXGeometryGetBound(m_handle, xform, &bound);
302 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry bound");
303 return bound;
304 }
305
306 RectF GetWidenBound(float lineWidth, const GXStrokeParams& params, const Matrix* xform = nullptr, float flatness = 0.75f) const {
307 if (Math::FloatEq(lineWidth, 0.0f))
308 lineWidth = flatness;
309 auto widenGeometry = Widen(lineWidth, params);
310 return widenGeometry.GetBound(xform);
311 }
312
313 void BeginFigure(const PointF& point) {
314 auto ec = GXGeometryBeginFigure(m_handle, &point);
315 PDF_CHECK_SUCCESS(ec, "Failed to begin figure");
316 }
317
318 void EndFigure() {
319 auto ec = GXGeometryEndFigure(m_handle);
320 PDF_CHECK_SUCCESS(ec, "Failed to end figure");
321 }
322
323 void EndFigureClose() {
324 auto ec = GXGeometryEndFigureClose(m_handle);
325 PDF_CHECK_SUCCESS(ec, "Failed to close figure");
326 }
327
328 void LineTo(const PointF& to) {
329 auto ec = GXGeometryLineTo(m_handle, &to);
330 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
331 }
332
333 void CurveTo(const PointF& c, const PointF& to) {
334 auto ec = GXGeometryConicCurveTo(m_handle, &c, &to);
335 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
336 }
337
338 void CurveTo(const PointF& c0, const PointF& c1, const PointF& to) {
339 auto ec = GXGeometryCubicCurveTo(m_handle, &c0, &c1, &to);
340 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
341 }
342
343 void Rectangle(const RectF& rect) {
344 auto ec = GXGeometryRectangle(m_handle, &rect);
345 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
346 }
347
348 void Ellipse(const RectF& bound) {
349 auto ec = GXGeometryEllipse(m_handle, &bound);
350 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
351 }
352
353 void RoundRectangle(const RectF& rect, float xradii, float yradii) {
354 auto ec = GXGeometryRoundRectangle(m_handle, &rect, xradii, yradii);
355 PDF_CHECK_SUCCESS(ec, "Failed to add points to the geometry");
356 }
357
358 Geometry Copy() const {
359 Geometry copy;
360 auto ec = GXGeometryCopy(m_handle, &copy);
361 PDF_CHECK_SUCCESS(ec, "Failed to copy the geometry");
362 return copy;
363 }
364
365 Geometry Transform(const Matrix& xform) const {
366 Geometry result;
367 auto ec = GXGeometryTransform(m_handle, &xform, &result);
368 PDF_CHECK_SUCCESS(ec, "Failed to transform the geometry");
369 return result;
370 }
371
372 Geometry Widen(float width, const GXStrokeParams& params, float flatness = 0.75) const {
373 Geometry result;
374 auto ec = GXGeometryWiden(m_handle, width, &params, flatness, &result);
375 PDF_CHECK_SUCCESS(ec, "Failed to widen the geometry");
376 return result;
377 }
378
379 Geometry Combine(GXCombineMode mode,
380 const Geometry& rhs,
381 const Matrix* xform = nullptr,
382 float flatness = 0.75) const {
383 Geometry result;
384 auto ec = GXGeometryCombine(m_handle, rhs.get(), xform, mode, flatness, &result);
385 PDF_CHECK_SUCCESS(ec, "Failed to combine the geometries");
386 return result;
387 }
388
389 bool HitTest(const PointF& point) const {
390 bool hit = false;
391 auto ec = GXGeometryHitTest(m_handle, &point, &hit);
392 PDF_CHECK_SUCCESS(ec, "Failed to hit test the geometry");
393 return hit;
394 }
395
396 Geometry Simplify(float flatness = 0.75) const {
397 Geometry result;
398 auto ec = GXGeometrySimplify(m_handle, flatness, &result);
399 PDF_CHECK_SUCCESS(ec, "Failed to simplify the geometries");
400 return result;
401 }
402
403 std::optional<RectF> IsRectangle(const Matrix& xform = Matrix{}) const {
404 bool isrectangle = false;
405 RectF rectangle;
406 auto ec = GXGeometryIsRectangle(m_handle, &xform, &isrectangle, &rectangle);
407 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry rectangle");
408 if (!isrectangle)
409 return std::nullopt;
410 return rectangle;
411 }
412
413 bool IsSingleLine() const {
414 if (GetNumFigures() > 1)
415 return false;
416
417 if (GetFigureNumPoints(0) != 2)
418 return false;
419
420 return true;
421 }
422
423 size_t GetNumFigures() const {
424 size_t numfigures = 0;
425 auto ec = GXGeometryGetNumFigures(m_handle, &numfigures);
426 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figures");
427 return numfigures;
428 }
429
430 size_t GetFigureNumSegments(size_t figureindex) const {
431 size_t numsegs = 0;
432 auto ec = GXGeometryGetFigureNumSegments(m_handle, figureindex, &numsegs);
433 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure segments");
434 return numsegs;
435 }
436
437 size_t GetFigureNumPoints(size_t figureindex) const {
438 size_t numpoints = 0;
439 auto ec = GXGeometryGetFigureNumPoints(m_handle, figureindex, &numpoints);
440 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure points");
441 return numpoints;
442 }
443
444 const PointF* GetFigurePointsPtr(size_t figureindex) const {
445 const PDPointF* points = nullptr;
446 auto ec = GXGeometryGetFigurePointsPtr(m_handle, figureindex, &points);
447 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure start point");
448 static_assert(sizeof(PointF) == sizeof(PDPointF), "Size of PointF and PDPointF must be equal");
449 return reinterpret_cast<const PointF*>(points);
450 }
451
452 bool IsFigureSegmentCurve(size_t figureindex, size_t segindex) const {
453 bool iscurve = false;
454 auto ec = GXGeometryIsFigureSegmentCurve(m_handle, figureindex, segindex, &iscurve);
455 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure segment points");
456 return iscurve;
457 }
458
459 size_t GetFigureSegmentPointsIndex(size_t figureindex, size_t segindex) const {
460 size_t pointsindex = 0;
461 auto ec = GXGeometryGetFigureSegmentPointsIndex(m_handle, figureindex, segindex, &pointsindex);
462 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure segment points");
463 return pointsindex;
464 }
465
466 bool IsFigureClosed(size_t figureindex) const {
467 bool isclosed = false;
468 auto ec = GXGeometryIsFigureClosed(m_handle, figureindex, &isclosed);
469 PDF_CHECK_SUCCESS(ec, "Failed to get the geometry figure closed");
470 return isclosed;
471 }
472
473 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Geometry, GXGeometry)
474};
475
480class SystemFont : public detail::RefCountedHandle<GXSysFont> {
481public:
482 std::wstring GetFamilyName() const {
483 return detail::GetWstringProperty(GXSysFontGetFamilyName, m_handle);
484 }
485
486 std::wstring GetPostScriptName() const {
487 return detail::GetWstringProperty(GXSysFontGetPostScriptName, m_handle);
488 }
489
490 std::wstring GetFontName() const {
491 return detail::GetWstringProperty(GXSysFontGetFontName, m_handle);
492 }
493
494 GXFontStyle GetStyle() const {
496 PDF_CHECK_SUCCESS_X(GXSysFontGetStyle(m_handle, &style));
497 return style;
498 }
499
500 GXFontFlags GetFontFlags() const {
501 GXFontFlags flags = 0;
502 PDF_CHECK_SUCCESS_X(GXSysFontGetFontFlags(m_handle, &flags));
503 return flags;
504 }
505
506 std::vector<GXUnicodeRange> GetUnicodeRanges() const {
507 size_t num_ranges = 0;
508 auto ec = GXSysFontGetUnicodeRanges(m_handle, nullptr, 0, &num_ranges);
509 if (ec == kPDErrSuccess)
510 return {};
511 if (ec != kPDErrBufferTooSmall)
512 PDF_CHECK_SUCCESS_X(ec);
513 std::vector<GXUnicodeRange> ranges(num_ranges);
514 PDF_CHECK_SUCCESS_X(GXSysFontGetUnicodeRanges(m_handle, ranges.data(), num_ranges, &num_ranges));
515 return ranges;
516 }
517
518 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(SystemFont, GXSysFont)
519};
520
521inline std::vector<SystemFont> ListSystemFonts() {
522 std::vector<SystemFont> fonts;
523 auto ec = GXEnumSysFonts(
524 [](void* userdata, GXSysFont sysfont) -> PDErrCode {
525 PDFSDK_CALLBACK_BEGIN
526 auto fonts = static_cast<std::vector<SystemFont>*>(userdata);
527 fonts->emplace_back(sysfont);
528 return kPDErrSuccess;
529 PDFSDK_CALLBACK_END
530 },
531 &fonts);
532 PDF_CHECK_SUCCESS_X(ec);
533 return fonts;
534}
535
536inline SystemFont FindSystemFont(const GXSysFontQuery& query) {
537 SystemFont sysfont;
538 auto ec = GXFindSysFont(&query, &sysfont);
539 if (ec == kPDErrNotFound)
540 return nullptr;
541
542 PDF_CHECK_SUCCESS_X(ec);
543 return sysfont;
544}
545
546inline SystemFont FindSystemFont(const std::wstring& family, GXFontStyle style = kGXFontStyleRegular) {
547 GXSysFontQuery query = {};
548 query.matchFlags = kGXSysFontQueryMatchFamily | kGXSysFontQueryMatchWeight | kGXSysFontQueryMatchItalic;
549 query.family = family.c_str();
550 query.style = style;
551 return FindSystemFont(query);
552}
553
560constexpr uint32_t MakeOpenTypeTag(std::string_view tag) {
561 auto result = uint32_t(0);
562 for (int i = 0; i < 4; ++i) {
563 const char c = static_cast<size_t>(i) < tag.size() ? tag[i] : ' ';
564 result = (result << 8) | static_cast<uint8_t>(c);
565 }
566 return result;
567}
568
577 uint32_t tag;
578 float value;
579};
580
588 uint32_t tag;
589 float minValue;
591 float maxValue;
592 std::wstring name;
593};
594
602 std::wstring name;
603 std::vector<FontVariationAxisValue> axisValues;
604};
605
610class FontFace : public detail::RefCountedHandle<GXFontFace> {
611public:
612 static FontFace FromSystemFont(const SystemFont& sysfont) {
613 FontFace fontface;
614 auto ec = GXCreateFontFaceFromSysFont(sysfont.get(), &fontface);
615 if (ec == kPDErrNotFound)
616 return nullptr;
617 PDF_CHECK_SUCCESS(ec, "Failed to create a font face");
618 return fontface;
619 }
620
621 static FontFace FromSystemFont(const std::wstring& family, GXFontStyle style = kGXFontStyleRegular) {
622 auto sysfont = FindSystemFont(family, style);
623 return FromSystemFont(sysfont);
624 }
625
626 static FontFace LoadFromFile(const std::filesystem::path& path, uint32_t faceindex = 0, uint32_t* ptotalfaces = nullptr) {
627 FontFace fontface;
628 auto path_string = path.wstring();
629 auto ec = GXCreateFontFaceFromFile(path_string.c_str(), faceindex, ptotalfaces, &fontface);
630 PDF_CHECK_SUCCESS(ec, "Failed to load a bitmap from file");
631 return fontface;
632 }
633
634 static FontFace LoadFromMemory(std::span<const Byte> data, bool copyData = true, uint32_t faceindex = 0, uint32_t* ptotalfaces = nullptr) {
635 FontFace fontface;
636 auto ec = GXCreateFontFaceFromMemory(data.data(), data.size(), copyData, faceindex, ptotalfaces, &fontface);
637 PDF_CHECK_SUCCESS(ec, "Failed to load a bitmap from memory");
638 return fontface;
639 }
640
641 std::wstring GetFamilyName() const {
642 return detail::GetWstringProperty(GXFontFaceGetFamilyName, m_handle);
643 }
644
645 std::wstring GetPostScriptName() const {
646 return detail::GetWstringProperty(GXFontFaceGetPostScriptName, m_handle);
647 }
648
649 std::wstring GetFontName() const {
650 return detail::GetWstringProperty(GXFontFaceGetFontName, m_handle);
651 }
652
653 GXFontStyle GetStyle() const {
655 PDF_CHECK_SUCCESS_X(GXFontFaceGetStyle(m_handle, &style));
656 return style;
657 }
658
659 GXFontFlags GetFontFlags() const {
660 GXFontFlags flags = 0;
661 PDF_CHECK_SUCCESS_X(GXFontFaceGetFontFlags(m_handle, &flags));
662 return flags;
663 }
664
665 std::vector<GXUnicodeRange> GetUnicodeRanges() const {
666 size_t num_ranges = 0;
667 auto ec = GXFontFaceGetUnicodeRanges(m_handle, nullptr, 0, &num_ranges);
668 if (ec == kPDErrSuccess)
669 return {};
670 if (ec != kPDErrBufferTooSmall)
671 PDF_CHECK_SUCCESS_X(ec);
672 std::vector<GXUnicodeRange> ranges(num_ranges);
673 PDF_CHECK_SUCCESS_X(GXFontFaceGetUnicodeRanges(m_handle, ranges.data(), num_ranges, &num_ranges));
674 return ranges;
675 }
676
677 GXFontMetrics GetMetrics() const {
678 GXFontMetrics metrics;
679 auto ec = GXFontFaceGetMetrics(m_handle, &metrics);
680 PDF_CHECK_SUCCESS(ec, "Failed to get the font metrics");
681 return metrics;
682 }
683
684 uint32_t GetGlyphIndex(uint32_t unicode) const {
685 uint32_t gid = 0;
686 auto ec = GXFontFaceGetGlyphIndex(m_handle, unicode, &gid);
687 PDF_CHECK_SUCCESS(ec, "Failed to get the glyph index");
688 return gid;
689 }
690
691 bool HasGlyph(uint32_t unicode) const {
692 return GetGlyphIndex(unicode) != 0;
693 }
694
695 uint32_t GetGlyphAdvance(uint32_t glyphIndex) const {
696 uint32_t advance = 0;
697 auto ec = GXFontFaceGetGlyphAdvance(m_handle, glyphIndex, &advance);
698 PDF_CHECK_SUCCESS(ec, "Failed to get the glyph advance");
699 return advance;
700 }
701
710 void RenderGlyphOutline(uint32_t glyphIndex, Geometry geometry, const Matrix& transform = Matrix()) const {
711 auto ec = GXFontFaceRenderGlyphOutline(m_handle, glyphIndex, &transform, geometry.get());
712 PDF_CHECK_SUCCESS(ec, "Failed to render the glyph outline");
713 }
714
715 /*
716 * Opens a stream for reading a specific table in the font.
717 * @param tableTag The tag of the table to open. If 0, the entire font data is returned.
718 * @return A read stream for the table data.
719 */
720 ReadStream OpenFontStream(uint32_t tableTag = 0) const {
721 ReadStream stream;
722 auto ec = GXFontFaceOpenFontStream(m_handle, tableTag, &stream);
723 PDF_CHECK_SUCCESS(ec, "Failed to open the font table stream");
724 return stream;
725 }
726
735 std::vector<FontVariationAxisInfo> GetVariationAxes() const {
736 size_t numAxes = 0;
737 PDF_CHECK_SUCCESS_X(GXFontFaceGetNumVariationAxes(m_handle, &numAxes));
738
739 std::vector<FontVariationAxisInfo> axes;
740 axes.reserve(numAxes);
741 for (size_t i = 0; i < numAxes; ++i) {
742 GXFontVariationAxisInfo info = {};
743 PDF_CHECK_SUCCESS_X(GXFontFaceGetVariationAxis(m_handle, i, &info));
744
745 FontVariationAxisInfo axis{info.tag, info.minValue, info.defaultValue, info.maxValue, {}};
746
747 size_t nameSize = 0;
748 auto ec = GXFontFaceGetVariationAxisName(m_handle, info.tag, nullptr, 0, &nameSize);
749 if (ec != kPDErrSuccess && ec != kPDErrBufferTooSmall)
750 PDF_CHECK_SUCCESS_X(ec);
751 if (ec == kPDErrBufferTooSmall) {
752 axis.name.resize(nameSize);
753 PDF_CHECK_SUCCESS_X(GXFontFaceGetVariationAxisName(m_handle, info.tag, axis.name.data(), nameSize, &nameSize));
754 }
755
756 axes.push_back(std::move(axis));
757 }
758 return axes;
759 }
760
770 std::vector<FontVariationInstanceInfo> GetVariationInstances() const {
771 size_t numInstances = 0;
772 PDF_CHECK_SUCCESS_X(GXFontFaceGetNumVariationInstances(m_handle, &numInstances));
773
774 std::vector<FontVariationInstanceInfo> instances;
775 instances.reserve(numInstances);
776 for (size_t i = 0; i < numInstances; ++i) {
778
779 size_t nameSize = 0;
780 auto ec = GXFontFaceGetVariationInstanceName(m_handle, i, nullptr, 0, &nameSize);
781 if (ec != kPDErrSuccess && ec != kPDErrBufferTooSmall)
782 PDF_CHECK_SUCCESS_X(ec);
783 if (ec == kPDErrBufferTooSmall) {
784 instance.name.resize(nameSize);
785 PDF_CHECK_SUCCESS_X(GXFontFaceGetVariationInstanceName(m_handle, i, instance.name.data(), nameSize, &nameSize));
786 }
787
788 size_t numAxisValues = 0;
789 ec = GXFontFaceGetVariationInstanceAxisValues(m_handle, i, nullptr, 0, &numAxisValues);
790 if (ec != kPDErrSuccess && ec != kPDErrBufferTooSmall)
791 PDF_CHECK_SUCCESS_X(ec);
792 if (ec == kPDErrBufferTooSmall) {
793 std::vector<GXFontVariationAxisValue> axisValues(numAxisValues);
794 PDF_CHECK_SUCCESS_X(GXFontFaceGetVariationInstanceAxisValues(m_handle, i, axisValues.data(), numAxisValues, &numAxisValues));
795
796 instance.axisValues.reserve(numAxisValues);
797 for (const auto& axisValue : axisValues)
798 instance.axisValues.push_back({axisValue.tag, axisValue.value});
799 }
800
801 instances.push_back(std::move(instance));
802 }
803 return instances;
804 }
805
811 std::vector<FontVariationAxisValue> GetVariation() const {
812 size_t numValues = 0;
813 auto ec = GXFontFaceGetVariation(m_handle, nullptr, 0, &numValues);
814 if (ec == kPDErrSuccess)
815 return {};
816 if (ec != kPDErrBufferTooSmall)
817 PDF_CHECK_SUCCESS_X(ec);
818
819 std::vector<GXFontVariationAxisValue> values(numValues);
820 PDF_CHECK_SUCCESS_X(GXFontFaceGetVariation(m_handle, values.data(), numValues, &numValues));
821
822 std::vector<FontVariationAxisValue> result;
823 result.reserve(numValues);
824 for (const auto& value : values)
825 result.push_back({value.tag, value.value});
826 return result;
827 }
828
838 void SetVariation(std::span<const FontVariationAxisValue> axisValues) const {
839 std::vector<GXFontVariationAxisValue> values;
840 values.reserve(axisValues.size());
841 for (const FontVariationAxisValue& axisValue : axisValues)
842 values.push_back({axisValue.tag, axisValue.value});
843
844 auto ec = GXFontFaceSetVariation(m_handle, values.data(), values.size());
845 PDF_CHECK_SUCCESS(ec, "Failed to set the font variation");
846 }
847
856 void SelectVariationInstance(std::wstring_view instanceName) const {
857 for (const FontVariationInstanceInfo& instance : GetVariationInstances()) {
858 if (instance.name == instanceName) {
859 SetVariation(instance.axisValues);
860 return;
861 }
862 }
863 PDF_THROW(kPDErrNotFound, "No such named instance");
864 }
865
866 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(FontFace, GXFontFace)
867};
868
880public:
881 virtual ~SystemFontsHandler() = default;
882
890 class FontEntry {
891 public:
892 virtual ~FontEntry() = default;
893 virtual std::wstring GetFamilyName() = 0;
894 virtual std::wstring GetPostScriptName() = 0;
895 virtual std::wstring GetFontName() = 0;
896 virtual GXFontStyle GetStyle() = 0;
897 virtual GXFontFlags GetFontFlags() = 0;
898 virtual std::vector<GXUnicodeRange> GetUnicodeRanges() = 0;
899 virtual FontFace LoadFontFace() = 0;
900 };
901
902 using FontEntryPtr = std::shared_ptr<FontEntry>;
903
909 virtual std::vector<FontEntryPtr> ListFonts() = 0;
910};
911
912namespace details {
913
914inline const GXSysFontsHandler& GetGXSysFontsHandler() {
915
916 struct GXSysFontsHandlerFontData {
917 std::shared_ptr<SystemFontsHandler> handler;
918 SystemFontsHandler::FontEntryPtr font;
919 };
920
921 static const GXSysFontsHandler sysFontsHandler = {
922 .enumFonts = [](void* handlerData, GXSysFontCustomEnumProc proc, void* userdata) -> PDErrCode {
923 PDFSDK_CALLBACK_BEGIN
924 auto handler = *static_cast<std::shared_ptr<SystemFontsHandler>*>(handlerData);
925 for (SystemFontsHandler::FontEntryPtr& font : handler->ListFonts()) {
926 if (!font)
927 continue;
928 auto fontData = std::make_unique<GXSysFontsHandlerFontData>(handler, std::move(font));
929 auto ec = proc(userdata, fontData.get());
930 if (ec != kPDErrSuccess)
931 return ec;
932 fontData.release(); // handed over to the SDK, which frees it via freeFontData
933 }
934 return kPDErrSuccess;
935 PDFSDK_CALLBACK_END
936 },
937 .getFamilyName = [](void* fontData, wchar_t* buffer, size_t bufsize, size_t* psize) -> PDErrCode {
938 PDFSDK_CALLBACK_BEGIN
939 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
940 return CopyDataToBuffer(font->GetFamilyName(), buffer, bufsize, psize);
941 PDFSDK_CALLBACK_END
942 },
943 .getPostScriptName = [](void* fontData, wchar_t* buffer, size_t bufsize, size_t* psize) -> PDErrCode {
944 PDFSDK_CALLBACK_BEGIN
945 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
946 return CopyDataToBuffer(font->GetPostScriptName(), buffer, bufsize, psize);
947 PDFSDK_CALLBACK_END
948 },
949 .getFontName = [](void* fontData, wchar_t* buffer, size_t bufsize, size_t* psize) -> PDErrCode {
950 PDFSDK_CALLBACK_BEGIN
951 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
952 return CopyDataToBuffer(font->GetFontName(), buffer, bufsize, psize);
953 PDFSDK_CALLBACK_END
954 },
955 .getStyle = [](void* fontData, GXFontStyle* pStyle) -> PDErrCode {
956 PDFSDK_CALLBACK_BEGIN
957 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
958 *pStyle = font->GetStyle();
959 return kPDErrSuccess;
960 PDFSDK_CALLBACK_END
961 },
962 .getFontFlags = [](void* fontData, GXFontFlags* pFlags) -> PDErrCode {
963 PDFSDK_CALLBACK_BEGIN
964 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
965 *pFlags = font->GetFontFlags();
966 return kPDErrSuccess;
967 PDFSDK_CALLBACK_END
968 },
969 .getUnicodeRanges = [](void* fontData, GXUnicodeRange* buffer, size_t bufsize, size_t* psize) -> PDErrCode {
970 PDFSDK_CALLBACK_BEGIN
971 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
972 return CopyDataToBuffer(font->GetUnicodeRanges(), buffer, bufsize, psize);
973 PDFSDK_CALLBACK_END
974 },
975 .loadFontFace = [](void* fontData, GXFontFace* pFontFace) -> PDErrCode {
976 PDFSDK_CALLBACK_BEGIN
977 const auto& font = static_cast<GXSysFontsHandlerFontData*>(fontData)->font;
978 *pFontFace = font->LoadFontFace().detach();
979 return kPDErrSuccess;
980 PDFSDK_CALLBACK_END
981 },
982 .freeFontData = [](void* fontData) {
983 delete static_cast<GXSysFontsHandlerFontData*>(fontData);
984 },
985 .freeHandlerData = [](void* handlerData) {
986 delete static_cast<std::shared_ptr<SystemFontsHandler>*>(handlerData);
987 }};
988 return sysFontsHandler;
989}
990
991} // namespace details
992
998inline GXSysFontsHandlerID AddSystemFontsHandler(std::shared_ptr<SystemFontsHandler> handler) {
999 PDF_CHECK(handler, kPDErrBadParam, "handler cannot be null");
1000 auto handlerData = std::make_unique<std::shared_ptr<SystemFontsHandler>>(std::move(handler));
1001 GXSysFontsHandlerID handlerId = 0;
1002 auto ec = GXAddCustomSysFontsHandler(&details::GetGXSysFontsHandler(), handlerData.get(), &handlerId);
1003 PDF_CHECK_SUCCESS(ec, "Failed to add a system fonts handler");
1004 handlerData.release();
1005 return handlerId;
1006}
1007
1012inline GXSysFontsHandlerID AddSystemFontsDirectory(const std::filesystem::path& directory) {
1013 auto directory_string = directory.wstring();
1014 GXSysFontsHandlerID handlerId = 0;
1015 auto ec = GXAddDirectorySysFontsHandler(directory_string.c_str(), &handlerId);
1016 PDF_CHECK_SUCCESS(ec, "Failed to add a system fonts directory");
1017 return handlerId;
1018}
1019
1024inline void SetSystemFontsHandler(std::shared_ptr<SystemFontsHandler> handler) {
1025 PDF_CHECK(handler, kPDErrBadParam, "handler cannot be null");
1026 auto handlerData = std::make_unique<std::shared_ptr<SystemFontsHandler>>(std::move(handler));
1027 auto ec = GXSetCustomSysFontsHandler(&details::GetGXSysFontsHandler(), handlerData.get());
1028 PDF_CHECK_SUCCESS(ec, "Failed to set the system fonts handler");
1029 handlerData.release();
1030}
1031
1036inline void SetSystemFontsDirectory(const std::filesystem::path& directory) {
1037 auto directory_string = directory.wstring();
1038 auto ec = GXSetDirectorySysFontsHandler(directory_string.c_str());
1039 PDF_CHECK_SUCCESS(ec, "Failed to set the system fonts directory");
1040}
1041
1046inline bool RemoveSystemFontsHandler(GXSysFontsHandlerID handlerId) {
1047 auto ec = GXRemoveSysFontsHandler(handlerId);
1048 if (ec == kPDErrNotFound)
1049 return false;
1050
1051 PDF_CHECK_SUCCESS(ec, "Failed to remove the system fonts handler");
1052 return true;
1053}
1054
1056inline void ResetSystemFontsHandlers() {
1057 auto ec = GXResetSysFontsHandlers();
1058 PDF_CHECK_SUCCESS(ec, "Failed to reset the system fonts handlers");
1059}
1060
1065class Gradient : public detail::RefCountedHandle<GXGradient> {
1066public:
1067 static Gradient NewLinearGradient(const GXLinearGradientAttrs& attrs) {
1068 Gradient gradient;
1069 auto ec = GXCreateGradientLinear(&attrs, &gradient);
1070 PDF_CHECK_SUCCESS(ec, "Failed to create a gradient");
1071 return gradient;
1072 }
1073
1074 static Gradient NewRadialGradient(const GXRadialGradientAttrs& attrs) {
1075 Gradient gradient;
1076 auto ec = GXCreateGradientRadial(&attrs, &gradient);
1077 PDF_CHECK_SUCCESS(ec, "Failed to create a gradient");
1078 return gradient;
1079 }
1080
1081 static Gradient NewTriMeshGradient(const GXMeshVertex* vertices, size_t num_vertices, GXColorValue bgcolor) {
1082 Gradient gradient;
1083 auto ec = GXCreateGradientTriMesh(vertices, num_vertices, bgcolor, &gradient);
1084 PDF_CHECK_SUCCESS(ec, "Failed to create a gradient");
1085 return gradient;
1086 }
1087
1088 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Gradient, GXGradient)
1089};
1090
1095class Brush : public detail::RefCountedHandle<GXBrush> {
1096public:
1097 static Brush NewSolidBrush(GXColorValue argb) {
1098 Brush brush;
1099 auto ec = GXCreateBrushSolidARGB(argb, &brush);
1100 PDF_CHECK_SUCCESS(ec, "Failed to create a brush");
1101 return brush;
1102 }
1103
1104 static Brush NewBitmapBrush(const Bitmap& bitmap,
1105 const GXBitmapBrushAttrs& attrs,
1106 float opacity = 1,
1107 const Matrix* xform = nullptr) {
1108 Brush brush;
1109 auto ec = GXCreateBrushBitmap(bitmap.get(), opacity, &attrs, xform, &brush);
1110 PDF_CHECK_SUCCESS(ec, "Failed to create a brush");
1111 return brush;
1112 }
1113
1114 static Brush NewGradientBrush(const Gradient& gradient, float opacity = 1, const Matrix* xform = nullptr) {
1115 Brush brush;
1116 auto ec = GXCreateBrushGradient(gradient.get(), opacity, xform, &brush);
1117 PDF_CHECK_SUCCESS(ec, "Failed to create a brush");
1118 return brush;
1119 }
1120
1121 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Brush, GXBrush)
1122};
1123
1128class Region : public detail::RefCountedHandle<GXRegion> {
1129public:
1130 static Region New() {
1131 Region region;
1132 auto ec = GXCreateRegion(&region);
1133 PDF_CHECK_SUCCESS(ec, "Failed to create a region");
1134 return region;
1135 }
1136
1137 static Region NewFromRect(const RectI& rect) {
1138 Region region;
1139 auto ec = GXCreateRegionFromRect(&rect, &region);
1140 PDF_CHECK_SUCCESS(ec, "Failed to create a region");
1141 return region;
1142 }
1143
1144 bool IsAreaEmpty() const {
1145 bool empty = false;
1146 auto ec = GXRegionIsAreaEmpty(m_handle, &empty);
1147 PDF_CHECK_SUCCESS(ec, "Failed to check the region area");
1148 return empty;
1149 }
1150
1151 RectI GetBound() const {
1152 RectI bound;
1153 auto ec = GXRegionGetBound(m_handle, &bound);
1154 PDF_CHECK_SUCCESS(ec, "Failed to get the region bound");
1155 return bound;
1156 }
1157
1158 bool Contains(const PointI& point) const {
1159 bool contains = false;
1160 auto ec = GXRegionContainsPoint(m_handle, &point, &contains);
1161 PDF_CHECK_SUCCESS(ec, "Failed to hit test the region");
1162 return contains;
1163 }
1164
1165 bool Contains(const RectI& rect) const {
1166 bool contains = false;
1167 auto ec = GXRegionContainsRect(m_handle, &rect, &contains);
1168 PDF_CHECK_SUCCESS(ec, "Failed to hit test the region");
1169 return contains;
1170 }
1171
1172 bool Contains(const Region& region) const {
1173 bool contains = false;
1174 auto ec = GXRegionContains(m_handle, region.get(), &contains);
1175 PDF_CHECK_SUCCESS(ec, "Failed to hit test the region");
1176 return contains;
1177 }
1178
1179 bool HasIntersection(const RectI& rect) const {
1180 bool isects = false;
1181 auto ec = GXRegionHasIntersectionWithRect(m_handle, &rect, &isects);
1182 PDF_CHECK_SUCCESS(ec, "Failed to check the regions intersection");
1183 return isects;
1184 }
1185
1186 bool HasIntersection(const Region& region) const {
1187 bool isects = false;
1188 auto ec = GXRegionHasIntersection(m_handle, region.get(), &isects);
1189 PDF_CHECK_SUCCESS(ec, "Failed to check the regions intersection");
1190 return isects;
1191 }
1192
1193 void Offset(int dx, int dy) {
1194 auto ec = GXRegionOffset(m_handle, dx, dy);
1195 PDF_CHECK_SUCCESS(ec, "Failed to offset the region");
1196 }
1197
1198 void Combine(GXCombineMode mode, const Region& region) {
1199 Region result;
1200 auto ec = GXRegionCombine(m_handle, region.get(), mode, &result);
1201 PDF_CHECK_SUCCESS(ec, "Failed to combine the regions");
1202 *this = std::move(result);
1203 }
1204
1205 void Combine(GXCombineMode mode, const RectI& rect) {
1206 Region result;
1207 auto ec = GXRegionCombineRect(m_handle, &rect, mode, &result);
1208 PDF_CHECK_SUCCESS(ec, "Failed to combine the regions");
1209 *this = std::move(result);
1210 }
1211
1212 using RectEnumFunc = std::function<bool(const RectI&)>;
1213
1214 void EnumRects(RectEnumFunc func) const {
1215 auto enumProc = [](void* userdata, const PDRectI* rect) -> PDErrCode {
1216 PDFSDK_CALLBACK_BEGIN
1217 auto& func = *reinterpret_cast<RectEnumFunc*>(userdata);
1218 return func(*rect) ? kPDErrSuccess : kPDErrCanceled;
1219 PDFSDK_CALLBACK_END
1220 };
1221 auto ec = GXRegionEnumRects(m_handle, enumProc, &func);
1222 if (ec != kPDErrCanceled)
1223 PDF_CHECK_SUCCESS(ec, "Failed to enum the region rects");
1224 }
1225
1226 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(Region, GXRegion)
1227};
1228
1233class RenderTarget : public detail::RefCountedHandle<GXRenderTarget> {
1234public:
1235 static RenderTarget NewBitmapRenderTarget(const Bitmap& bitmap) {
1236 RenderTarget target;
1237 auto ec = GXCreateRenderTargetBitmap(bitmap.get(), &target);
1238 PDF_CHECK_SUCCESS(ec, "Failed to create the render target");
1239 return target;
1240 }
1241
1242 static RenderTarget NewExtBufRenderTarget(void* pixels,
1243 int stride,
1244 const SizeI& size,
1245 GXPixelFormat format,
1246 float dpiX = 96,
1247 float dpiY = 96) {
1248 RenderTarget target;
1249 GXBitmapAttrs attrs = {size, format, dpiX, dpiY};
1250 auto ec = GXCreateRenderTargetExtBuf(pixels, stride, &attrs, &target);
1251 PDF_CHECK_SUCCESS(ec, "Failed to create the render target");
1252 return target;
1253 }
1254
1255#ifdef _WIN32
1256
1257 static RenderTarget NewHwndRenderTarget(void* hwnd, GXRuntimeMode mode = kGXRuntimeModeHardware) {
1258 RenderTarget target;
1259 auto ec = GXCreateRenderTargetHWND(hwnd, mode, &target);
1260 PDF_CHECK_SUCCESS(ec, "Failed to create the render target");
1261 return target;
1262 }
1263
1264 static RenderTarget NewPrintRenderTarget(void* hdc) {
1265 RenderTarget target;
1266 auto ec = GXCreateRenderTargetPrintDC(hdc, &target);
1267 PDF_CHECK_SUCCESS(ec, "Failed to create the render target");
1268 return target;
1269 }
1270
1271 static RenderTarget NewHdcRenderTarget(void* hdc, const RectI* rect = nullptr) {
1272 RenderTarget target;
1273 auto ec = GXCreateRenderTargetHDC(hdc, rect, &target);
1274 PDF_CHECK_SUCCESS(ec, "Failed to create the render target");
1275 return target;
1276 }
1277
1278#endif // _WIN32
1279
1280 GXPixelFormat GetPixelFormat() {
1282 auto ec = GXRenderTargetGetPixelFormat(m_handle, &format);
1283 PDF_CHECK_SUCCESS(ec, "Failed to get the render target pixel format");
1284 return format;
1285 }
1286
1287 SizeI GetSize() {
1288 SizeI size;
1289 auto ec = GXRenderTargetGetSize(m_handle, &size);
1290 PDF_CHECK_SUCCESS(ec, "Failed to get the render target size");
1291 return size;
1292 }
1293
1294 void Clear(GXColorValue clrcolor) {
1295 auto ec = GXRenderTargetClear(m_handle, clrcolor);
1296 PDF_CHECK_SUCCESS(ec, "Failed to clear the render target");
1297 }
1298
1299 class PaintScope {
1300 public:
1301 PaintScope(RenderTarget& target)
1302 : m_target(target) {
1303 m_target.BeginPaint();
1304 }
1305
1306 ~PaintScope() {
1307 try {
1308 m_target.EndPaint();
1309 } catch (...) {
1310 }
1311 }
1312
1313 PaintScope(const PaintScope&) = delete;
1314 PaintScope& operator=(const PaintScope&) = delete;
1315
1316 private:
1317 RenderTarget& m_target;
1318 };
1319
1320 void BeginPaint() {
1321 auto ec = GXRenderTargetBeginPaint(m_handle);
1322 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1323 }
1324
1325 void EndPaint() {
1326 auto ec = GXRenderTargetEndPaint(m_handle);
1327 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1328 }
1329
1330 class StateScope {
1331 public:
1332 StateScope(RenderTarget& target)
1333 : m_target(target) {
1334 m_target.PushState();
1335 }
1336
1337 ~StateScope() {
1338 try {
1339 m_target.PopState();
1340 } catch (...) {
1341 }
1342 }
1343
1344 StateScope(const StateScope&) = delete;
1345 StateScope& operator=(const StateScope&) = delete;
1346
1347 private:
1348 RenderTarget& m_target;
1349 };
1350
1351 void PushState() {
1352 auto ec = GXRenderTargetPushState(m_handle);
1353 PDF_CHECK_SUCCESS(ec, "Failed to push the render target state");
1354 }
1355
1356 void PopState() {
1357 auto ec = GXRenderTargetPopState(m_handle);
1358 PDF_CHECK_SUCCESS(ec, "Failed to pop the render target state");
1359 }
1360
1361 class CTMScope {
1362 public:
1363 CTMScope(RenderTarget& target)
1364 : m_target(target) {
1365 m_ctm = m_target.GetCTM();
1366 }
1367
1368 ~CTMScope() {
1369 try {
1370 m_target.SetCTM(m_ctm);
1371 } catch (...) {
1372 }
1373 }
1374
1375 CTMScope(const CTMScope&) = delete;
1376 CTMScope& operator=(const CTMScope&) = delete;
1377
1378 private:
1379 RenderTarget& m_target;
1380 Matrix m_ctm;
1381 };
1382
1383 Matrix GetCTM() const {
1384 Matrix ctm;
1385 auto ec = GXRenderTargetGetCTM(m_handle, &ctm);
1386 PDF_CHECK_SUCCESS(ec, "Failed to get the render target CTM");
1387 return ctm;
1388 }
1389
1390 void SetCTM(const Matrix& ctm) {
1391 auto ec = GXRenderTargetSetCTM(m_handle, &ctm);
1392 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1393 }
1394
1395 void ConcatCTM(const Matrix& xform) {
1396 auto ec = GXRenderTargetConcatCTM(m_handle, &xform);
1397 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1398 }
1399
1400 void RotateCTM(float radians) {
1401 auto ec = GXRenderTargetRotateCTM(m_handle, radians);
1402 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1403 }
1404
1405 void ScaleCTM(float scale) {
1406 auto ec = GXRenderTargetScaleCTM(m_handle, scale, scale);
1407 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1408 }
1409
1410 void ScaleCTM(float sx, float sy) {
1411 auto ec = GXRenderTargetScaleCTM(m_handle, sx, sy);
1412 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1413 }
1414
1415 void ScaleCTM(const SizeF& scale) {
1416 auto ec = GXRenderTargetScaleCTM(m_handle, scale.width, scale.height);
1417 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1418 }
1419
1420 void TranslateCTM(float dx, float dy) {
1421 auto ec = GXRenderTargetTranslateCTM(m_handle, dx, dy);
1422 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1423 }
1424
1425 void TranslateCTM(const PointF& delta) {
1426 auto ec = GXRenderTargetTranslateCTM(m_handle, delta.x, delta.y);
1427 PDF_CHECK_SUCCESS(ec, "Failed to modify the render target CTM");
1428 }
1429
1430 void SetBlendMode(GXBlendMode mode) {
1431 auto ec = GXRenderTargetSetBlendMode(m_handle, mode);
1432 PDF_CHECK_SUCCESS(ec, "Failed to set the render target blend mode");
1433 }
1434
1435 void SetStrokeAdjustment(bool adjust) {
1436 auto ec = GXRenderTargetSetStrokeAdjustment(m_handle, adjust);
1437 PDF_CHECK_SUCCESS(ec, "Failed to set the render target stroke adjust");
1438 }
1439
1440 bool GetStrokeAdjustment() const {
1441 bool adjust = false;
1442 auto ec = GXRenderTargetGetStrokeAdjustment(m_handle, &adjust);
1443 PDF_CHECK_SUCCESS(ec, "Failed to get the render target stroke adjust");
1444 return adjust;
1445 }
1446
1447 void SetOpacityMask(GXMaskMode mode, const Brush& mask) {
1448 auto ec = GXRenderTargetSetOpacityMask(m_handle, mode, mask.get());
1449 PDF_CHECK_SUCCESS(ec, "Failed to set the render target mask");
1450 }
1451
1452 void SetShapeMask(GXMaskMode mode, const Brush& mask) {
1453 auto ec = GXRenderTargetSetShapeMask(m_handle, mode, mask.get());
1454 PDF_CHECK_SUCCESS(ec, "Failed to set the render target mask");
1455 }
1456
1457 void BeginLayer(const GXLayerParams& params) {
1458 auto ec = GXRenderTargetBeginLayer(m_handle, &params);
1459 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1460 }
1461
1462 void EndLayer() {
1463 auto ec = GXRenderTargetEndLayer(m_handle);
1464 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1465 }
1466
1467 void FillGeometry(const Geometry& geom, const Brush& brush) {
1468 auto ec = GXRenderTargetFillGeometry(m_handle, geom.get(), brush.get());
1469 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1470 }
1471
1472 void FillTextGeometry(const Geometry& geom, const Brush& brush) {
1473 auto ec = GXRenderTargetFillTextGeometry(m_handle, geom.get(), brush.get());
1474 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1475 }
1476
1477 void FillRect(const RectF& rect, const Brush& brush) {
1478 auto ec = GXRenderTargetFillRect(m_handle, &rect, brush.get());
1479 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1480 }
1481
1482 void FillEllipse(const RectF& bound, const Brush& brush) {
1483 auto ec = GXRenderTargetFillEllipse(m_handle, &bound, brush.get());
1484 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1485 }
1486
1487 void StrokeGeometry(const Geometry& geom, const Brush& brush, float width, const GXStrokeParams* params = nullptr) {
1488 auto ec = GXRenderTargetStrokeGeometry(m_handle, geom.get(), brush.get(), width, params);
1489 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1490 }
1491
1492 void StrokeLine(const PointF& start,
1493 const PointF& end,
1494 const Brush& brush,
1495 float width,
1496 const GXStrokeParams* params = nullptr) {
1497 auto ec = GXRenderTargetStrokeLine(m_handle, &start, &end, brush.get(), width, params);
1498 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1499 }
1500
1501 void StrokeRect(const RectF& rect, const Brush& brush, float width, const GXStrokeParams* params = nullptr) {
1502 auto ec = GXRenderTargetStrokeRect(m_handle, &rect, brush.get(), width, params);
1503 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1504 }
1505
1506 void StrokeEllipse(const RectF& bound, const Brush& brush, float width, const GXStrokeParams* params = nullptr) {
1507 auto ec = GXRenderTargetStrokeEllipse(m_handle, &bound, brush.get(), width, params);
1508 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1509 }
1510
1511 void ClipGeometry(const Geometry& geom) {
1512 auto ec = GXRenderTargetClipGeometry(m_handle, geom.get());
1513 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1514 }
1515
1516 void ClipRect(const RectF& rect) {
1517 auto ec = GXRenderTargetClipRect(m_handle, &rect);
1518 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1519 }
1520
1521 void ClipEllipse(const RectF& bound) {
1522 auto ec = GXRenderTargetClipEllipse(m_handle, &bound);
1523 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1524 }
1525
1526 void DrawBitmap(const Bitmap& bitmap,
1527 float opacity = 1,
1529 auto ec = GXRenderTargetDrawBitmap(m_handle, bitmap.get(), opacity, imode);
1530 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1531 }
1532
1533 void StretchBitmap(const Bitmap& bitmap,
1534 const RectF& target_rect,
1535 float opacity = 1,
1537 auto ec = GXRenderTargetStretchBitmap(m_handle, bitmap.get(), &target_rect, opacity, imode);
1538 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1539 }
1540
1541 void DrawGradient(const Gradient& gradient, float opacity) {
1542 auto ec = GXRenderTargetDrawGradient(m_handle, gradient.get(), opacity);
1543 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1544 }
1545
1546 void FillMask(const Bitmap& mask,
1547 const Brush& brush,
1549 auto ec = GXRenderTargetFillMask(m_handle, mask.get(), brush.get(), imode);
1550 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1551 }
1552
1553 void InvertRect(const RectF& rect) {
1554 auto ec = GXRenderTargetInvertRect(m_handle, &rect);
1555 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1556 }
1557
1558 void InvertLine(const PointI& start, const PointI& end) {
1559 auto ec = GXRenderTargetInvertLine(m_handle, &start, &end);
1560 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1561 }
1562
1563 void FillText(const FontFace& font, float fontSize, const std::wstring& text, const Brush& brush) {
1564 auto ec = GXRenderTargetFillText(m_handle, font.get(), fontSize, text.c_str(), brush.get());
1565 PDF_CHECK_SUCCESS(ec, "Failed to paint the render target");
1566 }
1567
1568 RectI GetDrawBounds() {
1569 RectI bounds;
1570 auto ec = GXRenderTargetGetDrawBounds(m_handle, &bounds);
1571 PDF_CHECK_SUCCESS(ec, "Failed to get the render target draw bounds");
1572 return bounds;
1573 }
1574
1575 float GetDpiX() const {
1576 float dpiX = 96.0f;
1577 auto ec = GXRenderTargetGetDpiX(m_handle, &dpiX);
1578 PDF_CHECK_SUCCESS(ec, "Failed to get the render target DPI X");
1579 return dpiX;
1580 }
1581
1582 float GetDpiY() const {
1583 float dpiY = 96.0f;
1584 auto ec = GXRenderTargetGetDpiY(m_handle, &dpiY);
1585 PDF_CHECK_SUCCESS(ec, "Failed to get the render target DPI Y");
1586 return dpiY;
1587 }
1588
1589 PDF_CXX_CORE_WRAPPER_DEFINE_MEMBERS_(RenderTarget, GXRenderTarget)
1590};
1591
1592} // namespace Graphics
1593} // namespace PDF
1594
1595#endif // PDFSDK_CXX_GRAPHICS_H_INCLUDED_
Represents a bitmap.
Definition graphics.h:69
Represents a font face.
Definition graphics.h:610
void SelectVariationInstance(std::wstring_view instanceName) const
Selects one of the font's own designer-provided named instances (e.g. "Bold Condensed") by name,...
Definition graphics.h:856
void SetVariation(std::span< const FontVariationAxisValue > axisValues) const
Selects a point in the face's design-variation space, i.e. a variable-font instance....
Definition graphics.h:838
std::vector< FontVariationInstanceInfo > GetVariationInstances() const
Lists the variable font's designer-provided named instances (e.g. "Bold Condensed"),...
Definition graphics.h:770
std::vector< FontVariationAxisValue > GetVariation() const
Reports the face's current position in its design-variation space.
Definition graphics.h:811
std::vector< FontVariationAxisInfo > GetVariationAxes() const
Lists the design-variation axes this face supports, with their valid ranges and default coordinates.
Definition graphics.h:735
void RenderGlyphOutline(uint32_t glyphIndex, Geometry geometry, const Matrix &transform=Matrix()) const
Definition graphics.h:710
Represents a geometry.
Definition graphics.h:250
Represents a gradient.
Definition graphics.h:1065
Represents a color palette.
Definition graphics.h:32
Represents a system font.
Definition graphics.h:480
One of the fonts a handler provides.
Definition graphics.h:890
A callback interface that provides a set of fonts to the SDK, to be enumerated by ListSystemFonts and...
Definition graphics.h:879
virtual std::vector< FontEntryPtr > ListFonts()=0
Lists the fonts this handler provides. Called whenever the SDK rebuilds its font list,...
Represents a read stream for reading data from PDF objects.
Definition read_stream.h:19
@ kPDErrBadParam
Bad input parameter.
Definition errors.h:20
@ kPDErrSuccess
Operation was successful.
Definition errors.h:18
@ kPDErrBufferTooSmall
Memory buffer too small, increase buffer size.
Definition errors.h:25
@ kPDErrNotFound
Object not found.
Definition errors.h:21
@ kPDErrCanceled
Operation was cancelled by user.
Definition errors.h:17
int32_t PDErrCode
Definition errors.h:44
Graphics API.
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateBrushSolidARGB(GXColorValue argb, GXBrush *pbrush)
GXLockMode
Defines the level of access and control over the graphics content.
Definition graphics.h:99
@ kGXLockModeRead
Definition graphics.h:100
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateRenderTargetBitmap(GXBitmap bitmap, GXRenderTarget *ptarget)
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateBitmap(const GXBitmapAttrs *attrs, GXBitmap *pbitmap)
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateFontFaceFromSysFont(GXSysFont sysfont, GXFontFace *pfontface)
GXFillRule
Determines how a path (a series or points that define a shape) is filled with color.
Definition graphics.h:129
@ kGXFillRuleNonZero
Definition graphics.h:130
GXInterpolationMode
Defines the way through which pixel values are estimated or interpolated.
Definition graphics.h:116
@ kGXInterpolationModeAreaAverage
Definition graphics.h:119
GXRuntimeMode
Defines the runtime modes for the Graphics application.
Definition graphics.h:39
@ kGXRuntimeModeHardware
Definition graphics.h:40
GXBlendMode
Determines the way in which colors of overlapping objects are combined.
Definition graphics.h:148
GXCombineMode
Determines how the areas of different graphics interact with each other.
Definition graphics.h:202
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXEnumSysFonts(GXSysFontEnumProc proc, void *userdata)
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreatePalette(const GXColorValue *colors, size_t num_colors, GXPalette *ppalette)
GXFontStyle
Defines the various styles that can be applied to text within a PDF document.
Definition graphics.h:328
@ kGXFontStyleRegular
Definition graphics.h:329
GXMaskMode
Determines the type of mask used to control which parts of an image or graphical element are visible ...
Definition graphics.h:183
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateGradientLinear(const GXLinearGradientAttrs *attrs, GXGradient *pgradient)
GXPixelFormat
Defines the pixel format of the graphics application.
Definition graphics.h:76
@ kGXPixelFormatP8
Definition graphics.h:87
@ kGXPixelFormatA8
Definition graphics.h:86
@ kGXPixelFormatXRGB8
Definition graphics.h:84
@ kGXPixelFormatARGB8p
Definition graphics.h:79
@ kGXPixelFormatUnknown
Definition graphics.h:77
@ kGXPixelFormatL1
Definition graphics.h:91
@ kGXPixelFormatRGB8
Definition graphics.h:78
@ kGXPixelFormatA1
Definition graphics.h:89
@ kGXPixelFormatL8
Definition graphics.h:88
@ kGXPixelFormatP1
Definition graphics.h:90
@ kGXPixelFormatARGB8
Definition graphics.h:82
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateRegion(GXRegion *pregion)
PDF_CORE_API PDErrCode PDFSDK_CALLCONV GXCreateGeometry(GXGeometry *pgeom)
Definition graphics.h:265
Definition graphics.h:317
Definition graphics.h:335
Definition graphics.h:376
Definition graphics.h:277
Definition graphics.h:105
Definition graphics.h:299
Definition graphics.h:287
Definition graphics.h:258
Definition graphics.h:395
Definition graphics.h:409
Definition graphics.h:366
Describes one design-variation axis supported by a variable font: its tag, valid range,...
Definition graphics.h:587
std::wstring name
The name of the axis (e.g. "Weight"), or empty if the font provides none.
Definition graphics.h:592
uint32_t tag
Packed 4-character axis tag.
Definition graphics.h:588
float defaultValue
Coordinate value used for this axis in the font's default instance.
Definition graphics.h:590
float maxValue
Maximum coordinate value the font supports on this axis.
Definition graphics.h:591
float minValue
Minimum coordinate value the font supports on this axis.
Definition graphics.h:589
A single (axis, value) pair identifying a point along one axis of a variable font's design space....
Definition graphics.h:576
float value
Coordinate on this axis, in the font's own user-scale units for the tag.
Definition graphics.h:578
uint32_t tag
Packed 4-character axis tag.
Definition graphics.h:577
One of a variable font's designer-provided "named instances" - a pre-chosen point in the font's desig...
Definition graphics.h:601
std::wstring name
The instance name.
Definition graphics.h:602
std::vector< FontVariationAxisValue > axisValues
This instance's coordinates per axis.
Definition graphics.h:603
Definition math.h:1276
Definition math.h:154
Definition math.h:53
Definition math.h:752
Definition math.h:543
Definition math.h:461
Definition math_types.h:12
Definition math_types.h:44