def set_best_font(self):
        text_fits = 0

        while True:
            text_fits += 1

            font = skia.Font(skia.Typeface('Ubuntu'), text_fits)
            height_size = font.getSpacing()
            text_size = font.measureText("F#")

            if text_size > self.semitone_width:
                break
        
        self.font = skia.Font(skia.Typeface('Arial'), text_fits - 4)
    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)
示例#3
0
 def _getTypefaceAndTTFont(fontNameOrPath):
     cacheKey = fontNameOrPath
     if cacheKey not in _fontCache:
         if fontNameOrPath is None:
             typeface = skia.Typeface(None)
         else:
             fontNameOrPath = os.fspath(fontNameOrPath)
             if not os.path.exists(fontNameOrPath):
                 typeface = skia.Typeface(fontNameOrPath)
             else:
                 typeface = skia.Typeface.MakeFromFile(fontNameOrPath)
                 if typeface is None:
                     raise DrawbotError(f"can't load font: {fontNameOrPath}")
         ttFont = makeTTFontFromSkiaTypeface(typeface)
         _fontCache[cacheKey] = typeface, ttFont
     return _fontCache[cacheKey]
示例#4
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)
示例#5
0
 def setFont(self, fontNameOrPath):
     if os.path.exists(fontNameOrPath):
         path = os.path.normpath(os.path.abspath(os.fspath(fontNameOrPath)))
         tf = self._getFontFromFile(path)
     else:
         tf = skia.Typeface(fontNameOrPath)
     self.font.setTypeface(tf)
     # purge cached items:
     self._ttFont = None
     self._shape = None
示例#6
0
    def __init__(self, cachedTypefaces, _doInitialize=True):
        self._cachedTypefaces = cachedTypefaces
        self._ttFont = None
        self._shape = None

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

        self.font = skia.Font(skia.Typeface(None), 10)
        self.font.setForceAutoHinting(False)
        self.font.setHinting(skia.FontHinting.kNone)
        self.font.setSubpixel(True)
        self.font.setEdging(skia.Font.Edging.kAntiAlias)
        self.features = {}
        self.variations = {}
示例#7
0
def draw_text(text: str, point: tuple[float, float], color, *, size=40, font='Arial', align_x=Align.CENTER, align_y=Align.CENTER):
	if align_x not in (Align.LEFT, Align.CENTER, Align.RIGHT):
		raise ValueError(f"align_x bad value {align_x!r}.\nValid values are: {', '.join(map(repr, [Align.LEFT, Align.CENTER, Align.RIGHT]))}.")
	if align_y not in (Align.TOP, Align.CENTER, Align.BOTTOM):
		raise ValueError(f"align_y bad value {align_x!r}.\nValid values are: {', '.join(map(repr, [Align.TOP, Align.CENTER, Align.BOTTOM]))}.")

	try:
		cache = globals()['_text_cache']
	except:
		cache = globals()['_text_cache'] = {}
	try:
		blob, offsets = cache[(text, font, size)]
	except:
		sfont = skia.Font(skia.Typeface(font), size)
		blob: skia.TextBlob = skia.TextBlob.MakeFromText(text, sfont)
		glyphs = sfont.textToGlyphs(text)
		bounds = sfont.getBounds(glyphs)
		positions = sfont.getXPos(glyphs)
		min_y = min(-b.fBottom for b in bounds)
		max_y = max(-b.fTop for b in bounds)
		# take the average of the centers as the text center
		center_y = sum(-b.centerY() for b in bounds) / len(bounds)
		min_x = positions[0] + bounds[0].fLeft
		max_x = positions[-1] + bounds[-1].fRight
		center_x = (min_x + max_x) / 2
		offsets = {'min_x': min_x, 'center_x': center_x, 'max_x': max_x, 'min_y': min_y, 'center_y': center_y, 'max_y': max_y}
		cache[(text, font, size)] = blob, offsets

	x, y = point
	if align_x == 'left':
		x -= offsets['max_x']
	elif align_x == 'center':
		x -= offsets['center_x']
	elif align_x == 'right':
		x -= offsets['min_x']
	if align_y == 'bottom':
		y += offsets['max_y']
	elif align_y == 'center':
		y += offsets['center_y']
	elif align_y == 'top':
		y += offsets['min_y']

	_canvas.drawTextBlob(blob, x, y, Color._paint(color))
示例#8
0
        def draw(pen, state, data):
            if state != 0:
                return

            if not pen.visible:
                return

            if isinstance(pen, DATText):
                if isinstance(pen.style.font, str):
                    font = skia.Typeface(pen.style.font)
                else:
                    font = skia.Typeface.MakeFromFile(str(pen.style.font.path))
                    if len(pen.style.variations) > 0:
                        fa = skia.FontArguments()
                        # h/t https://github.com/justvanrossum/drawbot-skia/blob/master/src/drawbot_skia/gstate.py
                        to_int = lambda s: struct.unpack(
                            ">i", bytes(s, "ascii"))[0]
                        makeCoord = skia.FontArguments.VariationPosition.Coordinate
                        rawCoords = [
                            makeCoord(to_int(tag), value)
                            for tag, value in pen.style.variations.items()
                        ]
                        coords = skia.FontArguments.VariationPosition.Coordinates(
                            rawCoords)
                        fa.setVariationDesignPosition(
                            skia.FontArguments.VariationPosition(coords))
                        font = font.makeClone(fa)
                pt = pen.frame.point("SW")
                canvas.drawString(
                    pen.text, pt.x, rect.h - pt.y,
                    skia.Font(font, pen.style.fontSize),
                    skia.Paint(AntiAlias=True, Color=pen.style.fill.skia()))

            if state == 0:
                SkiaPen(pen,
                        rect,
                        canvas,
                        scale,
                        style=style,
                        alpha=pen.calc_alpha())
示例#9
0
        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
    yield surface
    context.abandonContext()

db = sqlite_utils.Database(':memory:')
db['gui_status'].insert_all([{'name': 'scroll_x', 'value': 0},
                             {'name': 'scroll_y', 'value': 0}], pk='name')

db['widget'].create({'text': str, 'x': int, 'y': int, 'width': int, 'height': int})

typeface = skia.Typeface('Arial')
font = skia.Font(typeface, 14, 1, 0)
font.setEdging(skia.Font.Edging.kAntiAlias)

def add_widget(text):
    y = (db.execute('select max(y) from widget').fetchone()[0] or 0) + 30
    x = 10
    db['widget'].insert({'text': text, 'x': x, 'y': y, 'width': 100, 'height': 20})

with glfw_window() as window:
    GL.glClear(GL.GL_COLOR_BUFFER_BIT)

    def scroll_callback(_win, dx, dy):
        new_scroll_x = db['gui_status'].get('scroll_x')['value'] + dx
        db['gui_status'].update('scroll_x', {'value': new_scroll_x})
示例#10
0
import glfw  # type: ignore
import skia  # type: ignore
import traceback
import random
import math
import ast
import importlib
from dataclasses import dataclass
from OpenGL import GL  # type: ignore
from typing import List
from functools import lru_cache, wraps
import numpy as np  # type: ignore
import matplotlib  # type: ignore
from buffer import Buffer

font = skia.Font(skia.Typeface('Liberation Mono'), 14)
line_height = font.getSpacing()
col_width = font.getWidths([ord('x')])[0]


@dataclass
class Cell:
    input: Buffer
    output: object


target_scroll = [0, 0]


def clamp(l, u, v):
    return max(min(v, u), l)
    def run(self):

        # Calculate fps?
        if self.pyskt_context.show_debug:
            frame_times = [0] * 120
            frame = 0
            last_time_completed = time.time()

        # Link events to parsers
        glfw.set_window_size_callback(self.window,
                                      self.events.on_window_resize)
        glfw.set_mouse_button_callback(self.window, self.events.mouse_callback)
        glfw.set_scroll_callback(self.window, self.events.mouse_callback)
        glfw.set_key_callback(self.window, self.events.keyboard_callback)

        glfw.set_drop_callback(self.window, self.events.on_file_drop)

        scroll_text_x = self.pyskt_context.width // 2
        scroll_text_y = self.pyskt_context.height // 2
        wants_to_go = [scroll_text_x, scroll_text_y]

        threading.Thread(target=self.events_loop).start()

        # Loop until the user closes the window
        while not glfw.window_should_close(self.window):

            # Wait events if said to
            # if self.pyskt_context.wait_events:

            # Clear canvas
            self.canvas.clear(self.colors.background)

            # Get mouse position
            self.mouse_pos = glfw.get_cursor_pos(self.window)
            self.check_mouse_moved()

            if self.events.left_click:
                wants_to_go[0] -= self.events.scroll * 50
            else:
                wants_to_go[1] -= self.events.scroll * 50

            # We have now to recursively search through the components dictionary

            scroll_text_x = scroll_text_x + (wants_to_go[0] -
                                             scroll_text_x) * 0.3
            scroll_text_y = scroll_text_y + (wants_to_go[1] -
                                             scroll_text_y) * 0.3

            self.draw_utils.anchored_text(
                canvas=self.canvas,
                text="A Really long and centered text",
                x=scroll_text_x,
                y=scroll_text_y,
                anchor_x=0.5,
                anchor_y=0.5,
            )

            # Hover testing
            for _ in range(20):
                random.seed(_)

                xywh_rect = [
                    random.randint(0, 1000),
                    random.randint(0, 1000),
                    random.randint(0, 400),
                    random.randint(0, 400)
                ]

                # Rectangle border
                # rect = self.pyskt_processing.rectangle_x_y_w_h_to_coordinates(*xywh_rect)

                info = self.pyskt_processing.point_against_rectangle(
                    self.mouse_pos, xywh_rect)

                if info["is_inside"]:
                    paint = skia.Paint(
                        AntiAlias=True,
                        Color=skia.Color4f(1, 0, 1, 1),
                        Style=skia.Paint.kFill_Style,
                        StrokeWidth=2,
                    )
                else:
                    c = 1 - (info["distance"] / 1080)
                    paint = skia.Paint(
                        AntiAlias=True,
                        Color=skia.Color4f(c, c, c, 1),
                        Style=skia.Paint.kFill_Style,
                        StrokeWidth=2,
                    )

                # Draw the border
                self.canvas.drawRect(
                    skia.Rect(
                        *self.pyskt_processing.rectangle_x_y_w_h_to_skia_rect(
                            *xywh_rect)), paint)

            # # #

            # Show fps
            if self.pyskt_context.show_debug:
                frame_times[frame % 120] = time.time() - last_time_completed
                absolute_frame_times = [x for x in frame_times if not x == 0]
                fps = 1 / (sum(absolute_frame_times) /
                           len(absolute_frame_times))

                last_time_completed = time.time()
                frame += 1

                self.draw_utils.anchored_text(
                    canvas=self.canvas,
                    text=[f"{fps=:.1f}", f"mouse_pos={self.mouse_pos}"],
                    x=0,
                    y=0,
                    anchor_x=0,
                    anchor_y=0,
                    # kwargs
                    font=skia.Font(skia.Typeface('Arial'), 12),
                )

            # If any event doesn't return to "None" state
            self.events.reset_non_ending_states()

            # Flush buffer
            self.surface.flushAndSubmit()

            # Swap front and back buffers
            glfw.swap_buffers(self.window)

            # Poll for and process events
            glfw.poll_events()

        # End glfw
        glfw.terminate()