/peek-build/src/netdepends/libcss/src/select/computed.c
C | 1009 lines | 656 code | 153 blank | 200 comment | 230 complexity | 6b9e650fee7f2a7c3afb7da149e32772 MD5 | raw file
1/* 2 * This file is part of LibCSS 3 * Licensed under the MIT License, 4 * http://www.opensource.org/licenses/mit-license.php 5 * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org> 6 */ 7 8#include <string.h> 9 10#include "select/computed.h" 11#include "select/dispatch.h" 12#include "select/propget.h" 13#include "select/propset.h" 14#include "utils/utils.h" 15 16static css_error compute_border_colors(css_computed_style *style); 17 18static css_error compute_absolute_border_width(css_computed_style *style, 19 const css_hint_length *ex_size); 20static css_error compute_absolute_border_side_width(css_computed_style *style, 21 const css_hint_length *ex_size, 22 uint8_t (*get)(const css_computed_style *style, 23 css_fixed *len, css_unit *unit), 24 css_error (*set)(css_computed_style *style, uint8_t type, 25 css_fixed len, css_unit unit)); 26static css_error compute_absolute_sides(css_computed_style *style, 27 const css_hint_length *ex_size); 28static css_error compute_absolute_clip(css_computed_style *style, 29 const css_hint_length *ex_size); 30static css_error compute_absolute_line_height(css_computed_style *style, 31 const css_hint_length *ex_size); 32static css_error compute_absolute_margins(css_computed_style *style, 33 const css_hint_length *ex_size); 34static css_error compute_absolute_padding(css_computed_style *style, 35 const css_hint_length *ex_size); 36static css_error compute_absolute_vertical_align(css_computed_style *style, 37 const css_hint_length *ex_size); 38static css_error compute_absolute_length(css_computed_style *style, 39 const css_hint_length *ex_size, 40 uint8_t (*get)(const css_computed_style *style, 41 css_fixed *len, css_unit *unit), 42 css_error (*set)(css_computed_style *style, uint8_t type, 43 css_fixed len, css_unit unit)); 44static css_error compute_absolute_length_auto(css_computed_style *style, 45 const css_hint_length *ex_size, 46 uint8_t (*get)(const css_computed_style *style, 47 css_fixed *len, css_unit *unit), 48 css_error (*set)(css_computed_style *style, uint8_t type, 49 css_fixed len, css_unit unit)); 50static css_error compute_absolute_length_none(css_computed_style *style, 51 const css_hint_length *ex_size, 52 uint8_t (*get)(const css_computed_style *style, 53 css_fixed *len, css_unit *unit), 54 css_error (*set)(css_computed_style *style, uint8_t type, 55 css_fixed len, css_unit unit)); 56static css_error compute_absolute_length_normal(css_computed_style *style, 57 const css_hint_length *ex_size, 58 uint8_t (*get)(const css_computed_style *style, 59 css_fixed *len, css_unit *unit), 60 css_error (*set)(css_computed_style *style, uint8_t type, 61 css_fixed len, css_unit unit)); 62static css_error compute_absolute_length_pair(css_computed_style *style, 63 const css_hint_length *ex_size, 64 uint8_t (*get)(const css_computed_style *style, 65 css_fixed *len1, css_unit *unit1, 66 css_fixed *len2, css_unit *unit2), 67 css_error (*set)(css_computed_style *style, uint8_t type, 68 css_fixed len1, css_unit unit1, 69 css_fixed len2, css_unit unit2)); 70 71 72/** 73 * Create a computed style 74 * 75 * \param alloc Memory (de)allocation function 76 * \param pw Pointer to client-specific data 77 * \param result Pointer to location to receive result 78 * \return CSS_OK on success, 79 * CSS_NOMEM on memory exhaustion, 80 * CSS_BADPARM on bad parameters. 81 */ 82css_error css_computed_style_create(css_allocator_fn alloc, void *pw, 83 css_computed_style **result) 84{ 85 css_computed_style *s; 86 87 if (alloc == NULL || result == NULL) 88 return CSS_BADPARM; 89 90 s = alloc(NULL, sizeof(css_computed_style), pw); 91 if (s == NULL) 92 return CSS_NOMEM; 93 94 memset(s, 0, sizeof(css_computed_style)); 95 96 s->alloc = alloc; 97 s->pw = pw; 98 99 *result = s; 100 101 return CSS_OK; 102} 103 104/** 105 * Destroy a computed style 106 * 107 * \param style Style to destroy 108 * \return CSS_OK on success, appropriate error otherwise 109 */ 110css_error css_computed_style_destroy(css_computed_style *style) 111{ 112 if (style == NULL) 113 return CSS_BADPARM; 114 115 if (style->uncommon != NULL) { 116 if (style->uncommon->counter_increment != NULL) { 117 css_computed_counter *c; 118 119 for (c = style->uncommon->counter_increment; 120 c->name != NULL; c++) { 121 lwc_string_unref(c->name); 122 } 123 124 style->alloc(style->uncommon->counter_increment, 0, 125 style->pw); 126 } 127 128 if (style->uncommon->counter_reset != NULL) { 129 css_computed_counter *c; 130 131 for (c = style->uncommon->counter_reset; 132 c->name != NULL; c++) { 133 lwc_string_unref(c->name); 134 } 135 136 style->alloc(style->uncommon->counter_reset, 0, 137 style->pw); 138 } 139 140 if (style->uncommon->cursor != NULL) { 141 lwc_string **s; 142 143 for (s = style->uncommon->cursor; *s != NULL; s++) { 144 lwc_string_unref(*s); 145 } 146 147 style->alloc(style->uncommon->cursor, 0, style->pw); 148 } 149 150 if (style->uncommon->content != NULL) { 151 css_computed_content_item *c; 152 153 for (c = style->uncommon->content; 154 c->type != CSS_COMPUTED_CONTENT_NONE; 155 c++) { 156 switch (c->type) { 157 case CSS_COMPUTED_CONTENT_STRING: 158 lwc_string_unref(c->data.string); 159 break; 160 case CSS_COMPUTED_CONTENT_URI: 161 lwc_string_unref(c->data.uri); 162 break; 163 case CSS_COMPUTED_CONTENT_ATTR: 164 lwc_string_unref(c->data.attr); 165 break; 166 case CSS_COMPUTED_CONTENT_COUNTER: 167 lwc_string_unref(c->data.counter.name); 168 break; 169 case CSS_COMPUTED_CONTENT_COUNTERS: 170 lwc_string_unref(c->data.counters.name); 171 lwc_string_unref(c->data.counters.sep); 172 break; 173 default: 174 break; 175 } 176 } 177 178 style->alloc(style->uncommon->content, 0, style->pw); 179 } 180 181 style->alloc(style->uncommon, 0, style->pw); 182 } 183 184 if (style->page != NULL) { 185 style->alloc(style->page, 0, style->pw); 186 } 187 188 if (style->aural != NULL) { 189 style->alloc(style->aural, 0, style->pw); 190 } 191 192 if (style->font_family != NULL) { 193 lwc_string **s; 194 195 for (s = style->font_family; *s != NULL; s++) { 196 lwc_string_unref(*s); 197 } 198 199 style->alloc(style->font_family, 0, style->pw); 200 } 201 202 if (style->quotes != NULL) { 203 lwc_string **s; 204 205 for (s = style->quotes; *s != NULL; s++) { 206 lwc_string_unref(*s); 207 } 208 209 style->alloc(style->quotes, 0, style->pw); 210 } 211 212 if (style->list_style_image != NULL) 213 lwc_string_unref(style->list_style_image); 214 215 if (style->background_image != NULL) 216 lwc_string_unref(style->background_image); 217 218 style->alloc(style, 0, style->pw); 219 220 return CSS_OK; 221} 222 223/** 224 * Populate a blank computed style with Initial values 225 * 226 * \param style Computed style to populate 227 * \param handler Dispatch table of handler functions 228 * \param pw Client-specific private data for handler functions 229 * \return CSS_OK on success. 230 */ 231css_error css_computed_style_initialise(css_computed_style *style, 232 css_select_handler *handler, void *pw) 233{ 234 css_select_state state; 235 uint32_t i; 236 css_error error; 237 238 if (style == NULL) 239 return CSS_BADPARM; 240 241 state.node = NULL; 242 state.pseudo_element = CSS_PSEUDO_ELEMENT_NONE; 243 state.media = CSS_MEDIA_ALL; 244 state.result = style; 245 state.handler = handler; 246 state.pw = pw; 247 248 for (i = 0; i < CSS_N_PROPERTIES; i++) { 249 /* No need to initialise anything other than the normal 250 * properties -- the others are handled by the accessors */ 251 if (prop_dispatch[i].inherited == false && 252 prop_dispatch[i].group == GROUP_NORMAL) { 253 error = prop_dispatch[i].initial(&state); 254 if (error != CSS_OK) 255 return error; 256 } 257 } 258 259 return CSS_OK; 260} 261 262/** 263 * Compose two computed styles 264 * 265 * \param parent Parent style 266 * \param child Child style 267 * \param compute_font_size Function to compute an absolute font size 268 * \param pw Client data for compute_font_size 269 * \param result Pointer to style to compose into 270 * \return CSS_OK on success, appropriate error otherwise. 271 * 272 * \pre \a parent is a fully composed style (thus has no inherited properties) 273 * 274 * \note \a child and \a result may point at the same object 275 */ 276css_error css_computed_style_compose(const css_computed_style *parent, 277 const css_computed_style *child, 278 css_error (*compute_font_size)(void *pw, 279 const css_hint *parent, css_hint *size), 280 void *pw, 281 css_computed_style *result) 282{ 283 css_error error = CSS_OK; 284 size_t i; 285 286 /* Iterate through the properties */ 287 for (i = 0; i < CSS_N_PROPERTIES; i++) { 288 /* Skip any in extension blocks if the block does not exist */ 289 if (prop_dispatch[i].group == GROUP_UNCOMMON && 290 parent->uncommon == NULL && 291 child->uncommon == NULL) 292 continue; 293 294 if (prop_dispatch[i].group == GROUP_PAGE && 295 parent->page == NULL && child->page == NULL) 296 continue; 297 298 if (prop_dispatch[i].group == GROUP_AURAL && 299 parent->aural == NULL && child->aural == NULL) 300 continue; 301 302 /* Compose the property */ 303 error = prop_dispatch[i].compose(parent, child, result); 304 if (error != CSS_OK) 305 break; 306 } 307 308 /* Finally, compute absolute values for everything */ 309 return compute_absolute_values(parent, result, compute_font_size, pw); 310} 311 312/****************************************************************************** 313 * Library internals * 314 ******************************************************************************/ 315 316/** 317 * Compute the absolute values of a style 318 * 319 * \param parent Parent style, or NULL for tree root 320 * \param style Computed style to process 321 * \param compute_font_size Callback to calculate an absolute font-size 322 * \param pw Private word for callback 323 * \return CSS_OK on success. 324 */ 325css_error compute_absolute_values(const css_computed_style *parent, 326 css_computed_style *style, 327 css_error (*compute_font_size)(void *pw, 328 const css_hint *parent, css_hint *size), 329 void *pw) 330{ 331 css_hint psize, size, ex_size; 332 css_error error; 333 334 /* Ensure font-size is absolute */ 335 if (parent != NULL) { 336 psize.status = get_font_size(parent, 337 &psize.data.length.value, 338 &psize.data.length.unit); 339 } 340 341 size.status = get_font_size(style, 342 &size.data.length.value, 343 &size.data.length.unit); 344 345 error = compute_font_size(pw, parent != NULL ? &psize : NULL, &size); 346 if (error != CSS_OK) 347 return error; 348 349 error = set_font_size(style, size.status, 350 size.data.length.value, 351 size.data.length.unit); 352 if (error != CSS_OK) 353 return error; 354 355 /* Compute the size of an ex unit */ 356 ex_size.status = CSS_FONT_SIZE_DIMENSION; 357 ex_size.data.length.value = INTTOFIX(1); 358 ex_size.data.length.unit = CSS_UNIT_EX; 359 error = compute_font_size(pw, &size, &ex_size); 360 if (error != CSS_OK) 361 return error; 362 363 /* Convert ex size into ems */ 364 if (size.data.length.value != 0) 365 ex_size.data.length.value = FDIV(ex_size.data.length.value, 366 size.data.length.value); 367 else 368 ex_size.data.length.value = 0; 369 ex_size.data.length.unit = CSS_UNIT_EM; 370 371 /* Fix up background-position */ 372 error = compute_absolute_length_pair(style, &ex_size.data.length, 373 get_background_position, 374 set_background_position); 375 if (error != CSS_OK) 376 return error; 377 378 /* Fix up border-{top,right,bottom,left}-color */ 379 error = compute_border_colors(style); 380 if (error != CSS_OK) 381 return error; 382 383 /* Fix up border-{top,right,bottom,left}-width */ 384 error = compute_absolute_border_width(style, &ex_size.data.length); 385 if (error != CSS_OK) 386 return error; 387 388 /* Fix up sides */ 389 error = compute_absolute_sides(style, &ex_size.data.length); 390 if (error != CSS_OK) 391 return error; 392 393 /* Fix up height */ 394 error = compute_absolute_length_auto(style, &ex_size.data.length, 395 get_height, set_height); 396 if (error != CSS_OK) 397 return error; 398 399 /* Fix up line-height (must be before vertical-align) */ 400 error = compute_absolute_line_height(style, &ex_size.data.length); 401 if (error != CSS_OK) 402 return error; 403 404 /* Fix up margins */ 405 error = compute_absolute_margins(style, &ex_size.data.length); 406 if (error != CSS_OK) 407 return error; 408 409 /* Fix up max-height */ 410 error = compute_absolute_length_none(style, &ex_size.data.length, 411 get_max_height, set_max_height); 412 if (error != CSS_OK) 413 return error; 414 415 /* Fix up max-width */ 416 error = compute_absolute_length_none(style, &ex_size.data.length, 417 get_max_width, set_max_width); 418 if (error != CSS_OK) 419 return error; 420 421 /* Fix up min-height */ 422 error = compute_absolute_length(style, &ex_size.data.length, 423 get_min_height, set_min_height); 424 if (error != CSS_OK) 425 return error; 426 427 /* Fix up min-width */ 428 error = compute_absolute_length(style, &ex_size.data.length, 429 get_min_width, set_min_width); 430 if (error != CSS_OK) 431 return error; 432 433 /* Fix up padding */ 434 error = compute_absolute_padding(style, &ex_size.data.length); 435 if (error != CSS_OK) 436 return error; 437 438 /* Fix up text-indent */ 439 error = compute_absolute_length(style, &ex_size.data.length, 440 get_text_indent, set_text_indent); 441 if (error != CSS_OK) 442 return error; 443 444 /* Fix up vertical-align */ 445 error = compute_absolute_vertical_align(style, &ex_size.data.length); 446 if (error != CSS_OK) 447 return error; 448 449 /* Fix up width */ 450 error = compute_absolute_length_auto(style, &ex_size.data.length, 451 get_width, set_width); 452 if (error != CSS_OK) 453 return error; 454 455 /* Uncommon properties */ 456 if (style->uncommon != NULL) { 457 /* Fix up border-spacing */ 458 error = compute_absolute_length_pair(style, 459 &ex_size.data.length, 460 get_border_spacing, 461 set_border_spacing); 462 if (error != CSS_OK) 463 return error; 464 465 /* Fix up clip */ 466 error = compute_absolute_clip(style, &ex_size.data.length); 467 if (error != CSS_OK) 468 return error; 469 470 /* Fix up letter-spacing */ 471 error = compute_absolute_length_normal(style, 472 &ex_size.data.length, 473 get_letter_spacing, 474 set_letter_spacing); 475 if (error != CSS_OK) 476 return error; 477 478 /* Fix up outline-width */ 479 error = compute_absolute_border_side_width(style, 480 &ex_size.data.length, 481 get_outline_width, 482 set_outline_width); 483 if (error != CSS_OK) 484 return error; 485 486 /* Fix up word spacing */ 487 error = compute_absolute_length_normal(style, 488 &ex_size.data.length, 489 get_word_spacing, 490 set_word_spacing); 491 if (error != CSS_OK) 492 return error; 493 } 494 495 return CSS_OK; 496} 497 498/****************************************************************************** 499 * Absolute value calculators 500 ******************************************************************************/ 501 502/** 503 * Compute border colours, replacing any set to initial with 504 * the computed value of color. 505 * 506 * \param style The style to process 507 * \return CSS_OK on success 508 */ 509css_error compute_border_colors(css_computed_style *style) 510{ 511 css_color color, bcol; 512 css_error error; 513 514 css_computed_color(style, &color); 515 516 if (get_border_top_color(style, &bcol) == CSS_BORDER_COLOR_INITIAL) { 517 error = set_border_top_color(style, 518 CSS_BORDER_COLOR_COLOR, color); 519 if (error != CSS_OK) 520 return error; 521 } 522 523 if (get_border_right_color(style, &bcol) == CSS_BORDER_COLOR_INITIAL) { 524 error = set_border_right_color(style, 525 CSS_BORDER_COLOR_COLOR, color); 526 if (error != CSS_OK) 527 return error; 528 } 529 530 if (get_border_bottom_color(style, &bcol) == CSS_BORDER_COLOR_INITIAL) { 531 error = set_border_bottom_color(style, 532 CSS_BORDER_COLOR_COLOR, color); 533 if (error != CSS_OK) 534 return error; 535 } 536 537 if (get_border_left_color(style, &bcol) == CSS_BORDER_COLOR_INITIAL) { 538 error = set_border_left_color(style, 539 CSS_BORDER_COLOR_COLOR, color); 540 if (error != CSS_OK) 541 return error; 542 } 543 544 return CSS_OK; 545} 546 547/** 548 * Compute absolute border widths 549 * 550 * \param style Style to process 551 * \param ex_size Ex size in ems 552 * \return CSS_OK on success 553 */ 554css_error compute_absolute_border_width(css_computed_style *style, 555 const css_hint_length *ex_size) 556{ 557 css_error error; 558 559 error = compute_absolute_border_side_width(style, ex_size, 560 get_border_top_width, 561 set_border_top_width); 562 if (error != CSS_OK) 563 return error; 564 565 error = compute_absolute_border_side_width(style, ex_size, 566 get_border_right_width, 567 set_border_right_width); 568 if (error != CSS_OK) 569 return error; 570 571 error = compute_absolute_border_side_width(style, ex_size, 572 get_border_bottom_width, 573 set_border_bottom_width); 574 if (error != CSS_OK) 575 return error; 576 577 error = compute_absolute_border_side_width(style, ex_size, 578 get_border_left_width, 579 set_border_left_width); 580 if (error != CSS_OK) 581 return error; 582 583 return CSS_OK; 584} 585 586/** 587 * Compute an absolute border side width 588 * 589 * \param style Style to process 590 * \param ex_size Ex size, in ems 591 * \param get Function to read length 592 * \param set Function to write length 593 * \return CSS_OK on success 594 */ 595css_error compute_absolute_border_side_width(css_computed_style *style, 596 const css_hint_length *ex_size, 597 uint8_t (*get)(const css_computed_style *style, 598 css_fixed *len, css_unit *unit), 599 css_error (*set)(css_computed_style *style, uint8_t type, 600 css_fixed len, css_unit unit)) 601{ 602 css_fixed length; 603 css_unit unit; 604 uint8_t type; 605 606 type = get(style, &length, &unit); 607 if (type == CSS_BORDER_WIDTH_THIN) { 608 length = INTTOFIX(1); 609 unit = CSS_UNIT_PX; 610 } else if (type == CSS_BORDER_WIDTH_MEDIUM) { 611 length = INTTOFIX(2); 612 unit = CSS_UNIT_PX; 613 } else if (type == CSS_BORDER_WIDTH_THICK) { 614 length = INTTOFIX(4); 615 unit = CSS_UNIT_PX; 616 } 617 618 if (unit == CSS_UNIT_EX) { 619 length = FMUL(length, ex_size->value); 620 unit = ex_size->unit; 621 } 622 623 return set(style, CSS_BORDER_WIDTH_WIDTH, length, unit); 624} 625 626/** 627 * Compute absolute clip 628 * 629 * \param style Style to process 630 * \param ex_size Ex size in ems 631 * \return CSS_OK on success 632 */ 633css_error compute_absolute_clip(css_computed_style *style, 634 const css_hint_length *ex_size) 635{ 636 css_computed_clip_rect rect = { 0, 0, 0, 0, CSS_UNIT_PX, CSS_UNIT_PX, 637 CSS_UNIT_PX, CSS_UNIT_PX, false, false, false, false }; 638 css_error error; 639 640 if (get_clip(style, &rect) == CSS_CLIP_RECT) { 641 if (rect.top_auto == false) { 642 if (rect.tunit == CSS_UNIT_EX) { 643 rect.top = FMUL(rect.top, ex_size->value); 644 rect.tunit = ex_size->unit; 645 } 646 } 647 648 if (rect.right_auto == false) { 649 if (rect.runit == CSS_UNIT_EX) { 650 rect.right = FMUL(rect.right, ex_size->value); 651 rect.runit = ex_size->unit; 652 } 653 } 654 655 if (rect.bottom_auto == false) { 656 if (rect.bunit == CSS_UNIT_EX) { 657 rect.bottom = FMUL(rect.bottom, ex_size->value); 658 rect.bunit = ex_size->unit; 659 } 660 } 661 662 if (rect.left_auto == false) { 663 if (rect.lunit == CSS_UNIT_EX) { 664 rect.left = FMUL(rect.left, ex_size->value); 665 rect.lunit = ex_size->unit; 666 } 667 } 668 669 error = set_clip(style, CSS_CLIP_RECT, &rect); 670 if (error != CSS_OK) 671 return error; 672 } 673 674 return CSS_OK; 675} 676 677/** 678 * Compute absolute line-height 679 * 680 * \param style Style to process 681 * \param ex_size Ex size, in ems 682 * \return CSS_OK on success 683 */ 684css_error compute_absolute_line_height(css_computed_style *style, 685 const css_hint_length *ex_size) 686{ 687 css_fixed length = 0; 688 css_unit unit = CSS_UNIT_PX; 689 uint8_t type; 690 css_error error; 691 692 type = get_line_height(style, &length, &unit); 693 694 if (type == CSS_LINE_HEIGHT_DIMENSION) { 695 if (unit == CSS_UNIT_EX) { 696 length = FMUL(length, ex_size->value); 697 unit = ex_size->unit; 698 } 699 700 error = set_line_height(style, type, length, unit); 701 if (error != CSS_OK) 702 return error; 703 } 704 705 return CSS_OK; 706} 707 708/** 709 * Compute the absolute values of {top,right,bottom,left} 710 * 711 * \param style Style to process 712 * \param ex_size Ex size, in ems 713 * \return CSS_OK on success 714 */ 715css_error compute_absolute_sides(css_computed_style *style, 716 const css_hint_length *ex_size) 717{ 718 css_error error; 719 720 /* Calculate absolute lengths for sides */ 721 error = compute_absolute_length_auto(style, ex_size, get_top, set_top); 722 if (error != CSS_OK) 723 return error; 724 725 error = compute_absolute_length_auto(style, ex_size, 726 get_right, set_right); 727 if (error != CSS_OK) 728 return error; 729 730 error = compute_absolute_length_auto(style, ex_size, 731 get_bottom, set_bottom); 732 if (error != CSS_OK) 733 return error; 734 735 error = compute_absolute_length_auto(style, ex_size, 736 get_left, set_left); 737 if (error != CSS_OK) 738 return error; 739 740 return CSS_OK; 741} 742 743/** 744 * Compute absolute margins 745 * 746 * \param style Style to process 747 * \param ex_size Ex size, in ems 748 * \return CSS_OK on success 749 */ 750css_error compute_absolute_margins(css_computed_style *style, 751 const css_hint_length *ex_size) 752{ 753 css_error error; 754 755 error = compute_absolute_length_auto(style, ex_size, 756 get_margin_top, set_margin_top); 757 if (error != CSS_OK) 758 return error; 759 760 error = compute_absolute_length_auto(style, ex_size, 761 get_margin_right, set_margin_right); 762 if (error != CSS_OK) 763 return error; 764 765 error = compute_absolute_length_auto(style, ex_size, 766 get_margin_bottom, set_margin_bottom); 767 if (error != CSS_OK) 768 return error; 769 770 error = compute_absolute_length_auto(style, ex_size, 771 get_margin_left, set_margin_left); 772 if (error != CSS_OK) 773 return error; 774 775 return CSS_OK; 776} 777 778/** 779 * Compute absolute padding 780 * 781 * \param style Style to process 782 * \param ex_size Ex size, in ems 783 * \return CSS_OK on success 784 */ 785css_error compute_absolute_padding(css_computed_style *style, 786 const css_hint_length *ex_size) 787{ 788 css_error error; 789 790 error = compute_absolute_length(style, ex_size, 791 get_padding_top, set_padding_top); 792 if (error != CSS_OK) 793 return error; 794 795 error = compute_absolute_length(style, ex_size, 796 get_padding_right, set_padding_right); 797 if (error != CSS_OK) 798 return error; 799 800 error = compute_absolute_length(style, ex_size, 801 get_padding_bottom, set_padding_bottom); 802 if (error != CSS_OK) 803 return error; 804 805 error = compute_absolute_length(style, ex_size, 806 get_padding_left, set_padding_left); 807 if (error != CSS_OK) 808 return error; 809 810 return CSS_OK; 811} 812 813/** 814 * Compute absolute vertical-align 815 * 816 * \param style Style to process 817 * \param ex_size Ex size, in ems 818 * \return CSS_OK on success 819 */ 820css_error compute_absolute_vertical_align(css_computed_style *style, 821 const css_hint_length *ex_size) 822{ 823 css_fixed length = 0; 824 css_unit unit = CSS_UNIT_PX; 825 uint8_t type; 826 css_error error; 827 828 type = get_vertical_align(style, &length, &unit); 829 830 if (type == CSS_VERTICAL_ALIGN_SET) { 831 if (unit == CSS_UNIT_EX) { 832 length = FMUL(length, ex_size->value); 833 unit = ex_size->unit; 834 } 835 836 error = set_vertical_align(style, type, length, unit); 837 if (error != CSS_OK) 838 return error; 839 } 840 841 return CSS_OK; 842} 843 844/** 845 * Compute the absolute value of length 846 * 847 * \param style Style to process 848 * \param ex_size Ex size, in ems 849 * \param get Function to read length 850 * \param set Function to write length 851 * \return CSS_OK on success 852 */ 853css_error compute_absolute_length(css_computed_style *style, 854 const css_hint_length *ex_size, 855 uint8_t (*get)(const css_computed_style *style, 856 css_fixed *len, css_unit *unit), 857 css_error (*set)(css_computed_style *style, uint8_t type, 858 css_fixed len, css_unit unit)) 859{ 860 css_fixed length; 861 css_unit unit; 862 uint8_t type; 863 864 type = get(style, &length, &unit); 865 866 if (unit == CSS_UNIT_EX) { 867 length = FMUL(length, ex_size->value); 868 unit = ex_size->unit; 869 } 870 871 return set(style, type, length, unit); 872} 873 874/** 875 * Compute the absolute value of length or auto 876 * 877 * \param style Style to process 878 * \param ex_size Ex size, in ems 879 * \param get Function to read length 880 * \param set Function to write length 881 * \return CSS_OK on success 882 */ 883css_error compute_absolute_length_auto(css_computed_style *style, 884 const css_hint_length *ex_size, 885 uint8_t (*get)(const css_computed_style *style, 886 css_fixed *len, css_unit *unit), 887 css_error (*set)(css_computed_style *style, uint8_t type, 888 css_fixed len, css_unit unit)) 889{ 890 css_fixed length; 891 css_unit unit; 892 uint8_t type; 893 894 type = get(style, &length, &unit); 895 if (type != CSS_BOTTOM_AUTO) { 896 if (unit == CSS_UNIT_EX) { 897 length = FMUL(length, ex_size->value); 898 unit = ex_size->unit; 899 } 900 901 return set(style, CSS_BOTTOM_SET, length, unit); 902 } 903 904 return set(style, CSS_BOTTOM_AUTO, 0, CSS_UNIT_PX); 905} 906 907/** 908 * Compute the absolute value of length or none 909 * 910 * \param style Style to process 911 * \param ex_size Ex size, in ems 912 * \param get Function to read length 913 * \param set Function to write length 914 * \return CSS_OK on success 915 */ 916css_error compute_absolute_length_none(css_computed_style *style, 917 const css_hint_length *ex_size, 918 uint8_t (*get)(const css_computed_style *style, 919 css_fixed *len, css_unit *unit), 920 css_error (*set)(css_computed_style *style, uint8_t type, 921 css_fixed len, css_unit unit)) 922{ 923 css_fixed length; 924 css_unit unit; 925 uint8_t type; 926 927 type = get(style, &length, &unit); 928 if (type != CSS_MAX_HEIGHT_NONE) { 929 if (unit == CSS_UNIT_EX) { 930 length = FMUL(length, ex_size->value); 931 unit = ex_size->unit; 932 } 933 934 return set(style, CSS_MAX_HEIGHT_SET, length, unit); 935 } 936 937 return set(style, CSS_MAX_HEIGHT_NONE, 0, CSS_UNIT_PX); 938} 939 940/** 941 * Compute the absolute value of length or normal 942 * 943 * \param style Style to process 944 * \param ex_size Ex size, in ems 945 * \param get Function to read length 946 * \param set Function to write length 947 * \return CSS_OK on success 948 */ 949css_error compute_absolute_length_normal(css_computed_style *style, 950 const css_hint_length *ex_size, 951 uint8_t (*get)(const css_computed_style *style, 952 css_fixed *len, css_unit *unit), 953 css_error (*set)(css_computed_style *style, uint8_t type, 954 css_fixed len, css_unit unit)) 955{ 956 css_fixed length; 957 css_unit unit; 958 uint8_t type; 959 960 type = get(style, &length, &unit); 961 if (type != CSS_LETTER_SPACING_NORMAL) { 962 if (unit == CSS_UNIT_EX) { 963 length = FMUL(length, ex_size->value); 964 unit = ex_size->unit; 965 } 966 967 return set(style, CSS_LETTER_SPACING_SET, length, unit); 968 } 969 970 return set(style, CSS_LETTER_SPACING_NORMAL, 0, CSS_UNIT_PX); 971} 972 973/** 974 * Compute the absolute value of length pair 975 * 976 * \param style Style to process 977 * \param ex_size Ex size, in ems 978 * \param get Function to read length 979 * \param set Function to write length 980 * \return CSS_OK on success 981 */ 982css_error compute_absolute_length_pair(css_computed_style *style, 983 const css_hint_length *ex_size, 984 uint8_t (*get)(const css_computed_style *style, 985 css_fixed *len1, css_unit *unit1, 986 css_fixed *len2, css_unit *unit2), 987 css_error (*set)(css_computed_style *style, uint8_t type, 988 css_fixed len1, css_unit unit1, 989 css_fixed len2, css_unit unit2)) 990{ 991 css_fixed length1, length2; 992 css_unit unit1, unit2; 993 uint8_t type; 994 995 type = get(style, &length1, &unit1, &length2, &unit2); 996 997 if (unit1 == CSS_UNIT_EX) { 998 length1 = FMUL(length1, ex_size->value); 999 unit1 = ex_size->unit; 1000 } 1001 1002 if (unit2 == CSS_UNIT_EX) { 1003 length2 = FMUL(length2, ex_size->value); 1004 unit2 = ex_size->unit; 1005 } 1006 1007 return set(style, type, length1, unit1, length2, unit2); 1008} 1009