当 cairo 要求读取比我从 png 创建和 ImageSurface 时拥有的数据更多的数据时该怎么办?

What to do when cairo asks to read more data than I have when creating and ImageSurface from png?

我正在使用 cairomm 1.12.0 版和 cairo 1.14.6 版。

我正在尝试从我作为字节向量存储在内存中的 png 在 cairo 中创建一个 ImageSurface。大多数情况下这是可行的,但有时 Cairo 会向我的读取函数(lambda)传递一个要读取的长度(长度参数),该长度大于向量中剩余的长度。当我在 visual studio 中调试它时,我当然得到一个失败的调试断言 Expression: cannot seek vector iterator after end

Cairo::RefPtr<Cairo::ImageSurface> someFunc(const std::vector<BYTE>& src)
{
  Cairo::RefPtr<Cairo::ImageSurface> ret;
  if(src.size() > 0)
  {
    unsigned int read = 0;
    ret = Cairo::ImageSurface::create_from_png_stream([&src, &read](unsigned char* data, unsigned int length) {
      std::copy_n(src.begin() + read, length, data);
      read += length;
      return CAIRO_STATUS_SUCCESS;
    });
  }
  return ret;
}

如果我尝试修改我的读取函数以复制剩余数据的最小值和 Cairo 要求读取的长度,我得到 CAIRO_STATUS_NO_MEMORY,这会导致 std::bad_alloc 异常抛出。

Cairo::RefPtr<Cairo::ImageSurface> someFunc(const std::vector<BYTE>& src)
{
  Cairo::RefPtr<Cairo::ImageSurface> ret;
  if(src.size() > 0)
  {
    unsigned int read = 0;
    ret = Cairo::ImageSurface::create_from_png_stream([&src, &read](unsigned char* data, unsigned int length) {
      length = std::min((unsigned int)src.size() - read, length); // added
      std::copy_n(src.begin() + read, length, data);
      read += length;
      return CAIRO_STATUS_SUCCESS;
    });
  }
  return ret;
}

我认为这与 cairo-stream_read_func 中对 _cairo_output_stream_write 的调用有关-png.c,因为它传递的大小与传递我的读取函数的大小相同,因此可能需要一些数据。

...
status = png_closure->read_func (png_closure->closure, data, size);
...
_cairo_output_stream_write (png_closure->png_data, data, size);

我应该写 null 还是什么来填补字节差异?

如果 cairo 要求的数据多于您拥有的数据,则您的 PNG 已损坏。 Cairo 要求的字节数与 libpng 要求的字节数一样多,据说 libpng 知道它在做什么 (tm) 并要求正确的字节数。如果你没有足够的字节,你应该 return CAIRO_STATUS_READ_ERROR 从你的读取功能。