エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

libRSVG と Cairo を使って SVG から PDF を生成しためも

それぞれのサイト。


今回参照したドキュメント。

#if 0
# このファイルを Ruby で実行すると、このファイルを C++ のソースとしてコンパイルします。
# $ ruby minimum-svg2pdf.cpp
system('g++ --std=c++11 `pkg-config --cflags --libs cairo librsvg-2.0` -o minimum-svg2pdf minimum-svg2pdf.cpp')
__END__
#endif

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <librsvg/rsvg.h>

#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>

static const std::string source =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
"<svg"
"   xmlns=\"http://www.w3.org/2000/svg\""
"   version=\"1.1\""
"   width=\"210mm\""
"   height=\"297mm\""
">"
"  <rect x=\"100\" y=\"100\" width=\"100\" height=\"100\" fill=\"red\" />"
"  <text"
"    font-family=\"sans-serif\""
"    font-size=\"18\""
"    x=\"200\""
"    y=\"200\">エンジニアのソフトウェア的愛情</text>"
"  <text"
"    font-size=\"12\""
"    x=\"200\""
"    y=\"220\">または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか</text>"
"</svg>";

int main(int argc, char* argv[])
{
    GError* error = 0; 
    RsvgHandle* svg = rsvg_handle_new_from_data(reinterpret_cast<const guint8*>(source.c_str()), source.length() , &error);

    if(error != 0)
    {
        std::cout << error->message << std::endl;
        return 0;
    }

    if(svg == 0)
    {
        std::cout << "no handle" << std::endl;
        return 0;
    }

    RsvgDimensionData dim;
    rsvg_handle_get_dimensions(svg, &dim);

    std::cout << "document size = " << dim.width << "x" << dim.height << std::endl;

    cairo_surface_t* surface = cairo_pdf_surface_create("sample.pdf", dim.width, dim.height);
    cairo_t* cairo = cairo_create(surface);
    cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
    rsvg_handle_render_cairo(svg, cairo);
    cairo_surface_flush(surface);

    cairo_destroy(cairo);
    cairo_surface_destroy(surface);

    rsvg_handle_close(svg, &error);

    if(error != 0)
    {
        std::cout << error->message << std::endl;
    }

    g_object_unref(svg);

    return 0;
}


コンパイルと実行*1

$ ruby minimum-svg2pdf.cpp
$ ./minimum-svg2pdf 
document size = 744x1052


こんなイメージの PDF ファイルが作成されます。

いつか読むはずっと読まない:今ここにある世界のSF

フィクションであり、フィクションでない。


遠隔機動歩兵 -ティン・メン- (ハヤカワ文庫SF)

遠隔機動歩兵 -ティン・メン- (ハヤカワ文庫SF)

*1:C/C++ のソースに Rubyスクリプトを埋め込んで自分に自分をコンパイルさせるやり方は横へなの鍋谷さんから教わりました。