28#include <Objectively.h>
43 release(this->attributes);
44 release(this->selectors);
56 return $((Array *) this->selectors, componentsJoinedByCharacters,
", ");
62static int hash(
const Object *self) {
68 hash = HashForObject(
hash, this->attributes);
69 hash = HashForObject(
hash, this->selectors);
77static bool isEqual(
const Object *self,
const Object *other) {
79 if (super(Object, self,
isEqual, other)) {
83 if (other && $(other, isKindOfClass,
_Style())) {
107 const char *longhands[4];
115 {
"corner-cut", {
"corner-cut-top-left",
"corner-cut-top-right",
116 "corner-cut-bottom-right",
"corner-cut-bottom-left" } },
117 {
"max-size", {
"max-width",
"max-height" } },
118 {
"min-size", {
"min-width",
"min-height" } },
119 {
"padding", {
"padding-top",
"padding-right",
"padding-bottom",
"padding-left" } },
160 if ($((Object *) value, isKindOfClass, _Number())) {
161 for (
size_t i = 0; i < count; i++) {
167 if ($((Object *) value, isKindOfClass, _Array())) {
168 const Array *array = value;
169 if (array->count == count) {
170 for (
size_t i = 0; i < count; i++) {
171 ident number = $(array, objectAtIndex, i);
188 $((Dictionary *) self->
attributes, setObjectForKeyPath, value, key);
201 char *key = strtrim(attr);
242 String *
string = $$(String, stringWithCharacters, value);
255 Number *r = $$(Number, numberWithValue, color->r);
256 Number *g = $$(Number, numberWithValue, color->g);
257 Number *b = $$(Number, numberWithValue, color->b);
258 Number *a = $$(Number, numberWithValue, color->a);
260 Array *array = $$(Array, arrayWithObjects, r, g, b, a, NULL);
277 Number *number = $$(Number, numberWithValue, value);
290 String *
string = nameof(names, value);
319 Number *x = $$(Number, numberWithValue, value->x);
320 Number *y = $$(Number, numberWithValue, value->y);
322 Array *array = $$(Array, arrayWithObjects, x, y, NULL);
337 Number *x = $$(Number, numberWithValue, value->x);
338 Number *y = $$(Number, numberWithValue, value->y);
339 Number *w = $$(Number, numberWithValue, value->w);
340 Number *h = $$(Number, numberWithValue, value->h);
342 Array *array = $$(Array, arrayWithObjects, x, y, w, h, NULL);
361 $((Array *) self->
selectors, addObject, selector);
370 Number *w = $$(Number, numberWithValue, value->w);
371 Number *h = $$(Number, numberWithValue, value->h);
373 Array *array = $$(Array, arrayWithObjects, w, h, NULL);
387 return $((Dictionary *) self->
attributes, objectForKeyPath, attr);
412 self = (
Style *) super(Object, self,
init);
418 for (
size_t i = 0; i < self->
selectors->count; i++) {
422 self->
attributes = (Dictionary *) $$(Dictionary, dictionaryWithCapacity, 4);
439 for (
size_t i = 0; i < self->
selectors->count; i++) {
444 if (strcmp(this->rule, that->
rule)) {
464 String *trimmed = $(
string, trimmedString);
467 StringReader *reader = $(alloc(StringReader),
initWithString, trimmed);
470 const Unicode *charset = L
", \n\t";
473 String *token = $(reader, readToken, charset, &stop);
476 NumberFormatter *formatter = $(alloc(NumberFormatter),
initWithFormat, NULL);
479 Number *number = $(formatter, numberFromString, token);
481 if (stop == READER_EOF) {
484 value = retain(number);
485 }
else if (strcmp(
"true", token->chars) == 0) {
486 value = retain($$(Boole, True));
487 }
else if (strcmp(
"false", token->chars) == 0) {
488 value = retain($$(Boole, False));
490 value = $((Object *) token, copy);
494 value = $$(Array, arrayWithCapacity, 4);
499 $((Array *) value, addObject, obj);
503 token = $(reader, readToken, charset, NULL);
506 value = retain(trimmed);
529 const size_t len = strlen(css);
531 char *out = calloc(1, len + 1);
535 for (
size_t r = 0; r < len; ) {
536 if (css[r] ==
'/' && css[r + 1] ==
'*') {
538 while (r < len && !(css[r] ==
'*' && css[r + 1] ==
'/')) {
541 r = (r < len) ? r + 2 : len;
556static Array *
parse(
const char *css) {
558 Array *styles = $$(Array, array);
573 const Unicode *charset = style ? L
"{:;}" : L
"{}";
576 String *token = $(reader, readToken, charset, &stop);
585 attr = strtrim(token->chars);
603 $(styles, addObject, style);
604 style = release(style);
619 return (Array *) styles;
627 $((Dictionary *) self->
attributes, removeObjectForKeyPath, attr);
635 $((Dictionary *) self->
attributes, removeAllObjects);
638#pragma mark - Class lifecycle
645 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
646 ((ObjectInterface *) clazz->interface)->description =
description;
647 ((ObjectInterface *) clazz->interface)->hash =
hash;
648 ((ObjectInterface *) clazz->interface)->isEqual =
isEqual;
650 ((StyleInterface *) clazz->interface)->addAttribute =
addAttribute;
651 ((StyleInterface *) clazz->interface)->addAttributes =
addAttributes;
661 ((StyleInterface *) clazz->interface)->addSelector =
addSelector;
663 ((StyleInterface *) clazz->interface)->attributeValue =
attributeValue;
667 ((StyleInterface *) clazz->interface)->parse =
parse;
669 ((StyleInterface *) clazz->interface)->removeAttribute =
removeAttribute;
681 clazz = _initialize(&(
const ClassDef) {
683 .superclass = _Object(),
684 .instanceSize =
sizeof(
Style),
685 .interfaceSize =
sizeof(StyleInterface),
static View * init(View *self)
static void addAttribute(Style *self, const char *attr, ident value)
static void addDoubleAttribute(Style *self, const char *attr, double value)
static const StyleShorthand styleShorthands[]
static bool isComputedEqual(const Style *self, const Style *other)
static void addAttributes_enumerate(const Dictionary *dictionary, ident obj, ident key, ident data)
DictionaryEnumerator for addAttributes.
static void addIntegerAttribute(Style *self, const char *attr, int value)
static void addEnumAttribute(Style *self, const char *attr, const EnumName *names, int value)
static const StyleShorthand * styleShorthandForKey(const char *key)
static bool addShorthandAttribute(Style *self, const StyleShorthand *shorthand, ident value)
Stores value as the longhands of shorthand, if it can be split into them.
static bool isEqual(const Object *self, const Object *other)
static Style * initWithRules(Style *self, const char *rules)
static char * stripComments(const char *css)
Returns a newly allocated copy of css with all / * ... * / comments removed. The tokenizer below spli...
static Array * parse(const char *css)
static String * description(const Object *self)
static void addCharactersAttribute(Style *self, const char *attr, const char *value)
static void removeAttribute(Style *self, const char *attr)
static void addSizeAttribute(Style *self, const char *attr, const SDL_Size *value)
static void removeAllAttributes(Style *self)
static void addColorAttribute(Style *self, const char *attr, const SDL_Color *color)
static Style * initWithAttributes(Style *self, const Dictionary *attributes)
static ident attributeValue(const Style *self, const char *attr)
static void addRectangleAttribute(Style *self, const char *attr, const SDL_Rect *value)
static void dealloc(Object *self)
static void addSelector(Style *self, Selector *selector)
static void addFloatAttribute(Style *self, const char *attr, float value)
static void initialize(Class *clazz)
static void setAttribute(Style *self, const char *key, ident value)
Stores value under key, expanding it into longhands if key is a shorthand.
static ident parseValue(String *string)
static void addBoolAttribute(Style *self, const char *attr, bool value)
static size_t styleShorthandCount(const StyleShorthand *shorthand)
static void addPointAttribute(Style *self, const char *attr, const SDL_Point *value)
static void addAttributes(Style *self, const Dictionary *attributes)
static int hash(const Object *self)
static Stylesheet * initWithString(Stylesheet *self, const String *string)
static Stylesheet * initWithCharacters(Stylesheet *self, const char *chars)
static Warning * initWithFormat(Warning *self, WarningType type, const char *fmt,...)
Selectors are comprised of one or more SelectorSequences.
char * rule
The rule, as provided by the user.
Array * selectors
The Selectors.
Style * initWithRules(Style *self, const char *rules)
Initializes this Style with the given CSS selector rules.
bool isComputedEqual(const Style *self, const Style *other)
Performs a fast, rule-based comparison of this Style to the given Style.
A shorthand attribute, and the longhands it stands for.
const char * longhands[4]