diff --git a/examples/starrect.pics b/examples/starrect.pics index f8b14b6..4e35fa6 100644 --- a/examples/starrect.pics +++ b/examples/starrect.pics @@ -2,31 +2,32 @@ IO :: import std.io Virtual :: import std.virtual Render :: import piccode.render +Pen :: import piccode.pen drawStar :: (ctx, padding=0) = ctx - |> Render::drawLine(50+padding, 50+padding, 150-padding, 150-padding) - |> Render::drawLine(150-padding, 50+padding, 50+padding, 150-padding) - |> Render::drawLine(50+padding, 100, 150-padding, 100) - |> Render::drawLine(100, 50+padding, 100, 150-padding) + |> Pen::drawLine(50+padding, 50+padding, 150-padding, 150-padding) + |> Pen::drawLine(150-padding, 50+padding, 50+padding, 150-padding) + |> Pen::drawLine(50+padding, 100, 150-padding, 100) + |> Pen::drawLine(100, 50+padding, 100, 150-padding) drawRect :: (ctx, x, y, w, h) = ctx - |> Render::drawLine(x, y, x + w, y) - |> Render::drawLine(x, y + h, x + w, y + h) - |> Render::drawLine(x, y, x, y + w) - |> Render::drawLine(x + w, y, x + w, y + h) + |> Pen::drawLine(x, y, x + w, y) + |> Pen::drawLine(x, y + h, x + w, y + h) + |> Pen::drawLine(x, y, x, y + w) + |> Pen::drawLine(x + w, y, x + w, y + h) drawDepth :: (ctx) = ctx - |> Render::drawLine(150, 50, 200, 70) - |> Render::drawLine(150, 150, 200, 170) - |> Render::drawLine(50, 150, 100, 170) + |> Pen::drawLine(150, 50, 200, 70) + |> Pen::drawLine(150, 150, 200, 170) + |> Pen::drawLine(50, 150, 100, 170) drawBackLines :: (ctx) = ctx - |> Render::drawLine(100, 170, 200, 170) - |> Render::drawLine(200, 70, 200, 170) + |> Pen::drawLine(100, 170, 200, 170) + |> Pen::drawLine(200, 70, 200, 170) main :: () = let diff --git a/piccode/context/ctx.pics b/piccode/context/ctx.pics new file mode 100644 index 0000000..302b808 --- /dev/null +++ b/piccode/context/ctx.pics @@ -0,0 +1,39 @@ + +// Module: Context +// Contains functions for creating contexts +Context :: module { + + // Function: fromRect + // Creates a new context based on the one provided + // + // Parameters: + // ctx - (Reference) The graphic context + // x - (Number) The x position + // y - (Number) The y position + // w - (Number) The width + // h - (Number) The height + // + // Returns: + // - (Reference) A new graphics sub-context derived from the given context. + fromRect :: (ctx, x, y, w, h) = pic_nat_gfx_from_rect(ctx, x, y, w, h) + + // Function: from + // Creates a new context based on the one provided + // + // Parameters: + // ctx - (Reference) The graphic context + // + // Returns: + // - (Reference) A new graphics context derived from the given context. + from :: (ctx) = pic_nat_gfx_from(ctx) + + // Function: drop + // Frees the given context + // + // Parameters: + // ctx - (Reference) The graphic context + // + // Returns: + // - (Unit) Nothing + drop :: (ctx) = pic_nat_gfx_(ctx) +} diff --git a/piccode/pen/draw.pics b/piccode/pen/draw.pics new file mode 100644 index 0000000..7f14334 --- /dev/null +++ b/piccode/pen/draw.pics @@ -0,0 +1,63 @@ + +Pen :: module { + + // Function: drawLine + // Draws a line inside the specified context, based on the provided coordinates + // + // Parameters: + // ctx - (Reference) The graphic context + // startx - (Number) The start x position + // starty - (Number) The start y position + // endx - (Number) The end x position + // endy - (Number) The end y position + // + // Returns: + // - (Reference) A modified context with the rendered element. + drawLine :: (ctx, startx, starty, endx, endy) = pic_nat_draw_line(ctx, startx, starty, endx, endy) + + // Function: drawRect + // Draws a rect inside the specified context, based on the provided coordinates + // + // Parameters: + // ctx - (Reference) The graphic context + // x - (Number) The x position + // y - (Number) The y position + // w - (Number) The width + // h - (Number) The height + // + // Returns: + // - (Reference) A modified context with the rendered element. + drawRect :: (ctx, x, y, w, h) = pic_nat_draw_rect(ctx, x, y, w, h) + + // Function: drawRoundRect + // Draws a rounded rectangle inside the specified context, based on the provided coordinates + // + // Parameters: + // ctx - (Reference) The graphic context + // x - (Number) The x position + // y - (Number) The y position + // w - (Number) The width + // h - (Number) The height + // aw - (Number) The arc width + // ah - (Number) The arc height + // + // Returns: + // - (Reference) A modified context with the rendered element. + drawRoundRect :: (ctx, x, y, w, h, aw, ah) = pic_nat_draw_round_rect(ctx, x, y, w, h, aw, ah) + + // Function: drawOval + // Draws a rect inside the specified context, based on the provided coordinates + // + // Parameters: + // ctx - (Reference) The graphic context + // x - (Number) The x position + // y - (Number) The y position + // w - (Number) The width + // h - (Number) The height + // + // Returns: + // - (Reference) A modified context with the rendered element. + drawOval :: (ctx, x, y, w, h) = pic_nat_draw_oval(ctx, x, y, w, h) + +} + diff --git a/piccode/render/context.pics b/piccode/render/context.pics index 15371a1..3c791c8 100644 --- a/piccode/render/context.pics +++ b/piccode/render/context.pics @@ -9,21 +9,8 @@ Render :: module { // None // // Returns: - // - (Object) an handler to the Graphics2D. + // - (Reference) a handler to the Graphics2D. getContext :: () = pic_nat_get_gfx() - // Function: drawLine - // Draws a line inside the specified context, based on the provided coordinates - // - // Parameters: - // ctx - (Object) The graphic context - // startx - (Number) The start x position - // starty - (Number) The start y position - // endx - (Number) The end x position - // endy - (Number) The end y position - // - // Returns: - // - (Object) A modified context with the rendered element. - drawLine :: (ctx, startx, starty, endx, endy) = pic_nat_draw_line(ctx, startx, starty, endx, endy) } diff --git a/src/main/java/org/editor/menu/Menus.java b/src/main/java/org/editor/menu/Menus.java index 01371cc..dac8564 100644 --- a/src/main/java/org/editor/menu/Menus.java +++ b/src/main/java/org/editor/menu/Menus.java @@ -118,7 +118,7 @@ private static void addEditMenu(JMenuBar menu_bar) { } private static void addNavigateMenu(JMenuBar menu_bar) { - JMenu navMenu = new JMenu("Navigage"); + JMenu navMenu = new JMenu("Navigate"); JMenu tabs = new JMenu("Tabs"); tabs.setIcon(Icons.getIcon("layout")); diff --git a/src/main/java/org/editor/nativemods/PiccodeGfxModule.java b/src/main/java/org/editor/nativemods/PiccodeGfxModule.java index 22987c6..6218fb8 100644 --- a/src/main/java/org/editor/nativemods/PiccodeGfxModule.java +++ b/src/main/java/org/editor/nativemods/PiccodeGfxModule.java @@ -9,6 +9,7 @@ import org.piccode.rt.PiccodeException; import org.piccode.rt.PiccodeNumber; import org.piccode.rt.PiccodeObject; +import org.piccode.rt.PiccodeReference; import org.piccode.rt.PiccodeString; import org.piccode.rt.PiccodeUnit; import org.piccode.rt.PiccodeValue; @@ -24,65 +25,82 @@ public class PiccodeGfxModule { public static void addFunctions() { NativeFunctionFactory.create("get_gfx", List.of(), (args, namedArgs, frame) -> { var gfx = CanvasFrame.gfx; - var obj = Context.getObject(gfx.hashCode()); - if (obj == null) { - Context.allocate(gfx); - return makeObj(gfx); - } - return makeObj(gfx); + return new PiccodeReference(gfx); }, null); - NativeFunctionFactory.create("draw_line", List.of("ctx", "x1", "y1", "x2", "y2"), (args, namedArgs, frame) -> { + NativeFunctionFactory.create("gfx_from_rect", List.of("ctx", "x", "y", "w", "h"), (args, namedArgs, frame) -> { var _ctx = namedArgs.get("ctx"); - var _x1 = namedArgs.get("x1"); - var _y1 = namedArgs.get("y1"); - var _x2 = namedArgs.get("x2"); - var _y2 = namedArgs.get("y2"); - - var ctx = frame == null ? - Context.top - : Context.getContextAt(frame); + var x = namedArgs.get("x"); + var y = namedArgs.get("y"); + var w = namedArgs.get("w"); + var h = namedArgs.get("h"); + + var ctx = frame == null + ? Context.top + : Context.getContextAt(frame); var caller = ctx.getTopFrame().caller; - - PiccodeValue.verifyType(caller, _ctx, Type.OBJECT); - PiccodeValue.verifyType(caller, _x1, Type.NUMBER); - PiccodeValue.verifyType(caller, _y1, Type.NUMBER); - PiccodeValue.verifyType(caller, _x2, Type.NUMBER); - PiccodeValue.verifyType(caller, _y2, Type.NUMBER); - - var obj = (PiccodeObject) _ctx; - var map = obj.obj; - if (!map.containsKey("hash")) { - throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not an object"); - } - - var _hash = map.get("hash"); - PiccodeValue.verifyType(caller, _hash, Type.NUMBER); - var hash = (int) (double) ((PiccodeNumber) _hash).raw(); - var _gfx = Context.getObject(hash); - if (_gfx == null) { - throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not allocated"); + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + PiccodeValue.verifyType(caller, x, Type.NUMBER); + PiccodeValue.verifyType(caller, y, Type.NUMBER); + PiccodeValue.verifyType(caller, w, Type.NUMBER); + PiccodeValue.verifyType(caller, h, Type.NUMBER); + + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); } + + var gfx = (Graphics2D) _gfx; + var _x = (int) (double) ((PiccodeNumber) x).raw(); + var _y = (int) (double) ((PiccodeNumber) y).raw(); + var _w = (int) (double) ((PiccodeNumber) w).raw(); + var _h = (int) (double) ((PiccodeNumber) h).raw(); + + var gfx2 = (Graphics2D) gfx.create(_x, _y, _w, _h); + return new PiccodeReference(gfx2); + }, null); + NativeFunctionFactory.create("gfx_from", List.of("ctx"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); + + var ctx = frame == null + ? Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); if (!(_gfx instanceof Graphics2D)) { throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); } var gfx = (Graphics2D) _gfx; - var x1 = (int) (double) ((PiccodeNumber) _x1).raw(); - var y1 = (int) (double) ((PiccodeNumber) _y1).raw(); - var x2 = (int) (double) ((PiccodeNumber) _x2).raw(); - var y2 = (int) (double) ((PiccodeNumber) _y2).raw(); - gfx.drawLine(x1, y1, x2, y2); - return obj; + var gfx2 = (Graphics2D) gfx.create(); + return new PiccodeReference(gfx2); }, null); - } + NativeFunctionFactory.create("gfx_drop", List.of("ctx"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); - private static PiccodeValue makeObj(Graphics2D obj) { - var _obj = new HashMap(); - _obj.put("hash", new PiccodeNumber(obj.hashCode())); - _obj.put("class", new PiccodeString(obj.getClass().getName())); - return new PiccodeObject(_obj); + var ctx = frame == null + ? Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); + } + + var gfx = (Graphics2D) _gfx; + gfx.dispose(); + return new PiccodeUnit(); + }, null); } + } diff --git a/src/main/java/org/editor/nativemods/PiccodePenModule.java b/src/main/java/org/editor/nativemods/PiccodePenModule.java new file mode 100644 index 0000000..11107c0 --- /dev/null +++ b/src/main/java/org/editor/nativemods/PiccodePenModule.java @@ -0,0 +1,170 @@ +package org.editor.nativemods; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.HashMap; +import java.util.List; +import org.editor.CanvasFrame; +import org.piccode.rt.Context; +import org.piccode.rt.PiccodeException; +import org.piccode.rt.PiccodeNumber; +import org.piccode.rt.PiccodeObject; +import org.piccode.rt.PiccodeReference; +import org.piccode.rt.PiccodeString; +import org.piccode.rt.PiccodeUnit; +import org.piccode.rt.PiccodeValue; +import org.piccode.rt.PiccodeValue.Type; +import org.piccode.rt.modules.NativeFunctionFactory; + +/** + * + * @author hexaredecimal + */ +public class PiccodePenModule { + + public static void addFunctions() { + + NativeFunctionFactory.create("draw_line", List.of("ctx", "x1", "y1", "x2", "y2"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); + var _x1 = namedArgs.get("x1"); + var _y1 = namedArgs.get("y1"); + var _x2 = namedArgs.get("x2"); + var _y2 = namedArgs.get("y2"); + + var ctx = frame == null ? + Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + PiccodeValue.verifyType(caller, _x1, Type.NUMBER); + PiccodeValue.verifyType(caller, _y1, Type.NUMBER); + PiccodeValue.verifyType(caller, _x2, Type.NUMBER); + PiccodeValue.verifyType(caller, _y2, Type.NUMBER); + + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); + } + + var gfx = (Graphics2D) _gfx; + var x1 = (int) (double) ((PiccodeNumber) _x1).raw(); + var y1 = (int) (double) ((PiccodeNumber) _y1).raw(); + var x2 = (int) (double) ((PiccodeNumber) _x2).raw(); + var y2 = (int) (double) ((PiccodeNumber) _y2).raw(); + + gfx.drawLine(x1, y1, x2, y2); + return obj; + }, null); + + NativeFunctionFactory.create("draw_rect", List.of("ctx", "x", "y", "w", "h"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); + var x = namedArgs.get("x"); + var y = namedArgs.get("y"); + var w = namedArgs.get("w"); + var h = namedArgs.get("h"); + + var ctx = frame == null ? + Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + PiccodeValue.verifyType(caller, x, Type.NUMBER); + PiccodeValue.verifyType(caller, y, Type.NUMBER); + PiccodeValue.verifyType(caller, w, Type.NUMBER); + PiccodeValue.verifyType(caller, h, Type.NUMBER); + + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); + } + + var gfx = (Graphics2D) _gfx; + var _x = (int) (double) ((PiccodeNumber) x).raw(); + var _y = (int) (double) ((PiccodeNumber) y).raw(); + var _w = (int) (double) ((PiccodeNumber) w).raw(); + var _h = (int) (double) ((PiccodeNumber) h).raw(); + + gfx.drawRect(_x, _y, _w, _h); + return obj; + }, null); + + NativeFunctionFactory.create("draw_round_rect", List.of("ctx", "x", "y", "w", "h", "aw", "ah"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); + var x = namedArgs.get("x"); + var y = namedArgs.get("y"); + var w = namedArgs.get("w"); + var h = namedArgs.get("h"); + var aw = namedArgs.get("aw"); + var ah = namedArgs.get("ah"); + + var ctx = frame == null ? + Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + PiccodeValue.verifyType(caller, x, Type.NUMBER); + PiccodeValue.verifyType(caller, y, Type.NUMBER); + PiccodeValue.verifyType(caller, w, Type.NUMBER); + PiccodeValue.verifyType(caller, h, Type.NUMBER); + PiccodeValue.verifyType(caller, aw, Type.NUMBER); + PiccodeValue.verifyType(caller, ah, Type.NUMBER); + + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); + } + + var gfx = (Graphics2D) _gfx; + var _x = (int) (double) ((PiccodeNumber) x).raw(); + var _y = (int) (double) ((PiccodeNumber) y).raw(); + var _w = (int) (double) ((PiccodeNumber) w).raw(); + var _h = (int) (double) ((PiccodeNumber) h).raw(); + var _aw = (int) (double) ((PiccodeNumber) aw).raw(); + var _ah = (int) (double) ((PiccodeNumber) ah).raw(); + + gfx.drawRoundRect(_x, _y, _w, _h, _aw, _ah); + return obj; + }, null); + + NativeFunctionFactory.create("draw_oval", List.of("ctx", "x", "y", "w", "h"), (args, namedArgs, frame) -> { + var _ctx = namedArgs.get("ctx"); + var x = namedArgs.get("x"); + var y = namedArgs.get("y"); + var w = namedArgs.get("w"); + var h = namedArgs.get("h"); + + var ctx = frame == null ? + Context.top + : Context.getContextAt(frame); + var caller = ctx.getTopFrame().caller; + + PiccodeValue.verifyType(caller, _ctx, Type.REFERENCE); + PiccodeValue.verifyType(caller, x, Type.NUMBER); + PiccodeValue.verifyType(caller, y, Type.NUMBER); + PiccodeValue.verifyType(caller, w, Type.NUMBER); + PiccodeValue.verifyType(caller, h, Type.NUMBER); + + var obj = (PiccodeReference) _ctx; + var _gfx = obj.deref(); + if (!(_gfx instanceof Graphics2D)) { + throw new PiccodeException(caller.file, caller.line, caller.column, "Context is not a correct object. Expected Graphics2D"); + } + + var gfx = (Graphics2D) _gfx; + var _x = (int) (double) ((PiccodeNumber) x).raw(); + var _y = (int) (double) ((PiccodeNumber) y).raw(); + var _w = (int) (double) ((PiccodeNumber) w).raw(); + var _h = (int) (double) ((PiccodeNumber) h).raw(); + + gfx.drawOval(_x, _y, _w, _h); + return obj; + }, null); + } + +} diff --git a/src/main/java/org/piccode/piccode/Piccode.java b/src/main/java/org/piccode/piccode/Piccode.java index 7375af2..ba34188 100644 --- a/src/main/java/org/piccode/piccode/Piccode.java +++ b/src/main/java/org/piccode/piccode/Piccode.java @@ -3,6 +3,7 @@ import org.editor.AccessFrame; import org.editor.EditorWindow; import org.editor.nativemods.PiccodeGfxModule; +import org.editor.nativemods.PiccodePenModule; import org.piccode.backend.Compiler; import org.piccode.piccodescript.ErrorAsciiKind; @@ -22,5 +23,6 @@ public static void main(String[] args) { private static void initializeNativeAppModules() { Compiler.addNativeFunctions(PiccodeGfxModule::addFunctions); + Compiler.addNativeFunctions(PiccodePenModule::addFunctions); } }