/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include #include #include #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 png; FCITX_ASSERT(cairo_surface_write_to_png_stream( surface.get(), +[](void *data, const unsigned char *bytes, unsigned int length) { auto &out = *static_cast *>(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 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(text.begin(), text.end())); }; auto rendered = 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( cairo_image_surface_get_data(rendered.get())); FCITX_ASSERT(pixel[0] == 0xffff0000); // Native-endian Cairo ARGB32. FCITX_ASSERT(!svg("")); FCITX_ASSERT(!svg("")); FCITX_ASSERT(!svg("")); FCITX_ASSERT(!svg(" oversized(16 * 1024 * 1024 + 1); FCITX_ASSERT(!loadRasterImage(oversized)); FCITX_ASSERT(!loadSvgImage(oversized)); }