diff --git a/sim/fakes/ctx.py b/sim/fakes/ctx.py
index ed92f05c5f11d3249861fb5c3e3dfb5ded96dca2..f9ddb1d76b997a9e119f2dcb14f41403d72241cc 100644
--- a/sim/fakes/ctx.py
+++ b/sim/fakes/ctx.py
@@ -100,10 +100,45 @@ class Ctx:
     def __init__(self, _ctx):
         self._ctx = _ctx
 
-        self.text_align = 'start'
-        self.text_baseline = 'alphabetic'
-        self.font_size = 10.0
-        self.line_join = 'bevel'
+    @property
+    def text_align(self):
+        return None
+
+    @text_align.setter
+    def text_align(self, v):
+        self._emit(f"textAlign {v}")
+    
+    @property
+    def text_baseline(self):
+        return None
+
+    @text_baseline.setter
+    def text_baseline(self, v):
+        self._emit(f"textBaseline {v}")
+
+    @property
+    def line_width(self):
+        return None
+
+    @line_width.setter
+    def line_width(self, v):
+        self._emit(f"lineWidth {v:.3f}")
+
+    @property
+    def font_size(self):
+        return None
+    
+    @font_size.setter
+    def font_size(self, v):
+        self._emit(f"fontSize {v:.3f}")
+
+    @property
+    def global_alpha(self):
+        return None
+    
+    @global_alpha.setter
+    def global_alpha(self, v):
+        self._emit(f"globalAlpha {v:.3f}")
 
     def _emit(self, text):
         _wasm.ctx_parse(self._ctx, text)
@@ -112,10 +147,34 @@ class Ctx:
         self._emit(f"moveTo {int(x)} {int(y)}")
         return self
 
+    def translate(self, x, y):
+        self._emit(f"translate {int(x)} {int(y)}")
+        return self
+
     def line_to(self, x, y):
         self._emit(f"lineTo {int(x)} {int(y)}")
         return self
 
+    def rotate(self, v):
+        self._emit(f"rotate {v:.3f}")
+        return self
+
+    def gray(self, v):
+        self._emit(f"gray {v:.3f}")
+        return self
+
+
+    def rgba(self, r, g, b, a):
+        # TODO(q3k): dispatch by type instead of value, warn on
+        # ambiguous/unexpected values for type.
+        if r > 1.0 or g > 1.0 or b > 1.0 or a > 1.0:
+            r /= 255.0
+            g /= 255.0
+            b /= 255.0
+            a /= 255.0
+        self._emit(f"rgba {r:.3f} {g:.3f} {b:.3f} {a:.3f}")
+        return self
+
     def rgb(self, r, g, b):
         # TODO(q3k): dispatch by type instead of value, warn on
         # ambiguous/unexpected values for type.
@@ -127,9 +186,6 @@ class Ctx:
         return self
 
     def text(self, s):
-        self._emit(f"textAlign {self.text_align}")
-        self._emit(f"textBaseline {self.text_baseline}")
-        self._emit(f"fontSize {self.font_size}")
         self._emit(f"text \"{s}\"")
         return self
 
@@ -142,10 +198,25 @@ class Ctx:
         return self
 
     def stroke(self):
-        self._emit(f"lineJoin {self.line_join}")
         self._emit(f"stroke")
         return self
 
+    def start_group(self):
+        self._emit(f"start_group")
+        return self
+
+    def end_group(self):
+        self._emit(f"end_group")
+        return self
+
+    def save(self):
+        self._emit(f"save")
+        return self
+
+    def restore(self):
+        self._emit(f"restore")
+        return self
+
     def fill(self):
         self._emit(f"fill")
         return self
@@ -155,5 +226,4 @@ class Ctx:
         return self
 
     def text_width(self, text):
-        self._emit(f"fontSize {self.font_size}")
-        return _wasm.ctx_text_width(self._ctx, text)
\ No newline at end of file
+        return _wasm.ctx_text_width(self._ctx, text)