/*
 * 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 ();
}
