Exemple #1
0
	void PaddingLTRBPropertyParser::parse(StylePropertySetter *setter, const std::string &name, StyleParser &parser)
	{
		auto &tokens = parser.tokens;

		StyleSetValue width = StyleSetValue::from_length(0.0f);

		size_t pos = 0;
		StyleToken token = next_token(pos, tokens);
		if (token.type == StyleTokenType::ident && pos == tokens.size())
		{
			if (equals(token.value, "inherit"))
				width = StyleSetValue::from_keyword("inherit");
			else
				return;
		}
		else if (is_length(token) && pos == tokens.size())
		{
			if (!parse_length(token, width))
			{
				return;
			}
		}
		else if (token.type == StyleTokenType::percentage && pos == tokens.size())
		{
			width = StyleSetValue::from_percentage(StringHelp::text_to_float(token.value));
		}
		else if (token.type == StyleTokenType::delim && token.value == "-")
		{
			token = next_token(pos, tokens);
			if (is_length(token) && pos == tokens.size())
			{
				StyleSetValue length;
				if (parse_length(token, length))
				{
					length.number = -length.number;
					width = length;
				}
				else
				{
					return;
				}
			}
			else if (token.type == StyleTokenType::percentage && pos == tokens.size())
			{
				width = StyleSetValue::from_percentage(-StringHelp::text_to_float(token.value));
			}
			else
			{
				return;
			}
		}
		else
		{
			return;
		}

		setter->set_value(name, width);
	}
tree
evaluate_unequal (tree t) {
  if (N(t)!=2) return evaluate_error ("bad unequal");
  tree t1= evaluate (t[0]);
  tree t2= evaluate (t[1]);
  if (is_atomic (t1) && is_atomic (t2) &&
      is_length (t1->label) && is_length (t2->label))
    return as_string_bool (as_length (t1) != as_length (t2));
  return as_string_bool (t1 != t2);
}
void CL_CSSParserBorderSpacing::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens, std::map<CL_String, CL_CSSBoxProperty *> *out_change_set)
{
	CL_CSSBoxLength length1, length2;

	size_t pos = 0;
	CL_CSSToken token = next_token(pos, tokens);
	if (token.type == CL_CSSToken::type_ident && equals(token.value, "inherit") && pos == tokens.size())
	{
		properties.border_spacing.type = CL_CSSBoxBorderSpacing::type_inherit;
		if (out_change_set)
		{
			(*out_change_set)["border-spacing"] = &properties.border_spacing;
		}
		return;
	}
	else if (is_length(token))
	{
		if (!parse_length(token, length1))
		{
			debug_parse_error(name, tokens);
			return;
		}
	}
	else
	{
		debug_parse_error(name, tokens);
		return;
	}

	if (pos != tokens.size())
	{
		token = next_token(pos, tokens);
		if (is_length(token) && pos == tokens.size())
		{
			if (parse_length(token, length2))
			{
				properties.border_spacing.type = CL_CSSBoxBorderSpacing::type_two_lengths;
				properties.border_spacing.length1 = length1;
				properties.border_spacing.length2 = length2;
			}
		}
	}
	else
	{
		properties.border_spacing.type = CL_CSSBoxBorderSpacing::type_one_length;
		properties.border_spacing.length1 = length1;
	}
	if (out_change_set)
	{
		(*out_change_set)["border-spacing"] = &properties.border_spacing;
	}
}
void CL_CSSParserTop::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens, std::map<CL_String, CL_CSSBoxProperty *> *out_change_set)
{
	size_t pos = 0;
	CL_CSSToken token = next_token(pos, tokens);
	if (token.type == CL_CSSToken::type_ident && pos == tokens.size())
	{
		if (equals(token.value, "auto"))
			properties.top.type = CL_CSSBoxTop::type_auto;
		else if (equals(token.value, "inherit"))
			properties.top.type = CL_CSSBoxTop::type_inherit;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CL_CSSBoxLength length;
		if (parse_length(token, length))
		{
			properties.top.type = CL_CSSBoxTop::type_length;
			properties.top.length = length;
		}
	}
	else if (token.type == CL_CSSToken::type_percentage && pos == tokens.size())
	{
		properties.top.type = CL_CSSBoxTop::type_percentage;
		properties.top.percentage = CL_StringHelp::text_to_float(token.value);
	}
	else if (token.type == CL_CSSToken::type_delim && token.value == "-")
	{
		token = next_token(pos, tokens);
		if (is_length(token) && pos == tokens.size())
		{
			CL_CSSBoxLength length;
			if (parse_length(token, length))
			{
				length.value = -length.value;
				properties.top.type = CL_CSSBoxTop::type_length;
				properties.top.length = length;
			}
		}
		else if (token.type == CL_CSSToken::type_percentage && pos == tokens.size())
		{
			properties.top.type = CL_CSSBoxTop::type_percentage;
			properties.top.percentage = -CL_StringHelp::text_to_float(token.value);
		}
	}
	if (out_change_set)
	{
		(*out_change_set)["top"] = &properties.top;
	}
}
tree
evaluate_lesseq (tree t) {
  if (N(t)!=2) return evaluate_error ("bad less or equal");
  tree t1= evaluate (t[0]);
  tree t2= evaluate (t[1]);
  if (is_compound (t1) || is_compound (t2))
    return evaluate_error ("bad less or equal");
  string s1= t1->label;
  string s2= t2->label;
  if (is_double (s1) && (is_double (s2)))
    return as_string_bool (as_double (s1) <= as_double (s2));
  if (is_length (s1) && is_length (s2))
    return as_string_bool (as_length (s1) <= as_length (s2));
  return evaluate_error ("bad less or equal");
}
void CL_CSSParserMinHeight::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens, std::map<CL_String, CL_CSSBoxProperty *> *out_change_set)
{
	size_t pos = 0;
	CL_CSSToken token = next_token(pos, tokens);
	if (token.type == CL_CSSToken::type_ident && pos == tokens.size())
	{
		if (equals(token.value, "inherit"))
			properties.min_height.type = CL_CSSBoxMinHeight::type_inherit;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CL_CSSBoxLength length;
		if (parse_length(token, length))
		{
			properties.min_height.type = CL_CSSBoxMinHeight::type_length;
			properties.min_height.length = length;
		}
	}
	else if (token.type == CL_CSSToken::type_percentage && pos == tokens.size())
	{
		properties.min_height.type = CL_CSSBoxMinHeight::type_percentage;
		properties.min_height.percentage = CL_StringHelp::text_to_float(token.value);
	}
	if (out_change_set)
	{
		(*out_change_set)["min-height"] = &properties.min_height;
	}
}
int				ft_check_param(char *fmt, int i, t_printf *conv)
{
	int		a;

	if (conv->wc_arg == 0)
	{
		a = i;
		i += is_flag(fmt, i, &conv[0]);
		i += is_mfw(fmt, i, &conv[0]);
		i += is_precision(fmt, i, &conv[0]);
		i += is_length(fmt, i, &conv[0]);
		while (fmt[i] == ' ')
			i++;
		i += is_letter(fmt[i], &conv[0]);
		conv->size_param = i - a;
		if (conv->letter == '*')
		{
			conv->prec_err = 0;
			conv->flag_err = 0;
			conv->size_param = ft_get_param(fmt, a, conv) + 1;
			ft_check_letter(fmt, a + conv->size_param - 1, conv);
			if (conv->display_errors == 1 && conv->count_errors++ >= 0)
				ft_error_msg(1, fmt, a, i - a);
		}
	}
	return ((conv->error_letter != NULL
				&& ft_strcmp(conv->error_letter, "eol") == 0) ? 0 : 1);
}
Exemple #8
0
static void copy_files(const char *fname, void *arg)
{
    struct CopyFileArg *cfa = (struct CopyFileArg *)arg;
    OutStream *os = cfa->to_store->new_output(cfa->to_store, fname);
    InStream *is = cfa->from_store->open_input(cfa->from_store, fname);
    int len = (int)is_length(is);
    uchar *buffer = ALLOC_N(uchar, len + 1);

    is_read_bytes(is, buffer, len);
    os_write_bytes(os, buffer, len);

    is_close(is);
    os_close(os);
    free(buffer);
}
Exemple #9
0
	void WidthPropertyParser::parse(StylePropertySetter *setter, const std::string &name, StyleParser &parser)
	{
		auto &tokens = parser.tokens;

		StyleSetValue width;

		size_t pos = 0;
		StyleToken token = next_token(pos, tokens);
		if (token.type == StyleTokenType::ident && pos == tokens.size())
		{
			if (equals(token.value, "auto"))
				width = StyleSetValue::from_keyword("auto");
			else if (equals(token.value, "inherit"))
				width = StyleSetValue::from_keyword("inherit");
			else
				return;
		}
		else if (is_length(token) && pos == tokens.size())
		{
			StyleSetValue length;
			if (parse_length(token, length) && length.number >= 0.0f)
			{
				width = length;
			}
			else
			{
				return;
			}
		}
		else if (token.type == StyleTokenType::percentage && pos == tokens.size())
		{
			float v = Text::parse_float(token.value);
			if (v >= 0.0f)
			{
				width = StyleSetValue::from_percentage(v);
			}
			else
			{
				return;
			}
		}
		else
		{
			return;
		}

		setter->set_value("width", width);
	}
void CSSParserLineHeight::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
    std::unique_ptr<CSSValueLineHeight> line_height(new CSSValueLineHeight());

    size_t pos = 0;
    CSSToken token = next_token(pos, tokens);
    if (token.type == CSSToken::type_ident && pos == tokens.size())
    {
        if (equals(token.value, "normal"))
            line_height->type = CSSValueLineHeight::type_normal;
        else if (equals(token.value, "inherit"))
            line_height->type = CSSValueLineHeight::type_inherit;
        else
            return;
    }
    else if (token.type == CSSToken::type_number && pos == tokens.size())
    {
        line_height->type = CSSValueLineHeight::type_number;
        line_height->number = StringHelp::text_to_float(token.value);
    }
    else if (is_length(token) && pos == tokens.size())
    {
        CSSLength length;
        if (parse_length(token, length))
        {
            line_height->type = CSSValueLineHeight::type_length;
            line_height->length = length;
        }
        else
        {
            return;
        }
    }
    else if (token.type == CSSToken::type_percentage && pos == tokens.size())
    {
        line_height->type = CSSValueLineHeight::type_percentage;
        line_height->percentage = StringHelp::text_to_float(token.value);
    }
    else
    {
        return;
    }

    inout_values.push_back(std::move(line_height));
}
Exemple #11
0
	void FlexBasisPropertyParser::parse(StylePropertySetter *setter, const std::string &name, StyleParser &parser)
	{
		auto &tokens = parser.tokens;

		StyleSetValue flex_basis;

		size_t pos = 0;
		StyleToken token = next_token(pos, tokens);
		if (token.type == StyleTokenType::ident && pos == tokens.size())
		{
			if (equals(token.value, "main-size"))
				flex_basis = StyleSetValue::from_keyword("main-size");
			else if (equals(token.value, "inherit"))
				flex_basis = StyleSetValue::from_keyword("inherit");
			else
				return;
		}
		else if (is_length(token) && pos == tokens.size())
		{
			StyleSetValue length;
			if (parse_length(token, length) && length.number >= 0.0f)
			{
				flex_basis = length;
			}
			else
			{
				return;
			}
		}
		else if (token.type == StyleTokenType::percentage && pos == tokens.size())
		{
			float v = StringHelp::text_to_float(token.value);
			if (v >= 0.0f)
			{
				flex_basis = StyleSetValue::from_percentage(v);
			}
			else
			{
				return;
			}
		}

		setter->set_value("flex-basis", flex_basis);
	}
void CL_CSSParserFontSize::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens)
{
	size_t pos = 0;
	CL_CSSToken token = next_token(pos, tokens);
	if (token.type == CL_CSSToken::type_ident && pos == tokens.size())
	{
		if (token.value == "xx-small")
			properties.font_size.type = CL_CSSBoxFontSize::type_xx_small;
		else if (token.value == "x-small")
			properties.font_size.type = CL_CSSBoxFontSize::type_x_small;
		else if (token.value == "small")
			properties.font_size.type = CL_CSSBoxFontSize::type_small;
		else if (token.value == "medium")
			properties.font_size.type = CL_CSSBoxFontSize::type_medium;
		else if (token.value == "large")
			properties.font_size.type = CL_CSSBoxFontSize::type_large;
		else if (token.value == "x-large")
			properties.font_size.type = CL_CSSBoxFontSize::type_x_large;
		else if (token.value == "xx-large")
			properties.font_size.type = CL_CSSBoxFontSize::type_xx_large;
		else if (token.value == "smaller")
			properties.font_size.type = CL_CSSBoxFontSize::type_smaller;
		else if (token.value == "larger")
			properties.font_size.type = CL_CSSBoxFontSize::type_larger;
		else if (token.value == "inherit")
			properties.font_size.type = CL_CSSBoxFontSize::type_inherit;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CL_CSSBoxLength length;
		if (parse_length(token, length))
		{
			properties.font_size.type = CL_CSSBoxFontSize::type_length;
			properties.font_size.length = length;
		}
	}
	else if (token.type == CL_CSSToken::type_percentage && pos == tokens.size())
	{
		properties.font_size.type = CL_CSSBoxFontSize::type_percentage;
		properties.font_size.percentage = CL_StringHelp::text_to_float(token.value);
	}
}
Exemple #13
0
	void MaxHeightPropertyParser::parse(StylePropertySetter *setter, const std::string &name, StyleParser &parser)
	{
		auto &tokens = parser.tokens;

		StyleSetValue max_height;

		size_t pos = 0;
		StyleToken token = next_token(pos, tokens);
		if (token.type == StyleTokenType::ident && pos == tokens.size())
		{
			if (equals(token.value, "none"))
				max_height = StyleSetValue::from_keyword("none");
			else if (equals(token.value, "inherit"))
				max_height = StyleSetValue::from_keyword("inherit");
			else
				return;
		}
		else if (is_length(token) && pos == tokens.size())
		{
			StyleSetValue length;
			if (parse_length(token, length))
			{
				max_height = length;
			}
			else
			{
				return;
			}
		}
		else if (token.type == StyleTokenType::percentage && pos == tokens.size())
		{
			max_height = StyleSetValue::from_percentage(Text::parse_float(token.value));
		}
		else
		{
			return;
		}

		setter->set_value("max-height", max_height);
	}
void CSSParserOutlineWidth::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueOutlineWidth> outline_width(new CSSValueOutlineWidth());

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);
	if (token.type == CSSToken::type_ident && pos == tokens.size())
	{
		if (equals(token.value, "thin"))
			outline_width->type = CSSValueOutlineWidth::type_thin;
		else if (equals(token.value, "medium"))
			outline_width->type = CSSValueOutlineWidth::type_medium;
		else if (equals(token.value, "thick"))
			outline_width->type = CSSValueOutlineWidth::type_thick;
		else if (equals(token.value, "inherit"))
			outline_width->type = CSSValueOutlineWidth::type_inherit;
		else
			return;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CSSLength length;
		if (parse_length(token, length))
		{
			outline_width->type = CSSValueOutlineWidth::type_length;
			outline_width->length = length;
		}
		else
		{
			return;
		}
	}
	else
	{
		return;
	}

	inout_values.push_back(std::move(outline_width));
}
void CL_CSSParserPaddingLTRB::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens)
{
	CL_CSSBoxPaddingWidth *width = 0;
	if (name == "padding-top")
		width = &properties.padding_width_top;
	else if (name == "padding-right")
		width = &properties.padding_width_right;
	else if (name == "padding-bottom")
		width = &properties.padding_width_bottom;
	else if (name == "padding-left")
		width = &properties.padding_width_left;

	if (width)
	{
		size_t pos = 0;
		CL_CSSToken token = next_token(pos, tokens);
		if (token.type == CL_CSSToken::type_ident && pos == tokens.size())
		{
			if (token.value == "inherit")
				width->type = CL_CSSBoxPaddingWidth::type_inherit;
		}
		else if (is_length(token) && pos == tokens.size())
		{
			CL_CSSBoxLength length;
			if (parse_length(token, length))
			{
				width->type = CL_CSSBoxPaddingWidth::type_length;
				width->length = length;
			}
		}
		else if (token.type == CL_CSSToken::type_percentage && pos == tokens.size())
		{
			width->type = CL_CSSBoxPaddingWidth::type_percentage;
			width->percentage = CL_StringHelp::text_to_float(token.value);
		}
	}
}
Exemple #16
0
static void cw_copy_file(CompoundWriter *cw, CWFileEntry *src, OutStream *os)
{
    off_t start_ptr = os_pos(os);
    off_t end_ptr;
    off_t remainder, length, len;
    uchar buffer[BUFFER_SIZE];

    InStream *is = cw->store->open_input(cw->store, src->name);

    remainder = length = is_length(is);

    while (remainder > 0) {
        len = MIN(remainder, BUFFER_SIZE);
        is_read_bytes(is, buffer, len);
        os_write_bytes(os, buffer, len);
        remainder -= len;
    }

    /* Verify that remainder is 0 */
    if (remainder != 0) {
        RAISE(IO_ERROR, "There seems to be an error in the compound file "
              "should have read to the end but there are <%"F_OFF_T_PFX"d> "
              "bytes left", remainder);
    }

    /* Verify that the output length diff is equal to original file */
    end_ptr = os_pos(os);
    len = end_ptr - start_ptr;
    if (len != length) {
        RAISE(IO_ERROR, "Difference in compound file output file offsets "
              "<%"F_OFF_T_PFX"d> does not match the original file lenght "
              "<%"F_OFF_T_PFX"d>", len, length);
    }

    is_close(is);
}
Exemple #17
0
	bool FlexPropertyParser::parse_basis(StyleSetValue &basis, size_t &parse_pos, const std::vector<StyleToken> &tokens)
	{
		size_t pos = parse_pos;
		StyleToken token = next_token(pos, tokens);

		if (token.type == StyleTokenType::ident)
		{
			if (equals(token.value, "main-size"))
				basis = StyleSetValue::from_keyword("main-size");
			else
				return false;
		}
		else if (is_length(token))
		{
			StyleSetValue length;
			if (parse_length(token, length) && length.number >= 0.0f)
			{
				basis = length;
			}
		}
		else if (token.type == StyleTokenType::percentage)
		{
			float v = StringHelp::text_to_float(token.value);
			if (v >= 0.0f)
			{
				basis = StyleSetValue::from_percentage(v);
			}
		}
		else
		{
			return false;
		}

		parse_pos = pos;
		return true;
	}
void CSSParserBorderImageWidth::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueBorderImageWidth> border_image_width(new CSSValueBorderImageWidth());

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);

	if (token.type == CSSToken::type_ident && pos == tokens.size() && equals(token.value, "inherit"))
	{
		border_image_width->type = CSSValueBorderImageWidth::type_inherit;
		inout_values.push_back(std::move(border_image_width));
	}
	else
	{
		int num_lengths;
		CSSValueBorderImageWidth::ValueType value_types[4];
		CSSLength lengths[4];
		float percentages[4] = { 0, 0, 0, 0 };
		float numbers[4] = { 0, 0, 0, 0 };
		for (num_lengths = 0; num_lengths < 4; num_lengths++)
		{
			if (is_length(token))
			{
				value_types[num_lengths] = CSSValueBorderImageWidth::value_type_length;
				if (!parse_length(token, lengths[num_lengths]))
					return;
			}
			else if (token.type == CSSToken::type_number)
			{
				value_types[num_lengths] = CSSValueBorderImageWidth::value_type_number;
				numbers[num_lengths] = StringHelp::text_to_float(token.value);
			}
			else if (token.type == CSSToken::type_percentage)
			{
				value_types[num_lengths] = CSSValueBorderImageWidth::value_type_percentage;
				percentages[num_lengths] = StringHelp::text_to_float(token.value);
			}
			else if (token.type == CSSToken::type_ident && equals(token.value, "auto"))
			{
				value_types[num_lengths] = CSSValueBorderImageWidth::value_type_auto;
			}
			else
			{
				break;
			}

			token = next_token(pos, tokens);
		}
		if (num_lengths < 1 || pos != tokens.size())
			return;

		border_image_width->type = CSSValueBorderImageWidth::type_values;

		if (num_lengths == 1)
		{
			for (int i = 1; i < 4; i++)
			{
				value_types[i] = value_types[0];
				lengths[i] = lengths[0];
				numbers[i] = numbers[0];
				percentages[i] = percentages[0];
			}
		}
		else if (num_lengths == 2)
		{
			value_types[2] = value_types[0];
			lengths[2] = lengths[0];
			numbers[2] = numbers[0];
			percentages[2] = percentages[0];
			value_types[3] = value_types[1];
			lengths[3] = lengths[1];
			numbers[3] = numbers[1];
			percentages[3] = percentages[1];
		}
		else if (num_lengths == 3)
		{
			value_types[3] = value_types[1];
			lengths[3] = lengths[1];
			numbers[3] = numbers[1];
			percentages[3] = percentages[1];
		}

		border_image_width->value_top = value_types[0];
		border_image_width->value_right = value_types[1];
		border_image_width->value_bottom = value_types[2];
		border_image_width->value_left = value_types[3];
		border_image_width->length_top = lengths[0];
		border_image_width->length_right = lengths[1];
		border_image_width->length_bottom = lengths[2];
		border_image_width->length_left = lengths[3];
		border_image_width->number_top = numbers[0];
		border_image_width->number_right = numbers[1];
		border_image_width->number_bottom = numbers[2];
		border_image_width->number_left = numbers[3];
		border_image_width->percentage_top = percentages[0];
		border_image_width->percentage_right = percentages[1];
		border_image_width->percentage_bottom = percentages[2];
		border_image_width->percentage_left = percentages[3];

		inout_values.push_back(std::move(border_image_width));
	}
}
Exemple #19
0
Store *open_cmpd_store(Store *store, const char *name)
{
    int count, i;
    off_t offset;
    char *fname;
    FileEntry *entry = NULL;
    Store *new_store = NULL;
    CompoundStore *volatile cmpd = NULL;
    InStream *volatile is = NULL;

    TRY
        cmpd = ALLOC_AND_ZERO(CompoundStore);

        cmpd->store       = store;
        cmpd->name        = name;
        cmpd->entries     = h_new_str(&free, &free);
        is = cmpd->stream = store->open_input(store, cmpd->name);

        /* read the directory and init files */
        count = is_read_vint(is);
        entry = NULL;
        for (i = 0; i < count; i++) {
            offset = (off_t)is_read_i64(is);
            fname = is_read_string(is);

            if (entry != NULL) {
                /* set length of the previous entry */
                entry->length = offset - entry->offset;
            }

            entry = ALLOC(FileEntry);
            entry->offset = offset;
            h_set(cmpd->entries, fname, entry);
        }
    XCATCHALL
        if (is) is_close(is);
        if (cmpd->entries) h_destroy(cmpd->entries);
        free(cmpd);
    XENDTRY

    /* set the length of the final entry */
    if (entry != NULL) {
        entry->length = is_length(is) - entry->offset;
    }

    new_store               = store_new();
    new_store->dir.cmpd     = cmpd;
    new_store->touch        = &cmpd_touch;
    new_store->exists       = &cmpd_exists;
    new_store->remove       = &cmpd_remove;
    new_store->rename       = &cmpd_rename;
    new_store->count        = &cmpd_count;
    new_store->clear        = &cmpd_clear;
    new_store->length       = &cmpd_length;
    new_store->each         = &cmpd_each;
    new_store->close_i      = &cmpd_close_i;
    new_store->new_output   = &cmpd_new_output;
    new_store->open_input   = &cmpd_open_input;
    new_store->open_lock_i  = &cmpd_open_lock_i;
    new_store->close_lock_i = &cmpd_close_lock_i;

    return new_store;
}
Exemple #20
0
void CSSParserFont::parse(const std::string &propname, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueFontStyle> style(new CSSValueFontStyle());
	std::unique_ptr<CSSValueFontVariant> variant(new CSSValueFontVariant());
	std::unique_ptr<CSSValueFontWeight> weight(new CSSValueFontWeight());
	std::unique_ptr<CSSValueFontSize> size(new CSSValueFontSize());
	std::unique_ptr<CSSValueLineHeight> line_height(new CSSValueLineHeight());
	std::unique_ptr<CSSValueFontFamily> family(new CSSValueFontFamily());
	style->type = CSSValueFontStyle::type_normal;
	variant->type = CSSValueFontVariant::type_normal;
	weight->type = CSSValueFontWeight::type_normal;
	size->type = CSSValueFontSize::type_medium;
	line_height->type = CSSValueLineHeight::type_normal;
	family->type = CSSValueFontFamily::type_names;
	family->names.push_back(CSSValueFontFamilyName());

	bool font_style_set = false;
	bool font_variant_set = false;
	bool font_weight_set = false;
	int normal_count = 0;
	size_t pos = 0;
	CSSToken token;
	while (pos < tokens.size())
	{
		token = next_token(pos, tokens);
		if (token.type == CSSToken::type_ident)
		{
			if (tokens.size() == 1 &&
				(equals(token.value, "caption") ||
				equals(token.value, "icon") ||
				equals(token.value, "menu") ||
				equals(token.value, "message-box") ||
				equals(token.value, "small-caption") ||
				equals(token.value, "status-bar")))
			{
				inout_values.push_back(std::move(style));
				inout_values.push_back(std::move(variant));
				inout_values.push_back(std::move(weight));
				inout_values.push_back(std::move(size));
				inout_values.push_back(std::move(line_height));
				inout_values.push_back(std::move(family));
				return;
			}
			else if (equals(token.value, "inherit") && tokens.size() == 1)
			{
				style->type = CSSValueFontStyle::type_inherit;
				variant->type = CSSValueFontVariant::type_inherit;
				weight->type = CSSValueFontWeight::type_inherit;
				size->type = CSSValueFontSize::type_inherit;
				line_height->type = CSSValueLineHeight::type_inherit;
				family->type = CSSValueFontFamily::type_inherit;
				
				inout_values.push_back(std::move(style));
				inout_values.push_back(std::move(variant));
				inout_values.push_back(std::move(weight));
				inout_values.push_back(std::move(size));
				inout_values.push_back(std::move(line_height));
				inout_values.push_back(std::move(family));
				return;
			}
			else if (equals(token.value, "normal")) // font-style or font-weight or font-variant
			{
				int allowed = 3;
				if (font_style_set)
					allowed--;
				if (font_weight_set)
					allowed--;
				if (font_variant_set)
					allowed--;
				if (normal_count < allowed)
					normal_count++;
			}
			else if (equals(token.value, "italic") && !font_style_set) // font-style
			{
				font_style_set = true;
				style->type = CSSValueFontStyle::type_italic;
			}
			else if (equals(token.value, "oblique") && !font_style_set) // font-style
			{
				font_style_set = true;
				style->type = CSSValueFontStyle::type_oblique;
			}
			else if (equals(token.value, "small-caps") && !font_variant_set) // font-variant
			{
				font_style_set = true;
				variant->type = CSSValueFontVariant::type_small_caps;
			}
			else if (equals(token.value, "bold") && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_bold;
			}
			else if (equals(token.value, "bolder") && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_bolder;
			}
			else if (equals(token.value, "lighter") && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_lighter;
			}
			else if (token.value == "100" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_100;
			}
			else if (token.value == "200" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_200;
			}
			else if (token.value == "300" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_300;
			}
			else if (token.value == "400" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_400;
			}
			else if (token.value == "500" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_500;
			}
			else if (token.value == "600" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_600;
			}
			else if (token.value == "700" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_700;
			}
			else if (token.value == "800" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_800;
			}
			else if (token.value == "900" && !font_weight_set) // font-weight
			{
				font_weight_set = true;
				weight->type = CSSValueFontWeight::type_900;
			}
			else
			{
				break;
			}
		}
		else
		{
			break;
		}
	}

	if (pos == tokens.size())
	{
		debug_parse_error(propname, tokens);
		return;
	}

	if (token.type == CSSToken::type_ident)
	{
		if (equals(token.value, "xx-small"))
			size->type = CSSValueFontSize::type_xx_small;
		else if (equals(token.value, "x-small"))
			size->type = CSSValueFontSize::type_x_small;
		else if (equals(token.value, "small"))
			size->type = CSSValueFontSize::type_small;
		else if (equals(token.value, "medium"))
			size->type = CSSValueFontSize::type_medium;
		else if (equals(token.value, "large"))
			size->type = CSSValueFontSize::type_large;
		else if (equals(token.value, "x-large"))
			size->type = CSSValueFontSize::type_x_large;
		else if (equals(token.value, "xx-large"))
			size->type = CSSValueFontSize::type_xx_large;
		else if (equals(token.value, "smaller"))
			size->type = CSSValueFontSize::type_smaller;
		else if (equals(token.value, "larger"))
			size->type = CSSValueFontSize::type_larger;
		else if (equals(token.value, "inherit"))
			size->type = CSSValueFontSize::type_inherit;
		else
		{
			debug_parse_error(propname, tokens);
			return;
		}
	}
	else if (is_length(token))
	{
		CSSLength length;
		if (parse_length(token, length))
		{
			size->type = CSSValueFontSize::type_length;
			size->length = length;
		}
		else
		{
			debug_parse_error(propname, tokens);
			return;
		}
	}
	else if (token.type == CSSToken::type_percentage)
	{
		size->type = CSSValueFontSize::type_percentage;
		size->percentage = StringHelp::text_to_float(token.value);
	}
	else
	{
		debug_parse_error(propname, tokens);
		return;
	}

	token = next_token(pos, tokens);
	if (token.type == CSSToken::type_delim && token.value == "/")
	{
		token = next_token(pos, tokens);

		if (token.type == CSSToken::type_ident)
		{
			if (equals(token.value, "normal"))
				line_height->type = CSSValueLineHeight::type_normal;
			else if (equals(token.value, "inherit"))
				line_height->type = CSSValueLineHeight::type_inherit;
			else
			{
				debug_parse_error(propname, tokens);
				return;
			}
		}
		else if (token.type == CSSToken::type_number)
		{
			line_height->type = CSSValueLineHeight::type_number;
			line_height->number = StringHelp::text_to_float(token.value);
		}
		else if (is_length(token))
		{
			CSSLength length;
			if (parse_length(token, length))
			{
				line_height->type = CSSValueLineHeight::type_length;
				line_height->length = length;
			}
			else
			{
				debug_parse_error(propname, tokens);
				return;
			}
		}
		else if (token.type == CSSToken::type_percentage)
		{
			line_height->type = CSSValueLineHeight::type_percentage;
			line_height->percentage = StringHelp::text_to_float(token.value);
		}
		else
		{
			debug_parse_error(propname, tokens);
			return;
		}

		token = next_token(pos, tokens);
	}

	family->names.clear();
	while (true)
	{
		if (token.type == CSSToken::type_ident)
		{
			CSSValueFontFamilyName name;
			if (equals(token.value, "serif"))
			{
				name.type = CSSValueFontFamilyName::type_serif;
			}
			else if (equals(token.value, "sans-serif"))
			{
				name.type = CSSValueFontFamilyName::type_sans_serif;
			}
			else if (equals(token.value, "cursive"))
			{
				name.type = CSSValueFontFamilyName::type_cursive;
			}
			else if (equals(token.value, "fantasy"))
			{
				name.type = CSSValueFontFamilyName::type_fantasy;
			}
			else if (equals(token.value, "monospace"))
			{
				name.type = CSSValueFontFamilyName::type_monospace;
			}
			else if (equals(token.value, "default"))
			{
				// reserved for future use
				return;
			}
			else if (equals(token.value, "initial"))
			{
				// reserved for future use
				return;
			}
			else
			{
				name.type = CSSValueFontFamilyName::type_family_name;
			}

			if (name.type == CSSValueFontFamilyName::type_family_name)
			{
				name.name = token.value;
				while (pos != tokens.size())
				{
					token = tokens[pos++];
					if (token.type == CSSToken::type_whitespace)
					{
						name.name += " ";
					}
					else if (token.type == CSSToken::type_ident)
					{
						name.name += token.value;
					}
					else if (token.type == CSSToken::type_delim && token.value == ",")
					{
						break;
					}
				}
				family->names.push_back(name);
				if (pos == tokens.size())
					break;
				token = next_token(pos, tokens);
			}
			else
			{
				family->names.push_back(name);

				if (pos == tokens.size())
					break;
				token = next_token(pos, tokens);
				if (token.type != CSSToken::type_delim || token.value != ",")
				{
					debug_parse_error(propname, tokens);
					return;
				}
				token = next_token(pos, tokens);
			}
		}
		else if (token.type == CSSToken::type_string)
		{
			CSSValueFontFamilyName name;
			name.type = CSSValueFontFamilyName::type_family_name;
			name.name = token.value;
			family->names.push_back(name);

			if (pos == tokens.size())
				break;
			token = next_token(pos, tokens);
			if (token.type != CSSToken::type_delim || token.value != ",")
			{
				debug_parse_error(propname, tokens);
				return;
			}
			token = next_token(pos, tokens);
		}
		else
		{
			debug_parse_error(propname, tokens);
			return;
		}
	}

	inout_values.push_back(std::move(style));
	inout_values.push_back(std::move(variant));
	inout_values.push_back(std::move(weight));
	inout_values.push_back(std::move(size));
	inout_values.push_back(std::move(line_height));
	inout_values.push_back(std::move(family));
}
void CSSParserPaddingLTRB::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValuePaddingWidth> width(new CSSValuePaddingWidth);
	if (equals(name, "padding-top"))
		width->value_type = CSSValuePaddingWidth::top_value;
	else if (equals(name, "padding-right"))
		width->value_type = CSSValuePaddingWidth::right_value;
	else if (equals(name, "padding-bottom"))
		width->value_type = CSSValuePaddingWidth::bottom_value;
	else if (equals(name, "padding-left"))
		width->value_type = CSSValuePaddingWidth::left_value;

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);
	if (token.type == CSSToken::type_ident && pos == tokens.size())
	{
		if (equals(token.value, "inherit"))
			width->type = CSSValuePaddingWidth::type_inherit;
		else
			return;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CSSLength length;
		if (parse_length(token, length))
		{
			width->type = CSSValuePaddingWidth::type_length;
			width->length = length;
		}
		else
		{
			return;
		}
	}
	else if (token.type == CSSToken::type_percentage && pos == tokens.size())
	{
		width->type = CSSValuePaddingWidth::type_percentage;
		width->percentage = StringHelp::text_to_float(token.value);
	}
	else if (token.type == CSSToken::type_delim && token.value == "-")
	{
		token = next_token(pos, tokens);
		if (is_length(token) && pos == tokens.size())
		{
			CSSLength length;
			if (parse_length(token, length))
			{
				length.value = -length.value;
				width->type = CSSValuePaddingWidth::type_length;
				width->length = length;
			}
			else
			{
				return;
			}
		}
		else if (token.type == CSSToken::type_percentage && pos == tokens.size())
		{
			width->type = CSSValuePaddingWidth::type_percentage;
			width->percentage = -StringHelp::text_to_float(token.value);
		}
		else
		{
			return;
		}
	}
	else
	{
		return;
	}

	inout_values.push_back(std::move(width));
}
void CL_CSSParserBackgroundPosition::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens, std::map<CL_String, CL_CSSBoxProperty *> *out_change_set)
{
	size_t pos = 0;
	CL_CSSToken token = next_token(pos, tokens);

	if (token.type == CL_CSSToken::type_ident && equals(token.value, "inherit") && tokens.size() == 1)
	{
		properties.background_position.type = CL_CSSBoxBackgroundPosition::type_inherit;
		if (out_change_set)
		{
			(*out_change_set)["background-position"] = &properties.background_position;
		}
		return;
	}

	CL_CSSBoxBackgroundPosition position;
	position.type = CL_CSSBoxBackgroundPosition::type_value;
	position.positions.clear();
	bool done = false;
	while (!done)
	{
		CL_CSSBoxBackgroundPosition::Position bg_pos;
		bool x_specified = false;
		bool y_specified = false;
		bool center_specified = false;

		while (true)
		{
			if (token.type == CL_CSSToken::type_ident)
			{
				if (!y_specified && equals(token.value, "top"))
				{
					bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_top;
					y_specified = true;

					if (center_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}
				}
				else if (!y_specified && equals(token.value, "bottom"))
				{
					bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_bottom;
					y_specified = true;

					if (center_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}
				}
				else if (!x_specified && equals(token.value, "left"))
				{
					bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_left;
					x_specified = true;

					if (center_specified)
					{
						bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_center;
						y_specified = true;
						center_specified = false;
					}
				}
				else if (!x_specified && equals(token.value, "right"))
				{
					bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_right;
					x_specified = true;

					if (center_specified)
					{
						bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_center;
						y_specified = true;
						center_specified = false;
					}
				}
				else if (equals(token.value, "center"))
				{
					if (center_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (x_specified && !y_specified)
					{
						bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_center;
						y_specified = true;
					}
					else if (y_specified && !x_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
					}
					else if (!x_specified && !y_specified)
					{
						center_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
			}
			else if (is_length(token))
			{
				CL_CSSBoxLength length;
				if (parse_length(token, length))
				{
					if (center_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (!x_specified && !y_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_length;
						bg_pos.length_x = length;
						x_specified = true;
					}
					else if (x_specified && !y_specified)
					{
						bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_length;
						bg_pos.length_y = length;
						y_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CL_CSSToken::type_percentage)
			{
				if (center_specified)
				{
					bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
					x_specified = true;
					center_specified = false;
				}

				if (!x_specified && !y_specified)
				{
					bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_percentage;
					bg_pos.percentage_x = CL_StringHelp::text_to_float(token.value);
					x_specified = true;
				}
				else if (x_specified && !y_specified)
				{
					bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_percentage;
					bg_pos.percentage_y = CL_StringHelp::text_to_float(token.value);
					y_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CL_CSSToken::type_delim && token.value == "-")
			{
				token = next_token(pos, tokens);
				if (is_length(token))
				{
					CL_CSSBoxLength length;
					if (parse_length(token, length))
					{
						length.value = -length.value;
						if (center_specified)
						{
							bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
							x_specified = true;
							center_specified = false;
						}

						if (!x_specified && !y_specified)
						{
							bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_length;
							bg_pos.length_x = length;
							x_specified = true;
						}
						else if (x_specified && !y_specified)
						{
							bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_length;
							bg_pos.length_y = length;
							y_specified = true;
						}
						else
						{
							debug_parse_error(name, tokens);
							return;
						}
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else if (token.type == CL_CSSToken::type_percentage)
				{
					if (center_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (!x_specified && !y_specified)
					{
						bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_percentage;
						bg_pos.percentage_x = -CL_StringHelp::text_to_float(token.value);
						x_specified = true;
					}
					else if (x_specified && !y_specified)
					{
						bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_percentage;
						bg_pos.percentage_y = -CL_StringHelp::text_to_float(token.value);
						y_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}

			if (pos == tokens.size())
			{
				done = true;
				break;
			}
			else
			{
				token = next_token(pos, tokens);
				if (token.type == CL_CSSToken::type_delim && token.value == ",")
					break;
			}
		}

		if (!x_specified)
			bg_pos.type_x = CL_CSSBoxBackgroundPosition::type1_center;
		else if (!y_specified)
			bg_pos.type_y = CL_CSSBoxBackgroundPosition::type2_center;

		position.positions.push_back(bg_pos);
	}

	properties.background_position = position;
	if (out_change_set)
	{
		(*out_change_set)["background-position"] = &properties.background_position;
	}
}
void CSSParserBackgroundPosition::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueBackgroundPosition> position(new CSSValueBackgroundPosition());

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);

	if (token.type == CSSToken::type_ident && equals(token.value, "inherit") && tokens.size() == 1)
	{
		position->type = CSSValueBackgroundPosition::type_inherit;
		inout_values.push_back(std::move(position));
		return;
	}

	position->type = CSSValueBackgroundPosition::type_value;
	position->positions.clear();
	bool done = false;
	while (!done)
	{
		CSSValueBackgroundPosition::Position bg_pos;
		bool x_specified = false;
		bool y_specified = false;
		bool center_specified = false;

		while (true)
		{
			if (token.type == CSSToken::type_ident)
			{
				if (!y_specified && equals(token.value, "top"))
				{
					bg_pos.type_y = CSSValueBackgroundPosition::type2_top;
					y_specified = true;

					if (center_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}
				}
				else if (!y_specified && equals(token.value, "bottom"))
				{
					bg_pos.type_y = CSSValueBackgroundPosition::type2_bottom;
					y_specified = true;

					if (center_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}
				}
				else if (!x_specified && equals(token.value, "left"))
				{
					bg_pos.type_x = CSSValueBackgroundPosition::type1_left;
					x_specified = true;

					if (center_specified)
					{
						bg_pos.type_y = CSSValueBackgroundPosition::type2_center;
						y_specified = true;
						center_specified = false;
					}
				}
				else if (!x_specified && equals(token.value, "right"))
				{
					bg_pos.type_x = CSSValueBackgroundPosition::type1_right;
					x_specified = true;

					if (center_specified)
					{
						bg_pos.type_y = CSSValueBackgroundPosition::type2_center;
						y_specified = true;
						center_specified = false;
					}
				}
				else if (equals(token.value, "center"))
				{
					if (center_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (x_specified && !y_specified)
					{
						bg_pos.type_y = CSSValueBackgroundPosition::type2_center;
						y_specified = true;
					}
					else if (y_specified && !x_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
					}
					else if (!x_specified && !y_specified)
					{
						center_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
			}
			else if (is_length(token))
			{
				CSSLength length;
				if (parse_length(token, length))
				{
					if (center_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (!x_specified && !y_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_length;
						bg_pos.length_x = length;
						x_specified = true;
					}
					else if (x_specified && !y_specified)
					{
						bg_pos.type_y = CSSValueBackgroundPosition::type2_length;
						bg_pos.length_y = length;
						y_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CSSToken::type_percentage)
			{
				if (center_specified)
				{
					bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
					x_specified = true;
					center_specified = false;
				}

				if (!x_specified && !y_specified)
				{
					bg_pos.type_x = CSSValueBackgroundPosition::type1_percentage;
					bg_pos.percentage_x = StringHelp::text_to_float(token.value);
					x_specified = true;
				}
				else if (x_specified && !y_specified)
				{
					bg_pos.type_y = CSSValueBackgroundPosition::type2_percentage;
					bg_pos.percentage_y = StringHelp::text_to_float(token.value);
					y_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CSSToken::type_delim && token.value == "-")
			{
				token = next_token(pos, tokens);
				if (is_length(token))
				{
					CSSLength length;
					if (parse_length(token, length))
					{
						length.value = -length.value;
						if (center_specified)
						{
							bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
							x_specified = true;
							center_specified = false;
						}

						if (!x_specified && !y_specified)
						{
							bg_pos.type_x = CSSValueBackgroundPosition::type1_length;
							bg_pos.length_x = length;
							x_specified = true;
						}
						else if (x_specified && !y_specified)
						{
							bg_pos.type_y = CSSValueBackgroundPosition::type2_length;
							bg_pos.length_y = length;
							y_specified = true;
						}
						else
						{
							debug_parse_error(name, tokens);
							return;
						}
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else if (token.type == CSSToken::type_percentage)
				{
					if (center_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
						x_specified = true;
						center_specified = false;
					}

					if (!x_specified && !y_specified)
					{
						bg_pos.type_x = CSSValueBackgroundPosition::type1_percentage;
						bg_pos.percentage_x = -StringHelp::text_to_float(token.value);
						x_specified = true;
					}
					else if (x_specified && !y_specified)
					{
						bg_pos.type_y = CSSValueBackgroundPosition::type2_percentage;
						bg_pos.percentage_y = -StringHelp::text_to_float(token.value);
						y_specified = true;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}

			if (pos == tokens.size())
			{
				done = true;
				break;
			}
			else
			{
				token = next_token(pos, tokens);
				if (token.type == CSSToken::type_delim && token.value == ",")
					break;
			}
		}

		if (!x_specified)
			bg_pos.type_x = CSSValueBackgroundPosition::type1_center;
		else if (!y_specified)
			bg_pos.type_y = CSSValueBackgroundPosition::type2_center;

		position->positions.push_back(bg_pos);
	}

	inout_values.push_back(std::move(position));
}
void CSSParserOutline::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueOutlineWidth> outline_width(new CSSValueOutlineWidth());
	std::unique_ptr<CSSValueOutlineStyle> outline_style(new CSSValueOutlineStyle());
	std::unique_ptr<CSSValueOutlineColor> outline_color(new CSSValueOutlineColor());
	bool width_specified = false;
	bool style_specified = false;
	bool color_specified = false;

	size_t pos = 0;
	while (pos != tokens.size())
	{
		Colorf color;
		if (!color_specified && parse_color(tokens, pos, color))
		{
			outline_color->type = CSSValueOutlineColor::type_color;
			outline_color->color = color;
			color_specified = true;
		}
		else
		{
			CSSToken token = next_token(pos, tokens);
			if (token.type == CSSToken::type_ident)
			{
				if (equals(token.value, "inherit") && tokens.size() == 1)
				{
					outline_width->type = CSSValueOutlineWidth::type_inherit;
					outline_style->type = CSSValueOutlineStyle::type_inherit;
					outline_color->type = CSSValueOutlineColor::type_inherit;
					inout_values.push_back(std::move(outline_width));
					inout_values.push_back(std::move(outline_style));
					inout_values.push_back(std::move(outline_color));
					return;
				}
				else if (!width_specified && equals(token.value, "thin"))
				{
					outline_width->type = CSSValueOutlineWidth::type_thin;
					width_specified = true;
				}
				else if (!width_specified && equals(token.value, "medium"))
				{
					outline_width->type = CSSValueOutlineWidth::type_medium;
					width_specified = true;
				}
				else if (!width_specified && equals(token.value, "thick"))
				{
					outline_width->type = CSSValueOutlineWidth::type_thick;
					width_specified = true;
				}
				else if (!style_specified && equals(token.value, "none"))
				{
					outline_style->type = CSSValueOutlineStyle::type_none;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "hidden"))
				{
					outline_style->type = CSSValueOutlineStyle::type_hidden;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "dotted"))
				{
					outline_style->type = CSSValueOutlineStyle::type_dotted;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "dashed"))
				{
					outline_style->type = CSSValueOutlineStyle::type_dashed;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "solid"))
				{
					outline_style->type = CSSValueOutlineStyle::type_solid;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "double"))
				{
					outline_style->type = CSSValueOutlineStyle::type_double;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "groove"))
				{
					outline_style->type = CSSValueOutlineStyle::type_groove;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "ridge"))
				{
					outline_style->type = CSSValueOutlineStyle::type_ridge;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "inset"))
				{
					outline_style->type = CSSValueOutlineStyle::type_inset;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "outset"))
				{
					outline_style->type = CSSValueOutlineStyle::type_outset;
					style_specified = true;
				}
				else if (!color_specified && equals(token.value, "invert"))
				{
					outline_color->type = CSSValueOutlineColor::type_invert;
					color_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (is_length(token))
			{
				CSSLength length;
				if (!width_specified && parse_length(token, length))
				{
					outline_width->type = CSSValueOutlineWidth::type_length;
					outline_width->length = length;
					width_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}
	}

	inout_values.push_back(std::move(outline_width));
	inout_values.push_back(std::move(outline_style));
	inout_values.push_back(std::move(outline_color));
}
Exemple #25
0
	void MarginPropertyParser::parse(StylePropertySetter *setter, const std::string &name, StyleParser &parser)
	{
		auto &tokens = parser.tokens;

		StyleSetValue margin_widths[4];
		int count;
		size_t pos = 0;
		for (count = 0; count < 4; count++)
		{
			StyleToken token = next_token(pos, tokens);
			if (token.type == StyleTokenType::ident && equals(token.value, "auto"))
			{
				margin_widths[count] = StyleSetValue::from_keyword("auto");
			}
			else if (token.type == StyleTokenType::ident && equals(token.value, "inherit") && count == 0 && pos == tokens.size())
			{
				margin_widths[0] = StyleSetValue::from_keyword("inherit");
				setter->set_value("margin-left", margin_widths[0]);
				setter->set_value("margin-top", margin_widths[0]);
				setter->set_value("margin-right", margin_widths[0]);
				setter->set_value("margin-bottom", margin_widths[0]);
				return;
			}
			else if (is_length(token))
			{
				StyleSetValue length;
				if (parse_length(token, length))
				{
					margin_widths[count] = length;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == StyleTokenType::percentage)
			{
				margin_widths[count] = StyleSetValue::from_percentage(StringHelp::text_to_float(token.value));
			}
			else if (token.type == StyleTokenType::delim && token.value == "-")
			{
				token = next_token(pos, tokens);
				if (is_length(token))
				{
					StyleSetValue length;
					if (parse_length(token, length))
					{
						length.number = -length.number;
						margin_widths[count] = length;
					}
					else
					{
						debug_parse_error(name, tokens);
						return;
					}
				}
				else if (token.type == StyleTokenType::percentage)
				{
					margin_widths[count] = StyleSetValue::from_percentage(-StringHelp::text_to_float(token.value));
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == StyleTokenType::null)
			{
				break;
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}

		if (pos == tokens.size())
		{
			switch (count)
			{
			case 1:
				setter->set_value("margin-left", margin_widths[0]);
				setter->set_value("margin-top", margin_widths[0]);
				setter->set_value("margin-right", margin_widths[0]);
				setter->set_value("margin-bottom", margin_widths[0]);
				break;
			case 2:
				setter->set_value("margin-top", margin_widths[0]);
				setter->set_value("margin-bottom", margin_widths[0]);
				setter->set_value("margin-left", margin_widths[1]);
				setter->set_value("margin-right", margin_widths[1]);
				break;
			case 3:
				setter->set_value("margin-top", margin_widths[0]);
				setter->set_value("margin-left", margin_widths[1]);
				setter->set_value("margin-right", margin_widths[1]);
				setter->set_value("margin-bottom", margin_widths[2]);
				break;
			case 4:
				setter->set_value("margin-top", margin_widths[0]);
				setter->set_value("margin-right", margin_widths[1]);
				setter->set_value("margin-bottom", margin_widths[2]);
				setter->set_value("margin-left", margin_widths[3]);
				break;
			default:
				break;
			}
		}
	}
void CSSParserBorderRadius::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	CSSValueBorderRadius radius[4];

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);
	if (token.type == CSSToken::type_ident && equals(token.value, "inherit") && pos == tokens.size())
	{
		radius[0].type = CSSValueBorderRadius::type_inherit;
		inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::top_left_value, radius[0])));
		inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::top_right_value, radius[0])));
		inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::bottom_left_value, radius[0])));
		inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::bottom_right_value, radius[0])));
		return;
	}

	int num_x_values = 0;
	int num_y_values = 0;
	for (int i = 0; i < 4; i++)
	{
		if (is_length(token))
		{
			if (!parse_length(token, radius[i].length1))
			{
				debug_parse_error(name, tokens);
				return;
			}
			radius[i].type = CSSValueBorderRadius::type_one_value;
			radius[i].value_type1 = CSSValueBorderRadius::value_type_length;
		}
		else if (token.type == CSSToken::type_percentage)
		{
			radius[i].type = CSSValueBorderRadius::type_one_value;
			radius[i].value_type1 = CSSValueBorderRadius::value_type_percentage;
			radius[i].percentage1 = StringHelp::text_to_float(token.value);
		}
		else
		{
			debug_parse_error(name, tokens);
			return;
		}

		num_x_values = i+1;

		token = next_token(pos, tokens);
		if (token.type == CSSToken::type_null)
			break;
		else if (i != 0 && token.type == CSSToken::type_delim && token.value == "/")
			break;
	}

	if (token.type == CSSToken::type_delim && token.value == "/")
	{
		token = next_token(pos, tokens);
		for (int i = 0; i < 4; i++)
		{
			if (is_length(token) && parse_length(token, radius[i].length2))
			{
				radius[i].type = CSSValueBorderRadius::type_two_values;
			}
			else if (token.type == CSSToken::type_percentage)
			{
				radius[i].type = CSSValueBorderRadius::type_two_values;
				radius[i].value_type2 = CSSValueBorderRadius::value_type_percentage;
				radius[i].percentage2 = StringHelp::text_to_float(token.value);
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}

			num_y_values = i+1;

			token = next_token(pos, tokens);
			if (token.type == CSSToken::type_null)
				break;
		}
	}
	else if (token.type != CSSToken::type_null)
	{
		debug_parse_error(name, tokens);
		return;
	}

	if (num_y_values > 0)
	{
		if (num_x_values < num_y_values)
		{
			for (int i = num_x_values; i < num_y_values; i++)
			{
				radius[i].type = CSSValueBorderRadius::type_two_values;
				radius[i].value_type1 = radius[i].value_type2;
				radius[i].length1 = radius[i].length2;
				radius[i].percentage1 = radius[i].percentage2;
			}
			num_x_values = num_y_values;
		}
		else if (num_y_values < num_x_values)
		{
			for (int i = num_y_values; i < num_x_values; i++)
			{
				radius[i].type = CSSValueBorderRadius::type_two_values;
				radius[i].value_type2 = radius[i].value_type1;
				radius[i].length2 = radius[i].length1;
				radius[i].percentage2 = radius[i].percentage1;
			}
			num_y_values = num_x_values;
		}
	}

	for (int i = num_x_values; i < 4; i++)
		radius[i] = radius[i-1];

	inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::top_right_value, radius[0])));
	inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::bottom_left_value, radius[1])));
	inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::bottom_right_value, radius[2])));
	inout_values.push_back(std::unique_ptr<CSSValueBorderRadius>(new CSSValueBorderRadius(CSSValueBorderRadius::top_left_value, radius[3])));
}
void CL_CSSParserPadding::parse(CL_CSSBoxProperties &properties, const CL_String &name, const std::vector<CL_CSSToken> &tokens, std::map<CL_String, CL_CSSBoxProperty *> *out_change_set)
{
	CL_CSSBoxPaddingWidth padding_widths[4];
	int count;
	size_t pos = 0;
	for (count = 0; count < 4; count++)
	{
		CL_CSSToken token = next_token(pos, tokens);
		if (token.type == CL_CSSToken::type_ident && equals(token.value, "inherit") && count == 0 && pos == tokens.size())
		{
			properties.padding_width_left.type = CL_CSSBoxPaddingWidth::type_inherit;
			properties.padding_width_top.type = CL_CSSBoxPaddingWidth::type_inherit;
			properties.padding_width_right.type = CL_CSSBoxPaddingWidth::type_inherit;
			properties.padding_width_bottom.type = CL_CSSBoxPaddingWidth::type_inherit;
			return;
		}
		else if (is_length(token))
		{
			CL_CSSBoxLength length;
			if (parse_length(token, length))
			{
				padding_widths[count].type = CL_CSSBoxPaddingWidth::type_length;
				padding_widths[count].length = length;
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}
		else if (token.type == CL_CSSToken::type_percentage)
		{
			padding_widths[count].type = CL_CSSBoxPaddingWidth::type_percentage;
			padding_widths[count].percentage = CL_StringHelp::text_to_float(token.value);
		}
		else if (token.type == CL_CSSToken::type_delim && token.value == "-")
		{
			token = next_token(pos, tokens);
			if (is_length(token))
			{
				CL_CSSBoxLength length;
				if (parse_length(token, length))
				{
					length.value = -length.value;
					padding_widths[count].type = CL_CSSBoxPaddingWidth::type_length;
					padding_widths[count].length = length;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CL_CSSToken::type_percentage)
			{
				padding_widths[count].type = CL_CSSBoxPaddingWidth::type_percentage;
				padding_widths[count].percentage = -CL_StringHelp::text_to_float(token.value);
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}
		else if (token.type == CL_CSSToken::type_null)
		{
			break;
		}
		else
		{
			debug_parse_error(name, tokens);
			return;
		}
	}

	if (pos == tokens.size())
	{
		switch (count)
		{
		case 1:
			properties.padding_width_left = padding_widths[0];
			properties.padding_width_top = padding_widths[0];
			properties.padding_width_right = padding_widths[0];
			properties.padding_width_bottom = padding_widths[0];
			break;
		case 2:
			properties.padding_width_top = padding_widths[0];
			properties.padding_width_bottom = padding_widths[0];
			properties.padding_width_left = padding_widths[1];
			properties.padding_width_right = padding_widths[1];
			break;
		case 3:
			properties.padding_width_top = padding_widths[0];
			properties.padding_width_left = padding_widths[1];
			properties.padding_width_right = padding_widths[1];
			properties.padding_width_bottom = padding_widths[2];
			break;
		case 4:
			properties.padding_width_top = padding_widths[0];
			properties.padding_width_right = padding_widths[1];
			properties.padding_width_bottom = padding_widths[2];
			properties.padding_width_left = padding_widths[3];
			break;
		default:
			break;
		}
	}
	if (out_change_set)
	{
		(*out_change_set)["padding-left"] = &properties.padding_width_left;
		(*out_change_set)["padding-right"] = &properties.padding_width_right;
		(*out_change_set)["padding-top"] = &properties.padding_width_top;
		(*out_change_set)["padding-bottom"] = &properties.padding_width_bottom;
	}
}
void CSSParserBottom::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	std::unique_ptr<CSSValueBottom> bottom(new CSSValueBottom());

	size_t pos = 0;
	CSSToken token = next_token(pos, tokens);
	if (token.type == CSSToken::type_ident && pos == tokens.size())
	{
		if (equals(token.value, "auto"))
			bottom->type = CSSValueBottom::type_auto;
		else if (equals(token.value, "inherit"))
			bottom->type = CSSValueBottom::type_inherit;
		else
			return;
	}
	else if (is_length(token) && pos == tokens.size())
	{
		CSSLength length;
		if (parse_length(token, length))
		{
			bottom->type = CSSValueBottom::type_length;
			bottom->length = length;
		}
		else
		{
			return;
		}
	}
	else if (token.type == CSSToken::type_percentage && pos == tokens.size())
	{
		bottom->type = CSSValueBottom::type_percentage;
		bottom->percentage = StringHelp::text_to_float(token.value);
	}
	else if (token.type == CSSToken::type_delim && token.value == "-")
	{
		token = next_token(pos, tokens);
		if (is_length(token) && pos == tokens.size())
		{
			CSSLength length;
			if (parse_length(token, length))
			{
				length.value = -length.value;
				bottom->type = CSSValueBottom::type_length;
				bottom->length = length;
			}
			else
			{
				return;
			}
		}
		else if (token.type == CSSToken::type_percentage && pos == tokens.size())
		{
			bottom->type = CSSValueBottom::type_percentage;
			bottom->percentage = -StringHelp::text_to_float(token.value);
		}
		else
		{
			return;
		}
	}

	inout_values.push_back(std::move(bottom));
}
void CSSParserBorder::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	CSSValueBorderWidth border_width;
	CSSValueBorderStyle border_style;
	CSSValueBorderColor border_color;
	bool width_specified = false;
	bool style_specified = false;
	bool color_specified = false;

	size_t pos = 0;
	while (pos != tokens.size())
	{
		Colorf color;
		if (!color_specified && parse_color(tokens, pos, color))
		{
			border_color.type = CSSValueBorderColor::type_color;
			border_color.color = color;
			color_specified = true;
		}
		else
		{
			CSSToken token = next_token(pos, tokens);
			if (token.type == CSSToken::type_ident)
			{
				if (equals(token.value, "inherit") && tokens.size() == 1)
				{
					border_width.type = CSSValueBorderWidth::type_inherit;
					border_style.type = CSSValueBorderStyle::type_inherit;
					border_color.type = CSSValueBorderColor::type_inherit;

					inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::left_value, border_width)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::right_value, border_width)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::top_value, border_width)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::bottom_value, border_width)));

					inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::left_value, border_style)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::right_value, border_style)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::top_value, border_style)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::bottom_value, border_style)));

					inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_color)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_color)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_color)));
					inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_color)));

					return;
				}
				else if (!width_specified && equals(token.value, "thin"))
				{
					border_width.type = CSSValueBorderWidth::type_thin;
					width_specified = true;
				}
				else if (!width_specified && equals(token.value, "medium"))
				{
					border_width.type = CSSValueBorderWidth::type_medium;
					width_specified = true;
				}
				else if (!width_specified && equals(token.value, "thick"))
				{
					border_width.type = CSSValueBorderWidth::type_thick;
					width_specified = true;
				}
				else if (!style_specified && equals(token.value, "none"))
				{
					border_style.type = CSSValueBorderStyle::type_none;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "hidden"))
				{
					border_style.type = CSSValueBorderStyle::type_hidden;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "dotted"))
				{
					border_style.type = CSSValueBorderStyle::type_dotted;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "dashed"))
				{
					border_style.type = CSSValueBorderStyle::type_dashed;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "solid"))
				{
					border_style.type = CSSValueBorderStyle::type_solid;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "double"))
				{
					border_style.type = CSSValueBorderStyle::type_double;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "groove"))
				{
					border_style.type = CSSValueBorderStyle::type_groove;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "ridge"))
				{
					border_style.type = CSSValueBorderStyle::type_ridge;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "inset"))
				{
					border_style.type = CSSValueBorderStyle::type_inset;
					style_specified = true;
				}
				else if (!style_specified && equals(token.value, "outset"))
				{
					border_style.type = CSSValueBorderStyle::type_outset;
					style_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (is_length(token))
			{
				CSSLength length;
				if (!width_specified && parse_length(token, length))
				{
					border_width.type = CSSValueBorderWidth::type_length;
					border_width.length = length;
					width_specified = true;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}
	}

	inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::left_value, border_width)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::right_value, border_width)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::top_value, border_width)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderWidth>(new CSSValueBorderWidth(CSSValueBorderWidth::bottom_value, border_width)));

	inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::left_value, border_style)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::right_value, border_style)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::top_value, border_style)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderStyle>(new CSSValueBorderStyle(CSSValueBorderStyle::bottom_value, border_style)));

	inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_color)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_color)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_color)));
	inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_color)));
}
bool CSSParserBorderImage::parse_outset(CSSValueBorderImageOutset &border_image_outset, size_t &parse_pos, const std::vector<CSSToken> &tokens)
{
    size_t pos = parse_pos;
    size_t last_pos = pos;
    CSSToken token = next_token(pos, tokens);

    int num_lengths;
    CSSValueBorderImageOutset::ValueType value_types[4];
    CSSLength lengths[4];
    float numbers[4] = { 0, 0, 0, 0 };
    for (num_lengths = 0; num_lengths < 4; num_lengths++)
    {
        if (is_length(token))
        {
            value_types[num_lengths] = CSSValueBorderImageOutset::value_type_length;
            if (!parse_length(token, lengths[num_lengths]))
                return false;
        }
        else if (token.type == CSSToken::type_number)
        {
            value_types[num_lengths] = CSSValueBorderImageOutset::value_type_number;
            numbers[num_lengths] = StringHelp::text_to_float(token.value);
        }
        else
        {
            break;
        }

        last_pos = pos;
        token = next_token(pos, tokens);
    }
    if (num_lengths < 1)
        return false;

    pos = last_pos;

    border_image_outset.type = CSSValueBorderImageOutset::type_values;
    if (num_lengths == 1)
    {
        for (int i = 1; i < 4; i++)
        {
            value_types[i] = value_types[0];
            lengths[i] = lengths[0];
            numbers[i] = numbers[0];
        }
    }
    else if (num_lengths == 2)
    {
        value_types[2] = value_types[0];
        lengths[2] = lengths[0];
        numbers[2] = numbers[0];
        value_types[3] = value_types[1];
        lengths[3] = lengths[1];
        numbers[3] = numbers[1];
    }
    else if (num_lengths == 3)
    {
        value_types[3] = value_types[1];
        lengths[3] = lengths[1];
        numbers[3] = numbers[1];
    }

    border_image_outset.value_top = value_types[0];
    border_image_outset.value_right = value_types[1];
    border_image_outset.value_bottom = value_types[2];
    border_image_outset.value_left = value_types[3];
    border_image_outset.length_top = lengths[0];
    border_image_outset.length_right = lengths[1];
    border_image_outset.length_bottom = lengths[2];
    border_image_outset.length_left = lengths[3];
    border_image_outset.number_top = numbers[0];
    border_image_outset.number_right = numbers[1];
    border_image_outset.number_bottom = numbers[2];
    border_image_outset.number_left = numbers[3];

    parse_pos = pos;

    return true;
}