首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >librsvg和cairo;rsvg_handle_render_cairo()失败;我做错了什么?

librsvg和cairo;rsvg_handle_render_cairo()失败;我做错了什么?
EN

Stack Overflow用户
提问于 2018-11-21 14:05:47
回答 1查看 269关注 0票数 0

我正在处理项目中的一些代码;具体地说,是一个获取SVG图像并从中生成pngs的函数。

我有这个:

代码语言:javascript
复制
    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文件中获得了正确的尺寸,在调用渲染函数之前似乎没有任何错误(所以我假设它是正确的),但可能不是?

EN

回答 1

Stack Overflow用户

发布于 2018-11-28 12:31:18

答案简单得离谱。我很怀念rsvg_handle_close(svgHandle.get(), &pError);

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53406129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档