diff options
-rw-r--r-- | dimension/common.nonterminals | 1 | ||||
-rw-r--r-- | dimension/common.rules | 30 | ||||
-rw-r--r-- | dimension/common.terminals | 2 | ||||
-rw-r--r-- | dimension/directives.declarations | 2 | ||||
-rw-r--r-- | dimension/grammar.declarations | 2 | ||||
-rw-r--r-- | dimension/grammar.epilogue | 4 | ||||
-rw-r--r-- | dimension/lexer.l | 1 | ||||
-rw-r--r-- | dimension/parse.h | 4 | ||||
-rw-r--r-- | dimension/realize.c | 117 | ||||
-rw-r--r-- | libdimension/dimension/array.h | 8 | ||||
-rw-r--r-- | tests/dimension/demo.pov | 2 | ||||
-rwxr-xr-x | tests/dimension/demo.sh | 10 |
12 files changed, 165 insertions, 18 deletions
diff --git a/dimension/common.nonterminals b/dimension/common.nonterminals index 08a6141..ddd0efb 100644 --- a/dimension/common.nonterminals +++ b/dimension/common.nonterminals @@ -68,6 +68,7 @@ %type <astnode> PIGMENT %type <astnode> PIGMENT_TYPE %type <astnode> PIGMENT_MODIFIERS +%type <astnode> COLOR_LIST2 %type <astnode> BITMAP_TYPE /* Finishes */ diff --git a/dimension/common.rules b/dimension/common.rules index dc8d0b3..7abae80 100644 --- a/dimension/common.rules +++ b/dimension/common.rules @@ -506,12 +506,20 @@ PIGMENT: "pigment" "{" { $$ = dmnsn_new_astnode2(DMNSN_AST_PIGMENT, @$, $3, $4); } + | "pigment" "{" + "checker" COLOR_LIST2 + PIGMENT_MODIFIERS + "}" + { + dmnsn_astnode checker = dmnsn_new_astnode(DMNSN_AST_CHECKER, @3); + dmnsn_astnode pattern = dmnsn_new_astnode1(DMNSN_AST_PATTERN, @3, + checker); + dmnsn_array_push($5.children, &$4); + $$ = dmnsn_new_astnode2(DMNSN_AST_PIGMENT, @$, pattern, $5); + } ; -PIGMENT_TYPE: /* empty */ { - $$ = dmnsn_new_astnode(DMNSN_AST_NONE, @$); - } - | COLOR +PIGMENT_TYPE: COLOR | "image_map" "{" BITMAP_TYPE STRING "}" @@ -541,6 +549,20 @@ PIGMENT_MODIFIERS: /* empty */ { } ; +COLOR_LIST2: /* empty */ { + dmnsn_astnode list = dmnsn_new_astnode(DMNSN_AST_ARRAY, @$); + $$ = dmnsn_new_astnode1(DMNSN_AST_COLOR_LIST, @$, list); + } + | COLOR { + dmnsn_astnode list = dmnsn_new_astnode1(DMNSN_AST_ARRAY, @$, $1); + $$ = dmnsn_new_astnode1(DMNSN_AST_COLOR_LIST, @$, list); + } + | COLOR "," COLOR { + dmnsn_astnode list = dmnsn_new_astnode2(DMNSN_AST_ARRAY, @$, + $1, $3); + $$ = dmnsn_new_astnode1(DMNSN_AST_COLOR_LIST, @$, list); + } + /* Finishes */ FINISH: "finish" "{" FINISH_ITEMS diff --git a/dimension/common.terminals b/dimension/common.terminals index 256474f..84f05eb 100644 --- a/dimension/common.terminals +++ b/dimension/common.terminals @@ -121,7 +121,7 @@ %token DMNSN_T_CEIL "ceil" %token DMNSN_T_CELLS %token DMNSN_T_CHARSET -%token DMNSN_T_CHECKER +%token DMNSN_T_CHECKER "checker" %token DMNSN_T_CHR %token DMNSN_T_CIRCULAR %token DMNSN_T_CLIPPED_BY diff --git a/dimension/directives.declarations b/dimension/directives.declarations index 541ae41..9562ec3 100644 --- a/dimension/directives.declarations +++ b/dimension/directives.declarations @@ -21,7 +21,7 @@ %name-prefix "dmnsn_ld_yy" -%expect 12 +%expect 14 %expect-rr 6 %parse-param {const char *filename} diff --git a/dimension/grammar.declarations b/dimension/grammar.declarations index 3eae498..b31ac26 100644 --- a/dimension/grammar.declarations +++ b/dimension/grammar.declarations @@ -23,7 +23,7 @@ %name-prefix "dmnsn_yy" -%expect 8 +%expect 10 %parse-param {const char *filename} %parse-param {void *yyscanner} diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue index a2bd743..6a8e164 100644 --- a/dimension/grammar.epilogue +++ b/dimension/grammar.epilogue @@ -147,10 +147,14 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type) dmnsn_astnode_map(DMNSN_AST_OBJECT_MODIFIERS, "object-modifiers"); + dmnsn_astnode_map(DMNSN_AST_PATTERN, "pattern"); + dmnsn_astnode_map(DMNSN_AST_CHECKER, "checker"); + dmnsn_astnode_map(DMNSN_AST_TEXTURE, "texture"); dmnsn_astnode_map(DMNSN_AST_PIGMENT, "pigment"); dmnsn_astnode_map(DMNSN_AST_PIGMENT_MODIFIERS, "pigment-modifiers"); + dmnsn_astnode_map(DMNSN_AST_COLOR_LIST, "color-list"); dmnsn_astnode_map(DMNSN_AST_IMAGE_MAP, "image_map"); dmnsn_astnode_map(DMNSN_AST_PNG, "png"); diff --git a/dimension/lexer.l b/dimension/lexer.l index 58a2dba..511e3df 100644 --- a/dimension/lexer.l +++ b/dimension/lexer.l @@ -182,6 +182,7 @@ unsigned long wchar; "blue" RETURN_TOKEN(DMNSN_T_BLUE); "ceil" RETURN_TOKEN(DMNSN_T_CEIL); "camera" RETURN_TOKEN(DMNSN_T_CAMERA); +"checker" RETURN_TOKEN(DMNSN_T_CHECKER); "color" RETURN_TOKEN(DMNSN_T_COLOR); "colour" RETURN_TOKEN(DMNSN_T_COLOR); "cone" RETURN_TOKEN(DMNSN_T_CONE); diff --git a/dimension/parse.h b/dimension/parse.h index 482c4ad..6e09302 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -61,10 +61,14 @@ typedef enum { DMNSN_AST_OBJECT_MODIFIERS, + DMNSN_AST_PATTERN, + DMNSN_AST_CHECKER, + DMNSN_AST_TEXTURE, DMNSN_AST_PIGMENT, DMNSN_AST_PIGMENT_MODIFIERS, + DMNSN_AST_COLOR_LIST, DMNSN_AST_IMAGE_MAP, DMNSN_AST_PNG, diff --git a/dimension/realize.c b/dimension/realize.c index 18de230..bac3d7e 100644 --- a/dimension/realize.c +++ b/dimension/realize.c @@ -446,6 +446,99 @@ dmnsn_realize_camera(dmnsn_astnode astnode) return camera; } +static dmnsn_pattern * +dmnsn_realize_pattern(dmnsn_astnode astnode) +{ + dmnsn_assert(astnode.type == DMNSN_AST_PATTERN, "Expected a pattern."); + + dmnsn_astnode type; + dmnsn_array_get(astnode.children, 0, &type); + + dmnsn_pattern *pattern = NULL; + + switch (type.type) { + case DMNSN_AST_CHECKER: + pattern = dmnsn_new_checker_pattern(); + break; + + default: + dmnsn_assert(false, "Unexpected pattern type."); + } + + return pattern; +} + +static dmnsn_color_map * +dmnsn_realize_color_list(dmnsn_astnode astnode) +{ + dmnsn_assert(astnode.type == DMNSN_AST_COLOR_LIST, "Expected a color list."); + + dmnsn_astnode array; + dmnsn_array_get(astnode.children, 0, &array); + + dmnsn_color_map *color_map = dmnsn_new_color_map(); + + double n = 0.0, i = 1.0/(dmnsn_array_size(array.children) - 1); + DMNSN_ARRAY_FOREACH (dmnsn_astnode *, entry, array.children) { + dmnsn_color color = dmnsn_realize_color(*entry); + dmnsn_add_color_map_entry(color_map, n, color); + n += i; + } + + return color_map; +} + +static dmnsn_pigment * +dmnsn_realize_pattern_pigment(dmnsn_astnode type, dmnsn_astnode modifiers) +{ + dmnsn_assert(modifiers.type == DMNSN_AST_PIGMENT_MODIFIERS, + "Expected pigment modifiers"); + + dmnsn_pattern *pattern = dmnsn_realize_pattern(type); + + dmnsn_color_map *color_map = NULL; + + /* Set up the color_map */ + DMNSN_ARRAY_FOREACH_REVERSE (dmnsn_astnode *, modifier, modifiers.children) { + switch (modifier->type) { + case DMNSN_AST_COLOR_LIST: + color_map = dmnsn_realize_color_list(*modifier); + break; + + default: + break; + } + + if (color_map) + break; + } + + /* Now add the default values */ + switch (type.type) { + case DMNSN_AST_CHECKER: + /* Default checker pattern is blue and green */ + if (!color_map) + color_map = dmnsn_new_color_map(); + if (dmnsn_array_size(color_map) < 1) + dmnsn_add_color_map_entry(color_map, 0.0, dmnsn_blue); + if (dmnsn_array_size(color_map) < 2) + dmnsn_add_color_map_entry(color_map, 1.0, dmnsn_green); + break; + + default: + /* Default map is grayscale */ + if (!color_map) { + color_map = dmnsn_new_color_map(); + dmnsn_add_color_map_entry(color_map, 0.0, dmnsn_black); + dmnsn_add_color_map_entry(color_map, 1.0, dmnsn_white); + } + break; + } + + dmnsn_pigment *pigment = dmnsn_new_color_map_pigment(pattern, color_map); + return pigment; +} + static void dmnsn_realize_pigment_modifiers(dmnsn_astnode astnode, dmnsn_pigment *pigment) { @@ -461,6 +554,10 @@ dmnsn_realize_pigment_modifiers(dmnsn_astnode astnode, dmnsn_pigment *pigment) ); break; + case DMNSN_AST_COLOR_LIST: + /* Already handled by dmnsn_realize_pattern_pigment() */ + break; + default: dmnsn_assert(false, "Invalid pigment modifier."); } @@ -474,18 +571,26 @@ dmnsn_realize_pigment(dmnsn_astnode astnode) dmnsn_pigment *pigment = NULL; - dmnsn_astnode type_node; + dmnsn_astnode type_node, modifiers; dmnsn_array_get(astnode.children, 0, &type_node); + dmnsn_array_get(astnode.children, 1, &modifiers); - dmnsn_color color; switch (type_node.type) { case DMNSN_AST_NONE: break; case DMNSN_AST_VECTOR: - color = dmnsn_realize_color(type_node); - pigment = dmnsn_new_solid_pigment(color); - break; + { + dmnsn_color color = dmnsn_realize_color(type_node); + pigment = dmnsn_new_solid_pigment(color); + break; + } + + case DMNSN_AST_PATTERN: + { + pigment = dmnsn_realize_pattern_pigment(type_node, modifiers); + break; + } case DMNSN_AST_IMAGE_MAP: { @@ -522,8 +627,6 @@ dmnsn_realize_pigment(dmnsn_astnode astnode) dmnsn_assert(false, "Invalid pigment type."); } - dmnsn_astnode modifiers; - dmnsn_array_get(astnode.children, 1, &modifiers); dmnsn_realize_pigment_modifiers(modifiers, pigment); return pigment; diff --git a/libdimension/dimension/array.h b/libdimension/dimension/array.h index b718021..fa48ac0 100644 --- a/libdimension/dimension/array.h +++ b/libdimension/dimension/array.h @@ -170,10 +170,16 @@ dmnsn_array_remove(dmnsn_array *array, size_t i) dmnsn_array_resize(array, size - 1); } -/* Macro to shorten array iteration */ +/* Macros to shorten array iteration */ + #define DMNSN_ARRAY_FOREACH(type, i, array) \ for (type i = dmnsn_array_first(array); \ i - (type)dmnsn_array_first(array) < dmnsn_array_size(array); \ ++i) +#define DMNSN_ARRAY_FOREACH_REVERSE(type, i, array) \ + for (type i = dmnsn_array_last(array); \ + (type)dmnsn_array_last(array) - i < dmnsn_array_size(array); \ + --i) + #endif /* DIMENSION_ARRAY_H */ diff --git a/tests/dimension/demo.pov b/tests/dimension/demo.pov index 3d6a879..544cd10 100644 --- a/tests/dimension/demo.pov +++ b/tests/dimension/demo.pov @@ -111,6 +111,6 @@ union { plane { y, -2 pigment { - color rgb 1 + checker color rgb 0, color rgb 1 } } diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh index 20eebb9..05b01aa 100755 --- a/tests/dimension/demo.sh +++ b/tests/dimension/demo.sh @@ -134,8 +134,14 @@ demo_exp=$(echo -n \ (integer -2)) (object-modifiers (pigment - (vector (integer 1) (integer 1) (integer 1) (integer 0) (integer 0)) - pigment-modifiers))))' \ + (pattern checker) + (pigment-modifiers + (color-list + (array + (vector (integer 0) (integer 0) (integer 0) + (integer 0) (integer 0)) + (vector (integer 1) (integer 1) (integer 1) + (integer 0) (integer 0)))))))))' \ | tr '\n' ' ' | sed -r 's/[[:space:]]+/ /g') if [ "$demo" != "$demo_exp" ]; then |