fixed aspect-ratio images added
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 18 Feb 2021 17:58:01 +0000 (11:58 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 18 Feb 2021 17:58:01 +0000 (11:58 -0600)
dist/images/first.jpg [new file with mode: 0644]
dist/index.js
src/canvas.onyx
src/prez.onyx
src/slides.onyx

diff --git a/dist/images/first.jpg b/dist/images/first.jpg
new file mode 100644 (file)
index 0000000..2dd4417
Binary files /dev/null and b/dist/images/first.jpg differ
index db3df5bd7dded248a5419ce96a4d6b12a4b35254..d484d49e70dfd60aed6071faa5e0298202a6a838 100644 (file)
@@ -2,6 +2,7 @@
 let wasm_instance;
 let canvasElem;
 let canvasCtx;
+let __loaded_images = [];
 
 const MAGIC_CANVAS_NUMBER = 0x5052455A;
 
@@ -134,6 +135,36 @@ let canvas_import_obj = {
         
         if (max_width > 0) canvasCtx.fillText(str, x, y, max_width);
         else               canvasCtx.fillText(str, x, y);
+    },
+
+    drawImage(canvas, image_idx, x, y, w, h) {
+        let image = __loaded_images[image_idx];
+
+        canvasCtx.drawImage(image, x, y, w, h);
+    }
+}
+
+let html_import_obj = {
+    load_image(path_str, path_len, out_image) {
+        const data = new Uint8Array(wasm_instance.exports.memory.buffer, path_str, path_len);
+        const path = new TextDecoder().decode(data);
+
+        let image = new Image();
+        __loaded_images.push(image);
+        
+        let data_view = new DataView(wasm_instance.exports.memory.buffer, out_image, 3 * 4);
+        data_view.setInt32(0, __loaded_images.length - 1, true);
+
+        image.src = path;
+    },
+
+    store_image_size(out_image) {
+        let data_view = new DataView(wasm_instance.exports.memory.buffer, out_image, 3 * 4);
+        let image_idx = data_view.getInt32(0, true);
+
+        let image = __loaded_images[image_idx];
+        data_view.setInt32(4, image.width, true);
+        data_view.setInt32(8, image.height, true);
     }
 }
 
@@ -159,6 +190,7 @@ let import_obj = {
 
     canvas: canvas_import_obj,
     event:  event_import_obj,
+    html:   html_import_obj,
 }
 
 function main() {
index c047bd4869394e8a39531f6576c7b122eef6be28..6dfe2ad221f689edda1784e636cdee330a1ecca3 100644 (file)
@@ -30,6 +30,8 @@ Canvas :: struct {
         r: f32, g: f32, b: f32, a := 1.0f) -> void #foreign "canvas" "fillRect" ---
 
     fill_text :: (handle: Handle, text: str, x: f32, y: f32, max_width: f32 = -1.0f) -> void #foreign "canvas" "fillText" ---
+
+    draw_image :: (handle: Handle, image: i32, x: f32, y: f32, width: f32, height: f32) -> void #foreign "canvas" "drawImage" ---
 }
 
 // :GlobalVariable
index 7c29f856b223b1206e52efcd960cb1a914d8d7f2..a3e26e4d26544c5adfa00eda68861faadb22dcf2 100644 (file)
@@ -40,6 +40,8 @@ poll_events :: () {
             }
         }
 
+        case #default do redraw = 0;
+
     } else {
         redraw = 0;
     }
@@ -87,11 +89,11 @@ create_dummy_show :: () {
 
     { // Slide 2
         slide := slideshow_insert_slide(^the_slideshow);
-        slide_init(slide, background_color = Color.{ 0.2, 0.1, 0.1 }, item_count = 3);
+        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! Duh duh duhhhh";
+        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;
@@ -101,7 +103,7 @@ create_dummy_show :: () {
         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 = .4;
+        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;
@@ -110,12 +112,22 @@ create_dummy_show :: () {
         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 = .45,
+            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,
+        };
     }
 }
 
index 452244fa4fbddde8999d3c304d470c7ee0877938..5b26633e03c9a92e50e9352fca7bfb73bf545146 100644 (file)
@@ -1,5 +1,11 @@
 use package core
 
+HTML_Image :: struct {
+    handle: i32 = -1;
+    width:  i32 = 1; // To avoid dividing by 0
+    height: i32 = 1;
+}
+
 Color :: struct {
     r, g, b: f32;
     a: f32 = 1;
@@ -14,6 +20,8 @@ Slideshow :: struct {
     slides : [..] Slide;
 
     current_slide : i32;
+
+    image_map : map.Map(str, HTML_Image);
 }
 
 Slide :: struct {
@@ -26,10 +34,12 @@ Slide_Item :: struct #union {
     Kind :: enum {
         Undefined;
         Text;
+        Image;
     }
 
     use base: Slide_Item_Base;
-    text: Slide_Item_Text;
+    text  : Slide_Item_Text;
+    image : Slide_Item_Image; 
 }
 
 Slide_Item_Base :: struct {
@@ -56,9 +66,9 @@ Slide_Item_Text :: struct {
 }
 
 Slide_Item_Image :: struct {
-    use base := Slide_Item_Base.{ Slide_Item.Kind.Text };
+    use base := Slide_Item_Base.{ Slide_Item.Kind.Image };
 
-    path  : str;
+    name  : str;
     x, y  : f32; // Between 0 and 1
     width : f32; // Between 0 and 1
 
@@ -80,12 +90,16 @@ slideshow_init :: (use s: ^Slideshow, allocator := context.allocator) {
 
     arena = alloc.arena.make(allocator, arena_size = 16 * 1024);
     array.init(^slides, 4);
+
+    map.init(^image_map, default = HTML_Image.{});
 }
 
 slideshow_reset :: (use s: ^Slideshow) {
     alloc.arena.free(^arena);
     array.free(^slides);
 
+    map.free(^image_map);
+
     slideshow_init(s);
 }
 
@@ -118,6 +132,20 @@ slideshow_make_item :: (use s: ^Slideshow) -> ^Slide_Item {
     return new(Slide_Item, allocator = allocator);
 }
 
+slideshow_load_image :: (use s: ^Slideshow, image_name: str, image_path: str) -> HTML_Image {
+    if map.has(^image_map, image_name) {
+        printf("Warning: the image '%s' was already defined.", image_name);
+        return image_map.default_value;
+    }
+
+    html_image_load :: (path: str, out_image: ^HTML_Image) -> void #foreign "html" "load_image" ---
+    image: HTML_Image;
+    html_image_load(image_path, ^image);
+
+    map.put(^image_map, image_name, image);
+    return image;
+}
+
 slide_init :: (use slide: ^Slide, background_color := Color.{0, 0, 0, 1}, item_count := 4) {
     background = background_color;
 
@@ -171,7 +199,22 @@ slide_item_render :: (use slide_item: ^Slide_Item, slide: ^Slide) {
         }
 
         case Image {
-            assert(false, "Slide_Item_Image not implemented!");
+            use Canvas
+
+            if html_image := map.get(^the_slideshow.image_map, image.name); html_image.handle != -1 {
+                width, height := cast(f32) get_width(canvas), cast(f32) get_height(canvas);
+
+                // @Speed: There is a much better way of doing this...
+                store_image_size :: (html_image: ^HTML_Image) -> void #foreign "html" "store_image_size" ---
+                store_image_size(^html_image);
+
+                x := image.x * width;
+                y := image.y * height;
+                w := image.width * width;
+                h := w * (cast(f32) html_image.height / cast(f32) html_image.width);
+                
+                draw_image(canvas, html_image.handle, x, y, w, h);
+            }
         }
     }