Exemple #1
0
    def draw_keylayer(self, canvas, rect, typeface):
        canvas.save()

        if self.keylayer == Keylayer.Cmd:
            canvas.drawRect(
                skia.Rect.MakeXYWH(0, rect.h - 50, rect.w, 50),
                skia.Paint(AntiAlias=True,
                           Color=hsl(0.9, l=0.25, a=0.85).skia()))
            canvas.drawString(
                "".join(self.keybuffer), 10, rect.h - 14,
                skia.Font(typeface, 30),
                skia.Paint(AntiAlias=True, Color=skia.ColorWHITE))

        elif self.keylayer == Keylayer.Text:
            canvas.drawRect(
                skia.Rect.MakeXYWH(0, 0, rect.w, 50),
                skia.Paint(AntiAlias=True,
                           Color=hsl(0.7, l=0.25, a=0.85).skia()))
            canvas.drawString(
                "".join(self.keybuffer), 10, 34, skia.Font(typeface, 30),
                skia.Paint(AntiAlias=True, Color=skia.ColorWHITE))

        elif self.keylayer == Keylayer.Editing:
            canvas.drawRect(
                skia.Rect(0, 0, 50, 50),
                skia.Paint(AntiAlias=True,
                           Color=hsl(0.95, l=0.5, a=0.75).skia()))
        canvas.restore()
Exemple #2
0
class Renderer(object):
    GREEN = skia.Paint(Color=skia.ColorGREEN)
    TEXT_COLOR = skia.Paint(Color=skia.ColorWHITE)

    def __init__(self, window):
        self.window = window
        self.context = skia.GrDirectContext.MakeGL()
        self.width, self.height = glfw.get_window_size(window)
        backend_render_target = skia.GrBackendRenderTarget(
            self.width,
            self.height,
            0,  # sampleCnt
            0,  # stencilBits
            skia.GrGLFramebufferInfo(0, GL.GL_RGBA8))
        self.surface = skia.Surface.MakeFromBackendRenderTarget(
            self.context, backend_render_target, skia.kBottomLeft_GrSurfaceOrigin,
            skia.kRGBA_8888_ColorType, skia.ColorSpace.MakeSRGB())
        # typeface = skia.Typeface.MakeFromFile('JetBrainsMono-Regular.ttf')
        self.font = skia.Font(skia.Typeface.MakeDefault(), size=40)
        print(self.font)
        self.text = skia.TextBlob.MakeFromString('drawTextBlob', self.font)
        self.start = time.time()
        assert self.surface is not None

    def __del__(self):
        self.context.abandonContext()

    def render(self):
        t = time.time() - self.start
        with self.surface as canvas:
            canvas.drawCircle(self.width/2 + 100 * math.cos(t), self.height/2 + 100 * math.sin(t), 40,
                              self.GREEN)
            canvas.drawString('drawString', x=100, y=100, font=self.font, paint=self.TEXT_COLOR)
            canvas.drawTextBlob(self.text, x=100, y=200, paint=self.TEXT_COLOR)
        self.surface.flushAndSubmit()
Exemple #3
0
    def draw_line(self, canvas, structure, x_values, y_values, style):
        ## Cache colors
        if not style.cached_renderer:
            style.cache_renderer(self)
        elif style.cached_renderer != self:
            style.cache_renderer(self)

        ## Create a path
        path = skia.Path()

        ## Load points into path
        pointer = 0
        for p_count in structure:
            path.moveTo(x_values[pointer], y_values[pointer])
            for index in range(pointer, pointer + p_count):
                path.lineTo(x_values[index], y_values[index])
            pointer += p_count

        ## Create outline paint
        paint = skia.Paint(style._outline_color_cache)
        paint.setStyle(skia.Paint.kStroke_Style)
        paint.setStrokeWidth(style.weight + style.outline_weight)
        paint.setAntiAlias(True)

        ## Draw outline path
        canvas.drawPath(path, paint)

        ## Create line paint
        paint = skia.Paint(style._color_cache)
        paint.setStyle(skia.Paint.kStroke_Style)
        paint.setStrokeWidth(style.weight)
        paint.setAntiAlias(True)

        ## Draw line path
        canvas.drawPath(path, paint)
Exemple #4
0
    def draw_point(self, canvas, structure, x_values, y_values, style):
        ## Cache colors
        if not style.cached_renderer:
            style.cache_renderer(self)
        elif style.cached_renderer != self:
            style.cache_renderer(self)

        ## Create a path
        path = skia.Path()

        ## Add points to path
        pointer = 0
        for p_count in structure:
            for index in range(pointer, pointer + p_count):
                path.addCircle(x_values[index], y_values[index], style.weight)
            pointer += p_count

        ## Draw background
        paint = skia.Paint(AntiAlias=True)
        paint.setColor(style._color_cache)
        canvas.drawPath(path, paint)

        ## Draw outline
        paint.setStyle(skia.Paint.kStroke_Style)
        paint.setColor(style._outline_color_cache)
        paint.setStrokeWidth(style.outline_weight)
        canvas.drawPath(path, paint)
    def anchored_text(self, canvas, text, x: int, y: int, anchor_x: float,
                      anchor_y: float, **kwargs):

        # If user sent a single string, it means a 1 item list
        if not isinstance(text, list):
            text = [text]

        # Get paint, font
        paint = kwargs.get("paint",
                           skia.Paint(AntiAlias=True, Color=skia.ColorWHITE))
        font = kwargs.get("font", skia.Font(skia.Typeface('Arial'), 24))

        # Width and height of text
        height_size = font.getSpacing()

        for line_number, text_string in enumerate(text):

            text_size = font.measureText(text_string)

            # Where we'll plot the top left text according to the anchor and whatnot
            real_x = x - (text_size * anchor_x)
            real_y = y - (height_size *
                          anchor_y) + height_size + (line_number * height_size)

            canvas.drawString(text_string, real_x, real_y, font, paint)
Exemple #6
0
    def blit(self) -> None:

        # Vectorial objects blit themselves on a .next() function
        if self.is_vectorial:
            return

        # Invert x and y because top left is (0, 0), y first
        y = int(self.x + self.offset[1])
        x = int(self.y + self.offset[0])

        if self.mask_filters:
            self.paint_dict["MaskFilter"] = self.mask_filters

        if self.image_filters:
            self.paint_dict["ImageFilter"] = skia.ImageFilters.Merge(
                self.image_filters)

        # Get a paint with the options, image filters (if any) for skia to draw
        paint = skia.Paint(self.paint_dict)

        # Blit this image
        self.mmvskia_main.skia.canvas.drawImage(
            self.image.image,
            x,
            y,
            paint=paint,
        )
Exemple #7
0
 def draw(self):
     for i in self.items:
         if 'fill' in i.style:
             paint = skia.Paint()
             paint.setStyle(skia.Paint.kFill_Style)
             paint.setAntiAlias(True)
             paint.setColor(i.style['fill'])
             self.canvas.drawPath(i.draw(), paint)
         if 'stroke' in i.style:
             paint = skia.Paint()
             paint.setStyle(skia.Paint.kStroke_Style)
             paint.setStrokeWidth(i.style['stroke_width'])
             paint.setColor(i.style['stroke'])
             paint.setAntiAlias(True)
             self.canvas.drawPath(i.draw(), paint)
     self.drawn = True
    def draw_markers(self):

        # The paint of markers in between white keys
        white_white_paint = skia.Paint(
            AntiAlias = True,
            Color = self.colors["marker_color_between_two_white"],
            Style = skia.Paint.kStroke_Style,
            StrokeWidth = 1,
        )

        current_center = 0

        # Check if prev and this key is white, keeps track of a current_center, create rect to draw and draw
        for index, key_index in enumerate(self.piano_keys.keys()):
            key = self.piano_keys[key_index]
            if not index == 0:
                prevkey = self.piano_keys[key_index - 1]
                if (prevkey.is_white) and (key.is_white):
                    current_center += self.tone_width
                    rect = skia.Rect(
                        current_center - self.semitone_width,
                        0,
                        current_center - self.semitone_width,
                        self.mmvskia_main.context.height
                    )
                    self.mmvskia_main.skia.canvas.drawRect(rect, white_white_paint)
                else:
                    current_center += self.semitone_width

        # Ask each key to draw their CENTERED marker
        for key_index in self.piano_keys.keys():
            self.piano_keys[key_index].draw_marker()
    def draw_marker(self):

        # If the note is a G, it's a mid way reference on the piano
        # This considers G# keys only
        if "G" in self.name and self.is_black:
            color = self.colors["marker_color_g_sharp"]
        elif self.is_black:
            color = self.colors["marker_color_sharp_keys"]
        else:
            return
        
        if color is None:
            return

        # The marker paint
        marker = skia.Paint(
            AntiAlias = True,
            Color = color,
            Style = skia.Paint.kFill_Style,
            # StrokeWidth = 2,
        )

        # Draw through the entire vertical space of the screen
        rect = skia.Rect(
            max(self.center_x - (self.width / 10), 1),
            0,
            max(self.center_x + (self.width / 10), 1),
            self.resolution_height - self.height
        )
        self.mmvskia_main.skia.canvas.drawRect(rect, marker)
    def draw_markers(self):

        c = 0.35
        white_white_color = skia.Color4f(c, c, c, 1)

        white_white_paint = skia.Paint(
            AntiAlias=True,
            Color=white_white_color,
            Style=skia.Paint.kStroke_Style,
            StrokeWidth=1,
        )

        current_center = 0

        for index, key_index in enumerate(self.piano_keys.keys()):
            key = self.piano_keys[key_index]
            if not index == 0:
                prevkey = self.piano_keys[key_index - 1]
                if (prevkey.is_white) and (key.is_white):
                    current_center += self.tone_width
                    rect = skia.Rect(current_center - self.semitone_width, 0,
                                     current_center + 1 - self.semitone_width,
                                     self.vectorial.context.height)
                    self.skia.canvas.drawRect(rect, white_white_paint)
                else:
                    current_center += self.semitone_width

        for key_index in self.piano_keys.keys():
            self.piano_keys[key_index].draw_marker()
Exemple #11
0
    def draw_text(self, canvas, text_line, x_pos, y_pos, text_style=None):
        """ """
        ## Create a list to hold Typeface constructor args
        typeface_args = [text_line.font]

        ## Append FontStyle objects to list depending on params
        if text_line.italic and text_line.bold:
            typeface_args.append(skia.FontStyle.BoldItalic())
        elif text_line.bold:
            typeface_args.append(skia.FontStyle.Bold())
        elif text_line.italic:
            typeface_args.append(skia.FontStyle.Italic())

        ## Create FontStyle object from constructor args
        typeface = skia.Typeface(*typeface_args)

        ## Create a font and set params
        font = skia.Font()
        font.setSize(float(text_line.size))
        font.setTypeface(typeface)

        ## Create a paint object
        paint = skia.Paint(self.cache_color(text_line.color))

        if text_style:
            width = font.measureText(text_line.text)
            height = font.getSize() * 1.334  #! I really hate this hack
            x_pos -= width / 2
            y_pos += height / 2

        ## Draw Text Line!
        canvas.drawSimpleText(text_line.text, x_pos, y_pos, font, paint)
Exemple #12
0
 def _makePaint(self, style):
     paint = skia.Paint(
         Color=0,
         AntiAlias=True,
         Style=style,
     )
     paint.setARGB(*self.color)
     paint.setBlendMode(_blendModeMapping[self.blendMode])
     return paint
Exemple #13
0
	def _paint(x, fill=True, thickness=0) -> skia.Paint:
		style = skia.Paint.kStrokeAndFill_Style if fill else skia.Paint.kStroke_Style
		color = Color._from_whatever(x)
		cache_key = (color, fill, thickness)
		if cache_key not in Color._cache:
			p = skia.Paint(AntiAlias=True, StrokeWidth=thickness, Color=color, Style=style)
			Color._cache[cache_key] = p
			return p
		return Color._cache[cache_key]
Exemple #14
0
    def drawBackgroundHighlighted(self, canvas, odd, rect):
        paint = skia.Paint()
        paint.setStyle(skia.Paint.kFill_Style)
        paint.setAntiAlias(True)
        paint.setColor(self.highlight_bg_color)

        canvas.drawRect(rect, paint)
        #Sidebar
        paint.setColor(self.highlight_sidebar_color)
        canvas.drawRect(skia.Rect(0, 0, 5, rect.height()), paint)
Exemple #15
0
    def drawBackground(self, canvas, odd, rect):
        paint = skia.Paint()
        paint.setStyle(skia.Paint.kFill_Style)
        paint.setAntiAlias(True)
        if odd:
            paint.setColor(self.odd_bg)
        else:
            paint.setColor(self.even_bg)

        canvas.drawRect(rect, paint)
    def draw(self, notes_playing):

        if self.is_black:
            away = (self.height * (0.33))
        else:
            away = 0

        coords = [
            self.center_x - (self.width / 2),
            self.resolution_height - self.height,
            self.center_x + (self.width / 2),
            self.resolution_height - away,
        ]

        self.active = self.note in notes_playing

        if self.active:
            color = self.color_active
        else:
            color = self.color_idle

        # Make the skia Paint and
        paint = skia.Paint(
            AntiAlias=True,
            Color=color,
            Style=skia.Paint.kFill_Style,
            StrokeWidth=2,
        )

        border = skia.Paint(
            AntiAlias=True,
            Color=skia.Color4f(0, 0, 0, 1),
            Style=skia.Paint.kStroke_Style,
            StrokeWidth=2,
        )

        # Rectangle border
        rect = skia.Rect(*coords)

        # Draw the border
        self.skia.canvas.drawRect(rect, paint)
        self.skia.canvas.drawRect(rect, border)
Exemple #17
0
 def _makePaint(self):
     paint = skia.Paint(
         Color=0,
         AntiAlias=True,
         Style=self._skPaintStyle,
     )
     paint.setARGB(*self.color)
     paint.setBlendMode(_blendModeMapping[self.blendMode])
     if self.shader is not None:
         paint.setShader(self.shader)
     return paint
Exemple #18
0
    def draw(self, notes_playing):

        # If the note is black we leave a not filled spot on the bottom, this is the ratio of it
        away = (self.height * (0.33)) if self.is_black else 0

        # Based on the away, center, width, height etc, get the coords of this piano key
        coords = [
            self.center_x - (self.width / 2),
            self.resolution_height - self.height,
            self.center_x + (self.width / 2),
            self.resolution_height - away,
        ]

        # Is the note active
        self.active = self.note in notes_playing

        # Get the color based on if the note is active or not
        color = self.color_active if self.active else self.color_idle

        # Make the skia Paint and
        key_paint = skia.Paint(
            AntiAlias=True,
            Color=color,
            Style=skia.Paint.kFill_Style,
            StrokeWidth=2,
        )

        # The border of the key
        key_border = skia.Paint(
            AntiAlias=True,
            Color=skia.Color4f(0, 0, 0, 1),
            Style=skia.Paint.kStroke_Style,
            StrokeWidth=2,
        )

        # Rectangle border
        rect = skia.Rect(*coords)

        # Draw the border
        self.mmvskia_main.skia.canvas.drawRect(rect, key_paint)
        self.mmvskia_main.skia.canvas.drawRect(rect, key_border)
Exemple #19
0
 def image(self, imagePath, position, alpha=1.0):
     im = self._getImage(imagePath)
     paint = skia.Paint()
     if alpha != 1.0:
         paint.setAlpha(round(alpha * 255))
     if self._gstate.fillPaint.blendMode != "normal":
         paint.setBlendMode(self._gstate.fillPaint.skPaint.getBlendMode())
     x, y = position
     with self._savedCanvasState():
         self._canvas.translate(x, y + im.height())
         if self._flipCanvas:
             self._canvas.scale(1, -1)
         self._canvas.drawImage(im, 0, 0, paint)
    def renderSnapshot(self, msg, canvas, ms, line):
        frame = msg.snapshot(ms)

        w = frame.width()
        h = frame.height()
        src = skia.Rect.MakeXYWH(0, 0, w, h)
        fW = w * msg.fade
        sW = (fW + w)
        sH = (line + h)

        dst = skia.Rect(fW, line, sW, sH)
        tempPaint = skia.Paint()
        tempPaint.setFilterQuality(skia.FilterQuality.kHigh_FilterQuality)
        canvas.drawImageRect(frame, src, dst, tempPaint)
    def __init__(self, cachedTypefaces=None, _doInitialize=True):
        if cachedTypefaces is None:
            cachedTypefaces = {}
        self.doFill = True
        self.doStroke = False
        self._cachedTypefaces = cachedTypefaces

        if not _doInitialize:
            # self.copy() will initialize further
            return

        self.fillPaint = skia.Paint(
            Color=0xFF000000,
            AntiAlias=True,
            Style=skia.Paint.kFill_Style,
        )
        self.strokePaint = skia.Paint(
            Color=0xFF000000,
            AntiAlias=True,
            Style=skia.Paint.kStroke_Style,
        )
        self.strokePaint.setStrokeMiter(5)  # default better matching DrawBot
        self.textStyle = TextStyle(cachedTypefaces)
Exemple #22
0
    def render_frame(self, ms):
        with skia_canvas(self.chatWidth, self.chatHeight) as canvas:
            paint = skia.Paint()
            paint.setStyle(skia.Paint.kFill_Style)
            paint.setColor(self.options['bg'])
            canvas.drawRect(self.frame_rect, paint)

            line = 0
            for msg in self.current_frame_msgs:
                self.renderSnapshot(msg, canvas, ms, line)
                line += msg.lheight * self.lineHeight

            canvas.readPixels(
                skia.ImageInfo.MakeN32Premul(self.chatWidth, self.chatHeight),
                self.buffer)
Exemple #23
0
    def particles(self):

        print(f"Saving generated particle N=[", end="", flush=True)

        # Repeat for N images
        for i in range(self.n_images):

            # Reset canvas to transparent
            self.skia.reset_canvas()

            # How much nodes of gradients in this particle
            npoints = random.randint(1, 6)

            # Random scalars for each node, plus ending at zero
            scalars = [random.uniform(0.2, 1) for _ in range(npoints)] + [0]

            # Colors list
            colors = []

            # Iterate in decreasing order
            for scalar in reversed(sorted(scalars)):
                colors.append(skia.Color4f(1, 1, 1, scalar))

            # Create the skia paint with a circle at the center that ends on the edge
            paint = skia.Paint(Shader=skia.GradientShader.MakeRadial(
                center=(self.width / 2, self.height / 2),
                radius=self.width / 2,
                colors=colors,
            ))

            # Draw the particles
            self.canvas.drawPaint(paint)

            # # Save the image

            # Get the PIL image from the array of the canvas
            img = Image.fromarray(self.skia.canvas_array())

            # Pretty print
            if not i == self.n_images - 1:
                print(f"{i}, ", end="", flush=True)
            else:
                print(f"{i}]")

            # Save the particle to the output dir
            img.save(self.output_dir + f"/particle-{i}.png", quality=100)
Exemple #24
0
    def drawScaledImage(self, image, scale, line, pos, canvas):
        w = image.width()
        h = image.height()

        of = round(line - (h * scale) / 2 - self.spacer / 4)

        #Destination
        nX = pos.x()
        nY = round(of + pos.y())
        sW = round(nX + w * scale)
        sH = round(nY + h * scale)
        dst = skia.Rect(nX, nY, sW, sH)

        tempPaint = skia.Paint()
        tempPaint.setFilterQuality(skia.FilterQuality.kHigh_FilterQuality)
        tempPaint.setAntiAlias(False)

        canvas.drawImageRect(image, skia.Rect(0, 0, w, h), dst, tempPaint)
    def draw_marker(self):
        if self.MARKER and self.is_black:
            if "G" in self.name:
                color = self.marker_color_subtle_brighter
            else:
                color = self.marker_color

            marker = skia.Paint(
                AntiAlias=True,
                Color=color,
                Style=skia.Paint.kFill_Style,
                # StrokeWidth = 2,
            )

            rect = skia.Rect(max(self.center_x - (self.width / 10), 1), 0,
                             max(self.center_x + (self.width / 10), 1),
                             self.resolution_height - self.height)
            self.skia.canvas.drawRect(rect, marker)
Exemple #26
0
    def skPaintShadowAndOffset(self):
        if self.shadow is None:
            return None, None
        offset, blur, color = self.shadow
        color = _colorTupleToInt(_colorArgs(color))
        if not blur:
            blur = 1
        # MaskFilter.MakeBlur(
        #   style: skia.BlurStyle,
        #   sigma: float,
        #   respectCTM: bool = True) → skia.MaskFilter
        blurMask = skia.MaskFilter.MakeBlur(skia.kNormal_BlurStyle, 0.5 * blur, False)

        paint = skia.Paint(
            Color=color,
            MaskFilter=blurMask,
            Style=self._skPaintStyle,
        )
        return paint, offset
Exemple #27
0
def draw(canvas):
    from math import cos, sin
    scale = 256.
    R = 0.45 * scale
    TAU = 6.2831853

    path = skia.Path()
    path.moveTo(R, 0.)
    for i in range(7):
        theta = 3 * i * TAU / 7
        path.lineTo(R * cos(theta), R * sin(theta))
    path.close()

    paint = skia.Paint()
    paint.setAntiAlias(True)

    canvas.clear(0xFFFFFFFF)
    canvas.translate(0.5 * scale, 0.5 * scale)
    canvas.drawPath(path, paint)
Exemple #28
0
 def render_gui():
     try:
         with skia_surface(window) as surface:
             with surface as canvas:
                 canvas.clear(skia.Color(0, 0, 0))
                 scroll = db['gui_status'].get('scroll_x')['value'], db['gui_status'].get('scroll_y')['value']
                 canvas.translate(*scroll)
                 for widget in db['widget'].rows:
                     blob = skia.TextBlob.MakeFromString(widget['text'], font)
                     canvas.save()
                     canvas.drawRect(skia.Rect(widget['x'], widget['y'], widget['x']+widget['width'], widget['y']+widget['height']),
                                     skia.Paint(AntiAlias=True, Style=skia.Paint.kFill_Style, Color=skia.ColorBLUE))
                     canvas.clipRect(skia.Rect(widget['x'], widget['y'], widget['x']+widget['width'], widget['y']+widget['height']))
                     canvas.drawTextBlob(blob, widget['x'], widget['y']+widget['height'], skia.Paint(AntiAlias=True, Color=skia.Color(255, 255, 255)))
                     canvas.restore()
             surface.flushAndSubmit()
             glfw.swap_buffers(window)
     except Exception as e:
         traceback.print_exc()
Exemple #29
0
    def __init__(self, dat, rect, canvas, scale, style=None, alpha=1):
        super().__init__(dat, rect.h)
        self.scale = scale
        self.canvas = canvas
        self.rect = rect
        self.blendmode = None
        self.style = style
        self.alpha = alpha

        all_attrs = list(self.findStyledAttrs(style))
        skia_paint_kwargs = dict(AntiAlias=True)
        for attrs, attr in all_attrs:
            method, *args = attr
            if method == "skp":
                skia_paint_kwargs = args[0]
                if "AntiAlias" not in skia_paint_kwargs:
                    skia_paint_kwargs["AntiAlias"] = True
            elif method == "blendmode":
                self.blendmode = args[0]

        for attrs, attr in all_attrs:
            self.paint = skia.Paint(**skia_paint_kwargs)
            if self.blendmode:
                self.paint.setBlendMode(self.blendmode)
            method, *args = attr
            if method == "skp":
                pass
            elif method == "skb":
                pass
            elif method == "blendmode":
                pass
            elif method == "stroke" and args[0].get("weight") == 0:
                pass
            else:
                canvas.save()
                did_draw = self.applyDATAttribute(attrs, attr)
                self.paint.setAlphaf(self.paint.getAlphaf() * self.alpha)
                if not did_draw:
                    canvas.drawPath(self.path, self.paint)
                canvas.restore()
Exemple #30
0
def main():
    if not glfw.init():
        return
    glfw.window_hint(glfw.STENCIL_BITS, 8)
    window = glfw.create_window(WIDTH, HEIGHT, 'Hello World', None, None)
    if not window:
        glfw.terminate()
        return

    glfw.make_context_current(window)

    context = skia.GrContext.MakeGL()
    backend_render_target = skia.GrBackendRenderTarget(
        WIDTH,
        HEIGHT,
        0,  # sampleCnt
        0,  # stencilBits
        skia.GrGLFramebufferInfo(0, gl.GL_RGBA8))
    surface = skia.Surface.MakeFromBackendRenderTarget(
        context, backend_render_target, skia.kBottomLeft_GrSurfaceOrigin,
        skia.kRGBA_8888_ColorType, skia.ColorSpace.MakeSRGB())
    assert surface is not None

    start = time.time()
    while (glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS
           and not glfw.window_should_close(window)):
        t = time.time() - start

        gl.glClear(gl.GL_COLOR_BUFFER_BIT)

        with surface as canvas:
            canvas.drawCircle(100 + 10 * t, 100 + 10 * t, 40,
                              skia.Paint(Color=skia.ColorGREEN))
        surface.flushAndSubmit()

        glfw.swap_buffers(window)
        glfw.poll_events()

    context.abandonContext()
    glfw.terminate()