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_CSSParserTextDecoration::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, "none"))
		{
			properties.text_decoration.type = CL_CSSBoxTextDecoration::type_none;
		}
		else if (equals(token.value, "inherit"))
		{
			properties.text_decoration.type = CL_CSSBoxTextDecoration::type_inherit;
		}
		else
		{
			int underline = 0;
			int overline = 0;
			int line_through = 0;
			int blink = 0;
			do
			{
				if (token.type == CL_CSSToken::type_ident)
				{
					if (equals(token.value, "underline"))
						underline++;
					else if (equals(token.value, "overline"))
						overline++;
					else if (equals(token.value, "line-through"))
						line_through++;
					else if (equals(token.value, "blink"))
						blink++;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}

				token = next_token(pos, tokens);
			} while (token.type != CL_CSSToken::type_null);

			if (underline < 2 && overline < 2 && line_through < 2 && blink < 2)
			{
				properties.text_decoration.type = CL_CSSBoxTextDecoration::type_values;
				properties.text_decoration.underline = (underline == 1);
				properties.text_decoration.overline = (overline == 1);
				properties.text_decoration.line_through = (line_through == 1);
				properties.text_decoration.blink = (blink == 1);
			}
		}
	}
	if (out_change_set)
	{
		(*out_change_set)["text-decoration"] = &properties.text_decoration;
	}
}
Beispiel #3
0
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)));
}
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;
	}
}
Beispiel #5
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 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));
}
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;
	}
}
Beispiel #9
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 CSSParserBorderColor::parse(const std::string &name, const std::vector<CSSToken> &tokens, std::vector<std::unique_ptr<CSSPropertyValue> > &inout_values)
{
	CSSValueBorderColor border_colors[4];
	int count;
	size_t pos = 0;
	for (count = 0; count < 4; count++)
	{
		Colorf color;
		if (parse_color(tokens, pos, color))
		{
			border_colors[count].type = CSSValueBorderColor::type_color;
			border_colors[count].color = color;
		}
		else
		{
			CSSToken token = next_token(pos, tokens);
			if (token.type == CSSToken::type_ident)
			{
				if (equals(token.value, "inherit"))
				{
					if (count == 0 && pos == tokens.size())
					{
						border_colors[0].type = CSSValueBorderColor::type_inherit;

						inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_colors[0])));
						inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_colors[0])));
						inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_colors[0])));
						inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_colors[0])));
					}
					else
					{
						debug_parse_error(name, tokens);
					}
					return;
				}
				else
				{
					debug_parse_error(name, tokens);
					return;
				}
			}
			else if (token.type == CSSToken::type_null)
			{
				break;
			}
			else
			{
				debug_parse_error(name, tokens);
				return;
			}
		}
	}

	if (pos == tokens.size())
	{
		switch (count)
		{
		case 1:
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_colors[0])));
			break;
		case 2:
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_colors[1])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_colors[1])));
			break;
		case 3:
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_colors[1])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_colors[1])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_colors[2])));
			break;
		case 4:
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::top_value, border_colors[0])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::right_value, border_colors[1])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::left_value, border_colors[2])));
			inout_values.push_back(std::unique_ptr<CSSValueBorderColor>(new CSSValueBorderColor(CSSValueBorderColor::bottom_value, border_colors[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])));
}