adding parsing; almost done with MVP work
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 18 Feb 2021 20:20:04 +0000 (14:20 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 18 Feb 2021 20:20:04 +0000 (14:20 -0600)
dist/index.js
src/build.onyx
src/canvas.onyx
src/prez.onyx
src/show_parser.onyx [new file with mode: 0644]
src/slides.onyx
test.prez [new file with mode: 0644]

index d484d49e70dfd60aed6071faa5e0298202a6a838..a6d998968606fd3805b246dff13e54b5fad27538 100644 (file)
@@ -108,6 +108,10 @@ let canvas_import_obj = {
         canvasCtx.font = str;
     },
 
+    setColor(canvas, r, g, b, a) {
+        canvasCtx.fillStyle = `rgba(${r * 255}, ${g * 255}, ${b * 255}, ${a})`; 
+    },
+
     measureText(canvas, text_ptr, text_len, measure_ptr) {
         const data = new Uint8Array(wasm_instance.exports.memory.buffer, text_ptr, text_len);
         const text = new TextDecoder().decode(data);
@@ -131,8 +135,6 @@ let canvas_import_obj = {
         const data = new Uint8Array(wasm_instance.exports.memory.buffer, text_ptr, text_len);
         const str  = new TextDecoder().decode(data);
 
-        canvasCtx.fillStyle = "#ffffff";
-        
         if (max_width > 0) canvasCtx.fillText(str, x, y, max_width);
         else               canvasCtx.fillText(str, x, y);
     },
index e5f5cde9ee61cf9cd5f501ddd5929fdd2e326fe0..4892f68725f2c25dad771fa76b16e86c198662e7 100644 (file)
@@ -10,3 +10,4 @@ use package build_opts as build_opts
 #load "src/events"
 #load "src/slides"
 #load "src/canvas"
+#load "src/show_parser"
index 6dfe2ad221f689edda1784e636cdee330a1ecca3..1bb19678d95e2efd4f41b89feae551f843a747f6 100644 (file)
@@ -12,6 +12,7 @@ Canvas :: struct {
     set_size :: (handle: Handle, width: u32, height: u32) -> void #foreign "canvas" "set_size" ---
 
     set_font :: (handle: Handle, font_name: str) -> u32 #foreign "canvas" "setFont" ---
+    set_color :: (handle: Handle, r: f32, g: f32, b: f32, a := 1.0f) -> void #foreign "canvas" "setColor" ---
 
     TextMetrics :: struct {
         width : f32;
index a3e26e4d26544c5adfa00eda68861faadb22dcf2..63533570f296121056ddc0480d35bb8f1b773e98 100644 (file)
@@ -60,82 +60,12 @@ loop :: () -> void #export "loop" {
 
 the_slideshow : Slideshow;
 
-create_dummy_show :: () {
-    the_slideshow = slideshow_make();
-    
-    { // Slide 1
-        slide := slideshow_insert_slide(^the_slideshow);
-        slide_init(slide, background_color = Color.{ 0.1, 0.1, 0.2 }, item_count = 2);
-        
-        slide.items[0] = slideshow_make_item(^the_slideshow);
-        slide.items[0].kind = Slide_Item.Kind.Text;
-        slide.items[0].text.text = "Hello, World!";
-        slide.items[0].text.y_pos = .5;
-        slide.items[0].text.font_name = "Arail";
-        slide.items[0].text.font_size = 72;
-        slide.items[0].text.font_attr = Slide_Item_Text.FontAttributes.Bold;
-        slide.items[0].text.justify = Slide_Item_Text.Justify.Center;
-
-        slide.items[1] = slideshow_make_item(^the_slideshow);
-        slide.items[1].kind = Slide_Item.Kind.Text;
-        slide.items[1].text.text = "Another, smaller, line of text below the first!";
-        slide.items[1].text.y_pos = .6;
-        slide.items[1].text.font_name = "Arail";
-        slide.items[1].text.font_size = 36;
-        slide.items[1].text.font_attr = Slide_Item_Text.FontAttributes.Italic;
-        slide.items[1].text.padding = .07;
-        slide.items[1].text.justify = Slide_Item_Text.Justify.Right;
-    }
-
-    { // Slide 2
-        slide := slideshow_insert_slide(^the_slideshow);
-        slide_init(slide, background_color = Color.{ 0.2, 0.1, 0.1 }, item_count = 4);
-        
-        slide.items[0] = slideshow_make_item(^the_slideshow);
-        slide.items[0].kind = Slide_Item.Kind.Text;
-        slide.items[0].text.text = "The Second Slide!";
-        slide.items[0].text.y_pos = .2;
-        slide.items[0].text.font_name = "Arail";
-        slide.items[0].text.font_size = 72;
-        slide.items[0].text.font_attr = Slide_Item_Text.FontAttributes.Bold;
-        slide.items[0].text.justify = Slide_Item_Text.Justify.Center;
-
-        slide.items[1] = slideshow_make_item(^the_slideshow);
-        slide.items[1].kind = Slide_Item.Kind.Text;
-        slide.items[1].text.text = "Here is some monospace text.";
-        slide.items[1].text.y_pos = .3;
-        slide.items[1].text.font_name = "monospace";
-        slide.items[1].text.font_size = 36;
-        slide.items[1].text.padding = .07;
-        slide.items[1].text.justify = Slide_Item_Text.Justify.Left;
-
-        slide.items[2] = slideshow_make_item(^the_slideshow);
-        slide.items[2].text = Slide_Item_Text.{
-            text = "Here is a block of much longer text that will not wrap correctly, which is annoying but I think the best thing to do is... I don't know yet.",
-            y_pos = .35,
-            font_name = "Calibri",
-            font_size = 36,
-            padding = .07,
-            justify = Slide_Item_Text.Justify.Left,
-        };
-
-        slideshow_load_image(^the_slideshow, "first_image", "images/first.jpg");
-
-        slide.items[3] = slideshow_make_item(^the_slideshow);
-        slide.items[3].image = Slide_Item_Image.{
-            name = "first_image",
-            x = .3,
-            y = .4,
-            width = .4,
-        };
-    }
-}
-
 main :: (args: [] cstr) {
     setup_canvas();
     event.init();
 
-    create_dummy_show();
+    the_slideshow = slideshow_make();
+    parse_slideshow(#file_contents "test.prez", ^the_slideshow);
 
     start_loop :: () -> void #foreign "host" "start_loop" ---
     start_loop();
diff --git a/src/show_parser.onyx b/src/show_parser.onyx
new file mode 100644 (file)
index 0000000..b83e8ce
--- /dev/null
@@ -0,0 +1,219 @@
+use package core
+
+parse_slideshow :: (source: str, slideshow: ^Slideshow) {
+    use io
+
+    parse_arena := alloc.arena.make(context.allocator, arena_size = 16 * 1024);
+    defer alloc.arena.free(^parse_arena);
+
+    parse_alloc := alloc.arena.make_allocator(^parse_arena);
+
+    show_stream := string_stream_make(source);
+    show_reader := reader_make(^show_stream);
+
+    default_text_style := Slide_Item_Text.{
+        font_name = "Calibri",
+        font_size = 12,
+        text = "UNDEFINED TEXT",
+        y_pos = 0, padding = 0, justify = Slide_Item_Text.Justify.Left,
+    };
+
+    text_styles := map.make(str, Slide_Item_Text, default_text_style);
+    defer map.free(^text_styles);
+
+    current_slide: ^Slide;
+    current_item_idx := 0;
+    current_text_style: Slide_Item_Text;
+
+    while !stream_end_of_file(^show_stream) {
+        skip_whitespace(^show_reader); 
+        defer skip_whitespace(^show_reader); 
+
+        _, next_byte := stream_peek_byte(^show_stream);
+        switch next_byte {
+            case #char "[" {
+                // Command
+                read_byte(^show_reader);
+
+                command_name := read_word(^show_reader, allocator=parse_alloc);
+                printf("Parsing command: %s\n", command_name);
+
+                if command_name == "slide" {
+                    prev_slide := ^slideshow.slides[slideshow.slides.count - 1];
+                    current_slide = slideshow_insert_slide(slideshow);
+                    current_item_idx = 0;
+
+                    // @Robustness @Incomplete: Currently, there is a fixed number of items
+                    // on EVERY slide, which both wastes memory for small slides, and limits
+                    // how many things can be in a slide.
+                    slide_init(current_slide, background_color=prev_slide.background, item_count = 16);
+                }
+                elseif command_name == "background" {
+                    r, g, b := parse_color(^show_reader);
+                    current_slide.background = Color.{ r, g, b };
+                }
+                elseif command_name == "y" {
+                    y := read_u32(^show_reader);
+                    current_text_style.y_pos = cast(f32) y / 100;
+                }
+                elseif command_name == "text_style" {
+                    text_style_name := read_word(^show_reader, numeric_allowed=true);
+                    if !map.has(^text_styles, text_style_name) {
+                        printf("Text style '%s' was never defined.\n", text_style_name);
+                    }
+
+                    text_style := map.get(^text_styles, text_style_name);
+                    current_text_style = text_style;
+
+                    parse_text_style(^show_reader, ^current_text_style, parse_alloc);
+                }
+                elseif command_name == "define_text_style" {
+                    text_style_name := read_word(^show_reader, numeric_allowed=true);
+
+                    current_text_style = default_text_style;
+                    parse_text_style(^show_reader, ^current_text_style, parse_alloc);
+                    map.put(^text_styles, text_style_name, current_text_style);
+                }
+                elseif command_name == "load_image" {
+                    image_name := read_word(^show_reader, numeric_allowed=true);
+                    image_path := parse_string(^show_reader, allocator=parse_alloc);
+
+                    slideshow_load_image(slideshow, image_name, image_path);
+                }
+                elseif command_name == "image" {
+                    new_slide_image := slideshow_make_item(slideshow);
+                    new_slide_image.kind = Slide_Item.Kind.Image;
+                    parse_image_style(^show_reader, ^new_slide_image.image, parse_alloc);
+
+                    current_slide.items[current_item_idx] = new_slide_image;
+                    current_item_idx += 1;
+                }
+                else {
+                    printf("******** Unknown command: '%s'.\n", command_name);
+                }
+                
+                read_until(^show_reader, #char "]", allocator=parse_alloc, consume_end=true);
+            }
+
+            // @Memory: should be able to use advance_line here instead, but
+            // there are some issue with that consuming two lines instead.
+            case #char "#" do read_line(^show_reader, allocator=parse_alloc);
+
+            case #default {
+                // @Memory
+                text := read_line(^show_reader);
+
+                new_slide_text := slideshow_make_item(slideshow);
+                new_slide_text.text = current_text_style;
+                new_slide_text.text.text = text; // Oofta...
+
+                current_slide.items[current_item_idx] = new_slide_text;
+                current_item_idx += 1;
+            }
+        }
+    }
+
+    printf("Total slide count: %i\n", slideshow.slides.count);
+}
+
+#private_file
+parse_text_style :: (reader: ^io.Reader, text_style: ^Slide_Item_Text, parse_alloc := context.allocator) {
+    use io
+
+    while !stream_end_of_file(reader.stream) && peek_byte(reader) != #char "]" {
+        skip_whitespace(reader);
+        defer skip_whitespace(reader);
+        style_name := read_word(reader, allocator=parse_alloc);
+        
+        if style_name == "color" {
+            r, g, b := parse_color(reader);
+            text_style.color = Color.{ r, g, b };
+            printf("Parsed color: %f %f %f\n", r, g, b);
+        }
+        elseif style_name == "font_size" {
+            text_style.font_size = read_u32(reader);
+        }
+        elseif style_name == "font_name" {
+            text_style.font_name = parse_string(reader);
+        }
+        elseif style_name == "font_attr" {
+            font_attr := read_word(reader, allocator=parse_alloc);
+
+            if     font_attr == "bold"   do text_style.font_attr |= Slide_Item_Text.FontAttributes.Bold;
+            elseif font_attr == "italic" do text_style.font_attr |= Slide_Item_Text.FontAttributes.Italic;
+        }
+        elseif style_name == "padding" {
+            padding := read_u32(reader);
+            text_style.padding = cast(f32) padding / 100;
+        }
+        elseif style_name == "left"     do text_style.justify = Slide_Item_Text.Justify.Left;
+        elseif style_name == "centered" do text_style.justify = Slide_Item_Text.Justify.Center;
+        elseif style_name == "right"    do text_style.justify = Slide_Item_Text.Justify.Right;
+        else {
+            use package core { printf as pf }
+            pf("Unknown style option: '%s'\n", style_name);
+            advance_line(reader);
+            break;
+        }
+    }
+}
+
+#private_file
+parse_image_style :: (reader: ^io.Reader, image_style: ^Slide_Item_Image, parse_alloc := context.allocator) {
+    use io
+
+    image_name := read_word(reader, numeric_allowed=true);
+    image_style.name = image_name;
+
+    while !stream_end_of_file(reader.stream) && peek_byte(reader) != #char "]" {
+        skip_whitespace(reader);
+        defer skip_whitespace(reader);
+        style_name := read_word(reader, allocator=parse_alloc);
+        
+        if style_name == "x" {
+            x := read_u32(reader);
+            image_style.x = cast(f32) x / 100;
+        }
+        elseif style_name == "y" {
+            y := read_u32(reader);
+            image_style.y = cast(f32) y / 100;
+        }
+        elseif style_name == "width" {
+            width := read_u32(reader);
+            image_style.width = cast(f32) width / 100;
+        }
+        else {
+            use package core { printf as pf }
+            pf("Unknown style option: '%s'\n", style_name);
+            advance_line(reader);
+            break;
+        }
+    }
+}
+
+#private_file
+parse_color :: (reader: ^io.Reader) -> (f32, f32, f32) {
+    r := io.read_u32(reader);
+    g := io.read_u32(reader);
+    b := io.read_u32(reader);
+
+    fr := cast(f32) r / 255;
+    fg := cast(f32) g / 255;
+    fb := cast(f32) b / 255;
+
+    return fr, fg, fb;
+}
+
+#private_file
+parse_string :: (reader: ^io.Reader, allocator := context.allocator) -> str {
+    use io
+
+    // @Cleanup
+    dummy := read_until(reader, #char "\"", context.temp_allocator);
+    read_byte(reader);
+
+    str_contents := read_until(reader, #char "\"", allocator=allocator);
+    read_byte(reader);
+
+    return str_contents;
+}
index 5b26633e03c9a92e50e9352fca7bfb73bf545146..122247dd7782bbc4e71217714ac1433103ecaff7 100644 (file)
@@ -171,6 +171,7 @@ slide_item_render :: (use slide_item: ^Slide_Item, slide: ^Slide) {
     switch kind {
         case Text {
             set_font_for_text(slide_item);
+            set_color(canvas, text.color.r, text.color.g, text.color.b, text.color.a);
 
             use Slide_Item_Text.Justify
             switch text.justify {
@@ -205,6 +206,12 @@ slide_item_render :: (use slide_item: ^Slide_Item, slide: ^Slide) {
                 width, height := cast(f32) get_width(canvas), cast(f32) get_height(canvas);
 
                 // @Speed: There is a much better way of doing this...
+                // @Robustness: Currently, because HTML images are asynchronously loaded,
+                // the image dimensions are not known when the load_image call is made.
+                // These means that the dimensions need to be queried later once the image
+                // has been loaded. The real bad thing here, is that the 'html_image' being
+                // passed is a local copy from the image_map. This means everytime this image
+                // is drawn, it has to requery the image dimensions... Uck...
                 store_image_size :: (html_image: ^HTML_Image) -> void #foreign "html" "store_image_size" ---
                 store_image_size(^html_image);
 
diff --git a/test.prez b/test.prez
new file mode 100644 (file)
index 0000000..05936fc
--- /dev/null
+++ b/test.prez
@@ -0,0 +1,39 @@
+
+[define_text_style normal_text color 255 255 255 font_size 36 font_name "Arial" left padding 10]
+[define_text_style bold_title color 255 255 255 font_attr bold font_size 72 font_name "Arial" centered]
+
+[load_image first_image "images/first.jpg"]
+
+# ------------------------------------------------------------------
+[slide]
+[background 25 25 40]
+[text_style bold_title]
+[y 50]
+First slide title!
+
+# ------------------------------------------------------------------
+[slide]
+[background 40 25 25]
+[text_style bold_title]
+[y 10]
+Second slide title!
+
+[text_style normal_text]
+[y 20]
+Some normal looking text is here.
+
+# Robustness: This shouldn't be necessary to declare.
+
+[text_style normal_text font_attr bold]
+[y 25]
+Some more normal looking text is here.
+
+[image first_image x 30 y 30 width 40]
+
+# ------------------------------------------------------------------
+[slide]
+[text_style bold_title color 255 50 50 font_size 96 font_attr italic]
+[y 10]
+Bigger image!
+
+[image first_image x 25 width 50 y 15]