summaryrefslogtreecommitdiff
path: root/lib/extensions/lettering_generate_json.py
blob: bfdd1055abfc0fc7bf3af661deda4fb6e59447ec (plain)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Authors: see git history
#
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later.  See the file LICENSE for details.

import json
import os

from inkex import Boolean, errormsg

from ..i18n import _
from ..lettering.categories import FONT_CATEGORIES
from ..lettering.font_info import FontFileInfo
from .base import InkstitchExtension


class LetteringGenerateJson(InkstitchExtension):
    '''
    This extension helps font creators to generate the json file for the lettering tool
    '''
    def __init__(self, *args, **kwargs):
        InkstitchExtension.__init__(self, *args, **kwargs)
        self.arg_parser.add_argument("--notebook")

        self.arg_parser.add_argument("-n", "--font-name", type=str, default="Font", dest="font_name")
        self.arg_parser.add_argument("-d", "--font-description", type=str, default="Description", dest="font_description")
        self.arg_parser.add_argument("-v", "--default_variant", type=int, default=0, dest="default_variant")
        self.arg_parser.add_argument("-x", "--text_direction", type=str, default="ltr", dest="text_direction")
        self.arg_parser.add_argument("-s", "--auto-satin", type=Boolean, default="true", dest="auto_satin")
        self.arg_parser.add_argument("-r", "--reversible", type=Boolean, default="true", dest="reversible")
        self.arg_parser.add_argument("-o", "--combine-at-sort-indices", type=str, default="", dest="combine_at_sort_indices")
        self.arg_parser.add_argument("-t", "--sortable", type=Boolean, default="false", dest="sortable")
        self.arg_parser.add_argument("-u", "--letter-case", type=str, default="", dest="letter_case")
        self.arg_parser.add_argument("-g", "--default-glyph", type=str, default="", dest="default_glyph")
        self.arg_parser.add_argument("-z", "--size", type=float, default=15, dest="size")
        self.arg_parser.add_argument("-i", "--min-scale", type=float, default=1.0, dest="min_scale")
        self.arg_parser.add_argument("-a", "--max-scale", type=float, default=1.0, dest="max_scale")
        self.arg_parser.add_argument("--use-custom-leading", type=Boolean, default="false", dest="use_custom_leading")
        self.arg_parser.add_argument("--use-custom-spacing", type=Boolean, default="false", dest="use_custom_spacing")
        self.arg_parser.add_argument("--use-custom-letter-spacing", type=Boolean, default="false", dest="use_custom_letter_spacing")
        self.arg_parser.add_argument("--use-glyph-width", type=Boolean, default="false", dest="use_glyph_width")
        self.arg_parser.add_argument("-l", "--leading", type=int, default=100, dest="leading")
        self.arg_parser.add_argument("-w", "--word-spacing", type=int, default=20, dest="word_spacing")
        self.arg_parser.add_argument("-b", "--letter-spacing", type=int, default=100, dest="letter_spacing")
        self.arg_parser.add_argument("-p", "--font-file", type=str, default="", dest="path")

        for category in FONT_CATEGORIES:
            self.arg_parser.add_argument(f"--{category.id}", type=Boolean, default="false", dest=category.id)

    def effect(self):
        # file paths
        path = self.options.path
        if not os.path.isfile(path):
            errormsg(_("Please specify a font file."))
            return
        output_path = os.path.join(os.path.dirname(path), 'font.json')

        # font info (kerning, glyphs)
        font_info = FontFileInfo(path)

        horiz_adv_x = font_info.horiz_adv_x()
        hkern = font_info.hkern()
        custom_leading = self.options.use_custom_leading
        custom_spacing = self.options.use_custom_spacing
        word_spacing = font_info.word_spacing()
        # use user input in case that the default word spacing is not defined
        # in the svg file or the user forces custom values
        if custom_spacing or not word_spacing:
            word_spacing = self.options.word_spacing

        letter_spacing = self._get_letter_spacing(font_info)

        units_per_em = font_info.units_per_em() or self.options.leading
        # use units_per_em for leading (line height) if defined in the font file,
        # unless the user wishes to overwrite the value
        if units_per_em and not custom_leading:
            leading = units_per_em
        else:
            leading = self.options.leading

        glyphs = font_info.glyph_list()

        keywords = []
        for category in FONT_CATEGORIES:
            if getattr(self.options, category.id):
                keywords.append(category.id)

        combine_at_sort_indices = self.options.combine_at_sort_indices.split(',')
        combine_at_sort_indices = set([index.strip() for index in combine_at_sort_indices if index.strip()])

        # The inx gui doesn't seem to be able to remember the arrow values,
        # therefore we used numbers which we need to convert now
        default_variant = "→"
        if self.options.default_variant == 1:
            default_variant = "←"
        elif self.options.default_variant == 2:
            default_variant = "↓"
        elif self.options.default_variant == 3:
            default_variant = "↑"

        # collect data
        data = {'name': self.options.font_name,
                'description': self.options.font_description,
                'default_variant': default_variant,
                'text_direction': self.options.text_direction,
                'keywords': keywords,
                'leading': leading,
                'auto_satin': self.options.auto_satin,
                'reversible': self.options.reversible,
                'sortable': self.options.sortable,
                'combine_at_sort_indices': list(combine_at_sort_indices),
                'letter_case': self.options.letter_case,
                'default_glyph': self.options.default_glyph,
                'size': self.options.size,
                'min_scale': round(self.options.min_scale, 1),
                'max_scale': round(self.options.max_scale, 1),
                'horiz_adv_x_default': letter_spacing,
                'horiz_adv_x_space': word_spacing,
                'units_per_em': units_per_em,
                'horiz_adv_x': horiz_adv_x,
                'kerning_pairs': hkern,
                'glyphs': glyphs
                }

        # write data to font.json into the same directory as the font file
        with open(output_path, 'w', encoding="utf8") as font_data:
            json.dump(data, font_data, indent=4, ensure_ascii=False)

    def _get_letter_spacing(self, font_info):
        letter_spacing = font_info.letter_spacing()
        # use user input in case that the default word spacing is not defined
        # in the svg file or the user forces custom values
        if self.options.use_custom_letter_spacing or not letter_spacing:
            letter_spacing = self.options.letter_spacing
        if self.options.use_glyph_width:
            letter_spacing = None
        return letter_spacing