Как запретить cairo растрировать мои узорные заливки?

Примерно в 2011 году я написал скрипт Pycairo для создания PDF-файла, который включал несколько заливок пользовательских векторных шаблонов. Сегодня я повторно запустил его (Python 3.5.2, Pycairo 1.10.0) и был удивлен, увидев, что все эти шаблоны визуализируются как растеризованные растровые изображения с низким разрешением. Я сократил свой скрипт до этого минимального примера:

#!/usr/bin/python3

import cairo

def main():
    surface = cairo.PDFSurface("test.pdf", 100, 100)
    ctx = cairo.Context(surface)
    pattern = make_pattern()
    ctx.rectangle(10, 10, 80, 80)
    ctx.set_source(pattern)
    ctx.fill()
    surface.finish()

def make_pattern():
    pattern_surface = cairo.PDFSurface(None, 32, 8)
    ctx = cairo.Context(pattern_surface)
    ctx.set_line_width(.5)
    ctx.set_source_rgb(0,0,0)
    ctx.move_to(5, 6)
    ctx.line_to(27, 2)
    ctx.stroke()
    pattern = cairo.SurfacePattern(pattern_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern

if __name__ == "__main__":
    main()

Результирующий PDF-файл, сильно увеличенный, отображает шаблон следующим образом:

вывод скрипта

Взгляд на текст файла PDF подтверждает, что это растровое изображение. Использование SVGSurface дает аналогичные результаты. Есть ли способ вернуться к старому поведению, при котором заливки шаблонов PDF отображались как векторные заливки в окончательном PDF, а не растеризировались, как это? Единственная ссылка на проблему, которую я нашел в Интернете, — это этот вопрос без ответа на список рассылки каира от января 2012 г.


person Pont    schedule 25.02.2019    source источник


Ответы (1)


Я до сих пор не нашел способа сделать это строго с помощью Pycairo, но нашел решение с помощью cairocffi, улучшенная замена Pycairo. cairocffi предлагает класс RecordingSurface,

поверхность, которая записывает все операции рисования на самом высоком уровне внутреннего интерфейса поверхности (то есть на уровне рисования, маски, обводки, заливки и show_text_glyphs). Записывающая поверхность затем может быть «воспроизведена» на любой целевой поверхности, используя ее в качестве исходной поверхности.

Я изменил скрипт, чтобы использовать cairocffi и RecordingSurface:

#!/usr/bin/python3

import cairocffi as cairo

def main():
    surface = cairo.PDFSurface("test.pdf", 100, 100)
    ctx = cairo.Context(surface)
    pattern = make_pattern()
    ctx.rectangle(10, 10, 80, 80)
    ctx.set_source(pattern)
    ctx.fill()
    surface.finish()

def make_pattern():
    pattern_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 32, 8))
    ctx = cairo.Context(pattern_surface)
    ctx.set_line_width(.5)
    ctx.set_source_rgb(0,0,0)
    ctx.move_to(5, 6)
    ctx.line_to(27, 2)
    ctx.stroke()
    pattern = cairo.SurfacePattern(pattern_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern

if __name__ == "__main__":
    main()

В результате получился не растеризованный шаблон:

вывод скрипта

person Pont    schedule 25.02.2019