104 n_wrap_item it[3] = {{1.0, 0}, {1.0, 0}, {1.0, 0}};
105 CHECK(
run(it, 3, 10.0, &c) == 1,
"fits -> 1 line");
117 CHECK(
run(it, 5, 5.0, &c) == 2,
"space wrap -> 2 lines");
118 CHECK(c.
n == 2,
"space wrap -> 2 emitted");
120 CHECK(
eq(c.
width[0], 5.0),
"line 0 width excludes the break space");
122 "line 1 starts AFTER the dropped space");
127 n_wrap_item it[3] = {{3.0, 0}, {3.0, 0}, {3.0, 0}};
128 CHECK(
run(it, 3, 5.0, &c) == 3,
"unbroken run -> one item per line");
129 CHECK(c.
first[1] == 1 && c.
last[1] == 2,
"mid-run break keeps order");
135 CHECK(
run(it, 1, 5.0, &c) == 1,
"over-wide item -> 1 line");
137 "over-wide item is placed alone");
138 CHECK(
eq(c.
width[0], 10.0),
"over-wide line reports its real width");
144 CHECK(
run(it, 2, 5.0, &c) == 2,
"narrow + over-wide -> 2 lines");
145 CHECK(c.
first[1] == 1 && c.
last[1] == 2,
"over-wide item on its own");
151 CHECK(
run(it, 3, 100.0, &c) == 2,
"newline -> 2 lines");
152 CHECK(c.
first[0] == 0 && c.
last[0] == 1,
"newline ends line 0 before it");
153 CHECK(c.
first[1] == 2 && c.
last[1] == 3,
"line 1 starts after it");
159 CHECK(
run(it, 2, 100.0, &c) == 2,
"trailing newline -> 2 lines counted");
160 CHECK(c.
n == 1,
"trailing newline emits only the non-empty line");
168 CHECK(
run(it, 3, 100.0, &c) == 3,
"blank line -> 3 lines");
176 CHECK(
run(it, 2, 5.0, &c) == 2,
"leading space -> 2 lines");
177 CHECK(c.
first[0] == 0 && c.
last[0] == 1,
"the leading space is kept");
183 CHECK(
run(it, 0, 5.0, &c) == 1,
"empty -> 1 line");
184 CHECK(c.
n == 0,
"empty emits nothing");
192 "NULL items -> 1 line");
193 CHECK(c.
n == 0,
"NULL items emit nothing");
199 size_t lines =
run(it, 3, 0.0, &c);
200 CHECK(lines >= 1 && lines <= 3,
"zero width terminates");
212 "index_at: line start -> 0");
214 "index_at: left half of 'a' -> before it");
216 "index_at: right half of 'a' -> after it");
218 "index_at: right half of 'b' -> line end");
220 "index_at: past line 0's end -> its end, not the next line");
222 "index_at: line 1 starts after the dropped space");
224 "index_at: left half of 'd'");
226 "index_at: right half of 'd' -> count");
228 "index_at: above the text -> 0");
230 "index_at: below the text -> count");
232 "index_at: NULL items -> 0");
237 n_wrap_item it[3] = {{1.0, 0}, {10.0, 0}, {1.0, 0}};
239 "index_at: left half of a cell -> before it");
241 "index_at: right half of a cell -> after it");
248 "index_at: empty line after a trailing break -> count");
261 "span_rects: 'b cd'-ish span crosses the break -> 2 rects");
264 "span_rects: line 0 covers 'b' only");
267 "span_rects: line 1 covers 'c' only");
270 "span_rects: reversed bounds are the same span");
272 "span_rects: only the dropped space -> nothing to paint");
274 "span_rects: empty span -> 0");
276 "span_rects: hi clamps to count");
static int collect(const char *path, const char *dir, const PK_OBJ *o, const char *prefix, N_PTH *pth, int depth)
collect the tensors under a dictionary, depth first
size_t n_wrap_span_rects(const n_wrap_item *items, size_t count, double max_width, size_t lo, size_t hi, n_wrap_rect_emit emit, void *user)
The rectangles that cover the items [lo, hi): one per line the range touches, in order,...
size_t n_wrap_index_at(const n_wrap_item *items, size_t count, double max_width, double line_height, double x, double y)
The item boundary nearest a point: the inverse of n_wrap_layout(), for turning a click or a drag into...