Приложение, которое я пишу, использует libcairo для вывода векторной графики; все прекрасно работает для форматов вывода, которые поддерживают несколько страниц (PDF, PostScript), однако я также хотел бы поддерживать форматы SVG и растровых изображений.
В настоящее время я просто нажимаю на страницы, используя showPage
всякий раз, когда я бы переполнял нижнее поле, и я хотел бы сохранить структурированный код таким образом. Я предложил два теоретически возможных решения:
a) Вспомогательная монада, которая оборачивается вокруг монады Каира Render
, но обеспечивает действие flushPage
, которое, будучи прикованным к ней, помещает текущее действие Render во внутренний стек страниц, действие liftRender
, которое хорошо, поднимите действие Render
в монаду, связав его с ранее буферизованным действием, и вспомогательную функцию для извлечения списка Render ()
действий, по одному для каждой страницы. Поэтому я бы просто вызвал свою основную функцию рендеринга, но вместо действия Render ()
он вернул бы действие-обертку для страниц, из которого я затем извлекал бы отдельные страницы и обрабатывал их - для многостраничных форматов я мог бы просто создать цепочку они вместе, вставляя между ними действия showPage
, тогда как для одностраничных форматов я бы отображал их по отдельности. Например, вот как это будет выглядеть:
-- original code
renderMe :: Render ()
renderMe = do
newPath
moveTo 10 10
lineTo 20 20
lineTo 10 30
lineTo 10 10
fill
showPage
newPath
moveTo 10 10
lineTo 20 20
lineTo 10 30
lineTo 10 10
fill
-- new code
renderPages :: PagedRender ()
renderPages = do
liftRender (do
newPath
moveTo 10 10
lineTo 20 20
lineTo 10 30
lineTo 10 10
fill)
flushPage
liftRender (do
newPath
moveTo 10 10
lineTo 20 20
lineTo 10 30
lineTo 10 10
fill)
flushPage
b) Каирский тип поверхности, который действует как многостраничный документ снаружи, но создает серию одностраничных документов снаружи. Это было бы идеально, так как это вообще не потребовало бы каких-либо изменений в коде рендеринга, но я не уверен, возможно ли это сделать без вмешательства в сам cairo на уровне исходного кода.
Итак, актуальный вопрос: Существует ли какое-либо из вышеперечисленных решений? Как, например, кто-нибудь написал «монаду обертки для пагинации» или «многостраничную поверхность SVG»? И, если ответ «нет»; какой из них предпочтительнее и как вы будете его реализовывать?