StyleSheetSpecification.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * This source file is part of libRocket, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://www.librocket.com
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. #include "precompiled.h"
  28. #include "../../Include/Rocket/Core/StyleSheetSpecification.h"
  29. #include "PropertyParserNumber.h"
  30. #include "PropertyParserAnimation.h"
  31. #include "PropertyParserColour.h"
  32. #include "PropertyParserKeyword.h"
  33. #include "PropertyParserString.h"
  34. #include "PropertyParserTransform.h"
  35. namespace Rocket {
  36. namespace Core {
  37. static StyleSheetSpecification* instance = NULL;
  38. StyleSheetSpecification::StyleSheetSpecification()
  39. {
  40. ROCKET_ASSERT(instance == NULL);
  41. instance = this;
  42. }
  43. StyleSheetSpecification::~StyleSheetSpecification()
  44. {
  45. ROCKET_ASSERT(instance == this);
  46. instance = NULL;
  47. }
  48. bool StyleSheetSpecification::Initialise()
  49. {
  50. if (instance == NULL)
  51. {
  52. new StyleSheetSpecification();
  53. instance->RegisterDefaultParsers();
  54. instance->RegisterDefaultProperties();
  55. }
  56. return true;
  57. }
  58. void StyleSheetSpecification::Shutdown()
  59. {
  60. if (instance != NULL)
  61. {
  62. for (ParserMap::iterator iterator = instance->parsers.begin(); iterator != instance->parsers.end(); ++iterator)
  63. (*iterator).second->Release();
  64. delete instance;
  65. }
  66. }
  67. // Registers a parser for use in property definitions.
  68. bool StyleSheetSpecification::RegisterParser(const String& parser_name, PropertyParser* parser)
  69. {
  70. ParserMap::iterator iterator = instance->parsers.find(parser_name);
  71. if (iterator != instance->parsers.end())
  72. (*iterator).second->Release();
  73. instance->parsers[parser_name] = parser;
  74. return true;
  75. }
  76. // Returns the parser registered with a specific name.
  77. PropertyParser* StyleSheetSpecification::GetParser(const String& parser_name)
  78. {
  79. ParserMap::iterator iterator = instance->parsers.find(parser_name);
  80. if (iterator == instance->parsers.end())
  81. return NULL;
  82. return (*iterator).second;
  83. }
  84. // Registers a property with a new definition.
  85. PropertyDefinition& StyleSheetSpecification::RegisterProperty(PropertyId property_id, const String& default_value, bool inherited, bool forces_layout)
  86. {
  87. return instance->properties.RegisterProperty(property_id, default_value, inherited, forces_layout);
  88. }
  89. // Returns a property definition.
  90. const PropertyDefinition* StyleSheetSpecification::GetProperty(PropertyId id)
  91. {
  92. return instance->properties.GetProperty(id);
  93. }
  94. // Fetches a list of the names of all registered property definitions.
  95. const PropertyIdList& StyleSheetSpecification::GetRegisteredProperties()
  96. {
  97. return instance->properties.GetRegisteredProperties();
  98. }
  99. const PropertyIdList & StyleSheetSpecification::GetRegisteredInheritedProperties()
  100. {
  101. return instance->properties.GetRegisteredInheritedProperties();
  102. }
  103. // Registers a shorthand property definition.
  104. bool StyleSheetSpecification::RegisterShorthand(PropertyId shorthand_id, const PropertyIdList& property_ids, PropertySpecification::ShorthandType type)
  105. {
  106. return instance->properties.RegisterShorthand(shorthand_id, property_ids, type);
  107. }
  108. // Returns a shorthand definition.
  109. const PropertyShorthandDefinition* StyleSheetSpecification::GetShorthand(PropertyId id)
  110. {
  111. return instance->properties.GetShorthand(id);
  112. }
  113. // Parses a property declaration, setting any parsed and validated properties on the given dictionary.
  114. bool StyleSheetSpecification::ParsePropertyDeclaration(PropertyDictionary& dictionary, PropertyId property_id, const String& property_value, const String& source_file, int source_line_number)
  115. {
  116. return instance->properties.ParsePropertyDeclaration(dictionary, property_id, property_value, source_file, source_line_number);
  117. }
  118. // Registers Rocket's default parsers.
  119. void StyleSheetSpecification::RegisterDefaultParsers()
  120. {
  121. RegisterParser("number", new PropertyParserNumber(Property::NUMBER));
  122. RegisterParser("length", new PropertyParserNumber(Property::LENGTH, Property::PX));
  123. RegisterParser("length_percent", new PropertyParserNumber(Property::LENGTH_PERCENT, Property::PX));
  124. RegisterParser("number_length_percent", new PropertyParserNumber(Property::NUMBER_LENGTH_PERCENT, Property::PX));
  125. RegisterParser("angle", new PropertyParserNumber(Property::ANGLE, Property::RAD));
  126. RegisterParser("keyword", new PropertyParserKeyword());
  127. RegisterParser("string", new PropertyParserString());
  128. RegisterParser("animation", new PropertyParserAnimation(PropertyParserAnimation::ANIMATION_PARSER));
  129. RegisterParser("transition", new PropertyParserAnimation(PropertyParserAnimation::TRANSITION_PARSER));
  130. RegisterParser("color", new PropertyParserColour());
  131. RegisterParser("transform", new PropertyParserTransform());
  132. }
  133. // Registers Rocket's default style properties.
  134. void StyleSheetSpecification::RegisterDefaultProperties()
  135. {
  136. // Style property specifications (ala RCSS).
  137. using Id = PropertyId;
  138. RegisterProperty(Id::MarginTop, "0px", false, true)
  139. .AddParser("keyword", "auto")
  140. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  141. RegisterProperty(Id::MarginRight, "0px", false, true)
  142. .AddParser("keyword", "auto")
  143. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  144. RegisterProperty(Id::MarginBottom, "0px", false, true)
  145. .AddParser("keyword", "auto")
  146. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  147. RegisterProperty(Id::MarginLeft, "0px", false, true)
  148. .AddParser("keyword", "auto")
  149. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  150. RegisterShorthand(Id::Margin, { Id::MarginTop, Id::MarginRight, Id::MarginBottom, Id::MarginLeft });
  151. RegisterProperty(Id::PaddingTop, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  152. RegisterProperty(Id::PaddingRight, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  153. RegisterProperty(Id::PaddingBottom, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  154. RegisterProperty(Id::PaddingLeft, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  155. RegisterShorthand(Id::Padding, { Id::PaddingTop, Id::PaddingRight, Id::PaddingBottom, Id::PaddingLeft });
  156. RegisterProperty(Id::BorderTopWidth, "0px", false, true).AddParser("length");
  157. RegisterProperty(Id::BorderRightWidth, "0px", false, true).AddParser("length");
  158. RegisterProperty(Id::BorderBottomWidth, "0px", false, true).AddParser("length");
  159. RegisterProperty(Id::BorderLeftWidth, "0px", false, true).AddParser("length");
  160. RegisterShorthand(Id::BorderWidth, { Id::BorderTopWidth, Id::BorderRightWidth, Id::BorderBottomWidth, Id::BorderLeftWidth });
  161. RegisterProperty(Id::BorderTopColor, "black", false, false).AddParser("color");
  162. RegisterProperty(Id::BorderRightColor, "black", false, false).AddParser("color");
  163. RegisterProperty(Id::BorderBottomColor, "black", false, false).AddParser("color");
  164. RegisterProperty(Id::BorderLeftColor, "black", false, false).AddParser("color");
  165. RegisterShorthand(Id::BorderColor, { Id::BorderTopColor, Id::BorderRightColor, Id::BorderBottomColor, Id::BorderLeftColor });
  166. RegisterShorthand(Id::BorderTop, { Id::BorderTopWidth, Id::BorderTopColor });
  167. RegisterShorthand(Id::BorderRight, { Id::BorderRightWidth, Id::BorderRightColor });
  168. RegisterShorthand(Id::BorderBottom, { Id::BorderBottomWidth, Id::BorderBottomColor });
  169. RegisterShorthand(Id::BorderLeft, { Id::BorderLeftWidth, Id::BorderLeftColor });
  170. RegisterShorthand(Id::Border, { Id::BorderTop, Id::BorderRight, Id::BorderBottom, Id::BorderLeft }, PropertySpecification::RECURSIVE);
  171. RegisterProperty(Id::Display, "inline", false, true).AddParser("keyword", "none, block, inline, inline-block");
  172. RegisterProperty(Id::Position, "static", false, true).AddParser("keyword", "static, relative, absolute, fixed");
  173. RegisterProperty(Id::Top, "auto", false, false)
  174. .AddParser("keyword", "auto")
  175. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
  176. RegisterProperty(Id::Right, "auto", false, false)
  177. .AddParser("keyword", "auto")
  178. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  179. RegisterProperty(Id::Bottom, "auto", false, false)
  180. .AddParser("keyword", "auto")
  181. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
  182. RegisterProperty(Id::Left, "auto", false, false)
  183. .AddParser("keyword", "auto")
  184. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  185. RegisterProperty(Id::Float, "none", false, true).AddParser("keyword", "none, left, right");
  186. RegisterProperty(Id::Clear, "none", false, true).AddParser("keyword", "none, left, right, both");
  187. RegisterProperty(Id::ZIndex, "auto", false, false)
  188. .AddParser("keyword", "auto, top, bottom")
  189. .AddParser("number");
  190. RegisterProperty(Id::Width, "auto", false, true)
  191. .AddParser("keyword", "auto")
  192. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  193. RegisterProperty(Id::MinWidth, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  194. RegisterProperty(Id::MaxWidth, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockWidth);
  195. RegisterProperty(Id::Height, "auto", false, true)
  196. .AddParser("keyword", "auto")
  197. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
  198. RegisterProperty(Id::MinHeight, "0px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
  199. RegisterProperty(Id::MaxHeight, "-1px", false, true).AddParser("length_percent").SetRelativeTarget(RelativeTarget::ContainingBlockHeight);
  200. RegisterProperty(Id::LineHeight, "1.2", true, true).AddParser("number_length_percent").SetRelativeTarget(RelativeTarget::FontSize);
  201. RegisterProperty(Id::VerticalAlign, "baseline", false, true)
  202. .AddParser("keyword", "baseline, middle, sub, super, text-top, text-bottom, top, bottom")
  203. .AddParser("length_percent").SetRelativeTarget(RelativeTarget::LineHeight);
  204. RegisterProperty(Id::OverflowX, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
  205. RegisterProperty(Id::OverflowY, "visible", false, true).AddParser("keyword", "visible, hidden, auto, scroll");
  206. RegisterShorthand(Id::Overflow, { Id::OverflowX, Id::OverflowY }, PropertySpecification::REPLICATE);
  207. RegisterProperty(Id::Clip, "auto", true, false).AddParser("keyword", "auto, none").AddParser("number");
  208. RegisterProperty(Id::Visibility, "visible", false, false).AddParser("keyword", "visible, hidden");
  209. // Need some work on this if we are to include images.
  210. RegisterProperty(Id::BackgroundColor, "transparent", false, false).AddParser("color");
  211. RegisterShorthand(Id::Background, { Id::BackgroundColor });
  212. RegisterProperty(Id::Color, "white", true, false).AddParser("color");
  213. RegisterProperty(Id::ImageColor, "white", false, false).AddParser("color");
  214. RegisterProperty(Id::Opacity, "1", true, false).AddParser("number");
  215. RegisterProperty(Id::FontFamily, "", true, true).AddParser("string");
  216. RegisterProperty(Id::FontCharset, "U+0020-007E", true, false).AddParser("string");
  217. RegisterProperty(Id::FontStyle, "normal", true, true).AddParser("keyword", "normal, italic");
  218. RegisterProperty(Id::FontWeight, "normal", true, true).AddParser("keyword", "normal, bold");
  219. RegisterProperty(Id::FontSize, "12px", true, true).AddParser("length").AddParser("length_percent").SetRelativeTarget(RelativeTarget::ParentFontSize);
  220. RegisterShorthand(Id::Font, { Id::FontStyle, Id::FontWeight, Id::FontSize, Id::FontFamily, Id::FontCharset });
  221. RegisterProperty(Id::TextAlign, "left", true, true).AddParser("keyword", "left, right, center, justify");
  222. RegisterProperty(Id::TextDecoration, "none", true, false).AddParser("keyword", "none, underline"/*"none, underline, overline, line-through"*/);
  223. RegisterProperty(Id::TextTransform, "none", true, true).AddParser("keyword", "none, capitalize, uppercase, lowercase");
  224. RegisterProperty(Id::WhiteSpace, "normal", true, true).AddParser("keyword", "normal, pre, nowrap, pre-wrap, pre-line");
  225. RegisterProperty(Id::Cursor, "auto", true, false).AddParser("keyword", "auto").AddParser("string");
  226. // Functional property specifications.
  227. RegisterProperty(Id::DragProperty, "none", false, false).AddParser("keyword", "none, drag, drag-drop, block, clone");
  228. RegisterProperty(Id::TabIndex, "none", false, false).AddParser("keyword", "none, auto");
  229. RegisterProperty(Id::Focus, "auto", true, false).AddParser("keyword", "none, auto");
  230. RegisterProperty(Id::ScrollbarMargin, "0", false, false).AddParser("length");
  231. RegisterProperty(Id::PointerEvents, "auto", true, false).AddParser("keyword", "auto, none");
  232. // Perspective and Transform specifications
  233. RegisterProperty(Id::Perspective, "none", false, false).AddParser("keyword", "none").AddParser("length");
  234. RegisterProperty(Id::PerspectiveOriginX, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
  235. RegisterProperty(Id::PerspectiveOriginY, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
  236. RegisterShorthand(Id::PerspectiveOrigin, { Id::PerspectiveOriginX, Id::PerspectiveOriginY});
  237. RegisterProperty(Id::Transform, "none", false, false).AddParser("transform");
  238. RegisterProperty(Id::TransformOriginX, "50%", false, false).AddParser("keyword", "left, center, right").AddParser("length_percent");
  239. RegisterProperty(Id::TransformOriginY, "50%", false, false).AddParser("keyword", "top, center, bottom").AddParser("length_percent");
  240. RegisterProperty(Id::TransformOriginZ, "0", false, false).AddParser("length");
  241. RegisterShorthand(Id::TransformOrigin, { Id::TransformOriginX, Id::TransformOriginY, Id::TransformOriginZ });
  242. RegisterProperty(Id::Transition, "none", false, false).AddParser("transition");
  243. RegisterProperty(Id::Animation, "none", false, false).AddParser("animation");
  244. }
  245. }
  246. }