Repository: beeware/toga

Issue:
Implement Canvas.quadratic_curve_to for GTK+
GTK+ doesn't have a method to create a quadratic bezier curve that would make use of the quadratic_curve_to method in the Canvas widget, and right now the quadratic_curve_to() native call for GTK+ doesn't draw anything.

Proposed solution: support quadratic_curve_to() by remapping the cubic bezier curve method called bezier_curve_to() to pass in the single set of control points in to both sets of the control points that bezier_curve_to() uses.


Discussion:

Resolving patch:
diff --git a/docs/tutorial/source/tutorial-4.py b/docs/tutorial/source/tutorial-4.py
--- a/docs/tutorial/source/tutorial-4.py
+++ b/docs/tutorial/source/tutorial-4.py
@@ -58,24 +58,24 @@ def draw_horns(self):
         with self.canvas.fill():
             self.canvas.fill_style('rgba(212, 212, 212, 1)')
             self.canvas.move_to(112, 99)
-            self.canvas.bezier_curve_to(145, 65, 145, 60, 139, 36)
-            self.canvas.bezier_curve_to(130, 60, 130, 60, 109, 75)
+            self.canvas.quadratic_curve_to(145, 65, 139, 36)
+            self.canvas.quadratic_curve_to(130, 60, 109, 75)
         with self.canvas.stroke():
             self.canvas.stroke_style()
             self.canvas.move_to(112, 99)
-            self.canvas.bezier_curve_to(145, 65, 145, 60, 139, 36)
-            self.canvas.bezier_curve_to(130, 60, 130, 60, 109, 75)
+            self.canvas.quadratic_curve_to(145, 65, 139, 36)
+            self.canvas.quadratic_curve_to(130, 60, 109, 75)
         # Left horn
         with self.canvas.fill():
             self.canvas.fill_style('rgba(212, 212, 212, 1)')
             self.canvas.move_to(35, 99)
-            self.canvas.bezier_curve_to(2, 65, 2, 60, 6, 36)
-            self.canvas.bezier_curve_to(17, 60, 17, 60, 37, 75)
+            self.canvas.quadratic_curve_to(2, 65, 6, 36)
+            self.canvas.quadratic_curve_to(17, 60, 37, 75)
         with self.canvas.stroke():
             self.canvas.stroke_style()
             self.canvas.move_to(35, 99)
-            self.canvas.bezier_curve_to(2, 65, 2, 60, 6, 36)
-            self.canvas.bezier_curve_to(17, 60, 17, 60, 37, 75)
+            self.canvas.quadratic_curve_to(2, 65, 6, 36)
+            self.canvas.quadratic_curve_to(17, 60, 37, 75)
 
     def draw_nostrils(self):
         with self.canvas.fill():
diff --git a/examples/tutorial4/tutorial/app.py b/examples/tutorial4/tutorial/app.py
--- a/examples/tutorial4/tutorial/app.py
+++ b/examples/tutorial4/tutorial/app.py
@@ -58,24 +58,24 @@ def draw_horns(self):
         with self.canvas.fill():
             self.canvas.fill_style('rgba(212, 212, 212, 1)')
             self.canvas.move_to(112, 99)
-            self.canvas.bezier_curve_to(145, 65, 145, 60, 139, 36)
-            self.canvas.bezier_curve_to(130, 60, 130, 60, 109, 75)
+            self.canvas.quadratic_curve_to(145, 65, 139, 36)
+            self.canvas.quadratic_curve_to(130, 60, 109, 75)
         with self.canvas.stroke():
             self.canvas.stroke_style()
             self.canvas.move_to(112, 99)
-            self.canvas.bezier_curve_to(145, 65, 145, 60, 139, 36)
-            self.canvas.bezier_curve_to(130, 60, 130, 60, 109, 75)
+            self.canvas.quadratic_curve_to(145, 65, 139, 36)
+            self.canvas.quadratic_curve_to(130, 60, 109, 75)
         # Left horn
         with self.canvas.fill():
             self.canvas.fill_style('rgba(212, 212, 212, 1)')
             self.canvas.move_to(35, 99)
-            self.canvas.bezier_curve_to(2, 65, 2, 60, 6, 36)
-            self.canvas.bezier_curve_to(17, 60, 17, 60, 37, 75)
+            self.canvas.quadratic_curve_to(2, 65, 6, 36)
+            self.canvas.quadratic_curve_to(17, 60, 37, 75)
         with self.canvas.stroke():
             self.canvas.stroke_style()
             self.canvas.move_to(35, 99)
-            self.canvas.bezier_curve_to(2, 65, 2, 60, 6, 36)
-            self.canvas.bezier_curve_to(17, 60, 17, 60, 37, 75)
+            self.canvas.quadratic_curve_to(2, 65, 6, 36)
+            self.canvas.quadratic_curve_to(17, 60, 37, 75)
 
     def draw_nostrils(self):
         with self.canvas.fill():
diff --git a/src/gtk/toga_gtk/widgets/canvas.py b/src/gtk/toga_gtk/widgets/canvas.py
--- a/src/gtk/toga_gtk/widgets/canvas.py
+++ b/src/gtk/toga_gtk/widgets/canvas.py
@@ -69,8 +69,7 @@ def bezier_curve_to(self, cp1x, cp1y, cp2x, cp2y, x, y):
         self.native.context.curve_to(cp1x, cp1y, cp2x, cp2y, x, y)
 
     def quadratic_curve_to(self, cpx, cpy, x, y):
-        # Not supported by cairo.Context
-        pass
+        self.native.context.curve_to(cpx, cpy, cpx, cpy, x, y)
 
     def arc(self, x, y, radius, startangle, endangle, anticlockwise):
         if anticlockwise:


Test patch: