librsvg和开罗; rsvg_handle_render_cairo()失败;我究竟做错了什么?

时间:2018-11-21 06:05:47

标签: c++ c cairo librsvg

我在一个项目中玩一些代码;专门用于获取SVG图像并从中生成png的功能。

我有这个:

    typedef std::vector<uint8_t> BinaryBuffer;

    BinaryBuffer readFile(fs::path const& path) {
        BinaryBuffer ret;
        fs::ifstream f(path, std::ios::binary);
        f.seekg(0, std::ios::end);
        ret.resize(f.tellg());
        f.seekg(0);
        f.read(reinterpret_cast<char*>(ret.data()), ret.size());
        if (!f) throw std::runtime_error("File cannot be read: " + path.string());
        return ret;
    }

void loadSVG(Bitmap& bitmap, fs::path const& filename) {
    double factor = config["graphic/svg_lod"].f();
    // Try to load a cached PNG instead
    if (cache::loadSVG(bitmap, filename, factor)) return;
    std::clog << "image/debug: Loading SVG: " + filename.string() << std::endl;
    // Open the SVG file in librsvg
#if !GLIB_CHECK_VERSION(2, 36, 0)   // Avoid deprecation warnings
    g_type_init();
#endif
    GError* pError = nullptr;
    std::shared_ptr<RsvgHandle> svgHandle(rsvg_handle_new_with_flags(RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA), g_object_unref);
    rsvg_handle_set_base_uri(svgHandle.get(),filename.string().c_str());
    BinaryBuffer data = readFile(filename);
    std::clog << "svg/debug: svg data size is: " << data.size() << std::endl;
    gboolean result = rsvg_handle_write(svgHandle.get(), data.data(), data.size(), &pError);
//  rsvg_handle_new_from_file(filename.string().c_str(), &pError)

    if (result != TRUE) {
        g_error_free(pError);
        throw std::runtime_error("Unable to load " + filename.string());
    }
    else {
        std::clog << "svg/debug: SVG loaded succesfully." << std::endl;
    }
    // Get SVG dimensions
    RsvgDimensionData svgDimension;
    rsvg_handle_get_dimensions(svgHandle.get(), &svgDimension);
    // Prepare the pixel buffer
    std::clog << "svg/debug: svg width is: " << svgDimension.width << ", and height: " << svgDimension.height << std::endl;
    bitmap.resize(svgDimension.width*factor, svgDimension.height*factor);
    bitmap.fmt = pix::INT_ARGB;
    bitmap.linearPremul = true;
    // Raster with Cairo
    std::shared_ptr<cairo_surface_t> surface(
      cairo_image_surface_create_for_data(&bitmap.buf[0], CAIRO_FORMAT_ARGB32, bitmap.width, bitmap.height, bitmap.width * 4),
      cairo_surface_destroy);
    std::shared_ptr<cairo_t> dc(cairo_create(surface.get()), cairo_destroy);
    cairo_scale(dc.get(), factor, factor);
    gboolean renderRes = TRUE;
    renderRes = rsvg_handle_render_cairo(svgHandle.get(), dc.get());
    if (renderRes != TRUE) {
        throw std::runtime_error("Unable to render " + filename.string());
        }
    // Change byte order from BGRA to RGBA
    for (uint32_t *ptr = reinterpret_cast<uint32_t*>(&*bitmap.buf.begin()), *end = ptr + bitmap.buf.size() / 4; ptr < end; ++ptr) {
        uint8_t* pixel = reinterpret_cast<uint8_t*>(ptr);
        uint8_t r = pixel[2], g = pixel[1], b = pixel[0], a = pixel[3];
        pixel[0] = r; pixel[1] = g; pixel[2] = b; pixel[3] = a;
    }
    bitmap.fmt = pix::CHAR_RGBA;
    // Write to cache so that it can be loaded faster the next time
    fs::path cache_filename = cache::constructSVGCacheFileName(filename, factor);
    fs::create_directories(cache_filename.parent_path());
    writePNG(cache_filename, bitmap);
}

但是它在rsvg_handle_render_cairo中失败了...我不知道为什么。使用rsvg_handle_new_from_file的函数的先前版本(不使用BinaryBuffer结构)可以正常工作。但是请注意,其他地方使用的结构和readFile函数基本上相同,没有任何问题。从我放入的调试消息中,我可以看到该文件确实已被读取。我也从我的svg文件中获取了正确的尺寸,并且在调用render函数之前似乎没有任何错误(所以我认为它已经解析了),但是也许没有?

1 个答案:

答案 0 :(得分:0)

答案很简单。我想念rsvg_handle_close(svgHandle.get(), &pError);

相关问题