librsvg и Каир;rsvg_handle_render_cairo () не работает;Что я делаю неправильно? - PullRequest
0 голосов
/ 21 ноября 2018

Я играю с некоторым кодом в проекте;в частности, функция, которая берет изображения SVG и делает из них pngs.

У меня есть это:

    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) работала нормально.Обратите внимание, что, по сути, одна и та же функция struct и readFile используется в другом месте без каких-либо проблем.И из отладочных сообщений, которые я туда зашёл, я вижу, что файл действительно читается.Я также получаю правильные размеры из моего файла SVG, и, кажется, нет никаких ошибок до вызова функции рендеринга (так что я бы предположил, что он проанализирован нормально), но, возможно, нет?

1 Ответ

0 голосов
/ 28 ноября 2018

Ответ был смехотворно прост.Я пропал без вести rsvg_handle_close(svgHandle.get(), &pError);

...