Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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 "bytecode/bytecode.h"
  9. #include "bytecode/opcodes.h"
  10. #include "select/propset.h"
  11. #include "select/propget.h"
  12. #include "utils/utils.h"
  13.  
  14. #include "select/properties/properties.h"
  15. #include "select/properties/helpers.h"
  16.  
  17. css_error css__cascade_font_family(uint32_t opv, css_style *style,
  18.                 css_select_state *state)
  19. {
  20.         uint16_t value = CSS_FONT_FAMILY_INHERIT;
  21.         lwc_string **fonts = NULL;
  22.         uint32_t n_fonts = 0;
  23.  
  24.         if (isInherit(opv) == false) {
  25.                 uint32_t v = getValue(opv);
  26.  
  27.                 while (v != FONT_FAMILY_END) {
  28.                         lwc_string *font = NULL;
  29.                         lwc_string **temp;
  30.  
  31.                         switch (v) {
  32.                         case FONT_FAMILY_STRING:
  33.                         case FONT_FAMILY_IDENT_LIST:
  34.                                 css__stylesheet_string_get(style->sheet,
  35.                                         *((css_code_t *) style->bytecode),
  36.                                         &font);
  37.                                 advance_bytecode(style, sizeof(css_code_t));
  38.                                 break;
  39.                         case FONT_FAMILY_SERIF:
  40.                                 if (value == CSS_FONT_FAMILY_INHERIT)
  41.                                         value = CSS_FONT_FAMILY_SERIF;
  42.                                 break;
  43.                         case FONT_FAMILY_SANS_SERIF:
  44.                                 if (value == CSS_FONT_FAMILY_INHERIT)
  45.                                         value = CSS_FONT_FAMILY_SANS_SERIF;
  46.                                 break;
  47.                         case FONT_FAMILY_CURSIVE:
  48.                                 if (value == CSS_FONT_FAMILY_INHERIT)
  49.                                         value = CSS_FONT_FAMILY_CURSIVE;
  50.                                 break;
  51.                         case FONT_FAMILY_FANTASY:
  52.                                 if (value == CSS_FONT_FAMILY_INHERIT)
  53.                                         value = CSS_FONT_FAMILY_FANTASY;
  54.                                 break;
  55.                         case FONT_FAMILY_MONOSPACE:
  56.                                 if (value == CSS_FONT_FAMILY_INHERIT)
  57.                                         value = CSS_FONT_FAMILY_MONOSPACE;
  58.                                 break;
  59.                         }
  60.  
  61.                         /* Only use family-names which occur before the first
  62.                          * generic-family. Any values which occur after the
  63.                          * first generic-family are ignored. */
  64.                         /** \todo Do this at bytecode generation time? */
  65.                         if (value == CSS_FONT_FAMILY_INHERIT && font != NULL) {
  66.                                 temp = state->computed->alloc(fonts,
  67.                                         (n_fonts + 1) * sizeof(lwc_string *),
  68.                                         state->computed->pw);
  69.                                 if (temp == NULL) {
  70.                                         if (fonts != NULL) {
  71.                                                 state->computed->alloc(fonts, 0,
  72.                                                         state->computed->pw);
  73.                                         }
  74.                                         return CSS_NOMEM;
  75.                                 }
  76.  
  77.                                 fonts = temp;
  78.  
  79.                                 fonts[n_fonts] = font;
  80.  
  81.                                 n_fonts++;
  82.                         }
  83.  
  84.                         v = *((uint32_t *) style->bytecode);
  85.                         advance_bytecode(style, sizeof(v));
  86.                 }
  87.         }
  88.  
  89.         /* Terminate array with blank entry, if needed */
  90.         if (n_fonts > 0) {
  91.                 lwc_string **temp;
  92.  
  93.                 temp = state->computed->alloc(fonts,
  94.                                 (n_fonts + 1) * sizeof(lwc_string *),
  95.                                 state->computed->pw);
  96.                 if (temp == NULL) {
  97.                         state->computed->alloc(fonts, 0, state->computed->pw);
  98.                         return CSS_NOMEM;
  99.                 }
  100.  
  101.                 fonts = temp;
  102.  
  103.                 fonts[n_fonts] = NULL;
  104.                
  105.                 if (value == CSS_FONT_FAMILY_INHERIT) {
  106.                         /* The stylesheet doesn't specify a generic family,
  107.                          * but it has specified named fonts.
  108.                          * Fall back to the user agent's default family.
  109.                          * We don't want to inherit, because that will
  110.                          * incorrectly overwrite the named fonts list too.
  111.                          */
  112.                         css_hint hint;
  113.                         css_error error;
  114.                        
  115.                         error = state->handler->ua_default_for_property(
  116.                                         state->pw, CSS_PROP_FONT_FAMILY, &hint);
  117.                         if (error == CSS_OK) {
  118.                                 lwc_string **item;
  119.  
  120.                                 value = hint.status;
  121.                
  122.                                 for (item = hint.data.strings;
  123.                                                 item != NULL && (*item) != NULL;
  124.                                                 item++) {
  125.                                         lwc_string_unref(*item);
  126.                                 }
  127.  
  128.                                 if (hint.data.strings != NULL) {
  129.                                         state->computed->alloc(
  130.                                                         hint.data.strings,
  131.                                                         0, state->computed->pw);
  132.                                 }
  133.                         }
  134.  
  135.                         if (value == CSS_FONT_FAMILY_INHERIT) {
  136.                                 /* No sane UA default: assume sans-serif */
  137.                                 value = CSS_FONT_FAMILY_SANS_SERIF;
  138.                         }
  139.                 }
  140.         }
  141.  
  142.         if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
  143.                         isInherit(opv))) {
  144.                 css_error error;
  145.  
  146.                 error = set_font_family(state->computed, value, fonts);
  147.                 if (error != CSS_OK && n_fonts > 0)
  148.                         state->computed->alloc(fonts, 0, state->computed->pw);
  149.  
  150.                 return error;
  151.         } else {
  152.                 if (n_fonts > 0)
  153.                         state->computed->alloc(fonts, 0, state->computed->pw);
  154.         }
  155.  
  156.         return CSS_OK;
  157. }
  158.  
  159. css_error css__set_font_family_from_hint(const css_hint *hint,
  160.                 css_computed_style *style)
  161. {
  162.         lwc_string **item;
  163.         css_error error;
  164.  
  165.         error = set_font_family(style, hint->status, hint->data.strings);
  166.  
  167.         for (item = hint->data.strings;
  168.                         item != NULL && (*item) != NULL; item++) {
  169.                 lwc_string_unref(*item);
  170.         }
  171.  
  172.         if (error != CSS_OK && hint->data.strings != NULL)
  173.                 style->alloc(hint->data.strings, 0, style->pw);
  174.  
  175.         return error;
  176. }
  177.  
  178. css_error css__initial_font_family(css_select_state *state)
  179. {
  180.         css_hint hint;
  181.         css_error error;
  182.  
  183.         error = state->handler->ua_default_for_property(state->pw,
  184.                         CSS_PROP_FONT_FAMILY, &hint);
  185.         if (error != CSS_OK)
  186.                 return error;
  187.  
  188.         return css__set_font_family_from_hint(&hint, state->computed);
  189. }
  190.  
  191. css_error css__compose_font_family(const css_computed_style *parent,
  192.                 const css_computed_style *child,
  193.                 css_computed_style *result)
  194. {
  195.         css_error error;
  196.         lwc_string **names = NULL;
  197.         uint8_t type = get_font_family(child, &names);
  198.  
  199.         if (type == CSS_FONT_FAMILY_INHERIT || result != child) {
  200.                 size_t n_names = 0;
  201.                 lwc_string **copy = NULL;
  202.  
  203.                 if (type == CSS_FONT_FAMILY_INHERIT)
  204.                         type = get_font_family(parent, &names);
  205.  
  206.                 if (names != NULL) {
  207.                         lwc_string **i;
  208.  
  209.                         for (i = names; (*i) != NULL; i++)
  210.                                 n_names++;
  211.  
  212.                         copy = result->alloc(NULL, (n_names + 1) *
  213.                                         sizeof(lwc_string *),
  214.                                         result->pw);
  215.                         if (copy == NULL)
  216.                                 return CSS_NOMEM;
  217.  
  218.                         memcpy(copy, names, (n_names + 1) *
  219.                                         sizeof(lwc_string *));
  220.                 }
  221.  
  222.                 error = set_font_family(result, type, copy);
  223.                 if (error != CSS_OK && copy != NULL)
  224.                         result->alloc(copy, 0, result->pw);
  225.  
  226.                 return error;
  227.         }
  228.  
  229.         return CSS_OK;
  230. }
  231.  
  232.