Files
fcitx5-m3ui/tests/testm3uiimageloader.cpp

78 lines
3.3 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <cstdint>
#include <string>
#include <vector>
#include "fcitx-utils/log.h"
#include "../src/imageloader.h"
using namespace fcitx::m3ui;
int main() {
FCITX_ASSERT(!loadRasterImage({}));
FCITX_ASSERT(!loadSvgImage({}));
FCITX_ASSERT(!loadRasterImage({'b', 'a', 'd'}));
FCITX_ASSERT(!loadSvgImage({'b', 'a', 'd'}));
// Valid PNG bytes exercise the real incremental decoder, regardless of
// extension. The reference must remain valid after loader destruction.
LoadedSurface surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 16, 16));
std::vector<uint8_t> png;
FCITX_ASSERT(cairo_surface_write_to_png_stream(
surface.get(),
+[](void *data, const unsigned char *bytes, unsigned int length) {
auto &out = *static_cast<std::vector<uint8_t> *>(data);
out.insert(out.end(), bytes, bytes + length);
return CAIRO_STATUS_SUCCESS;
},
&png) == CAIRO_STATUS_SUCCESS);
auto image = loadRasterImage(png);
FCITX_ASSERT(image);
FCITX_ASSERT(gdk_pixbuf_get_width(image.get()) == 16);
FCITX_ASSERT(gdk_pixbuf_get_height(image.get()) == 16);
png[16] = 255; // Huge IHDR, rejected before entering libpng.
FCITX_ASSERT(!loadRasterImage(png));
png.resize(23);
FCITX_ASSERT(!loadRasterImage(png));
// A real non-PNG image exercises size-prepared rather than PNG preflight.
gchar *bmpData = nullptr;
gsize bmpSize = 0;
FCITX_ASSERT(gdk_pixbuf_save_to_buffer(image.get(), &bmpData, &bmpSize,
"bmp", nullptr, nullptr));
std::vector<uint8_t> bmp(bmpData, bmpData + bmpSize);
g_free(bmpData);
FCITX_ASSERT(loadRasterImage(bmp));
// BMP BITMAPINFOHEADER width is little-endian at byte 18.
FCITX_ASSERT(bmp.size() > 26 && bmp[14] >= 40);
bmp[18] = 1;
bmp[19] = 32; // 8193 pixels wide
bmp[20] = bmp[21] = 0;
FCITX_ASSERT(!loadRasterImage(bmp));
auto svg = [](const std::string &text) {
return loadSvgImage(std::vector<uint8_t>(text.begin(), text.end()));
};
auto rendered = svg("<svg xmlns='http://www.w3.org/2000/svg' width='16' "
"height='16'><rect width='16' height='16' "
"fill='red'/></svg>");
FCITX_ASSERT(rendered);
FCITX_ASSERT(cairo_surface_get_type(rendered.get()) == CAIRO_SURFACE_TYPE_IMAGE);
FCITX_ASSERT(cairo_image_surface_get_width(rendered.get()) == 16);
FCITX_ASSERT(cairo_image_surface_get_height(rendered.get()) == 16);
cairo_surface_flush(rendered.get());
const auto *pixel = reinterpret_cast<const uint32_t *>(
cairo_image_surface_get_data(rendered.get()));
FCITX_ASSERT(pixel[0] == 0xffff0000); // Native-endian Cairo ARGB32.
FCITX_ASSERT(!svg("<svg xmlns='http://www.w3.org/2000/svg' "
"width='1e30' height='16'/>"));
FCITX_ASSERT(!svg("<svg xmlns='http://www.w3.org/2000/svg' "
"width='8192' height='8192'/>"));
FCITX_ASSERT(!svg("<svg xmlns='http://www.w3.org/2000/svg' "
"width='0' height='16'/>"));
FCITX_ASSERT(!svg("<svg xmlns='http://www.w3.org/2000/svg'"));
std::vector<uint8_t> oversized(16 * 1024 * 1024 + 1);
FCITX_ASSERT(!loadRasterImage(oversized));
FCITX_ASSERT(!loadSvgImage(oversized));
}