File: ot-svg-draw-skia.py

package info (click to toggle)
freetype-py 2.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,976 kB
  • sloc: python: 7,676; makefile: 111
file content (89 lines) | stat: -rwxr-xr-x 2,877 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  OT-SVG example with Skia
#
#  Copyright 2023 Hin-Tak Leung
#  Distributed under the terms of the new BSD license.

# This is an older example which works on skia m87 with known limitations.
# See "ot-svg-example-skia.py" for a full example which requires m117.

# Limitation:
#     Skia-python bundles with Skia m87 (at time of writing this).
#
#     Skia m88 is first version where SkSVG* is considered no longer experimental.
#
#     Skia m103 is the first Skia build which contains 9cbadcd9280dc139af2f4d41d25a6c9a750e0302.
#     That introduces "SkSVGDOM::renderNode()" among other stuff,
#     necessary for rendering "some" OT-SVG fonts. Guess what, that commit
#     is titled "Add optional OT-SVG support to FreeType"!
#
#     So the example below only works correctly for "some" glyphs in
#     "some other" OT-SVG fonts, and also with very limited functionality
#     beyond what is used below.
#
#     The missing functionality (and support for beyond Skia m103) is filed
#     as skia-python issue #192.

from freetype import *

import skia

if __name__ == '__main__':
    import sys
    execname = sys.argv[0]

    if len(sys.argv) < 2:
        print("Example usage: %s TrajanColor-Concept.otf" % execname)
        exit(1)

    face = Face(sys.argv[1])

    face.set_char_size( 160*64 )
    face.load_char('A', FT_LOAD_COLOR )
    slot = face.glyph._FT_GlyphSlot

    if (face.glyph.format == FT_GLYPH_FORMAT_SVG):
        document = ctypes.cast(slot.contents.other, FT_SVG_Document)
        doc = ctypes.string_at(document.contents.svg_document, # not terminated
                               size=document.contents.svg_document_length)
        d = skia.Data(doc)
        # skia-python #194 - the raw c++ api actually has a (ptr, len, bool) method!
        # Data() shouldn't be needed.
        m = skia.MemoryStream(d)
        h = skia.SVGDOM.MakeFromStream(m)

        WIDTH, HEIGHT = 160, 160
        
        size = skia.Size()
        size.fHeight = WIDTH
        size.fWidth = HEIGHT
        
        h.setContainerSize(size)

        surface = skia.Surface(WIDTH * 2, HEIGHT)
        
        with surface as canvas:
            canvas.translate(0,HEIGHT)
            h.render(canvas)
            canvas.translate(WIDTH/4,0)
            h.render(canvas)
            canvas.translate(WIDTH/4,0)
            h.render(canvas)
            canvas.translate(WIDTH/4,0)
            h.render(canvas)
            canvas.translate(WIDTH/4,0)
            h.render(canvas)
            canvas.translate(WIDTH/4,0)
            h.render(canvas)
            
        surface.flushAndSubmit()
        image = surface.makeImageSnapshot()
        image.save("ot-svg-draw-skia.png", skia.kPNG)

        from PIL import Image
        Image.open("ot-svg-draw-skia.png").show()

    else:
        print("Not SVG glyph.format")