From 4da6c3db24a9370ddefa6b9d26ceb19166d6df92 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Wed, 22 Nov 2017 23:18:24 +0100 Subject: Revert "Fix PDF+TeX output for text inside groups with clip/mask" This reverts commit e4dea66a338824037b6c35b262aa8db4004b6581. --- src/extension/internal/cairo-render-context.cpp | 35 +++---------------------- 1 file changed, 3 insertions(+), 32 deletions(-) (limited to 'src/extension/internal/cairo-render-context.cpp') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 4869472da..791073e90 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -128,8 +128,7 @@ CairoRenderContext::CairoRenderContext(CairoRenderer *parent) : _renderer(parent), _render_mode(RENDER_MODE_NORMAL), _clip_mode(CLIP_MODE_MASK), - _omittext_state(EMPTY), - _omittext_missing_pages(0) + _omittext_state(EMPTY) { } @@ -885,13 +884,6 @@ CairoRenderContext::finish(bool finish_surface) if (_vector_based_target && finish_surface) cairo_show_page(_cr); - // PDF+TeX Output, see CairoRenderContext::_prepareRenderGraphic() - while (_omittext_missing_pages > 0) { - _omittext_missing_pages--; - g_warning("PDF+TeX output: issuing blank PDF page at end (workaround for previous error)"); - cairo_show_page(_cr); - } - cairo_destroy(_cr); _cr = NULL; @@ -1445,29 +1437,8 @@ CairoRenderContext::_prepareRenderGraphic() // Only PDFLaTeX supports importing a single page of a graphics file, // so only PDF backend gets interleaved text/graphics if (_is_omittext && _target == CAIRO_SURFACE_TYPE_PDF) { - if (_omittext_state == NEW_PAGE_ON_GRAPHIC) { - if (cairo_get_group_target(_cr) != cairo_get_target(_cr)) { - // we are in the middle of a group, i. e., between cairo_push_group() and cairo_pop_group(). - // cairo_show_page() has no effect here! - // To ensure that the the generated TeX source doesn't try to include non-existing pages, - // we will later output an extra blank page. - // This is a workaround for bug #1417470. - g_warning("PDF+TeX output: Found text inside a clipped/masked group. This is not supported, the Z-order will be incorrect. Blank pages will be added to the PDF output to work around bug #1417470."); - _omittext_missing_pages++; - } else { - // no group is active, create new page - cairo_show_page(_cr); - // Output missing pages (workaround for the 'if' case above). - // With this solution, the Z-order is more wrong than necessary. - // It would be better to print the blank pages first, and then the actual current page. - // However, this isn't easily possible with cairo. - while (_omittext_missing_pages > 0) { - _omittext_missing_pages--; - g_warning("PDF+TeX output: issuing blank PDF page (workaround for previous error)"); - cairo_show_page(_cr); - } - } - } + if (_omittext_state == NEW_PAGE_ON_GRAPHIC) + cairo_show_page(_cr); _omittext_state = GRAPHIC_ON_TOP; } } -- cgit v1.2.3 From dae7facca7b1bf5ce99aaf9dc71b2da8b46f56c8 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 20:03:13 +0100 Subject: Proper fix for multipage PDF+Latex export The previous implementation [1] allowed to sandwich text between graphical objects by outputting multiple (partial) PDF pages which are then stacked in the final document to reveal the full image. However this code failed for clipped/masked/transparent objects as those are treated specially by the renderer resulting in missing pages in the output causing [2]. The attempt to workaround this issue which was committed in e4dea66a338824037b6c35b262aa8db4004b6581 (now reverted) fixed document creation in LaTeX by inserting blank pages but did not actually fix the issue with clipped/masked/transparent objects typically resulting in a single page with the full image and all text put on top. This commit resolves the underlying issue, making the former workaround unnecessary and allowing for proper overlaying of text and arbitrarily clipped/masked/transparent objects Fixed bugs: - https://bugs.launchpad.net/inkscape/+bug/771957 [1] - https://bugs.launchpad.net/inkscape/+bug/1417470 [2] --- src/extension/internal/cairo-render-context.cpp | 35 +++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'src/extension/internal/cairo-render-context.cpp') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 791073e90..87c726832 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -1436,9 +1436,40 @@ CairoRenderContext::_prepareRenderGraphic() { // Only PDFLaTeX supports importing a single page of a graphics file, // so only PDF backend gets interleaved text/graphics - if (_is_omittext && _target == CAIRO_SURFACE_TYPE_PDF) { - if (_omittext_state == NEW_PAGE_ON_GRAPHIC) + if (_is_omittext && _target == CAIRO_SURFACE_TYPE_PDF && _render_mode != RENDER_MODE_CLIP) { + if (_omittext_state == NEW_PAGE_ON_GRAPHIC) { + // better set this immediately (not sure if masks applied during "popLayer" could call + // this function, too, triggering the same code again in error + _omittext_state = GRAPHIC_ON_TOP; + + // As we can not emit the page in the middle of a layer (aka group) - it will not be fully painted yet! - + // the following basically mirrors the calls in CairoRenderer::renderItem (but in reversed order) + // - first traverse all saved states in reversed order (i.e. from deepest nesting to the top) + // and apply clipping / masking to layers on the way (this is done in popLayer) + // - then emit the page using cairo_show_page() + // - finally restore the previous state with proper transforms and appropriate layers again + // + // TODO: While this appears to be an ugly hack it seems to work + // Somebody with a more intimate understanding of cairo and the renderer implementation might + // be able to implement this in a cleaner way, though. + int stack_size = _state_stack.size(); + for (int i = stack_size-1; i > 0; i--) { + if (_state_stack[i]->need_layer) + popLayer(); + cairo_restore(_cr); + _state = _state_stack[i-1]; + } + cairo_show_page(_cr); + + for (int i = 1; i < stack_size; i++) { + cairo_save(_cr); + _state = _state_stack[i]; + if (_state->need_layer) + pushLayer(); + setTransform(_state->transform); + } + } _omittext_state = GRAPHIC_ON_TOP; } } -- cgit v1.2.3 From c40b0c3259279aba0bc79d4dcc09c70abb71aa34 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 4 Dec 2017 20:03:57 +0100 Subject: CairoRenderer: print warning if rendering failed It happen often that the rendering was interrupted early but the final "cairo_surface_status" claims success which results in incomplete output but no user-visible warning. --- src/extension/internal/cairo-render-context.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/extension/internal/cairo-render-context.cpp') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 87c726832..b631f8c04 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -884,12 +884,16 @@ CairoRenderContext::finish(bool finish_surface) if (_vector_based_target && finish_surface) cairo_show_page(_cr); + cairo_status_t status = cairo_status(_cr); + if (status != CAIRO_STATUS_SUCCESS) + g_critical("error while rendering output: %s", cairo_status_to_string(status)); + cairo_destroy(_cr); _cr = NULL; if (finish_surface) cairo_surface_finish(_surface); - cairo_status_t status = cairo_surface_status(_surface); + status = cairo_surface_status(_surface); cairo_surface_destroy(_surface); _surface = NULL; -- cgit v1.2.3