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 <assert.h>
  9. #include <string.h>
  10.  
  11. #include "bytecode/bytecode.h"
  12. #include "bytecode/opcodes.h"
  13. #include "parse/properties/properties.h"
  14. #include "parse/properties/utils.h"
  15.  
  16.  
  17. static css_error parse_system_font(css_language *c,
  18.                 css_style *result, css_system_font *system_font)
  19. {
  20.         css_error error;
  21.         bool match;
  22.  
  23.         /* style */
  24.         switch (system_font->style) {
  25.         case CSS_FONT_STYLE_NORMAL:
  26.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_NORMAL);
  27.                 break;
  28.  
  29.         case CSS_FONT_STYLE_ITALIC:
  30.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_ITALIC);
  31.                 break;
  32.  
  33.         case CSS_FONT_STYLE_OBLIQUE:
  34.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_OBLIQUE);
  35.                 break;
  36.  
  37.         default:
  38.                 error = CSS_BADPARM;
  39.                 break;
  40.         }
  41.         if (error != CSS_OK)
  42.                 return error;
  43.  
  44.         /* variant */
  45.         switch (system_font->variant) {
  46.         case CSS_FONT_VARIANT_NORMAL:
  47.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_VARIANT, 0, FONT_VARIANT_NORMAL);
  48.                 break;
  49.  
  50.         case CSS_FONT_VARIANT_SMALL_CAPS:
  51.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_VARIANT, 0, FONT_VARIANT_SMALL_CAPS);
  52.                 break;
  53.  
  54.         default:
  55.                 error = CSS_BADPARM;
  56.                 break;
  57.         }
  58.         if (error != CSS_OK)
  59.                 return error;          
  60.  
  61.         /* weight */
  62.         switch(system_font->weight) {
  63.         case CSS_FONT_WEIGHT_NORMAL:
  64.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_NORMAL);
  65.                 break;
  66.  
  67.         case CSS_FONT_WEIGHT_BOLD:
  68.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_BOLD);
  69.                 break;
  70.  
  71.         case CSS_FONT_WEIGHT_BOLDER:
  72.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_BOLDER);
  73.                 break;
  74.  
  75.         case CSS_FONT_WEIGHT_LIGHTER:
  76.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_LIGHTER);
  77.                 break;
  78.  
  79.         case CSS_FONT_WEIGHT_100:
  80.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_100);
  81.                 break;
  82.  
  83.         case CSS_FONT_WEIGHT_200:
  84.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_200);
  85.                 break;
  86.  
  87.         case CSS_FONT_WEIGHT_300:
  88.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_300);
  89.                 break;
  90.  
  91.         case CSS_FONT_WEIGHT_400:
  92.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_400);
  93.                 break;
  94.  
  95.         case CSS_FONT_WEIGHT_500:
  96.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_500);
  97.                 break;
  98.  
  99.         case CSS_FONT_WEIGHT_600:
  100.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_600);
  101.                 break;
  102.  
  103.         case CSS_FONT_WEIGHT_700:
  104.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_700);
  105.                 break;
  106.  
  107.         case CSS_FONT_WEIGHT_800:
  108.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_800);
  109.                 break;
  110.  
  111.         case CSS_FONT_WEIGHT_900:
  112.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_900);
  113.                 break;
  114.  
  115.         default:
  116.                 error = CSS_BADPARM;
  117.                 break;
  118.         }
  119.         if (error != CSS_OK)
  120.                 return error;
  121.  
  122.         /* size */
  123.         error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_SIZE, 0,  FONT_SIZE_DIMENSION);
  124.         if (error != CSS_OK)
  125.                 return error;
  126.  
  127.         error = css__stylesheet_style_vappend(result, 2, system_font->size.size, system_font->size.unit);
  128.         if (error != CSS_OK)
  129.                 return error;
  130.  
  131.         /* line height */
  132.         error = css__stylesheet_style_appendOPV(result, CSS_PROP_LINE_HEIGHT, 0, LINE_HEIGHT_DIMENSION);
  133.         if (error != CSS_OK)
  134.                 return error;
  135.  
  136.         error = css__stylesheet_style_vappend(result, 2, system_font->line_height.size, system_font->line_height.unit);
  137.         if (error != CSS_OK)
  138.                 return error;
  139.  
  140.         /* font family */
  141.         if ((lwc_string_caseless_isequal(system_font->family, c->strings[SERIF], &match) == lwc_error_ok && match))
  142.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_SERIF);
  143.         else if ((lwc_string_caseless_isequal(system_font->family, c->strings[SANS_SERIF], &match) == lwc_error_ok && match))
  144.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_SANS_SERIF);
  145.         else if ((lwc_string_caseless_isequal(system_font->family, c->strings[CURSIVE], &match) == lwc_error_ok && match))
  146.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_CURSIVE);
  147.         else if ((lwc_string_caseless_isequal(system_font->family, c->strings[FANTASY], &match) == lwc_error_ok && match))
  148.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_FANTASY);
  149.         else if ((lwc_string_caseless_isequal(system_font->family, c->strings[MONOSPACE], &match) == lwc_error_ok && match))
  150.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_MONOSPACE);
  151.         else {
  152.                 uint32_t snumber;
  153.  
  154.                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(system_font->family), &snumber);
  155.                 if (error != CSS_OK)
  156.                         return error;
  157.  
  158.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_STRING);
  159.                 if (error != CSS_OK)
  160.                         return error;
  161.  
  162.                 error = css__stylesheet_style_append(result, snumber);
  163.                 if (error != CSS_OK)
  164.                         return error;
  165.         }
  166.         error = css__stylesheet_style_append(result, FONT_FAMILY_END);
  167.  
  168.         return error;
  169. }
  170.  
  171. /**
  172.  * Parse font
  173.  *
  174.  * \param c       Parsing context
  175.  * \param vector  Vector of tokens to process
  176.  * \param ctx     Pointer to vector iteration context
  177.  * \param result  Pointer to location to receive resulting style
  178.  * \return CSS_OK on success,
  179.  *         CSS_NOMEM on memory exhaustion,
  180.  *         CSS_INVALID if the input is not valid
  181.  *
  182.  * Post condition: \a *ctx is updated with the next token to process
  183.  *                 If the input is invalid, then \a *ctx remains unchanged.
  184.  */
  185. css_error css__parse_font(css_language *c,
  186.                 const parserutils_vector *vector, int *ctx,
  187.                 css_style *result)
  188. {
  189.         const css_token *token;
  190.         css_error error;
  191.         int orig_ctx = *ctx;
  192.         int prev_ctx;
  193.         css_system_font system_font;
  194.  
  195.         bool style = true;
  196.         bool variant = true;
  197.         bool weight = true;
  198.         bool line_height = true;
  199.         css_style *style_style;
  200.         css_style *variant_style;
  201.         css_style *weight_style;
  202.         css_style *size_style;
  203.         css_style *line_height_style;
  204.         css_style *family_style;
  205.         int svw;
  206.  
  207.         /* Firstly, handle inherit */
  208.         token = parserutils_vector_peek(vector, *ctx);
  209.         if (token == NULL)
  210.                 return CSS_INVALID;
  211.                
  212.         if (is_css_inherit(c, token)) {
  213.                 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_STYLE);
  214.                 if (error != CSS_OK)
  215.                         return error;
  216.  
  217.                 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_VARIANT);
  218.                 if (error != CSS_OK)
  219.                         return error;          
  220.  
  221.                 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_WEIGHT);
  222.                 if (error != CSS_OK)
  223.                         return error;
  224.  
  225.                 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_SIZE);
  226.                 if (error != CSS_OK)
  227.                         return error;
  228.  
  229.                 error = css_stylesheet_style_inherit(result, CSS_PROP_LINE_HEIGHT);
  230.                 if (error != CSS_OK)
  231.                         return error;
  232.  
  233.                 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_FAMILY);
  234.                 if (error == CSS_OK)
  235.                         parserutils_vector_iterate(vector, ctx);
  236.  
  237.                 return error;
  238.         }
  239.  
  240.         /* Perhaps an unknown font name; ask the client */
  241.         if ((token->type == CSS_TOKEN_IDENT) &&
  242.             (c->sheet->font != NULL) &&
  243.             (c->sheet->font(c->sheet->font_pw,
  244.                             token->idata,
  245.                             &system_font) == CSS_OK)) {
  246.                
  247.                 error = parse_system_font(c, result, &system_font);
  248.  
  249.                 if (error == CSS_OK)
  250.                         parserutils_vector_iterate(vector, ctx);
  251.  
  252.                 return error;
  253.         }
  254.  
  255.  
  256.         /* allocate styles */
  257.         error = css__stylesheet_style_create(c->sheet, &style_style);
  258.         if (error != CSS_OK)
  259.                 return error;
  260.  
  261.         error = css__stylesheet_style_create(c->sheet, &variant_style);
  262.         if (error != CSS_OK) {
  263.                 css__stylesheet_style_destroy(style_style);
  264.                 return error;
  265.         }
  266.  
  267.         error = css__stylesheet_style_create(c->sheet, &weight_style);
  268.         if (error != CSS_OK) {
  269.                 css__stylesheet_style_destroy(style_style);
  270.                 css__stylesheet_style_destroy(variant_style);
  271.                 return error;
  272.         }
  273.  
  274.         error = css__stylesheet_style_create(c->sheet, &size_style);
  275.         if (error != CSS_OK) {
  276.                 css__stylesheet_style_destroy(style_style);
  277.                 css__stylesheet_style_destroy(variant_style);
  278.                 css__stylesheet_style_destroy(weight_style);
  279.                 return error;
  280.         }
  281.  
  282.         error = css__stylesheet_style_create(c->sheet, &line_height_style);
  283.         if (error != CSS_OK) {
  284.                 css__stylesheet_style_destroy(style_style);
  285.                 css__stylesheet_style_destroy(variant_style);
  286.                 css__stylesheet_style_destroy(weight_style);
  287.                 css__stylesheet_style_destroy(size_style);
  288.                 return error;
  289.         }
  290.  
  291.         error = css__stylesheet_style_create(c->sheet, &family_style);
  292.         if (error != CSS_OK) {
  293.                 css__stylesheet_style_destroy(style_style);
  294.                 css__stylesheet_style_destroy(variant_style);
  295.                 css__stylesheet_style_destroy(weight_style);
  296.                 css__stylesheet_style_destroy(size_style);
  297.                 css__stylesheet_style_destroy(line_height_style);
  298.                 return error;
  299.         }
  300.  
  301.  
  302.         /* Attempt to parse the optional style, variant, and weight */
  303.         for (svw = 0; svw < 3; svw++) {
  304.                 prev_ctx = *ctx;
  305.                 error = CSS_OK;
  306.  
  307.                 /* Ensure that we're not about to parse another inherit */
  308.                 token = parserutils_vector_peek(vector, *ctx);
  309.                 if ((token != NULL) && is_css_inherit(c, token)) {
  310.                         error = CSS_INVALID;
  311.                         goto css__parse_font_cleanup;
  312.                 }
  313.  
  314.                 if ((style) &&
  315.                     (error = css__parse_font_style(c, vector,
  316.                                         ctx, style_style)) == CSS_OK) {
  317.                         style = false;
  318.                 } else if ((variant) &&
  319.                            (error = css__parse_font_variant(c, vector, ctx,
  320.                                         variant_style)) == CSS_OK) {
  321.                         variant = false;
  322.                 } else if ((weight) &&
  323.                            (error = css__parse_font_weight(c, vector, ctx,
  324.                                 weight_style)) == CSS_OK) {
  325.                         weight = false;
  326.                 }
  327.  
  328.                 if (error == CSS_OK) {
  329.                         consumeWhitespace(vector, ctx);
  330.                 } else {
  331.                         break;
  332.                 }
  333.  
  334.                 if (*ctx == prev_ctx)
  335.                         break;
  336.         }
  337.  
  338.         consumeWhitespace(vector, ctx);
  339.  
  340.         /* Ensure that we're not about to parse another inherit */
  341.         token = parserutils_vector_peek(vector, *ctx);
  342.         if ((token != NULL) && is_css_inherit(c, token)) {
  343.                 error = CSS_INVALID;
  344.                 goto css__parse_font_cleanup;
  345.         }
  346.  
  347.         /* Now expect a font-size */
  348.         error = css__parse_font_size(c, vector, ctx, size_style);
  349.         if (error != CSS_OK)
  350.                 goto css__parse_font_cleanup;
  351.  
  352.         consumeWhitespace(vector, ctx);
  353.  
  354.         /* Potential line-height */
  355.         token = parserutils_vector_peek(vector, *ctx);
  356.         if ((token != NULL) && tokenIsChar(token, '/')) {
  357.                 parserutils_vector_iterate(vector, ctx);
  358.  
  359.                 consumeWhitespace(vector, ctx);
  360.  
  361.                 /* Ensure that we're not about to parse another inherit */
  362.                 token = parserutils_vector_peek(vector, *ctx);
  363.                 if ((token != NULL) && is_css_inherit(c, token)) {
  364.                         error = CSS_INVALID;
  365.                         goto css__parse_font_cleanup;
  366.                 }
  367.  
  368.                 error = css__parse_line_height(c, vector, ctx, line_height_style);
  369.                 if (error != CSS_OK)
  370.                         goto css__parse_font_cleanup;
  371.  
  372.                 line_height = false;
  373.         }
  374.  
  375.         consumeWhitespace(vector, ctx);
  376.  
  377.         /* Ensure that we're not about to parse another inherit */
  378.         token = parserutils_vector_peek(vector, *ctx);
  379.         if ((token != NULL) && is_css_inherit(c, token)) {
  380.                 error = CSS_INVALID;
  381.                 goto css__parse_font_cleanup;
  382.         }
  383.  
  384.         /* Now expect a font-family */
  385.         error = css__parse_font_family(c, vector, ctx, family_style);
  386.         if (error != CSS_OK)
  387.                 goto css__parse_font_cleanup;
  388.  
  389.         /* defaults */
  390.         if (style) {
  391.                 error = css__stylesheet_style_appendOPV(style_style,
  392.                                 CSS_PROP_FONT_STYLE, 0,
  393.                                 FONT_STYLE_NORMAL);
  394.                 if (error != CSS_OK)
  395.                         goto css__parse_font_cleanup;
  396.         }
  397.  
  398.         if (variant) {
  399.                 error = css__stylesheet_style_appendOPV(variant_style,
  400.                                 CSS_PROP_FONT_VARIANT, 0,
  401.                                 FONT_VARIANT_NORMAL);
  402.                 if (error != CSS_OK)
  403.                         goto css__parse_font_cleanup;
  404.         }
  405.  
  406.         if (weight) {
  407.                 error = css__stylesheet_style_appendOPV(weight_style,
  408.                                 CSS_PROP_FONT_WEIGHT,
  409.                                 0, FONT_WEIGHT_NORMAL);
  410.                 if (error != CSS_OK)
  411.                         goto css__parse_font_cleanup;
  412.         }
  413.  
  414.         if (line_height) {
  415.                 error = css__stylesheet_style_appendOPV(line_height_style,
  416.                                 CSS_PROP_LINE_HEIGHT,
  417.                                 0, LINE_HEIGHT_NORMAL);
  418.                 if (error != CSS_OK)
  419.                         goto css__parse_font_cleanup;
  420.         }
  421.  
  422.         /* merge final output */
  423.         error = css__stylesheet_merge_style(result, style_style);
  424.                 if (error != CSS_OK)
  425.                         goto css__parse_font_cleanup;
  426.  
  427.         error = css__stylesheet_merge_style(result, variant_style);
  428.                 if (error != CSS_OK)
  429.                         goto css__parse_font_cleanup;
  430.  
  431.         error = css__stylesheet_merge_style(result, weight_style);
  432.                 if (error != CSS_OK)
  433.                         goto css__parse_font_cleanup;
  434.  
  435.         error = css__stylesheet_merge_style(result, size_style);
  436.                 if (error != CSS_OK)
  437.                         goto css__parse_font_cleanup;
  438.  
  439.         error = css__stylesheet_merge_style(result, line_height_style);
  440.                 if (error != CSS_OK)
  441.                         goto css__parse_font_cleanup;
  442.  
  443.         error = css__stylesheet_merge_style(result, family_style);
  444.  
  445.  
  446.  
  447. css__parse_font_cleanup:
  448.         css__stylesheet_style_destroy(style_style);
  449.         css__stylesheet_style_destroy(variant_style);
  450.         css__stylesheet_style_destroy(weight_style);
  451.         css__stylesheet_style_destroy(size_style);
  452.         css__stylesheet_style_destroy(line_height_style);
  453.         css__stylesheet_style_destroy(family_style);
  454.  
  455.         if (error != CSS_OK)
  456.                 *ctx = orig_ctx;
  457.  
  458.         return error;
  459. }
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.