Files
RedBear-OS/local/recipes/libs/harfbuzz/source/test/api/test-raster.cc
T

243 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright © 2026 Behdad Esfahbod
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author(s): Behdad Esfahbod
*/
#include "hb-test.h"
#include "hb-raster.h"
#include <hb-ot.h>
/* ── Helpers ─────────────────────────────────────────────────────── */
/* Draw a closed rectangle by emitting raw draw callbacks. */
static void
draw_rect (hb_raster_draw_t *rdr,
float x0, float y0, float x1, float y1)
{
hb_draw_funcs_t *df = hb_raster_draw_get_funcs (rdr);
hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
hb_draw_move_to (df, rdr, &st, x0, y0);
hb_draw_line_to (df, rdr, &st, x1, y0);
hb_draw_line_to (df, rdr, &st, x1, y1);
hb_draw_line_to (df, rdr, &st, x0, y1);
hb_draw_close_path (df, rdr, &st); /* emits closing line_to(x0,y0) */
}
/* Read one A8 pixel value; returns 0 for out-of-bounds coordinates. */
static uint8_t
pixel_at (hb_raster_image_t *img, int x, int y)
{
hb_raster_extents_t ext;
hb_raster_image_get_extents (img, &ext);
int col = x - ext.x_origin;
int row = y - ext.y_origin;
if (col < 0 || row < 0 ||
(unsigned) col >= ext.width || (unsigned) row >= ext.height)
return 0;
return hb_raster_image_get_buffer (img)[row * ext.stride + col];
}
/* ── Test 1: rectangle geometry ──────────────────────────────────── */
static void
test_rectangle (void)
{
hb_raster_draw_t *rdr = hb_raster_draw_create_or_fail ();
draw_rect (rdr, 2.f, 2.f, 30.f, 30.f);
hb_raster_image_t *img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
hb_raster_extents_t ext;
hb_raster_image_get_extents (img, &ext);
g_assert_cmpint (ext.x_origin, ==, 2);
g_assert_cmpint (ext.y_origin, ==, 2);
g_assert_cmpuint (ext.width, ==, 28);
g_assert_cmpuint (ext.height, ==, 28);
/* Center: fully inside → full coverage */
g_assert_cmpint (pixel_at (img, 16, 16), ==, 255);
/* Well outside the box → zero */
g_assert_cmpint (pixel_at (img, 0, 0), ==, 0); /* out of image */
g_assert_cmpint (pixel_at (img, 31, 31), ==, 0); /* out of image */
/* Left-most and right-most pixel columns: still fully inside
because integer-coordinate box edges align with pixel boundaries */
g_assert_cmpint (pixel_at (img, 2, 16), ==, 255);
g_assert_cmpint (pixel_at (img, 29, 16), ==, 255);
/* One pixel beyond the box right edge: out of image */
g_assert_cmpint (pixel_at (img, 30, 16), ==, 0);
hb_raster_image_destroy (img);
/* render() with no accumulated edges → empty (0×0) image */
img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
hb_raster_image_get_extents (img, &ext);
g_assert_cmpuint (ext.width, ==, 0);
g_assert_cmpuint (ext.height, ==, 0);
hb_raster_image_destroy (img);
hb_raster_draw_destroy (rdr);
}
/* ── Test 2: multi-glyph accumulation ────────────────────────────── */
static void
test_accumulate (void)
{
hb_raster_draw_t *rdr = hb_raster_draw_create_or_fail ();
/* Two non-overlapping boxes accumulated before a single render() */
draw_rect (rdr, 0.f, 0.f, 10.f, 10.f);
draw_rect (rdr, 20.f, 0.f, 30.f, 10.f);
hb_raster_image_t *img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
/* Both interiors fully covered */
g_assert_cmpint (pixel_at (img, 5, 5), ==, 255);
g_assert_cmpint (pixel_at (img, 25, 5), ==, 255);
/* Gap between the two boxes is empty */
g_assert_cmpint (pixel_at (img, 15, 5), ==, 0);
hb_raster_image_destroy (img);
hb_raster_draw_destroy (rdr);
}
/* ── Test 3: sub-pixel edge coverage ─────────────────────────────── */
static void
test_subpixel_edge (void)
{
hb_raster_draw_t *rdr = hb_raster_draw_create_or_fail ();
/* Box with a half-pixel offset so the leftmost pixel column is split */
draw_rect (rdr, 2.5f, 2.f, 30.f, 30.f);
hb_raster_image_t *img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
/* The pixel at x=2 straddles the left edge → partial coverage */
int v = pixel_at (img, 2, 16);
g_assert_cmpint (v, >, 0);
g_assert_cmpint (v, <, 255);
/* The pixel at x=3 is fully inside */
g_assert_cmpint (pixel_at (img, 3, 16), ==, 255);
hb_raster_image_destroy (img);
hb_raster_draw_destroy (rdr);
}
/* ── Test 4: transform ───────────────────────────────────────────── */
static void
test_transform (void)
{
hb_raster_draw_t *rdr = hb_raster_draw_create_or_fail ();
/* Scale by 2 — same unit-square box maps to (0,0)→(20,20) */
hb_raster_draw_set_transform (rdr, 2.f, 0.f, 0.f, 2.f, 0.f, 0.f);
draw_rect (rdr, 0.f, 0.f, 10.f, 10.f);
hb_raster_image_t *img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
hb_raster_extents_t ext;
hb_raster_image_get_extents (img, &ext);
g_assert_cmpuint (ext.width, ==, 20);
g_assert_cmpuint (ext.height, ==, 20);
g_assert_cmpint (pixel_at (img, 10, 10), ==, 255); /* center of scaled box */
hb_raster_image_destroy (img);
hb_raster_draw_destroy (rdr);
}
/* ── Test 5: transformed glyph extents helper ───────────────────── */
static void
test_set_glyph_extents_with_transform (void)
{
hb_raster_draw_t *rdr = hb_raster_draw_create_or_fail ();
hb_raster_draw_set_transform (rdr, 2.f, 0.f, 0.f, 3.f, 5.f, 7.f);
hb_glyph_extents_t gext = {
1, /* x_bearing */
4, /* y_bearing */
10, /* width */
-6 /* height */
};
g_assert_true (hb_raster_draw_set_glyph_extents (rdr, &gext));
draw_rect (rdr, (float) gext.x_bearing,
(float) gext.y_bearing + gext.height,
(float) gext.x_bearing + gext.width,
(float) gext.y_bearing);
hb_raster_image_t *img = hb_raster_draw_render (rdr);
g_assert_nonnull (img);
hb_raster_extents_t ext;
hb_raster_image_get_extents (img, &ext);
g_assert_cmpint (ext.x_origin, ==, 7); /* 2*1 + 5 */
g_assert_cmpint (ext.y_origin, ==, 1); /* 3*(-2) + 7 */
g_assert_cmpuint (ext.width, ==, 20); /* 2*10 */
g_assert_cmpuint (ext.height, ==, 18); /* 3*6 */
hb_raster_image_destroy (img);
hb_raster_draw_destroy (rdr);
}
/* ── main ────────────────────────────────────────────────────────── */
int
main (int argc, char **argv)
{
hb_test_init (&argc, &argv);
hb_test_add (test_rectangle);
hb_test_add (test_accumulate);
hb_test_add (test_subpixel_edge);
hb_test_add (test_transform);
hb_test_add (test_set_glyph_extents_with_transform);
return hb_test_run ();
}