Bug Summary

File:content/handlers/html/layout_flex.c
Warning:line 438, column 5
Access to field 'height' results in a dereference of a null pointer (loaded from variable 'b')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name layout_flex.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I . -I include -I build/Linux-framebuffer -I frontends -I content/handlers -D WITH_JPEG -U WITH_PDF_EXPORT -D LIBICONV_PLUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /usr/include/x86_64-linux-gnu -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -D WITH_WEBP -I /usr/include/libpng16 -D WITH_PNG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include/ -D WITH_BMP -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_GIF -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NS_SVG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSSPRITE -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSPSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSLOG -D NETSURF_UA_FORMAT_STRING="Mozilla/5.0 (%s) NetSurf/%d.%d" -D NETSURF_HOMEPAGE="about:welcome" -D NETSURF_LOG_LEVEL=VERBOSE -D NETSURF_BUILTIN_LOG_FILTER="(level:WARNING || cat:jserrors)" -D NETSURF_BUILTIN_VERBOSE_FILTER="(level:VERBOSE || cat:jserrors)" -D STMTEXPR=1 -D nsframebuffer -D small -D NETSURF_FB_RESPATH="${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res" -D NETSURF_FB_FONTPATH="/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts" -D NETSURF_FB_FONT_SANS_SERIF="DejaVuSans.ttf" -D NETSURF_FB_FONT_SANS_SERIF_BOLD="DejaVuSans-Bold.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC="DejaVuSans-Oblique.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="DejaVuSans-BoldOblique.ttf" -D NETSURF_FB_FONT_SERIF="DejaVuSerif.ttf" -D NETSURF_FB_FONT_SERIF_BOLD="DejaVuSerif-Bold.ttf" -D NETSURF_FB_FONT_MONOSPACE="DejaVuSansMono.ttf" -D NETSURF_FB_FONT_MONOSPACE_BOLD="DejaVuSansMono-Bold.ttf" -D NETSURF_FB_FONT_CURSIVE="Comic_Sans_MS.ttf" -D NETSURF_FB_FONT_FANTASY="Impact.ttf" -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D _POSIX_C_SOURCE=200809L -D _XOPEN_SOURCE=700 -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _NETBSD_SOURCE -D DUK_OPT_HAVE_CUSTOM_H -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wwrite-strings -Wno-unused-parameter -Wno-unused-but-set-variable -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-netsurf/clangScanBuildReports/2024-03-19-091938-614606-1 -x c content/handlers/html/layout_flex.c

content/handlers/html/layout_flex.c

1/*
2 * Copyright 2022 Michael Drake <tlsa@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * HTML layout implementation: display: flex.
22 *
23 * Layout is carried out in two stages:
24 *
25 * 1. + calculation of minimum / maximum box widths, and
26 * + determination of whether block level boxes will have >zero height
27 *
28 * 2. + layout (position and dimensions)
29 *
30 * In most cases the functions for the two stages are a corresponding pair
31 * layout_minmax_X() and layout_X().
32 */
33
34#include <string.h>
35
36#include "utils/log.h"
37#include "utils/utils.h"
38
39#include "html/box.h"
40#include "html/html.h"
41#include "html/private.h"
42#include "html/box_inspect.h"
43#include "html/layout_internal.h"
44
45/**
46 * Flex item data
47 */
48struct flex_item_data {
49 enum css_flex_basis_e basis;
50 css_fixed basis_length;
51 css_unit basis_unit;
52 struct box *box;
53
54 css_fixed shrink;
55 css_fixed grow;
56
57 int min_main;
58 int max_main;
59 int min_cross;
60 int max_cross;
61
62 int target_main_size;
63 int base_size;
64 int main_size;
65 size_t line;
66
67 bool_Bool freeze;
68 bool_Bool min_violation;
69 bool_Bool max_violation;
70};
71
72/**
73 * Flex line data
74 */
75struct flex_line_data {
76 int main_size;
77 int cross_size;
78
79 int used_main_size;
80 int main_auto_margin_count;
81
82 int pos;
83
84 size_t first;
85 size_t count;
86 size_t frozen;
87};
88
89/**
90 * Flex layout context
91 */
92struct flex_ctx {
93 html_content *content;
94 const struct box *flex;
95 const css_unit_ctx *unit_len_ctx;
96
97 int main_size;
98 int cross_size;
99
100 int available_main;
101 int available_cross;
102
103 bool_Bool horizontal;
104 bool_Bool main_reversed;
105 enum css_flex_wrap_e wrap;
106
107 struct flex_items {
108 size_t count;
109 struct flex_item_data *data;
110 } item;
111
112 struct flex_lines {
113 size_t count;
114 size_t alloc;
115 struct flex_line_data *data;
116 } line;
117};
118
119/**
120 * Destroy a flex layout context
121 *
122 * \param[in] ctx Flex layout context
123 */
124static void layout_flex_ctx__destroy(struct flex_ctx *ctx)
125{
126 if (ctx != NULL((void*)0)) {
127 free(ctx->item.data);
128 free(ctx->line.data);
129 free(ctx);
130 }
131}
132
133/**
134 * Create a flex layout context
135 *
136 * \param[in] content HTML content containing flex box
137 * \param[in] flex Box to create layout context for
138 * \return flex layout context or NULL on error
139 */
140static struct flex_ctx *layout_flex_ctx__create(
141 html_content *content,
142 const struct box *flex)
143{
144 struct flex_ctx *ctx;
145
146 ctx = calloc(1, sizeof(*ctx));
147 if (ctx == NULL((void*)0)) {
4
Assuming 'ctx' is not equal to NULL
5
Taking false branch
148 return NULL((void*)0);
149 }
150 ctx->line.alloc = 1;
151
152 ctx->item.count = box_count_children(flex);
153 ctx->item.data = calloc(ctx->item.count, sizeof(*ctx->item.data));
6
Null pointer value stored to field 'box'
154 if (ctx->item.data == NULL((void*)0)) {
7
Assuming field 'data' is not equal to NULL
8
Taking false branch
155 layout_flex_ctx__destroy(ctx);
156 return NULL((void*)0);
157 }
158
159 ctx->line.alloc = 1;
160 ctx->line.data = calloc(ctx->line.alloc, sizeof(*ctx->line.data));
161 if (ctx->line.data == NULL((void*)0)) {
9
Assuming field 'data' is not equal to NULL
10
Taking false branch
162 layout_flex_ctx__destroy(ctx);
163 return NULL((void*)0);
164 }
165
166 ctx->flex = flex;
167 ctx->content = content;
168 ctx->unit_len_ctx = &content->unit_len_ctx;
169
170 ctx->wrap = css_computed_flex_wrap(flex->style);
171 ctx->horizontal = lh__flex_main_is_horizontal(flex);
11
Calling 'lh__flex_main_is_horizontal'
16
Returning from 'lh__flex_main_is_horizontal'
172 ctx->main_reversed = lh__flex_direction_reversed(flex);
173
174 return ctx;
175}
176
177/**
178 * Find box side representing the start of flex container in main direction.
179 *
180 * \param[in] ctx Flex layout context.
181 * \return the start side.
182 */
183static enum box_side layout_flex__main_start_side(
184 const struct flex_ctx *ctx)
185{
186 if (ctx->horizontal) {
187 return (ctx->main_reversed) ? RIGHT : LEFT;
188 } else {
189 return (ctx->main_reversed) ? BOTTOM : TOP;
190 }
191}
192
193/**
194 * Find box side representing the end of flex container in main direction.
195 *
196 * \param[in] ctx Flex layout context.
197 * \return the end side.
198 */
199static enum box_side layout_flex__main_end_side(
200 const struct flex_ctx *ctx)
201{
202 if (ctx->horizontal) {
203 return (ctx->main_reversed) ? LEFT : RIGHT;
204 } else {
205 return (ctx->main_reversed) ? TOP : BOTTOM;
206 }
207}
208
209/**
210 * Perform layout on a flex item
211 *
212 * \param[in] ctx Flex layout context
213 * \param[in] item Item to lay out
214 * \param[in] available_width Available width for item in pixels
215 * \return true on success false on failure
216 */
217static bool_Bool layout_flex_item(
218 const struct flex_ctx *ctx,
219 const struct flex_item_data *item,
220 int available_width)
221{
222 bool_Bool success;
223 struct box *b = item->box;
224
225 switch (b->type) {
1
Control jumps to 'case BOX_FLEX:' at line 234
226 case BOX_BLOCK:
227 success = layout_block_context(b, -1, ctx->content);
228 break;
229 case BOX_TABLE:
230 b->float_container = b->parent;
231 success = layout_table(b, available_width, ctx->content);
232 b->float_container = NULL((void*)0);
233 break;
234 case BOX_FLEX:
235 b->float_container = b->parent;
236 success = layout_flex(b, available_width, ctx->content);
2
Calling 'layout_flex'
237 b->float_container = NULL((void*)0);
238 break;
239 default:
240 assert(0 && "Bad flex item back type")((0 && "Bad flex item back type") ? (void) (0) : __assert_fail
("0 && \"Bad flex item back type\"", "content/handlers/html/layout_flex.c"
, 240, __extension__ __PRETTY_FUNCTION__))
;
241 success = false0;
242 break;
243 }
244
245 if (!success) {
246 NSLOG(flex, ERROR, "box %p: layout failed", b)do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_ERROR, "content/handlers/html/layout_flex.c", sizeof
("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 246, }; nslog__log(&_nslog_ctx
, "box %p: layout failed", b); } } while(0)
;
247 }
248
249 return success;
250}
251
252/**
253 * Calculate an item's base and target main sizes.
254 *
255 * \param[in] ctx Flex layout context
256 * \param[in] item Item to get sizes of
257 * \param[in] available_width Available width in pixels
258 * \return true on success false on failure
259 */
260static inline bool_Bool layout_flex__base_and_main_sizes(
261 const struct flex_ctx *ctx,
262 struct flex_item_data *item,
263 int available_width)
264{
265 struct box *b = item->box;
266 int content_min_width = b->min_width;
267 int content_max_width = b->max_width;
268 int delta_outer_main = lh__delta_outer_main(ctx->flex, b);
269
270 NSLOG(flex, DEEPDEBUG, "box %p: delta_outer_main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 271, }; nslog__log(&_nslog_ctx
, "box %p: delta_outer_main: %i", b, delta_outer_main); } } while
(0)
271 b, delta_outer_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 271, }; nslog__log(&_nslog_ctx
, "box %p: delta_outer_main: %i", b, delta_outer_main); } } while
(0)
;
272
273 if (item->basis == CSS_FLEX_BASIS_SET) {
274 if (item->basis_unit == CSS_UNIT_PCT) {
275 item->base_size = FPCT_OF_INT_TOINT(((((css_divide_fixed(((item->basis_length * available_width
)), (0x00019000)))) >> 10))
276 item->basis_length,((((css_divide_fixed(((item->basis_length * available_width
)), (0x00019000)))) >> 10))
277 available_width)((((css_divide_fixed(((item->basis_length * available_width
)), (0x00019000)))) >> 10))
;
278 } else {
279 item->base_size = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( b->style, ctx->unit_len_ctx, item
->basis_length, item->basis_unit)) >> 10)
280 b->style, ctx->unit_len_ctx,((css_unit_len2device_px( b->style, ctx->unit_len_ctx, item
->basis_length, item->basis_unit)) >> 10)
281 item->basis_length,((css_unit_len2device_px( b->style, ctx->unit_len_ctx, item
->basis_length, item->basis_unit)) >> 10)
282 item->basis_unit))((css_unit_len2device_px( b->style, ctx->unit_len_ctx, item
->basis_length, item->basis_unit)) >> 10)
;
283 }
284
285 } else if (item->basis == CSS_FLEX_BASIS_AUTO) {
286 item->base_size = ctx->horizontal ? b->width : b->height;
287 } else {
288 item->base_size = AUTO(-2147483647 -1);
289 }
290
291 if (ctx->horizontal == false0) {
292 if (b->width == AUTO(-2147483647 -1)) {
293 b->width = min(max(content_min_width, available_width),((((((content_min_width)>(available_width))?(content_min_width
):(available_width)))<(content_max_width))?((((content_min_width
)>(available_width))?(content_min_width):(available_width)
)):(content_max_width))
294 content_max_width)((((((content_min_width)>(available_width))?(content_min_width
):(available_width)))<(content_max_width))?((((content_min_width
)>(available_width))?(content_min_width):(available_width)
)):(content_max_width))
;
295 b->width -= lh__delta_outer_width(b);
296 }
297
298 if (!layout_flex_item(ctx, item, b->width)) {
299 return false0;
300 }
301 }
302
303 if (item->base_size == AUTO(-2147483647 -1)) {
304 if (ctx->horizontal == false0) {
305 item->base_size = b->height;
306 } else {
307 item->base_size = content_max_width - delta_outer_main;
308 }
309 }
310
311 item->base_size += delta_outer_main;
312
313 if (ctx->horizontal) {
314 item->base_size = min(item->base_size, available_width)(((item->base_size)<(available_width))?(item->base_size
):(available_width))
;
315 item->base_size = max(item->base_size, content_min_width)(((item->base_size)>(content_min_width))?(item->base_size
):(content_min_width))
;
316 }
317
318 item->target_main_size = item->base_size;
319 item->main_size = item->base_size;
320
321 if (item->max_main > 0 &&
322 item->main_size > item->max_main + delta_outer_main) {
323 item->main_size = item->max_main + delta_outer_main;
324 }
325
326 if (item->main_size < item->min_main + delta_outer_main) {
327 item->main_size = item->min_main + delta_outer_main;
328 }
329
330 NSLOG(flex, DEEPDEBUG, "flex-item box: %p: base_size: %i, main_size %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 331, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: base_size: %i, main_size %i", b, item->
base_size, item->main_size); } } while(0)
331 b, item->base_size, item->main_size)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 331, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: base_size: %i, main_size %i", b, item->
base_size, item->main_size); } } while(0)
;
332
333 return true1;
334}
335
336/**
337 * Fill out all item's data in a flex container.
338 *
339 * \param[in] ctx Flex layout context
340 * \param[in] flex Flex box
341 * \param[in] available_width Available width in pixels
342 */
343static void layout_flex_ctx__populate_item_data(
344 const struct flex_ctx *ctx,
345 const struct box *flex,
346 int available_width)
347{
348 size_t i = 0;
349 bool_Bool horizontal = ctx->horizontal;
350
351 for (struct box *b = flex->children; b != NULL((void*)0); b = b->next) {
352 struct flex_item_data *item = &ctx->item.data[i++];
353
354 b->float_container = b->parent;
355 layout_find_dimensions(ctx->unit_len_ctx, available_width, -1,
356 b, b->style, &b->width, &b->height,
357 horizontal ? &item->max_main : &item->max_cross,
358 horizontal ? &item->min_main : &item->min_cross,
359 horizontal ? &item->max_cross : &item->max_main,
360 horizontal ? &item->min_cross : &item->min_main,
361 b->margin, b->padding, b->border);
362 b->float_container = NULL((void*)0);
363
364 NSLOG(flex, DEEPDEBUG, "flex-item box: %p: width: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 365, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: width: %i", b, b->width); } } while(
0)
365 b, b->width)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 365, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: width: %i", b, b->width); } } while(
0)
;
366
367 item->box = b;
368 item->basis = css_computed_flex_basis(b->style,
369 &item->basis_length, &item->basis_unit);
370
371 css_computed_flex_shrink(b->style, &item->shrink);
372 css_computed_flex_grow(b->style, &item->grow);
373
374 layout_flex__base_and_main_sizes(ctx, item, available_width);
375 }
376}
377
378/**
379 * Ensure context's lines array has a free space
380 *
381 * \param[in] ctx Flex layout context
382 * \return true on success false on out of memory
383 */
384static bool_Bool layout_flex_ctx__ensure_line(struct flex_ctx *ctx)
385{
386 struct flex_line_data *temp;
387 size_t line_alloc = ctx->line.alloc * 2;
388
389 if (ctx->line.alloc
31.1
Field 'alloc' is > field 'count'
31.1
Field 'alloc' is > field 'count'
> ctx->line.count) {
32
Taking true branch
390 return true1;
33
Returning without writing to 'ctx->horizontal', which participates in a condition later
34
Returning the value 1, which participates in a condition later
391 }
392
393 temp = realloc(ctx->line.data, sizeof(*ctx->line.data) * line_alloc);
394 if (temp == NULL((void*)0)) {
395 return false0;
396 }
397 ctx->line.data = temp;
398
399 memset(ctx->line.data + ctx->line.alloc, 0,
400 sizeof(*ctx->line.data) * (line_alloc - ctx->line.alloc));
401 ctx->line.alloc = line_alloc;
402
403 return true1;
404}
405
406/**
407 * Assigns flex items to the line and returns the line
408 *
409 * \param[in] ctx Flex layout context
410 * \param[in] item_index Index to first item to assign to this line
411 * \return Pointer to the new line, or NULL on error.
412 */
413static struct flex_line_data *layout_flex__build_line(struct flex_ctx *ctx,
414 size_t item_index)
415{
416 enum box_side start_side = layout_flex__main_start_side(ctx);
417 enum box_side end_side = layout_flex__main_end_side(ctx);
418 struct flex_line_data *line;
419 int used_main = 0;
420
421 if (!layout_flex_ctx__ensure_line(ctx)) {
31
Calling 'layout_flex_ctx__ensure_line'
35
Returning from 'layout_flex_ctx__ensure_line'
36
Taking false branch
422 return NULL((void*)0);
423 }
424
425 line = &ctx->line.data[ctx->line.count];
426 line->first = item_index;
427
428 NSLOG(flex, DEEPDEBUG, "flex container %p: available main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 429, }; nslog__log(&_nslog_ctx
, "flex container %p: available main: %i", ctx->flex, ctx->
available_main); } } while(0)
37
Taking false branch
38
Loop condition is false. Exiting loop
429 ctx->flex, ctx->available_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 429, }; nslog__log(&_nslog_ctx
, "flex container %p: available main: %i", ctx->flex, ctx->
available_main); } } while(0)
;
430
431 while (item_index < ctx->item.count) {
39
Loop condition is true. Entering loop body
432 struct flex_item_data *item = &ctx->item.data[item_index];
433 struct box *b = item->box;
40
'b' initialized to a null pointer value
434 int pos_main;
435
436 pos_main = ctx->horizontal
40.1
Field 'horizontal' is false
40.1
Field 'horizontal' is false
?
41
'?' condition is false
437 item->main_size :
438 b->height + lh__delta_outer_main(ctx->flex, b);
42
Access to field 'height' results in a dereference of a null pointer (loaded from variable 'b')
439
440 if (ctx->wrap == CSS_FLEX_WRAP_NOWRAP ||
441 pos_main + used_main <= ctx->available_main ||
442 lh__box_is_absolute(item->box) ||
443 ctx->available_main == AUTO(-2147483647 -1) ||
444 line->count == 0 ||
445 pos_main == 0) {
446 if (lh__box_is_absolute(item->box) == false0) {
447 line->main_size += item->main_size;
448 used_main += pos_main;
449
450 if (b->margin[start_side] == AUTO(-2147483647 -1)) {
451 line->main_auto_margin_count++;
452 }
453 if (b->margin[end_side] == AUTO(-2147483647 -1)) {
454 line->main_auto_margin_count++;
455 }
456 }
457 item->line = ctx->line.count;
458 line->count++;
459 item_index++;
460 } else {
461 break;
462 }
463 }
464
465 if (line->count > 0) {
466 ctx->line.count++;
467 } else {
468 NSLOG(layout, ERROR, "Failed to fit any flex items")do { if (NSLOG_LEVEL_ERROR >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_layout
, NSLOG_LEVEL_ERROR, "content/handlers/html/layout_flex.c", sizeof
("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 468, }; nslog__log(&_nslog_ctx
, "Failed to fit any flex items"); } } while(0)
;
469 }
470
471 return line;
472}
473
474/**
475 * Freeze an item on a line
476 *
477 * \param[in] line Line to containing item
478 * \param[in] item Item to freeze
479 */
480static inline void layout_flex__item_freeze(
481 struct flex_line_data *line,
482 struct flex_item_data *item)
483{
484 item->freeze = true1;
485 line->frozen++;
486
487 if (!lh__box_is_absolute(item->box)){
488 line->used_main_size += item->target_main_size;
489 }
490
491 NSLOG(flex, DEEPDEBUG, "flex-item box: %p: "do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: " "Frozen at target_main_size: %i", item
->box, item->target_main_size); } } while(0)
492 "Frozen at target_main_size: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: " "Frozen at target_main_size: %i", item
->box, item->target_main_size); } } while(0)
493 item->box, item->target_main_size)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 493, }; nslog__log(&_nslog_ctx
, "flex-item box: %p: " "Frozen at target_main_size: %i", item
->box, item->target_main_size); } } while(0)
;
494}
495
496/**
497 * Calculate remaining free space and unfrozen item factor sum
498 *
499 * \param[in] ctx Flex layout context
500 * \param[in] line Line to calculate free space on
501 * \param[out] unfrozen_factor_sum Returns sum of unfrozen item's flex factors
502 * \param[in] initial_free_main Initial free space in main direction
503 * \param[in] available_main Available space in main direction
504 * \param[in] grow Whether to grow or shrink
505 * return remaining free space on line
506 */
507static inline int layout_flex__remaining_free_main(
508 struct flex_ctx *ctx,
509 struct flex_line_data *line,
510 css_fixed *unfrozen_factor_sum,
511 int initial_free_main,
512 int available_main,
513 bool_Bool grow)
514{
515 int remaining_free_main = available_main;
516 size_t item_count = line->first + line->count;
517
518 *unfrozen_factor_sum = 0;
519
520 for (size_t i = line->first; i < item_count; i++) {
521 struct flex_item_data *item = &ctx->item.data[i];
522
523 if (item->freeze) {
524 remaining_free_main -= item->target_main_size;
525 } else {
526 remaining_free_main -= item->base_size;
527
528 *unfrozen_factor_sum += grow ?
529 item->grow : item->shrink;
530 }
531 }
532
533 if (*unfrozen_factor_sum < F_10x00000400) {
534 int free_space = FIXTOINT(FMUL(INTTOFIX(initial_free_main),(((css_multiply_fixed(((css_int_to_fixed(initial_free_main)))
, (*unfrozen_factor_sum)))) >> 10)
535 *unfrozen_factor_sum))(((css_multiply_fixed(((css_int_to_fixed(initial_free_main)))
, (*unfrozen_factor_sum)))) >> 10)
;
536
537 if (free_space < remaining_free_main) {
538 remaining_free_main = free_space;
539 }
540 }
541
542 NSLOG(flex, DEEPDEBUG, "Remaining free space: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 543, }; nslog__log(&_nslog_ctx
, "Remaining free space: %i", remaining_free_main); } } while
(0)
543 remaining_free_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 543, }; nslog__log(&_nslog_ctx
, "Remaining free space: %i", remaining_free_main); } } while
(0)
;
544
545 return remaining_free_main;
546}
547
548/**
549 * Clamp flex item target main size and get min/max violations
550 *
551 * \param[in] ctx Flex layout context
552 * \param[in] line Line to align items on
553 * return total violation in pixels
554 */
555static inline int layout_flex__get_min_max_violations(
556 struct flex_ctx *ctx,
557 struct flex_line_data *line)
558{
559
560 int total_violation = 0;
561 size_t item_count = line->first + line->count;
562
563 for (size_t i = line->first; i < item_count; i++) {
564 struct flex_item_data *item = &ctx->item.data[i];
565 int target_main_size = item->target_main_size;
566
567 NSLOG(flex, DEEPDEBUG, "item %p: target_main_size: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 568, }; nslog__log(&_nslog_ctx
, "item %p: target_main_size: %i", item->box, target_main_size
); } } while(0)
568 item->box, target_main_size)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 568, }; nslog__log(&_nslog_ctx
, "item %p: target_main_size: %i", item->box, target_main_size
); } } while(0)
;
569
570 if (item->freeze) {
571 continue;
572 }
573
574 if (item->max_main > 0 &&
575 target_main_size > item->max_main) {
576 target_main_size = item->max_main;
577 item->max_violation = true1;
578 NSLOG(flex, DEEPDEBUG, "Violation: max_main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 579, }; nslog__log(&_nslog_ctx
, "Violation: max_main: %i", item->max_main); } } while(0)
579 item->max_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 579, }; nslog__log(&_nslog_ctx
, "Violation: max_main: %i", item->max_main); } } while(0)
;
580 }
581
582 if (target_main_size < item->min_main) {
583 target_main_size = item->min_main;
584 item->min_violation = true1;
585 NSLOG(flex, DEEPDEBUG, "Violation: min_main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 586, }; nslog__log(&_nslog_ctx
, "Violation: min_main: %i", item->min_main); } } while(0)
586 item->min_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 586, }; nslog__log(&_nslog_ctx
, "Violation: min_main: %i", item->min_main); } } while(0)
;
587 }
588
589 if (target_main_size < item->box->min_width) {
590 target_main_size = item->box->min_width;
591 item->min_violation = true1;
592 NSLOG(flex, DEEPDEBUG, "Violation: box min_width: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 593, }; nslog__log(&_nslog_ctx
, "Violation: box min_width: %i", item->box->min_width)
; } } while(0)
593 item->box->min_width)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 593, }; nslog__log(&_nslog_ctx
, "Violation: box min_width: %i", item->box->min_width)
; } } while(0)
;
594 }
595
596 if (target_main_size < 0) {
597 target_main_size = 0;
598 item->min_violation = true1;
599 NSLOG(flex, DEEPDEBUG, "Violation: less than 0")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 599, }; nslog__log(&_nslog_ctx
, "Violation: less than 0"); } } while(0)
;
600 }
601
602 total_violation += target_main_size - item->target_main_size;
603 item->target_main_size = target_main_size;
604 }
605
606 NSLOG(flex, DEEPDEBUG, "Total violation: %i", total_violation)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 606, }; nslog__log(&_nslog_ctx
, "Total violation: %i", total_violation); } } while(0)
;
607
608 return total_violation;
609}
610
611/**
612 * Distribute remaining free space proportional to the flex factors.
613 *
614 * Remaining free space may be negative.
615 *
616 * \param[in] ctx Flex layout context
617 * \param[in] line Line to distribute free space on
618 * \param[in] unfrozen_factor_sum Sum of unfrozen item's flex factors
619 * \param[in] remaining_free_main Remaining free space in main direction
620 * \param[in] grow Whether to grow or shrink
621 */
622static inline void layout_flex__distribute_free_main(
623 struct flex_ctx *ctx,
624 struct flex_line_data *line,
625 css_fixed unfrozen_factor_sum,
626 int remaining_free_main,
627 bool_Bool grow)
628{
629 size_t item_count = line->first + line->count;
630
631 if (grow) {
632 css_fixed remainder = 0;
633 for (size_t i = line->first; i < item_count; i++) {
634 struct flex_item_data *item = &ctx->item.data[i];
635 css_fixed result;
636 css_fixed ratio;
637
638 if (item->freeze) {
639 continue;
640 }
641
642 ratio = FDIV(item->grow, unfrozen_factor_sum)(css_divide_fixed((item->grow), (unfrozen_factor_sum)));
643 result = FMUL(INTTOFIX(remaining_free_main), ratio)(css_multiply_fixed(((css_int_to_fixed(remaining_free_main)))
, (ratio)))
+
644 remainder;
645
646 item->target_main_size = item->base_size +
647 FIXTOINT(result)((result) >> 10);
648 remainder = FIXFRAC(result)(result & ((1 << 10)- 1 ));
649 }
650 } else {
651 css_fixed scaled_shrink_factor_sum = 0;
652 css_fixed remainder = 0;
653
654 for (size_t i = line->first; i < item_count; i++) {
655 struct flex_item_data *item = &ctx->item.data[i];
656 css_fixed scaled_shrink_factor;
657
658 if (item->freeze) {
659 continue;
660 }
661
662 scaled_shrink_factor = FMUL((css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
663 item->shrink,(css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
664 INTTOFIX(item->base_size))(css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
;
665 scaled_shrink_factor_sum += scaled_shrink_factor;
666 }
667
668 for (size_t i = line->first; i < item_count; i++) {
669 struct flex_item_data *item = &ctx->item.data[i];
670 css_fixed scaled_shrink_factor;
671 css_fixed result;
672 css_fixed ratio;
673
674 if (item->freeze) {
675 continue;
676 } else if (scaled_shrink_factor_sum == 0) {
677 item->target_main_size = item->main_size;
678 layout_flex__item_freeze(line, item);
679 continue;
680 }
681
682 scaled_shrink_factor = FMUL((css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
683 item->shrink,(css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
684 INTTOFIX(item->base_size))(css_multiply_fixed((item->shrink), ((css_int_to_fixed(item
->base_size)))))
;
685 ratio = FDIV(scaled_shrink_factor,(css_divide_fixed((scaled_shrink_factor), (scaled_shrink_factor_sum
)))
686 scaled_shrink_factor_sum)(css_divide_fixed((scaled_shrink_factor), (scaled_shrink_factor_sum
)))
;
687 result = FMUL(INTTOFIX(abs(remaining_free_main)),(css_multiply_fixed(((css_int_to_fixed(abs(remaining_free_main
)))), (ratio)))
688 ratio)(css_multiply_fixed(((css_int_to_fixed(abs(remaining_free_main
)))), (ratio)))
+ remainder;
689
690 item->target_main_size = item->base_size -
691 FIXTOINT(result)((result) >> 10);
692 remainder = FIXFRAC(result)(result & ((1 << 10)- 1 ));
693 }
694 }
695}
696
697/**
698 * Resolve flexible item lengths along a line.
699 *
700 * See 9.7 of Tests CSS Flexible Box Layout Module Level 1.
701 *
702 * \param[in] ctx Flex layout context
703 * \param[in] line Line to resolve
704 * \return true on success, false on failure.
705 */
706static bool_Bool layout_flex__resolve_line(
707 struct flex_ctx *ctx,
708 struct flex_line_data *line)
709{
710 size_t item_count = line->first + line->count;
711 int available_main = ctx->available_main;
712 int initial_free_main;
713 bool_Bool grow;
714
715 if (available_main == AUTO(-2147483647 -1)) {
716 available_main = INT_MAX2147483647;
717 }
718
719 grow = (line->main_size < available_main);
720 initial_free_main = available_main;
721
722 NSLOG(flex, DEEPDEBUG, "box %p: line %zu: first: %zu, count: %zu",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 724, }; nslog__log(&_nslog_ctx
, "box %p: line %zu: first: %zu, count: %zu", ctx->flex, line
- ctx->line.data, line->first, line->count); } } while
(0)
723 ctx->flex, line - ctx->line.data,do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 724, }; nslog__log(&_nslog_ctx
, "box %p: line %zu: first: %zu, count: %zu", ctx->flex, line
- ctx->line.data, line->first, line->count); } } while
(0)
724 line->first, line->count)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 724, }; nslog__log(&_nslog_ctx
, "box %p: line %zu: first: %zu, count: %zu", ctx->flex, line
- ctx->line.data, line->first, line->count); } } while
(0)
;
725 NSLOG(flex, DEEPDEBUG, "Line main_size: %i, available_main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 726, }; nslog__log(&_nslog_ctx
, "Line main_size: %i, available_main: %i", line->main_size
, available_main); } } while(0)
726 line->main_size, available_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 726, }; nslog__log(&_nslog_ctx
, "Line main_size: %i, available_main: %i", line->main_size
, available_main); } } while(0)
;
727
728 for (size_t i = line->first; i < item_count; i++) {
729 struct flex_item_data *item = &ctx->item.data[i];
730
731 /* 3. Size inflexible items */
732 if (grow) {
733 if (item->grow == 0 ||
734 item->base_size > item->main_size) {
735 item->target_main_size = item->main_size;
736 layout_flex__item_freeze(line, item);
737 }
738 } else {
739 if (item->shrink == 0 ||
740 item->base_size < item->main_size) {
741 item->target_main_size = item->main_size;
742 layout_flex__item_freeze(line, item);
743 }
744 }
745
746 /* 4. Calculate initial free space */
747 if (item->freeze) {
748 initial_free_main -= item->target_main_size;
749 } else {
750 initial_free_main -= item->base_size;
751 }
752 }
753
754 /* 5. Loop */
755 while (line->frozen < line->count) {
756 css_fixed unfrozen_factor_sum;
757 int remaining_free_main;
758 int total_violation;
759
760 NSLOG(flex, DEEPDEBUG, "flex-container: %p: Resolver pass",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 761, }; nslog__log(&_nslog_ctx
, "flex-container: %p: Resolver pass", ctx->flex); } } while
(0)
761 ctx->flex)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 761, }; nslog__log(&_nslog_ctx
, "flex-container: %p: Resolver pass", ctx->flex); } } while
(0)
;
762
763 /* b */
764 remaining_free_main = layout_flex__remaining_free_main(ctx,
765 line, &unfrozen_factor_sum, initial_free_main,
766 available_main, grow);
767
768 /* c */
769 if (remaining_free_main != 0) {
770 layout_flex__distribute_free_main(ctx,
771 line, unfrozen_factor_sum,
772 remaining_free_main, grow);
773 }
774
775 /* d */
776 total_violation = layout_flex__get_min_max_violations(
777 ctx, line);
778
779 /* e */
780 for (size_t i = line->first; i < item_count; i++) {
781 struct flex_item_data *item = &ctx->item.data[i];
782
783 if (item->freeze) {
784 continue;
785 }
786
787 if (total_violation == 0 ||
788 (total_violation > 0 && item->min_violation) ||
789 (total_violation < 0 && item->max_violation)) {
790 layout_flex__item_freeze(line, item);
791 }
792 }
793 }
794
795 return true1;
796}
797
798/**
799 * Position items along a line
800 *
801 * \param[in] ctx Flex layout context
802 * \param[in] line Line to resolve
803 * \return true on success, false on failure.
804 */
805static bool_Bool layout_flex__place_line_items_main(
806 struct flex_ctx *ctx,
807 struct flex_line_data *line)
808{
809 int main_pos = ctx->flex->padding[layout_flex__main_start_side(ctx)];
810 int post_multiplier = ctx->main_reversed ? 0 : 1;
811 int pre_multiplier = ctx->main_reversed ? -1 : 0;
812 size_t item_count = line->first + line->count;
813 int extra_remainder = 0;
814 int extra = 0;
815
816 if (ctx->main_reversed) {
817 main_pos = lh__box_size_main(ctx->horizontal, ctx->flex) -
818 main_pos;
819 }
820
821 if (ctx->available_main != AUTO(-2147483647 -1) &&
822 ctx->available_main != UNKNOWN_WIDTH2147483647 &&
823 ctx->available_main > line->used_main_size) {
824 if (line->main_auto_margin_count > 0) {
825 extra = ctx->available_main - line->used_main_size;
826
827 extra_remainder = extra % line->main_auto_margin_count;
828 extra /= line->main_auto_margin_count;
829 }
830 }
831
832 for (size_t i = line->first; i < item_count; i++) {
833 enum box_side main_end = ctx->horizontal ? RIGHT : BOTTOM;
834 enum box_side main_start = ctx->horizontal ? LEFT : TOP;
835 struct flex_item_data *item = &ctx->item.data[i];
836 struct box *b = item->box;
837 int extra_total = 0;
838 int extra_post = 0;
839 int extra_pre = 0;
840 int box_size_main;
841 int *box_pos_main;
842
843 if (ctx->horizontal) {
844 b->width = item->target_main_size -
845 lh__delta_outer_width(b);
846
847 if (!layout_flex_item(ctx, item, b->width)) {
848 return false0;
849 }
850 }
851
852 box_size_main = lh__box_size_main(ctx->horizontal, b);
853 box_pos_main = ctx->horizontal ? &b->x : &b->y;
854
855 if (!lh__box_is_absolute(b)) {
856 if (b->margin[main_start] == AUTO(-2147483647 -1)) {
857 extra_pre = extra + extra_remainder;
858 }
859 if (b->margin[main_end] == AUTO(-2147483647 -1)) {
860 extra_post = extra + extra_remainder;
861 }
862 extra_total = extra_pre + extra_post;
863
864 main_pos += pre_multiplier *
865 (extra_total + box_size_main +
866 lh__delta_outer_main(ctx->flex, b));
867 }
868
869 *box_pos_main = main_pos + lh__non_auto_margin(b, main_start) +
870 extra_pre + b->border[main_start].width;
871
872 if (!lh__box_is_absolute(b)) {
873 int cross_size;
874 int box_size_cross = lh__box_size_cross(
875 ctx->horizontal, b);
876
877 main_pos += post_multiplier *
878 (extra_total + box_size_main +
879 lh__delta_outer_main(ctx->flex, b));
880
881 cross_size = box_size_cross + lh__delta_outer_cross(
882 ctx->flex, b);
883 if (line->cross_size < cross_size) {
884 line->cross_size = cross_size;
885 }
886 }
887 }
888
889 return true1;
890}
891
892/**
893 * Collect items onto lines and place items along the lines
894 *
895 * \param[in] ctx Flex layout context
896 * \return true on success, false on failure.
897 */
898static bool_Bool layout_flex__collect_items_into_lines(
899 struct flex_ctx *ctx)
900{
901 size_t pos = 0;
902
903 while (pos < ctx->item.count) {
29
Loop condition is true. Entering loop body
904 struct flex_line_data *line;
905
906 line = layout_flex__build_line(ctx, pos);
30
Calling 'layout_flex__build_line'
907 if (line == NULL((void*)0)) {
908 return false0;
909 }
910
911 pos += line->count;
912
913 NSLOG(flex, DEEPDEBUG, "flex-container: %p: "do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 916, }; nslog__log(&_nslog_ctx
, "flex-container: %p: " "fitted: %zu (total: %zu/%zu)", ctx->
flex, line->count, pos, ctx->item.count); } } while(0)
914 "fitted: %zu (total: %zu/%zu)",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 916, }; nslog__log(&_nslog_ctx
, "flex-container: %p: " "fitted: %zu (total: %zu/%zu)", ctx->
flex, line->count, pos, ctx->item.count); } } while(0)
915 ctx->flex, line->count,do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 916, }; nslog__log(&_nslog_ctx
, "flex-container: %p: " "fitted: %zu (total: %zu/%zu)", ctx->
flex, line->count, pos, ctx->item.count); } } while(0)
916 pos, ctx->item.count)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 916, }; nslog__log(&_nslog_ctx
, "flex-container: %p: " "fitted: %zu (total: %zu/%zu)", ctx->
flex, line->count, pos, ctx->item.count); } } while(0)
;
917
918 if (!layout_flex__resolve_line(ctx, line)) {
919 return false0;
920 }
921
922 if (!layout_flex__place_line_items_main(ctx, line)) {
923 return false0;
924 }
925
926 ctx->cross_size += line->cross_size;
927 if (ctx->main_size < line->main_size) {
928 ctx->main_size = line->main_size;
929 }
930 }
931
932 return true1;
933}
934
935/**
936 * Align items on a line.
937 *
938 * \param[in] ctx Flex layout context
939 * \param[in] line Line to align items on
940 * \param[in] extra Extra line width in pixels
941 */
942static void layout_flex__place_line_items_cross(struct flex_ctx *ctx,
943 struct flex_line_data *line, int extra)
944{
945 enum box_side cross_start = ctx->horizontal ? TOP : LEFT;
946 size_t item_count = line->first + line->count;
947
948 for (size_t i = line->first; i < item_count; i++) {
949 struct flex_item_data *item = &ctx->item.data[i];
950 struct box *b = item->box;
951 int cross_free_space;
952 int *box_size_cross;
953 int *box_pos_cross;
954
955 box_pos_cross = ctx->horizontal ? &b->y : &b->x;
956 box_size_cross = lh__box_size_cross_ptr(ctx->horizontal, b);
957
958 cross_free_space = line->cross_size + extra - *box_size_cross -
959 lh__delta_outer_cross(ctx->flex, b);
960
961 switch (lh__box_align_self(ctx->flex, b)) {
962 default:
963 case CSS_ALIGN_SELF_STRETCH:
964 if (lh__box_size_cross_is_auto(ctx->horizontal, b)) {
965 *box_size_cross += cross_free_space;
966
967 /* Relayout children for stretch. */
968 if (!layout_flex_item(ctx, item, b->width)) {
969 return;
970 }
971 }
972 fallthrough__attribute__((__fallthrough__));
973 case CSS_ALIGN_SELF_FLEX_START:
974 *box_pos_cross = ctx->flex->padding[cross_start] +
975 line->pos +
976 lh__non_auto_margin(b, cross_start) +
977 b->border[cross_start].width;
978 break;
979
980 case CSS_ALIGN_SELF_FLEX_END:
981 *box_pos_cross = ctx->flex->padding[cross_start] +
982 line->pos + cross_free_space +
983 lh__non_auto_margin(b, cross_start) +
984 b->border[cross_start].width;
985 break;
986
987 case CSS_ALIGN_SELF_BASELINE:
988 case CSS_ALIGN_SELF_CENTER:
989 *box_pos_cross = ctx->flex->padding[cross_start] +
990 line->pos + cross_free_space / 2 +
991 lh__non_auto_margin(b, cross_start) +
992 b->border[cross_start].width;
993 break;
994 }
995 }
996}
997
998/**
999 * Place the lines and align the items on the line.
1000 *
1001 * \param[in] ctx Flex layout context
1002 */
1003static void layout_flex__place_lines(struct flex_ctx *ctx)
1004{
1005 bool_Bool reversed = ctx->wrap == CSS_FLEX_WRAP_WRAP_REVERSE;
1006 int line_pos = reversed ? ctx->cross_size : 0;
1007 int post_multiplier = reversed ? 0 : 1;
1008 int pre_multiplier = reversed ? -1 : 0;
1009 int extra_remainder = 0;
1010 int extra = 0;
1011
1012 if (ctx->available_cross != AUTO(-2147483647 -1) &&
1013 ctx->available_cross > ctx->cross_size &&
1014 ctx->line.count > 0) {
1015 extra = ctx->available_cross - ctx->cross_size;
1016
1017 extra_remainder = extra % ctx->line.count;
1018 extra /= ctx->line.count;
1019 }
1020
1021 for (size_t i = 0; i < ctx->line.count; i++) {
1022 struct flex_line_data *line = &ctx->line.data[i];
1023
1024 line_pos += pre_multiplier * line->cross_size;
1025 line->pos = line_pos;
1026 line_pos += post_multiplier * line->cross_size +
1027 extra + extra_remainder;
1028
1029 layout_flex__place_line_items_cross(ctx, line,
1030 extra + extra_remainder);
1031
1032 if (extra_remainder > 0) {
1033 extra_remainder--;
1034 }
1035 }
1036}
1037
1038/**
1039 * Layout a flex container.
1040 *
1041 * \param[in] flex table to layout
1042 * \param[in] available_width width of containing block
1043 * \param[in] content memory pool for any new boxes
1044 * \return true on success, false on memory exhaustion
1045 */
1046bool_Bool layout_flex(struct box *flex, int available_width,
1047 html_content *content)
1048{
1049 int max_height, min_height;
1050 struct flex_ctx *ctx;
1051 bool_Bool success = false0;
1052
1053 ctx = layout_flex_ctx__create(content, flex);
3
Calling 'layout_flex_ctx__create'
17
Returning from 'layout_flex_ctx__create'
1054 if (ctx
17.1
'ctx' is not equal to NULL
17.1
'ctx' is not equal to NULL
== NULL((void*)0)) {
18
Taking false branch
1055 return false0;
1056 }
1057
1058 NSLOG(flex, DEEPDEBUG, "box %p: %s, available_width %i, width: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1060, }; nslog__log(&_nslog_ctx
, "box %p: %s, available_width %i, width: %i", flex, ctx->
horizontal ? "horizontal" : "vertical", available_width, flex
->width); } } while(0)
19
Taking false branch
20
Loop condition is false. Exiting loop
1059 flex, ctx->horizontal ? "horizontal" : "vertical",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1060, }; nslog__log(&_nslog_ctx
, "box %p: %s, available_width %i, width: %i", flex, ctx->
horizontal ? "horizontal" : "vertical", available_width, flex
->width); } } while(0)
1060 available_width, flex->width)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1060, }; nslog__log(&_nslog_ctx
, "box %p: %s, available_width %i, width: %i", flex, ctx->
horizontal ? "horizontal" : "vertical", available_width, flex
->width); } } while(0)
;
1061
1062 layout_find_dimensions(
1063 ctx->unit_len_ctx, available_width, -1,
1064 flex, flex->style, NULL((void*)0), &flex->height,
1065 NULL((void*)0), NULL((void*)0), &max_height, &min_height,
1066 flex->margin, flex->padding, flex->border);
1067
1068 available_width = min(available_width, flex->width)(((available_width)<(flex->width))?(available_width):(flex
->width))
;
21
Assuming 'available_width' is < field 'width'
22
'?' condition is true
1069
1070 if (ctx->horizontal
22.1
Field 'horizontal' is false
22.1
Field 'horizontal' is false
) {
23
Taking false branch
1071 ctx->available_main = available_width;
1072 ctx->available_cross = ctx->flex->height;
1073 } else {
1074 ctx->available_main = ctx->flex->height;
1075 ctx->available_cross = available_width;
1076 }
1077
1078 NSLOG(flex, DEEPDEBUG, "box %p: available_main: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1079, }; nslog__log(&_nslog_ctx
, "box %p: available_main: %i", flex, ctx->available_main)
; } } while(0)
24
Taking false branch
25
Loop condition is false. Exiting loop
1079 flex, ctx->available_main)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1079, }; nslog__log(&_nslog_ctx
, "box %p: available_main: %i", flex, ctx->available_main)
; } } while(0)
;
1080 NSLOG(flex, DEEPDEBUG, "box %p: available_cross: %i",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1081, }; nslog__log(&_nslog_ctx
, "box %p: available_cross: %i", flex, ctx->available_cross
); } } while(0)
26
Taking false branch
27
Loop condition is false. Exiting loop
1081 flex, ctx->available_cross)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1081, }; nslog__log(&_nslog_ctx
, "box %p: available_cross: %i", flex, ctx->available_cross
); } } while(0)
;
1082
1083 layout_flex_ctx__populate_item_data(ctx, flex, available_width);
1084
1085 /* Place items onto lines. */
1086 success = layout_flex__collect_items_into_lines(ctx);
28
Calling 'layout_flex__collect_items_into_lines'
1087 if (!success) {
1088 goto cleanup;
1089 }
1090
1091 layout_flex__place_lines(ctx);
1092
1093 if (flex->height == AUTO(-2147483647 -1)) {
1094 flex->height = ctx->horizontal ?
1095 ctx->cross_size :
1096 ctx->main_size;
1097 }
1098
1099 if (flex->height != AUTO(-2147483647 -1)) {
1100 if (max_height >= 0 && flex->height > max_height) {
1101 flex->height = max_height;
1102 }
1103 if (min_height > 0 && flex->height < min_height) {
1104 flex->height = min_height;
1105 }
1106 }
1107
1108 success = true1;
1109
1110cleanup:
1111 layout_flex_ctx__destroy(ctx);
1112
1113 NSLOG(flex, DEEPDEBUG, "box %p: %s: w: %i, h: %i", flex,do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1115, }; nslog__log(&_nslog_ctx
, "box %p: %s: w: %i, h: %i", flex, success ? "success" : "failure"
, flex->width, flex->height); } } while(0)
1114 success ? "success" : "failure",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1115, }; nslog__log(&_nslog_ctx
, "box %p: %s: w: %i, h: %i", flex, success ? "success" : "failure"
, flex->width, flex->height); } } while(0)
1115 flex->width, flex->height)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_flex
, NSLOG_LEVEL_DEEPDEBUG, "content/handlers/html/layout_flex.c"
, sizeof("content/handlers/html/layout_flex.c") - 1, __PRETTY_FUNCTION__
, sizeof(__PRETTY_FUNCTION__) - 1, 1115, }; nslog__log(&_nslog_ctx
, "box %p: %s: w: %i, h: %i", flex, success ? "success" : "failure"
, flex->width, flex->height); } } while(0)
;
1116 return success;
1117}

content/handlers/html/layout_internal.h

1/*
2 * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * HTML layout private interface.
22 */
23
24#ifndef NETSURF_HTML_LAYOUT_INTERNAL_H
25#define NETSURF_HTML_LAYOUT_INTERNAL_H
26
27#define AUTO(-2147483647 -1) INT_MIN(-2147483647 -1)
28
29/* Fixed point percentage (a) of an integer (b), to an integer */
30#define FPCT_OF_INT_TOINT(a, b)((((css_divide_fixed(((a * b)), (0x00019000)))) >> 10)) (FIXTOINT(FDIV((a * b), F_100))(((css_divide_fixed(((a * b)), (0x00019000)))) >> 10))
31
32/**
33 * Layout a block formatting context.
34 *
35 * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
36 * \param viewport_height Height of viewport in pixels or -ve if unknown
37 * \param content Memory pool for any new boxes
38 * \return true on success, false on memory exhaustion
39 *
40 * This function carries out layout of a block and its children, as described
41 * in CSS 2.1 9.4.1.
42 */
43bool_Bool layout_block_context(
44 struct box *block,
45 int viewport_height,
46 html_content *content);
47
48/**
49 * Layout a table.
50 *
51 * \param table table to layout
52 * \param available_width width of containing block
53 * \param content memory pool for any new boxes
54 * \return true on success, false on memory exhaustion
55 */
56bool_Bool layout_table(
57 struct box *table,
58 int available_width,
59 html_content *content);
60
61/**
62 * Layout a flex container.
63 *
64 * \param[in] flex table to layout
65 * \param[in] available_width width of containing block
66 * \param[in] content memory pool for any new boxes
67 * \return true on success, false on memory exhaustion
68 */
69bool_Bool layout_flex(
70 struct box *flex,
71 int available_width,
72 html_content *content);
73
74typedef uint8_t (*css_len_func)(
75 const css_computed_style *style,
76 css_fixed *length, css_unit *unit);
77typedef uint8_t (*css_border_style_func)(
78 const css_computed_style *style);
79typedef uint8_t (*css_border_color_func)(
80 const css_computed_style *style,
81 css_color *color);
82
83/** Array of per-side access functions for computed style margins. */
84extern const css_len_func margin_funcs[4];
85
86/** Array of per-side access functions for computed style paddings. */
87extern const css_len_func padding_funcs[4];
88
89/** Array of per-side access functions for computed style border_widths. */
90extern const css_len_func border_width_funcs[4];
91
92/** Array of per-side access functions for computed style border styles. */
93extern const css_border_style_func border_style_funcs[4];
94
95/** Array of per-side access functions for computed style border colors. */
96extern const css_border_color_func border_color_funcs[4];
97
98/** Layout helper: Check whether box is a float. */
99static inline bool_Bool lh__box_is_float_box(const struct box *b)
100{
101 return b->type == BOX_FLOAT_LEFT ||
102 b->type == BOX_FLOAT_RIGHT;
103}
104
105/** Layout helper: Check whether box takes part in inline flow. */
106static inline bool_Bool lh__box_is_inline_flow(const struct box *b)
107{
108 return b->type == BOX_INLINE ||
109 b->type == BOX_INLINE_FLEX ||
110 b->type == BOX_INLINE_BLOCK ||
111 b->type == BOX_TEXT ||
112 b->type == BOX_INLINE_END;
113}
114
115/** Layout helper: Check whether box takes part in inline flow. */
116static inline bool_Bool lh__box_is_flex_container(const struct box *b)
117{
118 return b->type == BOX_FLEX ||
119 b->type == BOX_INLINE_FLEX;
120}
121
122/** Layout helper: Check whether box takes part in inline flow. */
123static inline bool_Bool lh__box_is_flex_item(const struct box *b)
124{
125 return (b->parent != NULL((void*)0)) && lh__box_is_flex_container(b->parent);
126}
127
128/** Layout helper: Check whether box is inline level. (Includes BR.) */
129static inline bool_Bool lh__box_is_inline_level(const struct box *b)
130{
131 return lh__box_is_inline_flow(b) ||
132 b->type == BOX_BR;
133}
134
135/** Layout helper: Check whether box is inline level. (Includes BR, floats.) */
136static inline bool_Bool lh__box_is_inline_content(const struct box *b)
137{
138 return lh__box_is_float_box(b) ||
139 lh__box_is_inline_level(b);
140}
141
142/** Layout helper: Check whether box is an object. */
143static inline bool_Bool lh__box_is_object(const struct box *b)
144{
145 return b->object ||
146 (b->flags & (IFRAME | REPLACE_DIM));
147}
148
149/** Layout helper: Check whether box is replaced. */
150static inline bool_Bool lh__box_is_replace(const struct box *b)
151{
152 return b->gadget ||
153 lh__box_is_object(b);
154}
155
156/** Layout helper: Check for CSS border on given side. */
157static inline bool_Bool lh__have_border(
158 enum box_side side,
159 const css_computed_style *style)
160{
161 return border_style_funcs[side](style) != CSS_BORDER_STYLE_NONE;
162}
163
164static inline bool_Bool lh__box_is_absolute(const struct box *b)
165{
166 return css_computed_position(b->style) == CSS_POSITION_ABSOLUTE ||
167 css_computed_position(b->style) == CSS_POSITION_FIXED;
168}
169
170static inline bool_Bool lh__flex_main_is_horizontal(const struct box *flex)
171{
172 const css_computed_style *style = flex->style;
173
174 assert(style != NULL)((style != ((void*)0)) ? (void) (0) : __assert_fail ("style != NULL"
, "content/handlers/html/layout_internal.h", 174, __extension__
__PRETTY_FUNCTION__))
;
12
Assuming 'style' is not equal to null
13
'?' condition is true
175
176 switch (css_computed_flex_direction(style)) {
14
Control jumps to 'case CSS_FLEX_DIRECTION_COLUMN_REVERSE:' at line 182
177 default: /* Fallthrough. */
178 case CSS_FLEX_DIRECTION_ROW: /* Fallthrough. */
179 case CSS_FLEX_DIRECTION_ROW_REVERSE:
180 return true1;
181 case CSS_FLEX_DIRECTION_COLUMN: /* Fallthrough. */
182 case CSS_FLEX_DIRECTION_COLUMN_REVERSE:
183 return false0;
15
Returning zero, which participates in a condition later
184 }
185}
186
187static inline bool_Bool lh__flex_direction_reversed(const struct box *flex)
188{
189 switch (css_computed_flex_direction(flex->style)) {
190 default: /* Fallthrough. */
191 case CSS_FLEX_DIRECTION_ROW_REVERSE: /* Fallthrough. */
192 case CSS_FLEX_DIRECTION_COLUMN_REVERSE:
193 return true1;
194 case CSS_FLEX_DIRECTION_ROW: /* Fallthrough. */
195 case CSS_FLEX_DIRECTION_COLUMN:
196 return false0;
197 }
198}
199
200static inline int lh__non_auto_margin(const struct box *b, enum box_side side)
201{
202 return (b->margin[side] == AUTO(-2147483647 -1)) ? 0 : b->margin[side];
203}
204
205static inline int lh__delta_outer_height(const struct box *b)
206{
207 return b->padding[TOP] +
208 b->padding[BOTTOM] +
209 b->border[TOP].width +
210 b->border[BOTTOM].width +
211 lh__non_auto_margin(b, TOP) +
212 lh__non_auto_margin(b, BOTTOM);
213}
214
215static inline int lh__delta_outer_width(const struct box *b)
216{
217 return b->padding[LEFT] +
218 b->padding[RIGHT] +
219 b->border[LEFT].width +
220 b->border[RIGHT].width +
221 lh__non_auto_margin(b, LEFT) +
222 lh__non_auto_margin(b, RIGHT);
223}
224
225static inline int lh__delta_outer_main(
226 const struct box *flex,
227 const struct box *b)
228{
229 if (lh__flex_main_is_horizontal(flex)) {
230 return lh__delta_outer_width(b);
231 } else {
232 return lh__delta_outer_height(b);
233 }
234}
235
236static inline int lh__delta_outer_cross(
237 const struct box *flex,
238 const struct box *b)
239{
240 if (lh__flex_main_is_horizontal(flex) == false0) {
241 return lh__delta_outer_width(b);
242 } else {
243 return lh__delta_outer_height(b);
244 }
245}
246
247static inline int *lh__box_size_main_ptr(
248 bool_Bool horizontal,
249 struct box *b)
250{
251 return horizontal ? &b->width : &b->height;
252}
253
254static inline int *lh__box_size_cross_ptr(
255 bool_Bool horizontal,
256 struct box *b)
257{
258 return horizontal ? &b->height : &b->width;
259}
260
261static inline int lh__box_size_main(
262 bool_Bool horizontal,
263 const struct box *b)
264{
265 return horizontal ? b->width : b->height;
266}
267
268static inline int lh__box_size_cross(
269 bool_Bool horizontal,
270 const struct box *b)
271{
272 return horizontal ? b->height : b->width;
273}
274
275static inline bool_Bool lh__box_size_cross_is_auto(
276 bool_Bool horizontal,
277 struct box *b)
278{
279 css_fixed length;
280 css_unit unit;
281
282 if (horizontal) {
283 return css_computed_height(b->style,
284 &length, &unit) == CSS_HEIGHT_AUTO;
285 } else {
286 return css_computed_width(b->style,
287 &length, &unit) == CSS_WIDTH_AUTO;
288 }
289}
290
291static inline enum css_align_self_e lh__box_align_self(
292 const struct box *flex,
293 const struct box *item)
294{
295 enum css_align_self_e align_self = css_computed_align_self(item->style);
296
297 if (align_self == CSS_ALIGN_SELF_AUTO) {
298 align_self = css_computed_align_items(flex->style);
299 }
300
301 return align_self;
302}
303
304/**
305 * Determine width of margin, borders, and padding on one side of a box.
306 *
307 * \param unit_len_ctx CSS length conversion context for document
308 * \param style style to measure
309 * \param side side of box to measure
310 * \param margin whether margin width is required
311 * \param border whether border width is required
312 * \param padding whether padding width is required
313 * \param fixed increased by sum of fixed margin, border, and padding
314 * \param frac increased by sum of fractional margin and padding
315 */
316static inline void calculate_mbp_width(
317 const css_unit_ctx *unit_len_ctx,
318 const css_computed_style *style,
319 unsigned int side,
320 bool_Bool margin,
321 bool_Bool border,
322 bool_Bool padding,
323 int *fixed,
324 float *frac)
325{
326 css_fixed value = 0;
327 css_unit unit = CSS_UNIT_PX;
328
329 assert(style)((style) ? (void) (0) : __assert_fail ("style", "content/handlers/html/layout_internal.h"
, 329, __extension__ __PRETTY_FUNCTION__))
;
330
331 /* margin */
332 if (margin) {
333 enum css_margin_e type;
334
335 type = margin_funcs[side](style, &value, &unit);
336 if (type == CSS_MARGIN_SET) {
337 if (unit == CSS_UNIT_PCT) {
338 *frac += FIXTOFLT(FDIV(value, F_100))((float) ((css_divide_fixed((value), (0x00019000)))) / (float
) (1 << 10))
;
339 } else {
340 *fixed += FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
341 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
342 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
343 }
344 }
345 }
346
347 /* border */
348 if (border) {
349 if (lh__have_border(side, style)) {
350 border_width_funcs[side](style, &value, &unit);
351
352 *fixed += FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
353 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
354 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
355 }
356 }
357
358 /* padding */
359 if (padding) {
360 padding_funcs[side](style, &value, &unit);
361 if (unit == CSS_UNIT_PCT) {
362 *frac += FIXTOFLT(FDIV(value, F_100))((float) ((css_divide_fixed((value), (0x00019000)))) / (float
) (1 << 10))
;
363 } else {
364 *fixed += FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
365 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
366 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
367 }
368 }
369}
370
371/**
372 * Adjust a specified width or height for the box-sizing property.
373 *
374 * This turns the specified dimension into a content-box dimension.
375 *
376 * \param unit_len_ctx Length conversion context
377 * \param box gadget to adjust dimensions of
378 * \param available_width width of containing block
379 * \param setwidth set true if the dimension to be tweaked is a width,
380 * else set false for a height
381 * \param dimension current value for given width/height dimension.
382 * updated to new value after consideration of
383 * gadget properties.
384 */
385static inline void layout_handle_box_sizing(
386 const css_unit_ctx *unit_len_ctx,
387 const struct box *box,
388 int available_width,
389 bool_Bool setwidth,
390 int *dimension)
391{
392 enum css_box_sizing_e bs;
393
394 assert(box && box->style)((box && box->style) ? (void) (0) : __assert_fail (
"box && box->style", "content/handlers/html/layout_internal.h"
, 394, __extension__ __PRETTY_FUNCTION__))
;
395
396 bs = css_computed_box_sizing(box->style);
397
398 if (bs == CSS_BOX_SIZING_BORDER_BOX) {
399 int orig = *dimension;
400 int fixed = 0;
401 float frac = 0;
402
403 calculate_mbp_width(unit_len_ctx, box->style,
404 setwidth ? LEFT : TOP,
405 false0, true1, true1, &fixed, &frac);
406 calculate_mbp_width(unit_len_ctx, box->style,
407 setwidth ? RIGHT : BOTTOM,
408 false0, true1, true1, &fixed, &frac);
409 orig -= frac * available_width + fixed;
410 *dimension = orig > 0 ? orig : 0;
411 }
412}
413
414/**
415 * Calculate width, height, and thickness of margins, paddings, and borders.
416 *
417 * \param unit_len_ctx Length conversion context
418 * \param available_width width of containing block
419 * \param viewport_height height of viewport in pixels or -ve if unknown
420 * \param box current box
421 * \param style style giving width, height, margins, paddings,
422 * and borders
423 * \param width updated to width, may be NULL
424 * \param height updated to height, may be NULL
425 * \param max_width updated to max-width, may be NULL
426 * \param min_width updated to min-width, may be NULL
427 * \param max_height updated to max-height, may be NULL
428 * \param min_height updated to min-height, may be NULL
429 * \param margin filled with margins, may be NULL
430 * \param padding filled with paddings, may be NULL
431 * \param border filled with border widths, may be NULL
432 */
433static inline void layout_find_dimensions(
434 const css_unit_ctx *unit_len_ctx,
435 int available_width,
436 int viewport_height,
437 const struct box *box,
438 const css_computed_style *style,
439 int *width,
440 int *height,
441 int *max_width,
442 int *min_width,
443 int *max_height,
444 int *min_height,
445 int margin[4],
446 int padding[4],
447 struct box_border border[4])
448{
449 struct box *containing_block = NULL((void*)0);
450 unsigned int i;
451
452 if (width) {
453 enum css_width_e wtype;
454 css_fixed value = 0;
455 css_unit unit = CSS_UNIT_PX;
456
457 wtype = css_computed_width(style, &value, &unit);
458
459 if (wtype == CSS_WIDTH_SET) {
460 if (unit == CSS_UNIT_PCT) {
461 *width = FPCT_OF_INT_TOINT(((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
462 value, available_width)((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
;
463 } else {
464 *width = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
465 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
466 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
467 }
468 } else {
469 *width = AUTO(-2147483647 -1);
470 }
471
472 if (*width != AUTO(-2147483647 -1)) {
473 layout_handle_box_sizing(unit_len_ctx, box,
474 available_width, true1, width);
475 }
476 }
477
478 if (height) {
479 enum css_height_e htype;
480 css_fixed value = 0;
481 css_unit unit = CSS_UNIT_PX;
482
483 htype = css_computed_height(style, &value, &unit);
484
485 if (htype == CSS_HEIGHT_SET) {
486 if (unit == CSS_UNIT_PCT) {
487 enum css_height_e cbhtype;
488
489 if (css_computed_position(box->style) ==
490 CSS_POSITION_ABSOLUTE &&
491 box->parent) {
492 /* Box is absolutely positioned */
493 assert(box->float_container)((box->float_container) ? (void) (0) : __assert_fail ("box->float_container"
, "content/handlers/html/layout_internal.h", 493, __extension__
__PRETTY_FUNCTION__))
;
494 containing_block = box->float_container;
495 } else if (box->float_container &&
496 css_computed_position(box->style) !=
497 CSS_POSITION_ABSOLUTE &&
498 (css_computed_float(box->style) ==
499 CSS_FLOAT_LEFT ||
500 css_computed_float(box->style) ==
501 CSS_FLOAT_RIGHT)) {
502 /* Box is a float */
503 assert(box->parent &&((box->parent && box->parent->parent &&
box->parent->parent->parent) ? (void) (0) : __assert_fail
("box->parent && box->parent->parent && box->parent->parent->parent"
, "content/handlers/html/layout_internal.h", 505, __extension__
__PRETTY_FUNCTION__))
504 box->parent->parent &&((box->parent && box->parent->parent &&
box->parent->parent->parent) ? (void) (0) : __assert_fail
("box->parent && box->parent->parent && box->parent->parent->parent"
, "content/handlers/html/layout_internal.h", 505, __extension__
__PRETTY_FUNCTION__))
505 box->parent->parent->parent)((box->parent && box->parent->parent &&
box->parent->parent->parent) ? (void) (0) : __assert_fail
("box->parent && box->parent->parent && box->parent->parent->parent"
, "content/handlers/html/layout_internal.h", 505, __extension__
__PRETTY_FUNCTION__))
;
506
507 containing_block =
508 box->parent->parent->parent;
509 } else if (box->parent && box->parent->type !=
510 BOX_INLINE_CONTAINER) {
511 /* Box is a block level element */
512 containing_block = box->parent;
513 } else if (box->parent && box->parent->type ==
514 BOX_INLINE_CONTAINER) {
515 /* Box is an inline block */
516 assert(box->parent->parent)((box->parent->parent) ? (void) (0) : __assert_fail ("box->parent->parent"
, "content/handlers/html/layout_internal.h", 516, __extension__
__PRETTY_FUNCTION__))
;
517 containing_block = box->parent->parent;
518 }
519
520 if (containing_block) {
521 css_fixed f = 0;
522 css_unit u = CSS_UNIT_PX;
523
524 cbhtype = css_computed_height(
525 containing_block->style,
526 &f, &u);
527 }
528
529 if (containing_block &&
530 containing_block->height != AUTO(-2147483647 -1) &&
531 (css_computed_position(box->style) ==
532 CSS_POSITION_ABSOLUTE ||
533 cbhtype == CSS_HEIGHT_SET)) {
534 /* Box is absolutely positioned or its
535 * containing block has a valid
536 * specified height.
537 * (CSS 2.1 Section 10.5) */
538 *height = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * containing_block->height)),
(0x00019000)))) >> 10))
539 containing_block->height)((((css_divide_fixed(((value * containing_block->height)),
(0x00019000)))) >> 10))
;
540 } else if ((!box->parent ||
541 !box->parent->parent) &&
542 viewport_height >= 0) {
543 /* If root element or it's child
544 * (HTML or BODY) */
545 *height = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * viewport_height)), (0x00019000
)))) >> 10))
546 viewport_height)((((css_divide_fixed(((value * viewport_height)), (0x00019000
)))) >> 10))
;
547 } else {
548 /* precentage height not permissible
549 * treat height as auto */
550 *height = AUTO(-2147483647 -1);
551 }
552 } else {
553 *height = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
554 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
555 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
556 }
557 } else {
558 *height = AUTO(-2147483647 -1);
559 }
560
561 if (*height != AUTO(-2147483647 -1)) {
562 layout_handle_box_sizing(unit_len_ctx, box,
563 available_width, false0, height);
564 }
565 }
566
567 if (max_width) {
568 enum css_max_width_e type;
569 css_fixed value = 0;
570 css_unit unit = CSS_UNIT_PX;
571
572 type = css_computed_max_width(style, &value, &unit);
573
574 if (type == CSS_MAX_WIDTH_SET) {
575 if (unit == CSS_UNIT_PCT) {
576 *max_width = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
577 available_width)((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
;
578 } else {
579 *max_width = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
580 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
581 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
582 }
583 } else {
584 /* Inadmissible */
585 *max_width = -1;
586 }
587
588 if (*max_width != -1) {
589 layout_handle_box_sizing(unit_len_ctx, box,
590 available_width, true1, max_width);
591 }
592 }
593
594 if (min_width) {
595 enum css_min_width_e type;
596 css_fixed value = 0;
597 css_unit unit = CSS_UNIT_PX;
598
599 type = ns_computed_min_width(style, &value, &unit);
600
601 if (type == CSS_MIN_WIDTH_SET) {
602 if (unit == CSS_UNIT_PCT) {
603 *min_width = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
604 available_width)((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
;
605 } else {
606 *min_width = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
607 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
608 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
609 }
610 } else {
611 /* Inadmissible */
612 *min_width = 0;
613 }
614
615 if (*min_width != 0) {
616 layout_handle_box_sizing(unit_len_ctx, box,
617 available_width, true1, min_width);
618 }
619 }
620
621 if (max_height) {
622 enum css_max_height_e type;
623 css_fixed value = 0;
624 css_unit unit = CSS_UNIT_PX;
625
626 type = css_computed_max_height(style, &value, &unit);
627
628 if (type == CSS_MAX_HEIGHT_SET) {
629 if (unit == CSS_UNIT_PCT) {
630 /* TODO: handle percentage */
631 *max_height = -1;
632 } else {
633 *max_height = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
634 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
635 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
636 }
637 } else {
638 /* Inadmissible */
639 *max_height = -1;
640 }
641 }
642
643 if (min_height) {
644 enum css_min_height_e type;
645 css_fixed value = 0;
646 css_unit unit = CSS_UNIT_PX;
647
648 type = ns_computed_min_height(style, &value, &unit);
649
650 if (type == CSS_MIN_HEIGHT_SET) {
651 if (unit == CSS_UNIT_PCT) {
652 /* TODO: handle percentage */
653 *min_height = 0;
654 } else {
655 *min_height = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
656 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
657 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
658 }
659 } else {
660 /* Inadmissible */
661 *min_height = 0;
662 }
663 }
664
665 for (i = 0; i != 4; i++) {
666 if (margin) {
667 enum css_margin_e type = CSS_MARGIN_AUTO;
668 css_fixed value = 0;
669 css_unit unit = CSS_UNIT_PX;
670
671 type = margin_funcs[i](style, &value, &unit);
672
673 if (type == CSS_MARGIN_SET) {
674 if (unit == CSS_UNIT_PCT) {
675 margin[i] = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
676 available_width)((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
;
677 } else {
678 margin[i] = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
679 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
680 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
681 }
682 } else {
683 margin[i] = AUTO(-2147483647 -1);
684 }
685 }
686
687 if (padding) {
688 css_fixed value = 0;
689 css_unit unit = CSS_UNIT_PX;
690
691 padding_funcs[i](style, &value, &unit);
692
693 if (unit == CSS_UNIT_PCT) {
694 padding[i] = FPCT_OF_INT_TOINT(value,((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
695 available_width)((((css_divide_fixed(((value * available_width)), (0x00019000
)))) >> 10))
;
696 } else {
697 padding[i] = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
698 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
699 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
700 }
701 }
702
703 /* Table cell borders are populated in table.c */
704 if (border && box->type != BOX_TABLE_CELL) {
705 enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE;
706 css_color color = 0;
707 css_fixed value = 0;
708 css_unit unit = CSS_UNIT_PX;
709
710 border_width_funcs[i](style, &value, &unit);
711 bstyle = border_style_funcs[i](style);
712 border_color_funcs[i](style, &color);
713
714 border[i].style = bstyle;
715 border[i].c = color;
716
717 if (bstyle == CSS_BORDER_STYLE_HIDDEN ||
718 bstyle == CSS_BORDER_STYLE_NONE)
719 /* spec unclear: following Mozilla */
720 border[i].width = 0;
721 else
722 border[i].width = FIXTOINT(css_unit_len2device_px(((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
723 style, unit_len_ctx,((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
724 value, unit))((css_unit_len2device_px( style, unit_len_ctx, value, unit)) >>
10)
;
725
726 /* Special case for border-collapse: make all borders
727 * on table/table-row-group/table-row zero width. */
728 if (css_computed_border_collapse(style) ==
729 CSS_BORDER_COLLAPSE_COLLAPSE &&
730 (box->type == BOX_TABLE ||
731 box->type == BOX_TABLE_ROW_GROUP ||
732 box->type == BOX_TABLE_ROW))
733 border[i].width = 0;
734 }
735 }
736}
737
738#endif