20#ifndef PANGO_ENABLE_BACKEND
21#define PANGO_ENABLE_BACKEND
24#ifndef PANGO_ENABLE_ENGINE
25#define PANGO_ENABLE_ENGINE
35#include <glibmm/i18n.h>
66#ifdef CAIRO_HAS_PDF_SURFACE
69#ifdef CAIRO_HAS_PS_SURFACE
74#ifdef CAIRO_HAS_FT_FONT
77#ifdef CAIRO_HAS_WIN32_FONT
79#include <pango/pangowin32.h>
80#include <cairo-win32.h>
83#include <pango/pangofc-fontmap.h>
110static cairo_status_t
_write_callback(
void *closure,
const unsigned char *
data,
unsigned int length);
149 if (
this == &other) {
181 other._stream =
nullptr;
184 other._surface =
nullptr;
190 other._layout =
nullptr;
197 other._renderer =
nullptr;
198 other._is_valid =
false;
205 if (
auto font_face =
static_cast<cairo_font_face_t *
>(
data)) {
206 cairo_font_face_destroy(font_face);
224 state.opacity = SP_SCALE24_TO_FLOAT(style->
opacity.value);
226 state.has_filtereffect = style->
filter.set;
228 if (style->
fill.isPaintserver() || style->
stroke.isPaintserver())
229 state.merge_opacity =
false;
232 if (state.merge_opacity && !style->
fill.isNone() && !style->
stroke.isNone())
233 state.merge_opacity =
false;
251 if (is<SPText>(
item) || is<SPFlowtext>(
item) || is<SPImage>(
item)) {
252 state.parent_has_userspace =
true;
254 TRACE((
"setStateForItem opacity: %f\n", state.opacity));
268 new_context.
_surface = cairo_surface_create_similar(cairo_get_target(
_cr), CAIRO_CONTENT_COLOR_ALPHA,
270 new_context.
_cr = cairo_create(new_context.
_surface);
285 case CAIRO_FORMAT_ARGB32:
286 case CAIRO_FORMAT_RGB24:
287 case CAIRO_FORMAT_A8:
288 case CAIRO_FORMAT_A1:
290 _target = CAIRO_SURFACE_TYPE_IMAGE;
300template <cairo_surface_type_t type>
303#ifndef CAIRO_HAS_PDF_SURFACE
304 if constexpr (type == CAIRO_SURFACE_TYPE_PDF) {
309#ifndef CAIRO_HAS_PS_SURFACE
310 if constexpr (type == CAIRO_SURFACE_TYPE_PS) {
321 gsize bytesWritten = 0;
322 GError *error =
nullptr;
323 gchar *local_fn = g_filename_from_utf8(utf8_fn,
324 -1, &bytesRead, &bytesWritten, &error);
325 gchar
const *fn = local_fn;
335 while (isspace(*fn)) fn += 1;
337 osp = popen(fn,
"w");
339 osp = _popen(fn,
"w");
342 fprintf(stderr,
"inkscape: popen(%s): %s\n",
343 fn, strerror(errno));
347 }
else if (*fn ==
'>') {
349 while (isspace(*fn)) fn += 1;
353 fprintf(stderr,
"inkscape: fopen(%s): %s\n",
354 fn, strerror(errno));
361 ? g_strdup_printf(
"lpr -P %s", fn)
364 osp = popen(
qn,
"w");
366 osp = _popen(
qn,
"w");
369 fprintf(stderr,
"inkscape: popen(%s): %s\n",
370 qn, strerror(errno));
409 return cairo_surface_write_to_png(
_surface, file_name) == CAIRO_STATUS_SUCCESS;
442 TRACE((
"--pushLayer\n"));
443 cairo_push_group(
_cr);
448 cairo_set_operator(
_cr, CAIRO_OPERATOR_CLEAR);
459 TRACE((
"--popLayer w/ opacity %f\n", opacity));
478 if (clip_path || mask) {
484 TRACE((
" Applying clip\n"));
491 cairo_pop_group_to_source(
_cr);
496 cairo_paint_with_alpha(
_cr, opacity);
508 TRACE((
"clip: setupSurface failed\n"));
513 cairo_save(clip_ctx._cr);
514 cairo_set_operator(clip_ctx._cr, CAIRO_OPERATOR_CLEAR);
515 cairo_paint(clip_ctx._cr);
516 cairo_restore(clip_ctx._cr);
524 clip_ctx.pushState();
525 clip_ctx.setItemTransform(item_transform);
529 clip_mask = clip_ctx.getSurface();
530 TEST(clip_ctx->saveAsPng(
"clip_mask.png"));
533 cairo_pop_group_to_source(
_cr);
534 if (composite != CAIRO_OPERATOR_CLEAR){
535 cairo_set_operator(
_cr, composite);
537 cairo_mask_surface(
_cr, clip_mask, 0, 0);
544 TRACE((
" Applying mask\n"));
549 TRACE((
"mask: setupSurface failed\n"));
557 cairo_fill(mask_ctx.
_cr);
572 cairo_mask_surface(mask_ctx.
_cr, clip_mask, 0, 0);
576 int width = cairo_image_surface_get_width(mask_image);
577 int height = cairo_image_surface_get_height(mask_image);
578 int stride = cairo_image_surface_get_stride(mask_image);
579 unsigned char *pixels = cairo_image_surface_get_data(mask_image);
587 TRACE((
"premul w/ %f\n", opacity));
588 const float coeff_r = 0.2125 / 255.0;
589 const float coeff_g = 0.7154 / 255.0;
590 const float coeff_b = 0.0721 / 255.0;
591 for (
int row = 0 ; row <
height; row++) {
592 unsigned char *row_data = pixels + (row *
stride);
593 for (
int i = 0 ; i <
width; i++) {
595 float lum_alpha = (((*pixel & 0x00ff0000) >> 16) * coeff_r +
596 ((*pixel & 0x0000ff00) >> 8) * coeff_g +
597 ((*pixel & 0x000000ff) ) * coeff_b );
601 *pixel = (
guint32)(0xff000000 * lum_alpha * opacity);
605 cairo_pop_group_to_source(
_cr);
606 if (composite != CAIRO_OPERATOR_CLEAR){
607 cairo_set_operator(
_cr, composite);
617 cairo_matrix_t old_transform;
618 cairo_get_matrix(
_cr, &old_transform);
619 cairo_identity_matrix(
_cr);
622 cairo_mask_surface(
_cr, mask_image, 0, 0);
623 cairo_set_matrix(
_cr, &old_transform);
628 cairo_pop_group_to_source(
_cr);
629 if (composite != CAIRO_OPERATOR_CLEAR){
630 cairo_set_operator(
_cr, composite);
635 cairo_paint_with_alpha(
_cr, opacity);
641#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
642 cairo_tag_begin(
_cr, CAIRO_TAG_LINK, l);
648#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
649 cairo_tag_end(
_cr, CAIRO_TAG_LINK);
655#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
656 char* dest = g_strdup_printf(
"name='%s'", l);
657 cairo_tag_begin(
_cr, CAIRO_TAG_DEST, dest);
663#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
664 cairo_tag_end(
_cr, CAIRO_TAG_DEST);
677 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_EVEN_ODD);
679 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_WINDING);
708 cairo_matrix_init_identity (&ctm);
710 case CAIRO_SURFACE_TYPE_IMAGE:
713#ifdef CAIRO_HAS_PDF_SURFACE
714 case CAIRO_SURFACE_TYPE_PDF:
719#ifdef CAIRO_HAS_PS_SURFACE
720 case CAIRO_SURFACE_TYPE_PS:
722 if(CAIRO_STATUS_SUCCESS != cairo_surface_status(
surface)) {
726 cairo_ps_surface_set_eps(
surface, (cairo_bool_t)
_eps);
747 cairo_surface_reference(
surface);
774 _metadata.
creator = Glib::ustring::compose(
"Inkscape %1 (https://inkscape.org)",
779 if (!cdate.empty()) {
791 if(CAIRO_STATUS_SUCCESS != cairo_surface_status(
surface)) {
796 if(CAIRO_STATUS_SUCCESS != cairo_status(
_cr)) {
800 cairo_set_matrix(
_cr, ctm);
805 }
else if (cairo_surface_get_content(
_surface) != CAIRO_CONTENT_ALPHA) {
808 cairo_set_source_rgb(
_cr, 1.0, 1.0, 1.0);
822#if defined CAIRO_HAS_PDF_SURFACE && CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4)
823 case CAIRO_SURFACE_TYPE_PDF:
847#if defined CAIRO_HAS_PS_SURFACE
848 case CAIRO_SURFACE_TYPE_PS:
873 cairo_show_page(
_cr);
877 auto status = cairo_status(
_cr);
878 if (status != CAIRO_STATUS_SUCCESS) {
879 g_critical(
"error while rendering page: %s", cairo_status_to_string(status));
909 auto status = cairo_surface_status(
_surface);
910 if (status != CAIRO_STATUS_SUCCESS) {
911 g_critical(
"error while sizing page: %s", cairo_status_to_string(status));
922 cairo_show_page(
_cr);
924 cairo_status_t status = cairo_status(
_cr);
925 if (status != CAIRO_STATUS_SUCCESS)
926 g_critical(
"error while rendering output: %s", cairo_status_to_string(status));
933 status = cairo_surface_status(
_surface);
951 return status == CAIRO_STATUS_SUCCESS;
967 cairo_matrix_t matrix;
969 cairo_set_matrix(
_cr, &matrix);
984 cairo_get_matrix(
_cr, &ctm);
991 if (state->parent_has_userspace) {
994 return state->item_transform;
1010 auto const current_transform =
_state_stack.back().transform;
1027 g_assert( is<SPPattern>(paintserver) );
1035 double x = pat->
x();
1036 double y = pat->
y();
1039 double bbox_width_scaler;
1040 double bbox_height_scaler;
1045 bbox_width_scaler = pbox->width();
1046 bbox_height_scaler = pbox->height();
1047 ps2user[4] = x * bbox_width_scaler + pbox->left();
1048 ps2user[5] = y * bbox_height_scaler + pbox->top();
1050 bbox_width_scaler = 1.0;
1051 bbox_height_scaler = 1.0;
1058 ps2user *= pattern_transform;
1068 w =
width * bbox_width_scaler;
1069 h =
height * bbox_height_scaler;
1072 pcs2dev[0] =
w / view_box.
width();
1073 pcs2dev[3] = h / view_box.
height();
1074 pcs2dev[4] = x - view_box.
left() * pcs2dev[0];
1075 pcs2dev[5] = y - view_box.
top() * pcs2dev[3];
1077 pcs2dev[0] = pbox->width();
1078 pcs2dev[3] = pbox->height();
1082#define SUBPIX_SCALE 100
1086 double surface_width =
MAX(ceil(SUBPIX_SCALE * bbox_width_scaler *
width - 0.5), 1);
1087 double surface_height =
MAX(ceil(SUBPIX_SCALE * bbox_height_scaler *
height - 0.5), 1);
1088 TRACE((
"pattern surface size: %f x %f\n", surface_width, surface_height));
1094 double scale_width = surface_width / (bbox_width_scaler *
width);
1095 double scale_height = surface_height / (bbox_height_scaler *
height);
1097 TRACE((
"needed to scale with %f %f\n", scale_width, scale_height));
1098 pcs2dev *=
Geom::Scale(SUBPIX_SCALE,SUBPIX_SCALE);
1099 ps2user *=
Geom::Scale(1.0/SUBPIX_SCALE,1.0/SUBPIX_SCALE);
1115 if (pat_i && pat_i->hasItemChildren()) {
1116 for (
auto&
child: pat_i->children) {
1117 if (is<SPItem>(&
child)) {
1118 cast<SPItem>(&
child)->invoke_show(drawing, dkey, SP_ITEM_REFERENCE_FLAGS);
1132 cairo_pattern_set_extend(
result, CAIRO_EXTEND_REPEAT);
1135 cairo_matrix_t pattern_matrix;
1137 cairo_matrix_invert(&pattern_matrix);
1138 cairo_pattern_set_matrix(
result, &pattern_matrix);
1142 if (pat_i && pat_i->hasItemChildren()) {
1143 for (
auto&
child: pat_i->children) {
1144 if (is<SPItem>(&
child)) {
1145 cast<SPItem>(&
child)->invoke_hide(dkey);
1157 SPHatch const *hatch = cast<SPHatch>(paintserver);
1160 g_assert(hatch->
pitch() > 0);
1168 evil->
show(drawing, dkey, pbox);
1176 const int subpix_scale = 10;
1177 double surface_width =
MAX(ceil(subpix_scale * tile_rect.
width() - 0.5), 1);
1178 double surface_height =
MAX(ceil(subpix_scale * tile_rect.
height() - 0.5), 1);
1183 child_transform *= drawing_transform;
1189 gdouble overflow_right_strip = 0.0;
1190 int overflow_steps = 1;
1195 overflow_steps = ceil((overflow_right_strip -
bounds.
min()) / hatch->
pitch()) + 1;
1204 std::vector<SPHatchPath *> children(evil->
hatchPaths());
1206 for (
int i = 0; i < overflow_steps; i++) {
1207 for (
auto path : children) {
1210 pattern_ctx.
transform(overflow_transform);
1219 cairo_pattern_set_extend(
result, CAIRO_EXTEND_REPEAT);
1234 bool apply_bbox2user = FALSE;
1236 auto const paintserver_mutable =
const_cast<SPPaintServer *
>(paintserver);
1238 if (
auto lg = cast<SPLinearGradient>(paintserver_mutable)) {
1242 Geom::Point p1 (lg->x1.computed, lg->y1.computed);
1243 Geom::Point p2 (lg->x2.computed, lg->y2.computed);
1246 Geom::Affine bbox2user(pbox->width(), 0, 0, pbox->height(), pbox->left(), pbox->top());
1255 for (gint i = 0; unsigned(i) < lg->vector.stops.size(); i++) {
1258 }
else if (
auto rg = cast<SPRadialGradient>(paintserver_mutable)) {
1264 double r = rg->r.computed;
1265 double fr = rg->fr.computed;
1267 apply_bbox2user =
true;
1273 for (gint i = 0; unsigned(i) < rg->vector.stops.size(); i++) {
1276 }
else if (
auto mg = cast<SPMeshGradient>(paintserver_mutable)) {
1277 pattern = mg->create_drawing_paintserver()->create_pattern(
_cr, pbox, 1.0);
1278 }
else if (is<SPPattern>(paintserver)) {
1280 }
else if (is<SPHatch>(paintserver) ) {
1286 if (pattern && is<SPGradient>(paintserver)) {
1287 auto g = cast<SPGradient>(paintserver_mutable);
1293 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
1297 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
1301 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
1305 cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
1310 cairo_matrix_t pattern_matrix;
1311 if (g->gradientTransform_set) {
1313 cairo_matrix_init(&pattern_matrix,
1314 g->gradientTransform[0], g->gradientTransform[1],
1315 g->gradientTransform[2], g->gradientTransform[3],
1316 g->gradientTransform[4], g->gradientTransform[5]);
1318 cairo_matrix_init_identity (&pattern_matrix);
1321 if (apply_bbox2user) {
1323 cairo_matrix_t bbox2user;
1324 cairo_matrix_init (&bbox2user, pbox->width(), 0, 0, pbox->height(), pbox->left(), pbox->top());
1325 cairo_matrix_multiply (&pattern_matrix, &bbox2user, &pattern_matrix);
1327 cairo_matrix_invert(&pattern_matrix);
1328 cairo_pattern_set_matrix(pattern, &pattern_matrix);
1337 return state.merge_opacity ? source_opacity * state.opacity : source_opacity;
1342 g_return_if_fail( !style->
fill.set
1343 || style->
fill.isColor()
1344 || style->
fill.isContext()
1345 || style->
fill.isPaintserver() );
1349 if (style->
fill.isContext()) {
1351 }
else if (paint_server && paint_server->
isValid()) {
1353 g_assert(is<SPGradient>(SP_STYLE_FILL_SERVER(style))
1354 || is<SPPattern>(SP_STYLE_FILL_SERVER(style))
1355 || is<SPHatch>(SP_STYLE_FILL_SERVER(style)));
1358 cairo_set_source(
_cr, pattern);
1359 cairo_pattern_destroy(pattern);
1361 }
else if (style->
fill.isColor()) {
1364 g_assert(!style->
fill.set
1365 || (paint_server && !paint_server->
isValid()));
1374 if (style->
stroke.isContext()) {
1379 g_assert( style->
stroke.isPaintserver()
1380 || is<SPGradient>(SP_STYLE_STROKE_SERVER(style))
1381 || is<SPPattern>(SP_STYLE_STROKE_SERVER(style))
1382 || cast<SPHatch>(SP_STYLE_STROKE_SERVER(style)));
1387 cairo_set_source(
_cr, pattern);
1388 cairo_pattern_destroy(pattern);
1395 size_t num_dashes = dash_values.size();
1396 std::vector<double> dashes;
1398 dashes.reserve(num_dashes);
1399 std::transform(dash_values.begin(), dash_values.end(), std::back_inserter(dashes),
1400 [](
SPILength const &dash_length) ->
double { return dash_length.value; });
1404 cairo_set_dash(
_cr,
nullptr, 0, 0.0);
1417 cairo_line_join_t
join = CAIRO_LINE_JOIN_MITER;
1420 join = CAIRO_LINE_JOIN_MITER;
1423 join = CAIRO_LINE_JOIN_ROUND;
1426 join = CAIRO_LINE_JOIN_BEVEL;
1429 cairo_set_line_join(
_cr,
join);
1432 cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
1435 cap = CAIRO_LINE_CAP_BUTT;
1438 cap = CAIRO_LINE_CAP_ROUND;
1441 cap = CAIRO_LINE_CAP_SQUARE;
1444 cairo_set_line_cap(
_cr, cap);
1479 cairo_show_page(
_cr);
1481 for (
int i = 1; i < original_stack.size(); i++) {
1519 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_EVEN_ODD);
1521 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_WINDING);
1527 TEST(cairo_surface_write_to_png (
_surface,
"pathmask.png"));
1533 style->
fill.isNone() ||
1534 style->
fill.isContext() ||
1538 style->
stroke.isNone() ||
1539 style->
stroke.isContext() ||
1544 if (no_fill && no_stroke)
1548 bool need_layer = !state.merge_opacity && !state.need_layer &&
1549 (state.opacity != 1.0 || state.clip_path !=
nullptr || state.mask !=
nullptr);
1562 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_EVEN_ODD);
1564 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_WINDING);
1576 cairo_fill_preserve(
_cr);
1585 cairo_stroke_preserve(
_cr);
1623 if (cairo_surface_status(
const_cast<cairo_surface_t*
>(image_surface))) {
1624 TRACE((
"Image surface creation failed:\n%s\n", cairo_status_to_string(cairo_surface_status(image_surface))));
1634 cairo_set_source_surface(
_cr,
const_cast<cairo_surface_t*
>(image_surface), 0.0, 0.0);
1638 cairo_new_path(
_cr);
1658 cairo_pattern_set_filter(cairo_get_source(
_cr), CAIRO_FILTER_NEAREST);
1663 cairo_pattern_set_filter(cairo_get_source(
_cr), CAIRO_FILTER_BEST);
1678#define GLYPH_ARRAY_SIZE 64
1683 std::vector<CairoGlyphInfo>
const &glyphtext,
1686 std::vector<cairo_glyph_t> glyphs;
1687 glyphs.reserve(glyphtext.size());
1689 for (
const auto &it_info : glyphtext) {
1691 if (it_info.index == PANGO_GLYPH_EMPTY || it_info.index & PANGO_GLYPH_UNKNOWN_FLAG) {
1692 TRACE((
"INVALID GLYPH found\n"));
1693 g_message(
"Invalid glyph found, continuing...");
1697 .index = it_info.index,
1703 const unsigned num_valid_glyphs = glyphs.size();
1705 cairo_glyph_path(cr, glyphs.data(), num_valid_glyphs);
1707 cairo_show_glyphs(cr, glyphs.data(), num_valid_glyphs);
1710 return num_valid_glyphs;
1727 std::vector<CairoGlyphInfo>
const &glyphtext,
SPStyle const *style,
1734 gpointer fonthash = (gpointer)font;
1735 cairo_font_face_t *font_face =
nullptr;
1737 font_face = it->second;
1740 FcPattern *fc_pattern =
nullptr;
1742# ifdef CAIRO_HAS_FT_FONT
1743 PangoFcFont *fc_font = PANGO_FC_FONT(font);
1744 fc_pattern = fc_font->font_pattern;
1745 if (font_face ==
nullptr) {
1746 font_face = cairo_ft_font_face_create_for_pattern(fc_pattern);
1752 cairo_set_font_face(
_cr, font_face);
1755 cairo_matrix_t matrix;
1757 cairo_set_font_matrix(
_cr, &matrix);
1762 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_EVEN_ODD);
1764 cairo_set_fill_rule(
_cr, CAIRO_FILL_RULE_WINDING);
1779 bool fill = style->
fill.isColor() || style->
fill.isPaintserver();
1780 bool stroke = style->
stroke.isColor() || style->
stroke.isPaintserver();
1781 if (!fill && !stroke) {
1789 || !fill || !stroke;
1791 bool fill_pass = fill && stroke_over_fill != second_pass;
1792 bool stroke_pass = stroke && !second_pass;
1798 cairo_fill_preserve(
_cr);
1812 return !stroke_over_fill && !second_pass;
1819 cairo_new_path(
_cr);
1830 size_t const written = fwrite(
data, 1, length, (FILE*)closure);
1831 return (written == length) ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
TEST(AngleIntervalTest, InnerAngleConstrutor)
Declaration of CairoRenderContext, a class used for rendering with Cairo.
struct _PangoFont PangoFont
Declaration of CairoRenderer, a class used for rendering via a CairoRenderContext.
void ink_cairo_set_source_color(Cairo::RefPtr< Cairo::Context > ctx, Inkscape::Colors::Color const &color, double opacity)
The following functions interact between Inkscape color model, and cairo surface rendering.
void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m)
void ink_cairo_pattern_add_color_stop(cairo_pattern_t *ptn, double offset, Inkscape::Colors::Color const &color, double opacity)
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m)
void feed_pathvector_to_cairo(cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width)
Feeds path-creating calls to the cairo context translating them from the PathVector,...
void ink_cairo_set_hairline(cairo_t *ct)
void ink_matrix_to_cairo(cairo_matrix_t &cm, Geom::Affine const &m)
void ink_matrix_to_2geom(Geom::Affine &m, cairo_matrix_t const &cm)
cairo_operator_t ink_css_blend_to_cairo_operator(SPBlendMode css_blend)
Cairo integration helpers.
Cairo::RefPtr< Cairo::ImageSurface > surface
3x3 matrix representing an affine transformation.
Affine inverse() const
Compute the inverse matrix.
C top() const
Return top coordinate of the rectangle (+Y is downwards).
C left() const
Return leftmost coordinate of the rectangle (+X is to the right).
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
CPoint max() const
Get the corner of the rectangle with largest coordinate values.
Range of real numbers that is never empty.
Axis-aligned rectangle that can be empty.
Two-dimensional point that doubles as a vector.
Axis aligned, non-empty rectangle.
bool setPdfTarget(gchar const *utf8_fn)
bool setPsTarget(gchar const *utf8_fn)
void setPathVector(Geom::PathVector const &pv)
std::vector< CairoRenderState > _state_stack
CairoRenderer * _renderer
Geom::Affine getItemTransform() const
bool _finishSurfaceSetup(cairo_surface_t *surface, cairo_matrix_t *ctm=nullptr)
OmitTextPageState _omittext_state
void _prepareRenderText()
void setPSLevel(unsigned int level)
CairoRenderContext(CairoRenderContext const &other)=delete
void setPDFLevel(unsigned int level)
cairo_pattern_t * _createPatternPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox)
unsigned int _showGlyphs(cairo_t *cr, PangoFont *font, std::vector< CairoGlyphInfo > const &glyphtext, bool is_stroke)
void addClipPath(Geom::PathVector const &pv, SPIEnum< SPWindRule > const *fill_rule)
CairoRenderMode _render_mode
bool saveAsPng(const char *file_name)
Saves the contents of the context to a PNG file.
bool _setVectorTarget(gchar const *utf8_fn)
struct Inkscape::Extension::Internal::CairoRenderContext::CairoRenderContextMetadata _metadata
void setTransform(Geom::Affine const &transform)
void setMetadata(SPDocument const &document)
Extract metadata from the document and store it in the context.
std::map< gpointer, cairo_font_face_t * > _font_table
Geom::Affine getParentTransform() const
cairo_pattern_t * _createPatternForPaintServer(SPPaintServer const *const paintserver, Geom::OptRect const &pbox, float alpha)
bool renderPathVector(Geom::PathVector const &pathv, SPStyle const *style, Geom::OptRect const &pbox, CairoPaintOrder order=STROKE_OVER_FILL)
bool renderGlyphtext(PangoFont *font, Geom::Affine const &font_matrix, std::vector< CairoGlyphInfo > const &glyphtext, SPStyle const *style, bool second_pass=false)
Called by Layout-TNG-Output, this function decides how to apply styles and write out the final shapes...
bool finish(bool finish_surface=true)
const CairoRenderState * getParentState() const
void setStateForItem(SPItem const *item)
cairo_surface_type_t _target
Geom::Affine getTransform() const
bool renderImage(Inkscape::Pixbuf const *pb, Geom::Affine const &image_transform, SPStyle const *style)
CairoRenderContext createSimilar(double width, double height) const
Creates a new render context which will be compatible with the given context's Cairo surface.
cairo_format_t _target_format
CairoRenderState * _addState()
CairoRenderContext & operator=(CairoRenderContext const &other)=delete
cairo_surface_t * _surface
void destBegin(const char *link)
unsigned int _clip_winding_failed
void _setSurfaceMetadata(cairo_surface_t *surface)
bool setSurfaceTarget(cairo_surface_t *surface, bool is_vector, cairo_matrix_t *ctm=nullptr)
Set the cairo_surface_t from an external source.
const CairoRenderState * getCurrentState() const
bool setImageTarget(cairo_format_t format)
bool nextPage(double width, double height, char const *label)
When writing multiple pages, resize the next page.
unsigned int _vector_based_target
void setClipMode(CairoClipMode mode)
void _prepareRenderGraphic()
void _setStrokeStyle(SPStyle const *style, Geom::OptRect const &pbox)
void transform(Geom::Affine const &transform)
bool finishPage()
Each page that's made should call finishPage to complete it.
void tagBegin(const char *link)
void setRenderMode(CairoRenderMode mode)
void setItemTransform(Geom::Affine const &transform)
void setStateForStyle(SPStyle const *style)
bool setupSurface(double width, double height)
Creates the cairo_surface_t for the context with the given width, height and with the currently set t...
void addClippingRect(double x, double y, double width, double height)
cairo_pattern_t * _createHatchPainter(SPPaintServer const *const paintserver, Geom::OptRect const &pbox)
static void font_data_free(gpointer data)
unsigned _bitmapresolution
void addPathVector(Geom::PathVector const &pv)
cairo_surface_t * getSurface()
float _mergedOpacity(float source_opacity) const
void popLayer(cairo_operator_t composite=CAIRO_OPERATOR_CLEAR)
void _setFillStyle(SPStyle const *style, Geom::OptRect const &pbox)
void renderItem(CairoRenderContext *ctx, SPItem const *item, SPItem const *origin=nullptr, SPPage const *page=nullptr)
Traverses the object tree and invokes the render methods.
void applyMask(CairoRenderContext *ctx, SPMask const *mask)
void renderHatchPath(CairoRenderContext *ctx, SPHatchPath const &hatchPath, unsigned key)
CairoRenderContext createContext()
void applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp)
Class to hold image data for raster images.
cairo_surface_t * getSurfaceRaw()
Converts the pixbuf to Cairo pixel format and returns an image surface which can be used as a source.
static double convert(double from_dist, Unit const *from, Unit const *to)
Convert distances.
Typed SVG document implementation.
RenderInfo calculateRenderInfo(unsigned key) const
Inkscape::DrawingPattern * show(Inkscape::Drawing &drawing, unsigned key, Geom::OptRect const &bbox) override
void hide(unsigned key) override
std::vector< SPHatchPath * > hatchPaths()
Geom::Interval bounds() const
Enum type internal to SPStyle.
Length type internal to SPStyle.
Base class for visual SVG elements.
SPMask * getMaskObject() const
static unsigned int display_key_new(unsigned numkeys)
Allocates unique integer keys.
SPClipPath * getClipObject() const
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
virtual bool isValid() const
SPPattern * getObject() const
SPPattern::PatternUnits patternUnits() const
SPPattern::PatternUnits patternContentUnits() const
Geom::OptRect viewbox() const
Geom::Affine const & getTransform() const
@ UNITS_OBJECTBOUNDINGBOX
SPPaintServer * getFillPaintServer()
T< SPAttr::FILL, SPIPaint > fill
fill
T< SPAttr::STROKE_DASHARRAY, SPIDashArray > stroke_dasharray
stroke-dasharray
T< SPAttr::STROKE, SPIPaint > stroke
stroke
SPPaintServer * getStrokePaintServer()
T< SPAttr::PAINT_ORDER, SPIPaintOrder > paint_order
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
T< SPAttr::FILL_RULE, SPIEnum< SPWindRule > > fill_rule
fill-rule: 0 nonzero, 1 evenodd
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
T< SPAttr::STROKE_LINEJOIN, SPIEnum< SPStrokeJoinType > > stroke_linejoin
stroke-linejoin
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
T< SPAttr::STROKE_MITERLIMIT, SPIFloat > stroke_miterlimit
stroke-miterlimit
T< SPAttr::MIX_BLEND_MODE, SPIEnum< SPBlendMode > > mix_blend_mode
T< SPAttr::OPACITY, SPIScale24 > opacity
opacity
T< SPAttr::FILTER, SPIFilter > filter
Filter effect.
T< SPAttr::STROKE_LINECAP, SPIEnum< SPStrokeCapType > > stroke_linecap
stroke-linecap
T< SPAttr::IMAGE_RENDERING, SPIEnum< SPImageRendering > > image_rendering
T< SPAttr::STROKE_DASHOFFSET, SPILength > stroke_dashoffset
stroke-dashoffset
T< SPAttr::STROKE_EXTENSIONS, SPIStrokeExtensions > stroke_extensions
-inkscape-stroke
T< SPAttr::OVERFLOW_, SPIEnum< SPOverflow > > overflow
overflow
A way to clear the N_ macro, which is defined as an inline function.
static char const *const parent
Representation of paint servers used when rendering.
_cairo_pattern cairo_pattern_t
struct _cairo_surface cairo_surface_t
auto floor(Geom::Rect const &rect)
Mini static library that contains the version of Inkscape.
Affine identity()
Create an identity matrix.
static cairo_status_t _write_callback(void *closure, const unsigned char *data, unsigned int length)
void dump_fopen_call(char const *utf8name, char const *id)
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Open a file with g_fopen().
Helper class to stream background task notifications as a series of messages.
static Glib::ustring join(std::vector< Glib::ustring > const &accels, char const separator)
char const * version_string_without_revision
version string excluding revision and date
Glib::ustring now_iso_8601()
like ReproducibleBuilds::now() but returns a ISO 8601 formatted string
void cairo_rectangle(cairo_t *cr, Geom::Rect const &r)
PathVector - a sequence of subpaths.
struct rdf_work_entity_t * rdf_find_entity(gchar const *name)
Retrieves a known RDF/Work entity by name.
const gchar * rdf_get_work_entity(SPDocument const *doc, struct rdf_work_entity_t *entity)
Retrieves a known RDF/Work entity's contents from the document XML by name.
Functions to parse the "SOURCE_DATE_EPOCH" environment variable for reproducible build hacks,...
TODO: insert short description here.
@ SP_GRADIENT_SPREAD_REPEAT
@ SP_GRADIENT_SPREAD_REFLECT
@ SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX
SVG <hatch> implementation.
SVG <image> implementation.
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
TODO: insert short description here.
TODO: insert short description here.
SVG <pattern> implementation.
TODO: insert short description here.
Geom::Affine child_transform
Geom::Affine pattern_to_user_transform
@ SP_CSS_OVERFLOW_VISIBLE
@ SP_STROKE_LINEJOIN_MITER
@ SP_STROKE_LINEJOIN_BEVEL
@ SP_STROKE_LINEJOIN_ROUND
@ SP_CSS_IMAGE_RENDERING_PIXELATED
@ SP_CSS_IMAGE_RENDERING_OPTIMIZEQUALITY
@ SP_CSS_IMAGE_RENDERING_AUTO
@ SP_CSS_IMAGE_RENDERING_OPTIMIZESPEED
@ SP_CSS_IMAGE_RENDERING_CRISPEDGES
@ SP_STROKE_LINECAP_SQUARE
@ SP_STROKE_LINECAP_ROUND
@ SP_CSS_PAINT_ORDER_STROKE
@ SP_CSS_PAINT_ORDER_FILL
void cairo_set_source_rgba(cairo_t *cr, colour c)