# -*- coding: utf-8 -*-
#
#    TypeAtlas Data Definitions for Open Font Format/OpenType Font Files
#    Copyright (C) 2018-2021 Milko Krachounov
#
#    This file is part of TypeAtlas
#
#    TypeAtlas is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    TypeAtlas is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with TypeAtlas.  If not, see <http://www.gnu.org/licenses/>.
#
#                                 ***
#
#    Alternatively, you may use this file (part of TypeAtlas libraries)
#    under the terms of the X11/MIT license as follows:
#
#    Permission is hereby granted, free of charge, to any person
#    obtaining a copy of this software and associated documentation
#    files (the "Software"), to deal in the Software without
#    restriction, including without limitation the rights to use,
#    copy, modify, merge, publish, distribute, sublicense, and/or sell
#    copies of the Software, and to permit persons to whom the
#    Software is furnished to do so, subject to the following
#    conditions:
#
#    The above copyright notice and this permission notice shall be
#    included in all copies or substantial portions of the Software.
#
#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
#    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#    OTHER DEALINGS IN THE SOFTWARE.
#


"""OpenType format constants, types and class information parsers."""

from collections import namedtuple, OrderedDict
from collections.abc import Callable, Mapping
import struct
from typeatlas.util import N_, generic_type

Union = generic_type('Union')
TupleOf = generic_type('Tuple')
IteratorOf = generic_type('Iterator')
SequenceOf = generic_type('Sequence')
MappingOf = generic_type('Mapping')


# TODO: Transitional serifs
#       PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF,
#       PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF may be
#       displayed as a separate category, or shown in both sans-serif
#       and serif by GUI). Or just make the PAN transitional fonts go to
#       sans-serif?

# TODO: PANOSE 0 and 1 are actually Any and No Fit


COPYRIGHT_NAME_ID = 0
FAMILY_NAME_ID = 1
STYLE_NAME_ID = 2
UNIQUE_NAME_ID = 3
FULL_NAME_ID = 4
VERSION_NAME_ID = 5
POSTSCRIPT_NAME_ID = 6
TRADEMARK_NAME_ID = 7
MANUFACTURER_NAME_ID = 8
DESIGNER_NAME_ID = 9
DESCRIPTION_NAME_ID = 10
VENDOR_URL_NAME_ID = 11
DESIGNER_URL_NAME_ID = 12
LICENSE_NAME_ID = 13
LICENSE_URL_NAME_ID = 14
TYPOGRAPHIC_FAMILY_NAME_ID = 16
TYPOGRAPHIC_STYLE_NAME_ID = 17
SAMPLE_TEXT_ID = 19


# Layers using 0xFFFF as their colour should use the text
# foreground colour
COLR_DEFAULT_TEXT_FOREGROUND = 0xFFFF


###################
### IBM classes ###
###################

IBM_UNCLASSIFIED = 0
IBM_OLDSTYLE_SERIF = 1
IBM_TRANSITIONAL_SERIF = 2
IBM_MODERN_SERIF = 3
IBM_CLARENDON_SERIF = 4
IBM_SLAB_SERIF = 5
IBM_FREEFORM_SERIF = 7
IBM_SANS_SERIF = 8
IBM_ORNAMENTAL = 9
IBM_SCRIPT = 10
IBM_SYMBOLIC = 12


IBM_SERIFS = frozenset([IBM_OLDSTYLE_SERIF, IBM_TRANSITIONAL_SERIF,
                        IBM_MODERN_SERIF, IBM_CLARENDON_SERIF, IBM_SLAB_SERIF,
                        IBM_FREEFORM_SERIF])
IBM_SANS_SERIFS = frozenset([IBM_SANS_SERIF])
IBM_SYMBOLIC_CLASSES = frozenset([IBM_SYMBOLIC])
IBM_CURSIVE_CLASSES = frozenset([IBM_SCRIPT])
IBM_FANTASY_CLASSES = frozenset([IBM_ORNAMENTAL])


IBM_MISC_SUBCLASS = 15


IBM_OLDSTYLE_UNCLASSIFIED = 1 * 256 + 0
IBM_OLDSTYLE_ROUNDED_LEGIBILITY = 1 * 256 + 1
IBM_OLDSTYLE_GARALDE = 1 * 256 + 2
IBM_OLDSTYLE_VENETIAN =  1 * 256 + 3
IBM_OLDSTYLE_MODIFIED_VENETIAN = 1 * 256 + 4
IBM_OLDSTYLE_DUTCH_MODERN = 1 * 256 + 5
IBM_OLDSTYLE_DUTCH_TRADITIONAL = 1 * 256 + 6
IBM_OLDSTYLE_CONTEMPORARY = 1 * 256 + 7
IBM_OLDSTYLE_CALLIGRAPHIC = 1 * 256 + 8
IBM_OLDSTYLE_MISC = 1 * 256 + 15

IBM_TRANSITIONAL_UNCLASSIFIED = 2 * 256 + 0
IBM_TRANSITIONAL_DIRECT_LINE = 2 * 256 + 1
IBM_TRANSITIONAL_SCRIPT = 2 * 256 + 2
IBM_TRANSITIONAL_MISC = 2 * 256 + 15

IBM_MODERN_UNCLASSIFIED = 3 * 256 + 0
IBM_MODERN_ITALIAN = 3 * 256 + 1
IBM_MODERN_SCRIPT = 3 * 256 + 2
IBM_MODERN_MISC = 3 * 256 + 15

IBM_CLARENDON_UNCLASSIFIED = 4 * 256 + 0
IBM_CLARENDON_CLARENDON = 4 * 256 + 1
IBM_CLARENDON_MODERN = 4 * 256 + 2
IBM_CLARENDON_TRADITIONAL = 4 * 256 + 3
IBM_CLARENDON_NEWSPAPER = 4 * 256 + 4
IBM_CLARENDON_STUB_SERIF = 4 * 256 + 5
IBM_CLARENDON_MONOTONE = 4 * 256 + 6
IBM_CLARENDON_TYPEWRITER = 4 * 256 + 7
IBM_CLARENDON_MISC = 4 * 256 + 15


IBM_SLAB_UNCLASSIFIED = 5 * 256 + 0
IBM_SLAB_MONOTONE = 5 * 256 + 1
IBM_SLAB_HUMANIST = 5 * 256 + 2
IBM_SLAB_GEOMETRIC = 5 * 256 + 3
IBM_SLAB_SWISS = 5 * 256 + 4
IBM_SLAB_TYPEWRITER = 5 * 256 + 5
IBM_SLAB_MISC = 5 * 256 + 15


IBM_FREEFORM_UNCLASSIFIED = 7 * 256 + 0
IBM_FREEFORM_MODERN = 7 * 256 + 1
IBM_FREEFORM_MISC = 7 * 256 + 15


IBM_SANS_UNCLASSIFIED = 8 * 256 + 0
IBM_SANS_IBM_NEOGROTESQUE_GOTHIC = 8 * 256 + 1
IBM_SANS_HUMANIST = 8 * 256 + 2
IBM_SANS_LOWX_ROUND_GEOMETRIC = 8 * 256 + 3
IBM_SANS_HIGHX_ROUND_GEOMETRIC = 8 * 256 + 4
IBM_SANS_NEOGROTESQUE_GOTHIC = 8 * 256 + 5
IBM_SANS_MODIFIED_NEOGROTESQUE_GOTHIC = 8 * 256 + 6
IBM_SANS_TYPEWRITER_GOTHIC = 8 * 256 + 9
IBM_SANS_MATRIX = 8 * 256 + 10
IBM_SANS_MISC = 8 * 256 + 15


IBM_ORNAMENTAL_UNCLASSIFIED = 9 * 256 + 0
IBM_ORNAMENTAL_ENGRAVER = 9 * 256 + 1
IBM_ORNAMENTAL_BLACK_LETTER = 9 * 256 + 2
IBM_ORNAMENTAL_DECORATIVE = 9 * 256 + 3
IBM_ORNAMENTAL_3D = 9 * 256 + 4
IBM_ORNAMENTAL_MISC = 9 * 256 + 15

IBM_SCRIPT_UNCLASSIFIED = 10 * 256 + 0
IBM_SCRIPT_UNCIAL = 10 * 256 + 1
IBM_SCRIPT_BRUSH_JOINED = 10 * 256 + 2
IBM_SCRIPT_FORMAL_JOINED = 10 * 256 + 3
IBM_SCRIPT_MONOTONE_JOINED = 10 * 256 + 4
IBM_SCRIPT_CALLIGRAPHIC = 10 * 256 + 5
IBM_SCRIPT_BRUSH_UNJOINED = 10 * 256 + 6
IBM_SCRIPT_FORMAL_UNJOINED = 10 * 256 + 7
IBM_SCRIPT_MONOTONE_UNJOINED = 10 * 256 + 8
IBM_SCRIPT_MISC = 10 * 256 + 15

IBM_SYMBOLIC_UNCLASSIFIED = 12 * 256 + 0
IBM_SYMBOLIC_MIXED_SERIF = 12 * 256 + 3
IBM_SYMBOLIC_OLDSTYLE_SERIF = 12 * 256 + 6
IBM_SYMBOLIC_NEOGROTESQUE_SANS_SERIF = 12 * 256 + 7
IBM_SYMBOLIC_MISC = 12 * 256 + 15


IBM_CLASSES = {
    IBM_UNCLASSIFIED : N_('Unclassfied'),
    IBM_OLDSTYLE_SERIF : N_('Old-style Serif'),
    IBM_TRANSITIONAL_SERIF : N_('Transitional Serif'),
    IBM_MODERN_SERIF : N_('Modern Serif'),
    IBM_CLARENDON_SERIF : N_('Clarendon Serif'),
    IBM_SLAB_SERIF : N_('Slab Serif'),
    IBM_FREEFORM_SERIF : N_('Freeform Serif'),
    IBM_SANS_SERIF : N_('Sans Serif'),
    IBM_ORNAMENTAL : N_('Ornamental'),
    IBM_SCRIPT : N_('class|Script'),
    IBM_SYMBOLIC : N_('Symbol'),
}


IBM_GENERIC_SUBCLASSES = {
    0: N_('Unclassified'),
    IBM_MISC_SUBCLASS: N_('Miscellaneous'),
}

IBM_SUBCLASSES = {
    IBM_OLDSTYLE_ROUNDED_LEGIBILITY : N_('IBM Rounded Legibility'),
    IBM_OLDSTYLE_GARALDE : N_('Garalde'),
    IBM_OLDSTYLE_VENETIAN : N_('Venetian'),
    IBM_OLDSTYLE_MODIFIED_VENETIAN : N_('Modified Venetian'),
    IBM_OLDSTYLE_DUTCH_MODERN : N_('Dutch Modern'),
    IBM_OLDSTYLE_DUTCH_TRADITIONAL : N_('Dutch Traditional'),
    IBM_OLDSTYLE_CONTEMPORARY : N_('Contemporary'),
    IBM_OLDSTYLE_CALLIGRAPHIC : N_('Calligraphic'),

    IBM_TRANSITIONAL_DIRECT_LINE : N_('Direct Line'),
    IBM_TRANSITIONAL_SCRIPT : N_('class|Script'),

    IBM_MODERN_ITALIAN : N_('Italian'),
    IBM_MODERN_SCRIPT : N_('class|Script'),

    IBM_CLARENDON_CLARENDON : N_('Clarendon'),
    IBM_CLARENDON_MODERN : N_('Modern'),
    IBM_CLARENDON_TRADITIONAL : N_('Traditional'),
    IBM_CLARENDON_NEWSPAPER : N_('Newspaper'),
    IBM_CLARENDON_STUB_SERIF : N_('Stub Serif'),
    IBM_CLARENDON_MONOTONE : N_('Monotone'),
    IBM_CLARENDON_TYPEWRITER : N_('Typewriter'),

    IBM_SLAB_MONOTONE : N_('Monotone'),
    IBM_SLAB_HUMANIST : N_('Humanist'),
    IBM_SLAB_GEOMETRIC : N_('Geometric'),
    IBM_SLAB_SWISS : N_('Swiss'),
    IBM_SLAB_TYPEWRITER : N_('Typewriter'),

    IBM_FREEFORM_MODERN : N_('Modern'),

    IBM_SANS_IBM_NEOGROTESQUE_GOTHIC : N_('IBM Neo-grotesque Gothic'),
    IBM_SANS_HUMANIST : N_('Humanist'),
    IBM_SANS_LOWX_ROUND_GEOMETRIC : N_('Low-X Round Geometric'),
    IBM_SANS_HIGHX_ROUND_GEOMETRIC : N_('High-X Round Geometric'),
    IBM_SANS_NEOGROTESQUE_GOTHIC : N_('Neo-grotesque Gothic'),
    IBM_SANS_MODIFIED_NEOGROTESQUE_GOTHIC : N_('Modified Neo-grotesque Gothic'),
    IBM_SANS_TYPEWRITER_GOTHIC : N_('Typewriter Gothic'),
    IBM_SANS_MATRIX : N_('Matrix'),

    IBM_ORNAMENTAL_ENGRAVER : N_('Engraver'),
    IBM_ORNAMENTAL_BLACK_LETTER : N_('Black Letter'),
    IBM_ORNAMENTAL_DECORATIVE : N_('Decorative'),
    IBM_ORNAMENTAL_3D : N_('Three-dimensional'),

    IBM_SCRIPT_UNCIAL : N_('Uncial'),
    IBM_SCRIPT_BRUSH_JOINED : N_('Brush Joined'),
    IBM_SCRIPT_FORMAL_JOINED : N_('Formal Joined'),
    IBM_SCRIPT_MONOTONE_JOINED : N_('Monotone Joined'),
    IBM_SCRIPT_CALLIGRAPHIC : N_('Monotone Joined'),
    IBM_SCRIPT_BRUSH_UNJOINED : N_('Brush Unjoined'),
    IBM_SCRIPT_FORMAL_UNJOINED : N_('Formal Unjoined'),
    IBM_SCRIPT_MONOTONE_UNJOINED : N_('Monotone Unjoined'),

    IBM_SYMBOLIC_MIXED_SERIF : N_('Mixed Serif'),
    IBM_SYMBOLIC_OLDSTYLE_SERIF : N_('Old-style Serif'),
    IBM_SYMBOLIC_NEOGROTESQUE_SANS_SERIF : N_('Neo-grotesque Sans Serif'),
}

IBM_CLASS_SUBCLASSES = {
    clsid: {subclsid: name
            for subclsid, name in IBM_SUBCLASSES.items()
            if subclsid // 256 == clsid}
    for clsid in IBM_CLASSES
}


######################
### PANOSE classes ###
######################

PANOSE_UNCLASSIFIED = 0
PANOSE_MISC = 1
PANOSE_TEXT = 2
PANOSE_HANDWRITTEN = 3
PANOSE_DECORATIVE = 4
PANOSE_SYMBOL = 5

PANOSE_CLASSES = {
    PANOSE_UNCLASSIFIED: N_('Unclassified'),
    PANOSE_MISC: N_('Miscellaneous'),
    PANOSE_TEXT: N_('Text'),
    PANOSE_HANDWRITTEN: N_('Handwritten'),
    PANOSE_DECORATIVE: N_('Decorative'),
    PANOSE_SYMBOL: N_('Symbol'),
}

PANOSE_TEXT_UNCLASSIFIED = 0
PANOSE_TEXT_MISC = 1
PANOSE_TEXT_COVE_SERIF = 2
PANOSE_TEXT_OBTUSE_COVE_SERIF = 3
PANOSE_TEXT_SQUARE_COVE_SERIF = 4
PANOSE_TEXT_OBTUSE_SQUARE_COVE = 5
PANOSE_TEXT_SQUARE_SERIF = 6
PANOSE_TEXT_THIN_SERIF = 7
PANOSE_TEXT_OVAL_SERIF = 8
PANOSE_TEXT_EXAGGERATED_SERIF = 9
PANOSE_TEXT_TRIANGLE_SERIF = 10
PANOSE_TEXT_NORMAL_SANS = 11
PANOSE_TEXT_OBTUSE_SANS = 12
PANOSE_TEXT_PERPENDICULAR_SANS = 13
PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF = 14
PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF = 15

PANOSE_SERIFS = frozenset([
    PANOSE_TEXT_COVE_SERIF, PANOSE_TEXT_OBTUSE_COVE_SERIF,
    PANOSE_TEXT_SQUARE_COVE_SERIF, PANOSE_TEXT_OBTUSE_SQUARE_COVE,
    PANOSE_TEXT_SQUARE_SERIF, PANOSE_TEXT_THIN_SERIF, PANOSE_TEXT_OVAL_SERIF,
    PANOSE_TEXT_EXAGGERATED_SERIF, PANOSE_TEXT_TRIANGLE_SERIF,
])

PANOSE_SANS_SERIFS = frozenset([
    PANOSE_TEXT_NORMAL_SANS,
    PANOSE_TEXT_OBTUSE_SANS,
    PANOSE_TEXT_PERPENDICULAR_SANS,
    PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF,
    PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF,
])

PANOSE_HANDWRITTEN_UNCLASSIFIED = 0
PANOSE_HANDWRITTEN_MISC = 1
PANOSE_HANDWRITTEN_FLAT_NIB = 2
PANOSE_HANDWRITTEN_PRESSURE_POINT = 3
PANOSE_HANDWRITTEN_ENGRAVED = 4
PANOSE_HANDWRITTEN_BALL = 5
PANOSE_HANDWRITTEN_BRUSH = 6
PANOSE_HANDWRITTEN_ROUGH = 7
PANOSE_HANDWRITTEN_FELT_PEN = 8
PANOSE_HANDWRITTEN_WILD_BRUSH = 9


PANOSE_DECORATIVE_UNCLASSIFIED = 0
PANOSE_DECORATIVE_MISC = 1
PANOSE_DECORATIVE_DERIVATIVE = 2
PANOSE_DECORATIVE_NONSTANDARD_TOPOLOGY = 3
PANOSE_DECORATIVE_NONSTANDARD_ELEMENTS = 4
PANOSE_DECORATIVE_NONSTANDARD_ASPECT = 5
PANOSE_DECORATIVE_INITIALS = 6
PANOSE_DECORATIVE_CARTOON = 7
PANOSE_DECORATIVE_PICTURE_STEMS = 8
PANOSE_DECORATIVE_ORNAMENTED = 9
PANOSE_DECORATIVE_TEXT_AND_BACKGROUND = 10
PANOSE_DECORATIVE_COLLAGE = 11
PANOSE_DECORATIVE_MONTAGE = 12


PANOSE_SYMBOL_UNCLASSIFIED = 0
PANOSE_SYMBOL_MISC = 1
PANOSE_SYMBOL_MONTAGES = 2
PANOSE_SYMBOL_PICTURES = 3
PANOSE_SYMBOL_SHAPES = 4
PANOSE_SYMBOL_SCIENTIFIC = 5
PANOSE_SYMBOL_MUSIC = 6
PANOSE_SYMBOL_EXPERT = 7
PANOSE_SYMBOL_PATTERNS = 8
PANOSE_SYMBOL_BOARDERS = 9
PANOSE_SYMBOL_ICONS = 10
PANOSE_SYMBOL_LOGOS = 11
PANOSE_SYMBOL_INDUSTRY_SPECIFIC = 12


PANOSE_GENERIC_UNCLASSIFIED = 0
PANOSE_GENERIC_MISC = 1

PANOSE_GENERIC_VALUES = {
    PANOSE_GENERIC_UNCLASSIFIED: N_('Unclassified'),
    PANOSE_GENERIC_MISC: N_('Miscellaneous'),
}


PANOSE_GENERIC_SUBCLASSES = PANOSE_GENERIC_VALUES


PANOSE_TEXT_SUBCLASSES = {
    PANOSE_TEXT_COVE_SERIF:                 N_('Cove Serif'),
    PANOSE_TEXT_OBTUSE_COVE_SERIF:          N_('Obtuse Cove Serif'),
    PANOSE_TEXT_SQUARE_COVE_SERIF:          N_('Square Cove Serif'),
    PANOSE_TEXT_OBTUSE_SQUARE_COVE:         N_('Obtuse Square Cove Serif'),
    PANOSE_TEXT_SQUARE_SERIF:               N_('Square Serif'),
    PANOSE_TEXT_THIN_SERIF:                 N_('Thin Serif'),
    # FontForge and FontMatrix call this Bone, but image search examples
    # call it Oval. Went for Oval, because the serif looks oval on those
    # images.
    PANOSE_TEXT_OVAL_SERIF:                 N_('Oval Serif'),
    PANOSE_TEXT_EXAGGERATED_SERIF:          N_('Exaggerated Serif'),
    PANOSE_TEXT_TRIANGLE_SERIF:             N_('Triangle Serif'),
    PANOSE_TEXT_NORMAL_SANS:                N_('Normal Sans'),
    PANOSE_TEXT_OBTUSE_SANS:                N_('Obtuse Sans'),
    PANOSE_TEXT_PERPENDICULAR_SANS:         N_('Perpendicular Sans'),
    PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF:  N_('Flared Transitional Serif'),
    PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF: N_('Rounded Transitional Serif'),
}

PANOSE_TEXT_ICONS = {
    PANOSE_TEXT_COVE_SERIF:                 'text-cove-serif',
    PANOSE_TEXT_OBTUSE_COVE_SERIF:          'text-obtuse-cove-serif',
    PANOSE_TEXT_SQUARE_COVE_SERIF:          'text-square-cove-serif',
    PANOSE_TEXT_OBTUSE_SQUARE_COVE:         'text-obtuse-square-cove',
    PANOSE_TEXT_SQUARE_SERIF:               'text-square-serif',
    PANOSE_TEXT_THIN_SERIF:                 'text-thin-serif',
    PANOSE_TEXT_OVAL_SERIF:                 'text-oval-serif',
    PANOSE_TEXT_EXAGGERATED_SERIF:          'text-exaggerated-serif',
    PANOSE_TEXT_TRIANGLE_SERIF:             'text-triangle-serif',
    PANOSE_TEXT_NORMAL_SANS:                'text-normal-sans',
    PANOSE_TEXT_OBTUSE_SANS:                'text-obtuse-sans',
    PANOSE_TEXT_PERPENDICULAR_SANS:         'text-perpendicular-sans',
    PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF:  'text-flared-transitional-serif',
    PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF: 'text-rounded-transitional-serif',
}

PANOSE_HANDWRITTEN_SUBCLASSES = {
    PANOSE_HANDWRITTEN_FLAT_NIB:        N_('Flat Nib'),
    PANOSE_HANDWRITTEN_PRESSURE_POINT:  N_('Pressure Point'),
    PANOSE_HANDWRITTEN_ENGRAVED:        N_('Engraved'),
    PANOSE_HANDWRITTEN_BALL:            N_('Ball (Round Cap)'),
    PANOSE_HANDWRITTEN_BRUSH:           N_('Brush'),
    PANOSE_HANDWRITTEN_ROUGH:           N_('Rough'),
    PANOSE_HANDWRITTEN_FELT_PEN:        N_('Felt Pen / Brush Tip'),
    PANOSE_HANDWRITTEN_WILD_BRUSH:      N_('Wild Brush (Drips and splatters)'),
}

PANOSE_DECORATIVE_SUBCLASSES = {
    PANOSE_DECORATIVE_DERIVATIVE:           N_('Derivative'),
    PANOSE_DECORATIVE_NONSTANDARD_TOPOLOGY: N_('Non-standard Topology'),
    PANOSE_DECORATIVE_NONSTANDARD_ELEMENTS: N_('Non-standard Elements'),
    PANOSE_DECORATIVE_NONSTANDARD_ASPECT:   N_('Non-standard Aspect'),
    PANOSE_DECORATIVE_INITIALS:             N_('Initials'),
    PANOSE_DECORATIVE_CARTOON:              N_('Cartoon'),
    PANOSE_DECORATIVE_PICTURE_STEMS:        N_('Picture Stems'),
    PANOSE_DECORATIVE_ORNAMENTED:           N_('Ornamented'),
    PANOSE_DECORATIVE_TEXT_AND_BACKGROUND:  N_('Text and Background'),
    PANOSE_DECORATIVE_COLLAGE:              N_('Collage'),
    PANOSE_DECORATIVE_MONTAGE:              N_('Montage'),
}

PANOSE_SYMBOL_SUBCLASSES = {
    PANOSE_SYMBOL_MONTAGES:             N_('Montages'),
    PANOSE_SYMBOL_PICTURES:             N_('Pictures'),
    PANOSE_SYMBOL_SHAPES:               N_('Shapes'),
    PANOSE_SYMBOL_SCIENTIFIC:           N_('Scientific'),
    PANOSE_SYMBOL_MUSIC:                N_('Music'),
    PANOSE_SYMBOL_EXPERT:               N_('Expert'),
    PANOSE_SYMBOL_PATTERNS:             N_('Patterns'),
    PANOSE_SYMBOL_BOARDERS:             N_('Boarders'),
    PANOSE_SYMBOL_ICONS:                N_('Icons'),
    PANOSE_SYMBOL_LOGOS:                N_('Logos'),
    PANOSE_SYMBOL_INDUSTRY_SPECIFIC:    N_('Industry specific'),
}

PANOSE_CLASS_SUBCLASSES = {
    PANOSE_TEXT: PANOSE_TEXT_SUBCLASSES,
    PANOSE_HANDWRITTEN: PANOSE_HANDWRITTEN_SUBCLASSES,
    PANOSE_DECORATIVE: PANOSE_DECORATIVE_SUBCLASSES,
    PANOSE_SYMBOL: PANOSE_SYMBOL_SUBCLASSES,
}

PANOSE_CLASS_ICONS = {
    PANOSE_TEXT: PANOSE_TEXT_ICONS,
}


#########################
### PANOSE properties ###
#########################

# The variety of properties is insane. Special thanks FontForge / George
# Williams and, whose source codes were studied as documentation for
# putting these down.


# Generic
PANOSE_FAMILY = 0
PANOSE_SUBFAMILY = 1
PANOSE_WEIGHT = 2

PANOSE_GENERIC_PROPERTIES = {
    PANOSE_FAMILY:            N_('Family'),
    # Doesn't really exist, but default to something for bad fonts
    PANOSE_SUBFAMILY:         N_('Subfamily'),
    PANOSE_WEIGHT:            N_('Weight'),
}

# These are offsets
PANOSE_TEXT_SERIF = 1
PANOSE_TEXT_WEIGHT = 2
PANOSE_TEXT_PROPORTION = 3
PANOSE_TEXT_CONTRAST = 4
PANOSE_TEXT_STROKE_VARIATION = 5
PANOSE_TEXT_ARM_STYLE = 6
PANOSE_TEXT_LETTERFORM = 7
PANOSE_TEXT_MIDLINE = 8
PANOSE_TEXT_XHEIGHT = 9

PANOSE_HANDWRITTEN_TOOL = 1
PANOSE_HANDWRITTEN_WEIGHT = 2
PANOSE_HANDWRITTEN_SPACING = 3
PANOSE_HANDWRITTEN_ASPECT_RATIO = 4
PANOSE_HANDWRITTEN_CONTRAST = 5
PANOSE_HANDWRITTEN_TOPOLOGY = 6
PANOSE_HANDWRITTEN_FORM = 7
PANOSE_HANDWRITTEN_FINIALS = 8
PANOSE_HANDWRITTEN_XASCENT = 9


PANOSE_DECORATIVE_CLASS = 1
PANOSE_DECORATIVE_WEIGHT = 2
PANOSE_DECORATIVE_ASPECT = 3
PANOSE_DECORATIVE_CONTRAST = 4
PANOSE_DECORATIVE_SERIF = 5
PANOSE_DECORATIVE_TREATMENT = 6
PANOSE_DECORATIVE_LINING = 7
PANOSE_DECORATIVE_TOPOLOGY = 8
PANOSE_DECORATIVE_CHAR_RANGE = 9


PANOSE_SYMBOL_KIND = 1
PANOSE_SYMBOL_WEIGHT = 2
PANOSE_SYMBOL_SPACING = 3
PANOSE_SYMBOL_ASPECT_AND_CONTRAST = 4
PANOSE_SYMBOL_ASPECT_RATIO_C94 = 5
PANOSE_SYMBOL_ASPECT_RATIO_C119 = 6
PANOSE_SYMBOL_ASPECT_RATIO_C157 = 7
PANOSE_SYMBOL_ASPECT_RATIO_C163 = 8
PANOSE_SYMBOL_ASPECT_RATIO_C211 = 9


PANOSE_TEXT_PROPERTIES = {
    PANOSE_TEXT_SERIF:            N_('Serif'),
    PANOSE_TEXT_WEIGHT:           N_('Weight'),
    PANOSE_TEXT_PROPORTION:       N_('Proportion'),
    PANOSE_TEXT_CONTRAST:         N_('Contrast'),
    PANOSE_TEXT_STROKE_VARIATION: N_('Stroke Variation'),
    PANOSE_TEXT_ARM_STYLE:        N_('Arm Style'),
    PANOSE_TEXT_LETTERFORM:       N_('Letterform'),
    PANOSE_TEXT_MIDLINE:          N_('Midline'),
    PANOSE_TEXT_XHEIGHT:          N_('X-Height'),
}


PANOSE_HANDWRITTEN_PROPERTIES = {
    PANOSE_HANDWRITTEN_TOOL:         N_('Tool'),
    PANOSE_HANDWRITTEN_WEIGHT:       N_('Weight'),
    PANOSE_HANDWRITTEN_SPACING:      N_('Spacing'),
    PANOSE_HANDWRITTEN_ASPECT_RATIO: N_('Aspect Ratio'),
    PANOSE_HANDWRITTEN_CONTRAST:     N_('Contrast'),
    PANOSE_HANDWRITTEN_TOPOLOGY:     N_('Topology'),
    PANOSE_HANDWRITTEN_FORM:         N_('Form'),
    PANOSE_HANDWRITTEN_FINIALS:      N_('Finials'),
    PANOSE_HANDWRITTEN_XASCENT:      N_('X-Ascent'),
}


PANOSE_DECORATIVE_PROPERTIES = {
    PANOSE_DECORATIVE_CLASS:      N_('Class'),
    PANOSE_DECORATIVE_WEIGHT:     N_('Weight'),
    PANOSE_DECORATIVE_ASPECT:     N_('Aspect'),
    PANOSE_DECORATIVE_CONTRAST:   N_('Contrast'),
    PANOSE_DECORATIVE_SERIF:      N_('Serif'),
    PANOSE_DECORATIVE_TREATMENT:  N_('Treatment'),
    PANOSE_DECORATIVE_LINING:     N_('Lining'),
    PANOSE_DECORATIVE_TOPOLOGY:   N_('Topology'),
    PANOSE_DECORATIVE_CHAR_RANGE: N_('Character Range'),
}

PANOSE_SYMBOL_PROPERTIES = {
    PANOSE_SYMBOL_KIND:                N_('Kind'),
    PANOSE_SYMBOL_WEIGHT:              N_('Weight'),
    PANOSE_SYMBOL_SPACING:             N_('Spacing'),
    PANOSE_SYMBOL_ASPECT_AND_CONTRAST: N_('Aspect and Contrast'),
    PANOSE_SYMBOL_ASPECT_RATIO_C94:    N_('Asp. ratio char. 94'),
    PANOSE_SYMBOL_ASPECT_RATIO_C119:   N_('Asp. ratio char. 119'),
    PANOSE_SYMBOL_ASPECT_RATIO_C157:   N_('Asp. ratio char. 157'),
    PANOSE_SYMBOL_ASPECT_RATIO_C163:   N_('Asp. ratio char. 163'),
    PANOSE_SYMBOL_ASPECT_RATIO_C211:   N_('Asp. ratio char. 211'),

}

PANOSE_WEIGHT_VERY_LIGHT = 2
PANOSE_WEIGHT_LIGHT = 3
PANOSE_WEIGHT_THIN = 4
PANOSE_WEIGHT_BOOK = 5
PANOSE_WEIGHT_MEDIUM = 6
PANOSE_WEIGHT_DEMI = 7
PANOSE_WEIGHT_BOLD = 8
PANOSE_WEIGHT_HEAVY = 9
PANOSE_WEIGHT_BLACK = 10
PANOSE_WEIGHT_NORD = 11


PANOSE_TEXT_WIDTH_OLD_STYLE = 2
PANOSE_TEXT_WIDTH_MODERN = 3
PANOSE_TEXT_WIDTH_EVEN_WIDTH = 4
PANOSE_TEXT_WIDTH_EXTENDED = 5
PANOSE_TEXT_WIDTH_CONDENSED = 6
PANOSE_TEXT_WIDTH_VERY_EXTENDED = 7
PANOSE_TEXT_WIDTH_VERY_CONDENSED = 8
PANOSE_TEXT_WIDTH_MONOSPACED = 9


PANOSE_TEXT_CONTRAST_NONE = 2
PANOSE_TEXT_CONTRAST_VERY_LOW = 3
PANOSE_TEXT_CONTRAST_LOW = 4
PANOSE_TEXT_CONTRAST_MEDIUM_LOW = 5
PANOSE_TEXT_CONTRAST_MEDIUM = 6
PANOSE_TEXT_CONTRAST_MEDIUM_HIGH = 7
PANOSE_TEXT_CONTRAST_HIGH = 8
PANOSE_TEXT_CONTRAST_VERY_HIGH = 9


PANOSE_TEXT_STROKE_NO_VARIATION = 2
PANOSE_TEXT_STROKE_GRADUAL_DIAGONAL = 3
PANOSE_TEXT_STROKE_GRADUAL_TRANSITIONAL = 4
PANOSE_TEXT_STROKE_GRADUAL_VERTICAL = 5
PANOSE_TEXT_STROKE_GRADUAL_HORIZONTAL = 6
PANOSE_TEXT_STROKE_RAPID_VERTICAL = 7
PANOSE_TEXT_STROKE_RAPID_HORIZONTAL = 8
PANOSE_TEXT_STROKE_INSTANT_VERTICAL = 9
PANOSE_TEXT_STROKE_INSTANT_HORIZONTAL = 10


PANOSE_TEXT_ARMS_STRAIGHT_HORIZONTAL = 2
PANOSE_TEXT_ARMS_STRAIGHT_WEDGE = 3
PANOSE_TEXT_ARMS_STRAIGHT_VERTICAL = 4
PANOSE_TEXT_ARMS_STRAIGHT_SINGLE_SERIF = 5
PANOSE_TEXT_ARMS_STRAIGHT_DOUBLE_SERIF = 6
PANOSE_TEXT_ARMS_NONSTRAIGHT_HORIZONTAL = 7
PANOSE_TEXT_ARMS_NONSTRAIGHT_WEDGE = 8
PANOSE_TEXT_ARMS_NONSTRAIGHT_VERTICAL = 9
PANOSE_TEXT_ARMS_NONSTRAIGHT_SINGLE_SERIF = 10
PANOSE_TEXT_ARMS_NONSTRAIGHT_DOUBLE_SERIF = 11


PANOSE_TEXT_LETTERFORM_NORMAL_CONTACT = 2
PANOSE_TEXT_LETTERFORM_NORMAL_WEIGHTED = 3
PANOSE_TEXT_LETTERFORM_NORMAL_BOXED = 4
PANOSE_TEXT_LETTERFORM_NORMAL_FLATTENED = 5
PANOSE_TEXT_LETTERFORM_NORMAL_ROUNDED = 6
PANOSE_TEXT_LETTERFORM_NORMAL_OFF_CENTER = 7
PANOSE_TEXT_LETTERFORM_NORMAL_SQUARE = 8
PANOSE_TEXT_LETTERFORM_OBLIQUE_CONTACT = 9
PANOSE_TEXT_LETTERFORM_OBLIQUE_WEIGHTED = 10
PANOSE_TEXT_LETTERFORM_OBLIQUE_BOXED = 11
PANOSE_TEXT_LETTERFORM_OBLIQUE_FLATTENED = 12
PANOSE_TEXT_LETTERFORM_OBLIQUE_ROUNDED = 13
PANOSE_TEXT_LETTERFORM_OBLIQUE_OFF_CENTER = 14
PANOSE_TEXT_LETTERFORM_OBLIQUE_SQUARE = 15



PANOSE_TEXT_MIDLINE_STANDARD_TRIMMED = 2
PANOSE_TEXT_MIDLINE_STANDARD_POINTED = 3
PANOSE_TEXT_MIDLINE_STANDARD_SERIFED = 4
PANOSE_TEXT_MIDLINE_HIGH_TRIMMED = 5
PANOSE_TEXT_MIDLINE_HIGH_POINTED = 6
PANOSE_TEXT_MIDLINE_HIGH_SERIFED = 7
PANOSE_TEXT_MIDLINE_CONSTANT_TRIMMED = 8
PANOSE_TEXT_MIDLINE_CONSTANT_POINTED = 9
PANOSE_TEXT_MIDLINE_CONSTANT_SERIFED = 10
PANOSE_TEXT_MIDLINE_LOW_TRIMMED = 11
PANOSE_TEXT_MIDLINE_LOW_POINTED = 12
PANOSE_TEXT_MIDLINE_LOW_SERIFED = 13



PANOSE_TEXT_XHEIGHT_CONSTANT_SMALL = 2
PANOSE_TEXT_XHEIGHT_CONSTANT_STANDARD = 3
PANOSE_TEXT_XHEIGHT_CONSTANT_LARGE = 4
PANOSE_TEXT_XHEIGHT_DUCKING_SMALL = 5
PANOSE_TEXT_XHEIGHT_DUCKING_STANDARD = 6
PANOSE_TEXT_XHEIGHT_DUCKING_LARGE = 7



PANOSE_WEIGHTS = {
    PANOSE_WEIGHT_VERY_LIGHT: N_('Very Light'),
    PANOSE_WEIGHT_LIGHT:      N_('Light'),
    PANOSE_WEIGHT_THIN:       N_('Thin'),
    PANOSE_WEIGHT_BOOK:       N_('Book'),
    PANOSE_WEIGHT_MEDIUM:     N_('Medium'),
    PANOSE_WEIGHT_DEMI:       N_('Demi'),
    PANOSE_WEIGHT_BOLD:       N_('Bold'),
    PANOSE_WEIGHT_HEAVY:      N_('Heavy'),
    PANOSE_WEIGHT_BLACK:      N_('Black'),
    PANOSE_WEIGHT_NORD:       N_('Nord'),
}

PANOSE_TEXT_PROPORTIONS = {

    PANOSE_TEXT_WIDTH_OLD_STYLE:      N_('Old Style'),
    PANOSE_TEXT_WIDTH_MODERN:         N_('Modern'),
    PANOSE_TEXT_WIDTH_EVEN_WIDTH:     N_('Even Width'),
    PANOSE_TEXT_WIDTH_EXTENDED:       N_('Extended'),
    PANOSE_TEXT_WIDTH_CONDENSED:      N_('Condensed'),
    PANOSE_TEXT_WIDTH_VERY_EXTENDED:  N_('Very Extended'),
    PANOSE_TEXT_WIDTH_VERY_CONDENSED: N_('Very Condensed'),
    PANOSE_TEXT_WIDTH_MONOSPACED:     N_('Monospace'),
}

PANOSE_TEXT_CONTRASTS = {

    PANOSE_TEXT_CONTRAST_NONE:        N_('contrast|None'),
    PANOSE_TEXT_CONTRAST_VERY_LOW:    N_('contrast|Very Low'),
    PANOSE_TEXT_CONTRAST_LOW:         N_('contrast|Low'),
    PANOSE_TEXT_CONTRAST_MEDIUM_LOW:  N_('contrast|Medium Low'),
    PANOSE_TEXT_CONTRAST_MEDIUM:      N_('contrast|Medium'),
    PANOSE_TEXT_CONTRAST_MEDIUM_HIGH: N_('contrast|Medium High'),
    PANOSE_TEXT_CONTRAST_HIGH:        N_('contrast|High'),
    PANOSE_TEXT_CONTRAST_VERY_HIGH:   N_('contrast|Very High'),
}

PANOSE_TEXT_STROKE_VARIATIONS = {

    PANOSE_TEXT_STROKE_NO_VARIATION:         N_('No Variation'),
    PANOSE_TEXT_STROKE_GRADUAL_DIAGONAL:     (N_('Gradual'), N_('Diagonal')),
    PANOSE_TEXT_STROKE_GRADUAL_TRANSITIONAL: (N_('Gradual'), N_('stroke|Transitional')),
    PANOSE_TEXT_STROKE_GRADUAL_VERTICAL:     (N_('Gradual'), N_('Vertical')),
    PANOSE_TEXT_STROKE_GRADUAL_HORIZONTAL:   (N_('Gradual'), N_('Horizontal')),
    PANOSE_TEXT_STROKE_RAPID_VERTICAL:       (N_('Rapid'), N_('Vertical')),
    PANOSE_TEXT_STROKE_RAPID_HORIZONTAL:     (N_('Rapid'), N_('Horizontal')),
    PANOSE_TEXT_STROKE_INSTANT_VERTICAL:     (N_('Instant'), N_('Vertical')),
    PANOSE_TEXT_STROKE_INSTANT_HORIZONTAL:   (N_('Instant'), N_('Horizontal')),
}

PANOSE_TEXT_ARM_STYLES = {
    PANOSE_TEXT_ARMS_STRAIGHT_HORIZONTAL:      (N_('Straight Arms'), N_('arms|Horizontal')),
    PANOSE_TEXT_ARMS_STRAIGHT_WEDGE:           (N_('Straight Arms'), N_('Wedge')),
    PANOSE_TEXT_ARMS_STRAIGHT_VERTICAL:        (N_('Straight Arms'), N_('arms|Vertical')),
    PANOSE_TEXT_ARMS_STRAIGHT_SINGLE_SERIF:    (N_('Straight Arms'), N_('Single Serif')),
    PANOSE_TEXT_ARMS_STRAIGHT_DOUBLE_SERIF:    (N_('Straight Arms'), N_('Double Serif')),
    PANOSE_TEXT_ARMS_NONSTRAIGHT_HORIZONTAL:   (N_('Non-Straight Arms'), N_('arms|Horizontal')),
    PANOSE_TEXT_ARMS_NONSTRAIGHT_WEDGE:        (N_('Non-Straight Arms'), N_('Wedge')),
    PANOSE_TEXT_ARMS_NONSTRAIGHT_VERTICAL:     (N_('Non-Straight Arms'), N_('arms|Vertical')),
    PANOSE_TEXT_ARMS_NONSTRAIGHT_SINGLE_SERIF: (N_('Non-Straight Arms'), N_('Single Serif')),
    PANOSE_TEXT_ARMS_NONSTRAIGHT_DOUBLE_SERIF: (N_('Non-Straight Arms'), N_('Double Serif')),
}

PANOSE_TEXT_LETTERFORMS = {
    PANOSE_TEXT_LETTERFORM_NORMAL_CONTACT:     (N_('Normal'), N_('Contact')),
    PANOSE_TEXT_LETTERFORM_NORMAL_WEIGHTED:    (N_('Normal'), N_('Weighted')),
    PANOSE_TEXT_LETTERFORM_NORMAL_BOXED:       (N_('Normal'), N_('Boxed')),
    PANOSE_TEXT_LETTERFORM_NORMAL_FLATTENED:   (N_('Normal'), N_('Flattened')),
    PANOSE_TEXT_LETTERFORM_NORMAL_ROUNDED:     (N_('Normal'), N_('Rounded')),
    PANOSE_TEXT_LETTERFORM_NORMAL_OFF_CENTER:  (N_('Normal'), N_('Off-Center')),
    PANOSE_TEXT_LETTERFORM_NORMAL_SQUARE:      (N_('Normal'), N_('Square')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_CONTACT:    (N_('Oblique'), N_('Contact')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_WEIGHTED:   (N_('Oblique'), N_('Weighted')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_BOXED:      (N_('Oblique'), N_('Boxed')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_FLATTENED:  (N_('Oblique'), N_('Flattened')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_ROUNDED:    (N_('Oblique'), N_('Rounded')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_OFF_CENTER: (N_('Oblique'), N_('Off-Center')),
    PANOSE_TEXT_LETTERFORM_OBLIQUE_SQUARE:     (N_('Oblique'), N_('Square')),
}


PANOSE_TEXT_MIDLINES = {
    PANOSE_TEXT_MIDLINE_STANDARD_TRIMMED: (N_('midline|Standard'), N_('Trimmed')),
    PANOSE_TEXT_MIDLINE_STANDARD_POINTED: (N_('midline|Standard'), N_('Pointed')),
    PANOSE_TEXT_MIDLINE_STANDARD_SERIFED: (N_('midline|Standard'), N_('Serifed')),
    PANOSE_TEXT_MIDLINE_HIGH_TRIMMED:     (N_('midline|High'), N_('Trimmed')),
    PANOSE_TEXT_MIDLINE_HIGH_POINTED:     (N_('midline|High'), N_('Pointed')),
    PANOSE_TEXT_MIDLINE_HIGH_SERIFED:     (N_('midline|High'), N_('Serifed')),
    PANOSE_TEXT_MIDLINE_CONSTANT_TRIMMED: (N_('midline|Constant'), N_('Trimmed')),
    PANOSE_TEXT_MIDLINE_CONSTANT_POINTED: (N_('midline|Constant'), N_('Pointed')),
    PANOSE_TEXT_MIDLINE_CONSTANT_SERIFED: (N_('midline|Constant'), N_('Serifed')),
    PANOSE_TEXT_MIDLINE_LOW_TRIMMED:      (N_('midline|Low'), N_('Trimmed')),
    PANOSE_TEXT_MIDLINE_LOW_POINTED:      (N_('midline|Low'), N_('Pointed')),
    PANOSE_TEXT_MIDLINE_LOW_SERIFED:      (N_('midline|Low'), N_('Serifed')),
}

PANOSE_TEXT_XHEIGHTS = {
    PANOSE_TEXT_XHEIGHT_CONSTANT_SMALL:     (N_('Constant'), N_('Small')),
    PANOSE_TEXT_XHEIGHT_CONSTANT_STANDARD:  (N_('Constant'), N_('Standard')),
    PANOSE_TEXT_XHEIGHT_CONSTANT_LARGE:     (N_('Constant'), N_('Large')),
    PANOSE_TEXT_XHEIGHT_DUCKING_SMALL:      (N_('Ducking'), N_('Small')),
    PANOSE_TEXT_XHEIGHT_DUCKING_STANDARD:   (N_('Ducking'), N_('Standard')),
    PANOSE_TEXT_XHEIGHT_DUCKING_LARGE:      (N_('Ducking'), N_('Large')),
}



PANOSE_HANDWRITTEN_PROPORTIONAL = 2
PANOSE_HANDWRITTEN_MONOSPACED = 3

PANOSE_HANDWRITTEN_ASPECT_VERY_CONDENSED = 2
PANOSE_HANDWRITTEN_ASPECT_CONDENSED = 3
PANOSE_HANDWRITTEN_ASPECT_NORMAL = 4
PANOSE_HANDWRITTEN_ASPECT_EXPANDED = 5
PANOSE_HANDWRITTEN_ASPECT_VERY_EXPANDED = 6


PANOSE_HANDWRITTEN_CONTRAST_NONE = 2
PANOSE_HANDWRITTEN_CONTRAST_VERY_LOW = 3
PANOSE_HANDWRITTEN_CONTRAST_LOW = 4
PANOSE_HANDWRITTEN_CONTRAST_MEDIUM_LOW = 5
PANOSE_HANDWRITTEN_CONTRAST_MEDIUM = 6
PANOSE_HANDWRITTEN_CONTRAST_MEDIUM_HIGH = 7
PANOSE_HANDWRITTEN_CONTRAST_HIGH = 8
PANOSE_HANDWRITTEN_CONTRAST_VERY_HIGH = 9

PANOSE_HANDWRITTEN_ROMAN_DISCONNECTED = 2
PANOSE_HANDWRITTEN_ROMAN_TRAILING = 3
PANOSE_HANDWRITTEN_ROMAN_CONNECTED = 4
PANOSE_HANDWRITTEN_CURSIVE_DISCONNECTED = 5
PANOSE_HANDWRITTEN_CURSIVE_TRAILING = 6
PANOSE_HANDWRITTEN_CURSIVE_CONNECTED = 7
PANOSE_HANDWRITTEN_BLACKLETTER_DISCONNECTED = 8
PANOSE_HANDWRITTEN_BLACKLETTER_TRAILING = 9
PANOSE_HANDWRITTEN_BLACKLETTER_CONNECTED = 10


PANOSE_HANDWRITTEN_UPRIGHT_NO_WRAPPING = 2
PANOSE_HANDWRITTEN_UPRIGHT_SOME_WRAPPING = 3
PANOSE_HANDWRITTEN_UPRIGHT_MORE_WRAPPING = 4
PANOSE_HANDWRITTEN_UPRIGHT_EXTREME_WRAPPING = 5
PANOSE_HANDWRITTEN_OBLIQUE_NO_WRAPPING = 6
PANOSE_HANDWRITTEN_OBLIQUE_SOME_WRAPPING = 7
PANOSE_HANDWRITTEN_OBLIQUE_MORE_WRAPPING = 8
PANOSE_HANDWRITTEN_OBLIQUE_EXTREME_WRAPPING = 9
PANOSE_HANDWRITTEN_EXAGGERATED_NO_WRAPPING = 10
PANOSE_HANDWRITTEN_EXAGGERATED_SOME_WRAPPING = 11
PANOSE_HANDWRITTEN_EXAGGERATED_MORE_WRAPPING = 12
PANOSE_HANDWRITTEN_EXAGGERATED_EXTREME_WRAPPING = 13

PANOSE_HANDWRITTEN_FINIALS_NONE_NO_LOOPS = 2
PANOSE_HANDWRITTEN_FINIALS_NONE_CLOSED_LOOPS = 3
PANOSE_HANDWRITTEN_FINIALS_NONE_OPEN_LOOPS = 4
PANOSE_HANDWRITTEN_FINIALS_SHARP_NO_LOOPS = 5
PANOSE_HANDWRITTEN_FINIALS_SHARP_CLOSED_LOOPS = 6
PANOSE_HANDWRITTEN_FINIALS_SHARP_OPEN_LOOPS = 7
PANOSE_HANDWRITTEN_FINIALS_TAPERED_NO_LOOPS = 8
PANOSE_HANDWRITTEN_FINIALS_TAPERED_CLOSED_LOOPS = 9
PANOSE_HANDWRITTEN_FINIALS_TAPERED_OPEN_LOOPS = 10
PANOSE_HANDWRITTEN_FINIALS_ROUND_NO_LOOPS = 11
PANOSE_HANDWRITTEN_FINIALS_ROUND_CLOSED_LOOPS = 12
PANOSE_HANDWRITTEN_FINIALS_ROUND_OPEN_LOOPS = 13

PANOSE_HANDWRITTEN_XASCENT_VERY_LOW = 2
PANOSE_HANDWRITTEN_XASCENT_LOW = 3
PANOSE_HANDWRITTEN_XASCENT_MEDIUM = 4
PANOSE_HANDWRITTEN_XASCENT_HIGH = 5
PANOSE_HANDWRITTEN_XASCENT_VERY_HIGH = 6


PANOSE_HANDWRITTEN_SPACINGS = {
    PANOSE_HANDWRITTEN_PROPORTIONAL: N_('Proportional'),
    PANOSE_HANDWRITTEN_MONOSPACED:   N_('Monospace'),
}

PANOSE_HANDWRITTEN_ASPECT_RATIOS = {
    PANOSE_HANDWRITTEN_ASPECT_VERY_CONDENSED: N_('Very Condensed'),
    PANOSE_HANDWRITTEN_ASPECT_CONDENSED:      N_('Condensed'),
    PANOSE_HANDWRITTEN_ASPECT_NORMAL:         N_('Normal'),
    PANOSE_HANDWRITTEN_ASPECT_EXPANDED:       N_('Expanded'),
    PANOSE_HANDWRITTEN_ASPECT_VERY_EXPANDED:  N_('Very Expanded'),

}

PANOSE_HANDWRITTEN_CONTRASTS = {
    PANOSE_HANDWRITTEN_CONTRAST_NONE:        N_('contrast|None'),
    PANOSE_HANDWRITTEN_CONTRAST_VERY_LOW:    N_('contrast|Very Low'),
    PANOSE_HANDWRITTEN_CONTRAST_LOW:         N_('contrast|Low'),
    PANOSE_HANDWRITTEN_CONTRAST_MEDIUM_LOW:  N_('contrast|Medium Low'),
    PANOSE_HANDWRITTEN_CONTRAST_MEDIUM:      N_('contrast|Medium'),
    PANOSE_HANDWRITTEN_CONTRAST_MEDIUM_HIGH: N_('contrast|Medium High'),
    PANOSE_HANDWRITTEN_CONTRAST_HIGH:        N_('contrast|High'),
    PANOSE_HANDWRITTEN_CONTRAST_VERY_HIGH:   N_('contrast|Very High'),
}

PANOSE_HANDWRITTEN_TOPOLOGIES = {
    PANOSE_HANDWRITTEN_ROMAN_DISCONNECTED:         (N_('Roman'), N_('Disconnected')),
    PANOSE_HANDWRITTEN_ROMAN_TRAILING:             (N_('Roman'), N_('Trailing')),
    PANOSE_HANDWRITTEN_ROMAN_CONNECTED:            (N_('Roman'), N_('Connected')),
    PANOSE_HANDWRITTEN_CURSIVE_DISCONNECTED:       (N_('Cursive'), N_('Disconnected')),
    PANOSE_HANDWRITTEN_CURSIVE_TRAILING:           (N_('Cursive'), N_('Trailing')),
    PANOSE_HANDWRITTEN_CURSIVE_CONNECTED:          (N_('Cursive'), N_('Connected')),
    PANOSE_HANDWRITTEN_BLACKLETTER_DISCONNECTED:   (N_('Blackletter'), N_('Disconnected')),
    PANOSE_HANDWRITTEN_BLACKLETTER_TRAILING:       (N_('Blackletter'), N_('Trailing')),
    PANOSE_HANDWRITTEN_BLACKLETTER_CONNECTED:      (N_('Blackletter'), N_('Connected')),
}

PANOSE_HANDWRITTEN_FORMS = {
    PANOSE_HANDWRITTEN_UPRIGHT_NO_WRAPPING:          (N_('Upright'), N_('No Wrapping')),
    PANOSE_HANDWRITTEN_UPRIGHT_SOME_WRAPPING:        (N_('Upright'), N_('Some Wrapping')),
    PANOSE_HANDWRITTEN_UPRIGHT_MORE_WRAPPING:        (N_('Upright'), N_('More Wrapping')),
    PANOSE_HANDWRITTEN_UPRIGHT_EXTREME_WRAPPING:     (N_('Upright'), N_('Extreme Wrapping')),
    PANOSE_HANDWRITTEN_OBLIQUE_NO_WRAPPING:          (N_('Oblique'), N_('No Wrapping')),
    PANOSE_HANDWRITTEN_OBLIQUE_SOME_WRAPPING:        (N_('Oblique'), N_('Some Wrapping')),
    PANOSE_HANDWRITTEN_OBLIQUE_MORE_WRAPPING:        (N_('Oblique'), N_('More Wrapping')),
    PANOSE_HANDWRITTEN_OBLIQUE_EXTREME_WRAPPING:     (N_('Oblique'), N_('Extreme Wrapping')),
    PANOSE_HANDWRITTEN_EXAGGERATED_NO_WRAPPING:      (N_('Exaggerated'), N_('No Wrapping')),
    PANOSE_HANDWRITTEN_EXAGGERATED_SOME_WRAPPING:    (N_('Exaggerated'), N_('Some Wrapping')),
    PANOSE_HANDWRITTEN_EXAGGERATED_MORE_WRAPPING:    (N_('Exaggerated'), N_('More Wrapping')),
    PANOSE_HANDWRITTEN_EXAGGERATED_EXTREME_WRAPPING: (N_('Exaggerated'), N_('Extreme Wrapping')),
}


PANOSE_HANDWRITTEN_FINIAL_TYPES = {
    PANOSE_HANDWRITTEN_FINIALS_NONE_NO_LOOPS:        (N_('finials|None'), N_('No loops')),
    PANOSE_HANDWRITTEN_FINIALS_NONE_CLOSED_LOOPS:    (N_('finials|None'), N_('Closed loops')),
    PANOSE_HANDWRITTEN_FINIALS_NONE_OPEN_LOOPS:      (N_('finials|None'), N_('Open loops')),
    PANOSE_HANDWRITTEN_FINIALS_SHARP_NO_LOOPS:       (N_('finials|Sharp'), N_('No loops')),
    PANOSE_HANDWRITTEN_FINIALS_SHARP_CLOSED_LOOPS:   (N_('finials|Sharp'), N_('Closed loops')),
    PANOSE_HANDWRITTEN_FINIALS_SHARP_OPEN_LOOPS:     (N_('finials|Sharp'), N_('Open loops')),
    PANOSE_HANDWRITTEN_FINIALS_TAPERED_NO_LOOPS:     (N_('finials|Tapered'), N_('No loops')),
    PANOSE_HANDWRITTEN_FINIALS_TAPERED_CLOSED_LOOPS: (N_('finials|Tapered'), N_('Closed loops')),
    PANOSE_HANDWRITTEN_FINIALS_TAPERED_OPEN_LOOPS:   (N_('finials|Tapered'), N_('Open loops')),
    PANOSE_HANDWRITTEN_FINIALS_ROUND_NO_LOOPS:       (N_('finials|Round'), N_('No loops')),
    PANOSE_HANDWRITTEN_FINIALS_ROUND_CLOSED_LOOPS:   (N_('finials|Round'), N_('Closed loops')),
    PANOSE_HANDWRITTEN_FINIALS_ROUND_OPEN_LOOPS:     (N_('finials|Round'), N_('Open loops')),
}



PANOSE_HANDWRITTEN_XASCENTS = {
    PANOSE_HANDWRITTEN_XASCENT_VERY_LOW:  N_('xascent|Very Low'),
    PANOSE_HANDWRITTEN_XASCENT_LOW:       N_('xascent|Low'),
    PANOSE_HANDWRITTEN_XASCENT_MEDIUM:    N_('xascent|Medium'),
    PANOSE_HANDWRITTEN_XASCENT_HIGH:      N_('xascent|High'),
    PANOSE_HANDWRITTEN_XASCENT_VERY_HIGH: N_('xascent|Very High'),
}

PANOSE_DECORATIVE_ASPECT_SUPER_CONDENSED = 2
PANOSE_DECORATIVE_ASPECT_VERY_CONDENSED = 3
PANOSE_DECORATIVE_ASPECT_CONDENSED = 4
PANOSE_DECORATIVE_ASPECT_NORMAL = 5
PANOSE_DECORATIVE_ASPECT_EXTENDED = 6
PANOSE_DECORATIVE_ASPECT_VERY_EXTENDED = 7
PANOSE_DECORATIVE_ASPECT_SUPER_EXTENDED = 8
PANOSE_DECORATIVE_ASPECT_MONOSPACED = 9


PANOSE_DECORATIVE_CONTRAST_NONE = 2
PANOSE_DECORATIVE_CONTRAST_VERY_LOW = 3
PANOSE_DECORATIVE_CONTRAST_LOW = 4
PANOSE_DECORATIVE_CONTRAST_MEDIUM_LOW = 5
PANOSE_DECORATIVE_CONTRAST_MEDIUM = 6
PANOSE_DECORATIVE_CONTRAST_MEDIUM_HIGH = 7
PANOSE_DECORATIVE_CONTRAST_HIGH = 8
PANOSE_DECORATIVE_CONTRAST_VERY_HIGH = 9
PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_LOW = 10
PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_MEDIUM = 11
PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_HIGH = 12
PANOSE_DECORATIVE_CONTRAST_BROKEN = 13


PANOSE_DECORATIVE_COVE_SERIF = PANOSE_TEXT_COVE_SERIF
PANOSE_DECORATIVE_OBTUSE_COVE_SERIF = PANOSE_TEXT_OBTUSE_COVE_SERIF
PANOSE_DECORATIVE_SQUARE_COVE_SERIF = PANOSE_TEXT_SQUARE_COVE_SERIF
PANOSE_DECORATIVE_OBTUSE_SQUARE_COVE = PANOSE_TEXT_OBTUSE_SQUARE_COVE
PANOSE_DECORATIVE_SQUARE_SERIF = PANOSE_TEXT_SQUARE_SERIF
PANOSE_DECORATIVE_THIN_SERIF = PANOSE_TEXT_THIN_SERIF
PANOSE_DECORATIVE_OVAL_SERIF = PANOSE_TEXT_OVAL_SERIF
PANOSE_DECORATIVE_EXAGGERATED_SERIF = PANOSE_TEXT_EXAGGERATED_SERIF
PANOSE_DECORATIVE_TRIANGLE_SERIF = PANOSE_TEXT_TRIANGLE_SERIF
PANOSE_DECORATIVE_NORMAL_SANS = PANOSE_TEXT_NORMAL_SANS
PANOSE_DECORATIVE_OBTUSE_SANS = PANOSE_TEXT_OBTUSE_SANS
PANOSE_DECORATIVE_PERPENDICULAR_SANS = PANOSE_TEXT_PERPENDICULAR_SANS
PANOSE_DECORATIVE_FLARED_TRANSITIONAL_SERIF = PANOSE_TEXT_FLARED_TRANSITIONAL_SERIF
PANOSE_DECORATIVE_ROUNDED_TRANSITIONAL_SERIF = PANOSE_TEXT_ROUNDED_TRANSITIONAL_SERIF
PANOSE_DECORATIVE_SCRIPT = 16

PANOSE_DECORATIVE_SOLID_FILL = 2
PANOSE_DECORATIVE_NO_FILL = 3
PANOSE_DECORATIVE_PATTERNED_FILL = 4
PANOSE_DECORATIVE_COMPLEX_FILL = 5
PANOSE_DECORATIVE_SHAPED_FILL = 6
PANOSE_DECORATIVE_DRAWN_DISTRESSED = 7


PANOSE_DECORATIVE_LINING_NONE = 2
PANOSE_DECORATIVE_LINING_INLINE = 3
PANOSE_DECORATIVE_LINING_OUTLINE = 4
PANOSE_DECORATIVE_LINING_ENGRAVED = 5
PANOSE_DECORATIVE_LINING_SHADOW = 6
PANOSE_DECORATIVE_LINING_RELIEF = 7
PANOSE_DECORATIVE_LINING_BACKDROP = 8


PANOSE_DECORATIVE_TOPOLOGY_STANDARD = 2
PANOSE_DECORATIVE_TOPOLOGY_SQUARE = 3
PANOSE_DECORATIVE_TOPOLOGY_MULTIPLE_SEGMENT = 4
PANOSE_DECORATIVE_TOPOLOGY_DECO_EMS_WACO_MIDLINE = 5
PANOSE_DECORATIVE_TOPOLOGY_UNEVEN_WEIGHTING = 6
PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_ARMS = 7
PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_FORMS = 8
PANOSE_DECORATIVE_TOPOLOGY_LOMBARDIC_FORMS = 9
PANOSE_DECORATIVE_TOPOLOGY_UPPER_CASE_IN_LOWER_CASE = 10
PANOSE_DECORATIVE_TOPOLOGY_IMPLIED_TOPOLOGY = 11
PANOSE_DECORATIVE_TOPOLOGY_HORSESHOE_E_AND_A = 12
PANOSE_DECORATIVE_TOPOLOGY_CURSIVE = 13
PANOSE_DECORATIVE_TOPOLOGY_BLACKLETTER = 14
PANOSE_DECORATIVE_TOPOLOGY_SWASH_VARIANCE = 15


PANOSE_DECORATIVE_CHAR_RANGE_EXTENDED_COLLECTION = 2
PANOSE_DECORATIVE_CHAR_RANGE_LITERALS = 3
PANOSE_DECORATIVE_CHAR_RANGE_NO_LOWER_CASE = 4
PANOSE_DECORATIVE_CHAR_RANGE_SMALL_CAPS = 5


PANOSE_DECORATIVE_ASPECTS = {
    PANOSE_DECORATIVE_ASPECT_SUPER_CONDENSED: N_('Super Condensed'),
    PANOSE_DECORATIVE_ASPECT_VERY_CONDENSED:  N_('Very Condensed'),
    PANOSE_DECORATIVE_ASPECT_CONDENSED:       N_('Condensed'),
    PANOSE_DECORATIVE_ASPECT_NORMAL:          N_('Normal'),
    PANOSE_DECORATIVE_ASPECT_EXTENDED:        N_('Extended'),
    PANOSE_DECORATIVE_ASPECT_VERY_EXTENDED:   N_('Very Extended'),
    PANOSE_DECORATIVE_ASPECT_SUPER_EXTENDED:  N_('Super Extended'),
    PANOSE_DECORATIVE_ASPECT_MONOSPACED:      N_('Monospace'),
}

PANOSE_DECORATIVE_CONTRASTS = {
    PANOSE_DECORATIVE_CONTRAST_NONE:              N_('contrast|None'),
    PANOSE_DECORATIVE_CONTRAST_VERY_LOW:          N_('contrast|Very Low'),
    PANOSE_DECORATIVE_CONTRAST_LOW:               N_('contrast|Low'),
    PANOSE_DECORATIVE_CONTRAST_MEDIUM_LOW:        N_('contrast|Medium Low'),
    PANOSE_DECORATIVE_CONTRAST_MEDIUM:            N_('contrast|Medium'),
    PANOSE_DECORATIVE_CONTRAST_MEDIUM_HIGH:       N_('contrast|Medium High'),
    PANOSE_DECORATIVE_CONTRAST_HIGH:              N_('contrast|High'),
    PANOSE_DECORATIVE_CONTRAST_VERY_HIGH:         N_('contrast|Very High'),
    PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_LOW:    N_('contrast|Horizontal Low'),
    PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_MEDIUM: N_('contrast|Horizontal Medium'),
    PANOSE_DECORATIVE_CONTRAST_HORIZONTAL_HIGH:   N_('contrast|Horizontal High'),
    PANOSE_DECORATIVE_CONTRAST_BROKEN:            N_('contrast|Broken'),
}

PANOSE_DECORATIVE_SERIFS = dict(PANOSE_TEXT_SUBCLASSES)
PANOSE_DECORATIVE_SERIFS.update({
    PANOSE_DECORATIVE_SCRIPT: N_('class|Script'),
})



PANOSE_DECORATIVE_TREATMENTS = {
    PANOSE_DECORATIVE_SOLID_FILL:       N_('Solid Fill'),
    PANOSE_DECORATIVE_NO_FILL:          N_('No Fill'),
    PANOSE_DECORATIVE_PATTERNED_FILL:   N_('Patterned Fill'),
    PANOSE_DECORATIVE_COMPLEX_FILL:     N_('Complex Fill'),
    PANOSE_DECORATIVE_SHAPED_FILL:      N_('Shaped Fill'),
    PANOSE_DECORATIVE_DRAWN_DISTRESSED: N_('Drawn / Distressed'),
}


PANOSE_DECORATIVE_LININGS = {
    PANOSE_DECORATIVE_LINING_NONE:     N_('lining|None'),
    PANOSE_DECORATIVE_LINING_INLINE:   N_('Inline'),
    PANOSE_DECORATIVE_LINING_OUTLINE:  N_('Outline'),
    PANOSE_DECORATIVE_LINING_ENGRAVED: N_('Engraved (Multiple Lines)'),
    PANOSE_DECORATIVE_LINING_SHADOW:   N_('Shadow'),
    PANOSE_DECORATIVE_LINING_RELIEF:   N_('Relief'),
    PANOSE_DECORATIVE_LINING_BACKDROP: N_('Backdrop'),
}

PANOSE_DECORATIVE_TOPOLOGIES = {
    PANOSE_DECORATIVE_TOPOLOGY_STANDARD:                 N_('topology|Standard'),
    PANOSE_DECORATIVE_TOPOLOGY_SQUARE:                   N_('topology|Square'),
    PANOSE_DECORATIVE_TOPOLOGY_MULTIPLE_SEGMENT:         N_('Multiple Segment'),
    PANOSE_DECORATIVE_TOPOLOGY_DECO_EMS_WACO_MIDLINE:    N_('Deco (E,M,S) Waco midline'),
    PANOSE_DECORATIVE_TOPOLOGY_UNEVEN_WEIGHTING:         N_('Uneven Weighting'),
    PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_ARMS:             N_('Diverse Arms'),
    PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_FORMS:            N_('Diverse Forms'),
    PANOSE_DECORATIVE_TOPOLOGY_LOMBARDIC_FORMS:          N_('Lombardic Forms'),
    PANOSE_DECORATIVE_TOPOLOGY_UPPER_CASE_IN_LOWER_CASE: N_('Upper Case in Lower Case'),
    PANOSE_DECORATIVE_TOPOLOGY_IMPLIED_TOPOLOGY:         N_('Implied Topology'),
    PANOSE_DECORATIVE_TOPOLOGY_HORSESHOE_E_AND_A:        N_('Horseshoe E and A'),
    PANOSE_DECORATIVE_TOPOLOGY_CURSIVE:                  N_('Cursive'),
    PANOSE_DECORATIVE_TOPOLOGY_BLACKLETTER:              N_('Blackletter'),
    PANOSE_DECORATIVE_TOPOLOGY_SWASH_VARIANCE:           N_('Swash Variance'),
}

PANOSE_DECORATIVE_CHAR_RANGES = {
    PANOSE_DECORATIVE_CHAR_RANGE_EXTENDED_COLLECTION: N_('Extended Collection'),
    PANOSE_DECORATIVE_CHAR_RANGE_LITERALS:            N_('Literals'),
    PANOSE_DECORATIVE_CHAR_RANGE_NO_LOWER_CASE:       N_('No Lower Case'),
    PANOSE_DECORATIVE_CHAR_RANGE_SMALL_CAPS:          N_('Small Caps'),

}

PANOSE_SYMBOL_PROPORTIONAL = 2
PANOSE_SYMBOL_MONOSPACED = 3

PANOSE_SYMBOL_ASPECT_RATIO_NO_WIDTH = 2
PANOSE_SYMBOL_ASPECT_RATIO_EXCEPTIONALLY_WIDE = 3
PANOSE_SYMBOL_ASPECT_RATIO_SUPER_WIDE = 4
PANOSE_SYMBOL_ASPECT_RATIO_VERY_WIDE = 5
PANOSE_SYMBOL_ASPECT_RATIO_WIDE = 6
PANOSE_SYMBOL_ASPECT_RATIO_NORMAL = 7
PANOSE_SYMBOL_ASPECT_RATIO_NARROW = 8
PANOSE_SYMBOL_ASPECT_RATIO_VERY_NARROW = 9


PANOSE_SYMBOL_SPACINGS = {
    PANOSE_SYMBOL_PROPORTIONAL: N_('Proportional'),
    PANOSE_SYMBOL_MONOSPACED:   N_('Monospace'),
}

PANOSE_SYMBOL_ASPECT_RATIOS = {
    PANOSE_SYMBOL_ASPECT_RATIO_NO_WIDTH:            N_('No Width'),
    PANOSE_SYMBOL_ASPECT_RATIO_EXCEPTIONALLY_WIDE:  N_('Exceptionally Wide'),
    PANOSE_SYMBOL_ASPECT_RATIO_SUPER_WIDE:          N_('Super Wide'),
    PANOSE_SYMBOL_ASPECT_RATIO_VERY_WIDE:           N_('Very Wide'),
    PANOSE_SYMBOL_ASPECT_RATIO_WIDE:                N_('Wide'),
    PANOSE_SYMBOL_ASPECT_RATIO_NORMAL:              N_('Normal'),
    PANOSE_SYMBOL_ASPECT_RATIO_NARROW:              N_('Narrow'),
    PANOSE_SYMBOL_ASPECT_RATIO_VERY_NARROW:         N_('Very Narrow'),
}

# Now, let's summarise...


PANOSE_GENERIC_PROPERTY_VALUES = {
    PANOSE_FAMILY: PANOSE_CLASSES,
    PANOSE_WEIGHT: PANOSE_WEIGHTS,
}

PANOSE_TEXT_PROPERTY_VALUES = {
    PANOSE_TEXT_SERIF:            PANOSE_TEXT_SUBCLASSES,

    PANOSE_TEXT_WEIGHT:           PANOSE_WEIGHTS,
    PANOSE_TEXT_PROPORTION:       PANOSE_TEXT_PROPORTIONS,
    PANOSE_TEXT_CONTRAST:         PANOSE_TEXT_CONTRASTS,
    PANOSE_TEXT_STROKE_VARIATION: PANOSE_TEXT_STROKE_VARIATIONS,
    PANOSE_TEXT_ARM_STYLE:        PANOSE_TEXT_ARM_STYLES,
    PANOSE_TEXT_LETTERFORM:       PANOSE_TEXT_LETTERFORMS,
    PANOSE_TEXT_MIDLINE:          PANOSE_TEXT_MIDLINES,
    PANOSE_TEXT_XHEIGHT:          PANOSE_TEXT_XHEIGHTS,

}


PANOSE_HANDWRITTEN_PROPERTY_VALUES = {
    PANOSE_HANDWRITTEN_TOOL:         PANOSE_HANDWRITTEN_SUBCLASSES,

    PANOSE_HANDWRITTEN_WEIGHT:       PANOSE_WEIGHTS,
    PANOSE_HANDWRITTEN_SPACING:      PANOSE_HANDWRITTEN_SPACINGS,
    PANOSE_HANDWRITTEN_ASPECT_RATIO: PANOSE_HANDWRITTEN_ASPECT_RATIOS,
    PANOSE_HANDWRITTEN_CONTRAST:     PANOSE_HANDWRITTEN_CONTRASTS,
    PANOSE_HANDWRITTEN_TOPOLOGY:     PANOSE_HANDWRITTEN_TOPOLOGIES,
    PANOSE_HANDWRITTEN_FORM:         PANOSE_HANDWRITTEN_FORMS,
    PANOSE_HANDWRITTEN_FINIALS:      PANOSE_HANDWRITTEN_FINIAL_TYPES,
    PANOSE_HANDWRITTEN_XASCENT:      PANOSE_HANDWRITTEN_XASCENTS,
}


PANOSE_DECORATIVE_PROPERTY_VALUES = {
    PANOSE_DECORATIVE_CLASS:      PANOSE_DECORATIVE_SUBCLASSES,

    PANOSE_DECORATIVE_WEIGHT:     PANOSE_WEIGHTS,
    PANOSE_DECORATIVE_ASPECT:     PANOSE_DECORATIVE_ASPECTS,
    PANOSE_DECORATIVE_CONTRAST:   PANOSE_DECORATIVE_CONTRASTS,
    PANOSE_DECORATIVE_SERIF:      PANOSE_DECORATIVE_SERIFS,
    PANOSE_DECORATIVE_TREATMENT:  PANOSE_DECORATIVE_TREATMENTS,
    PANOSE_DECORATIVE_LINING:     PANOSE_DECORATIVE_LININGS,
    PANOSE_DECORATIVE_TOPOLOGY:   PANOSE_DECORATIVE_TOPOLOGIES,
    PANOSE_DECORATIVE_CHAR_RANGE: PANOSE_DECORATIVE_CHAR_RANGES,
}


PANOSE_SYMBOL_PROPERTY_VALUES = {
    PANOSE_SYMBOL_KIND:                PANOSE_SYMBOL_SUBCLASSES,

    # No weights, no aspects, and no contrasts
    PANOSE_SYMBOL_WEIGHT:              {},
    PANOSE_SYMBOL_SPACING:             PANOSE_SYMBOL_SPACINGS,
    PANOSE_SYMBOL_ASPECT_AND_CONTRAST: {},
    PANOSE_SYMBOL_ASPECT_RATIO_C94:    PANOSE_SYMBOL_ASPECT_RATIOS,
    PANOSE_SYMBOL_ASPECT_RATIO_C119:   PANOSE_SYMBOL_ASPECT_RATIOS,
    PANOSE_SYMBOL_ASPECT_RATIO_C157:   PANOSE_SYMBOL_ASPECT_RATIOS,
    PANOSE_SYMBOL_ASPECT_RATIO_C163:   PANOSE_SYMBOL_ASPECT_RATIOS,
    PANOSE_SYMBOL_ASPECT_RATIO_C211:   PANOSE_SYMBOL_ASPECT_RATIOS,

}


PANOSE_CLASS_PROPERTIES = {
    PANOSE_TEXT: (PANOSE_TEXT_PROPERTIES, PANOSE_TEXT_PROPERTY_VALUES),
    PANOSE_HANDWRITTEN: (PANOSE_HANDWRITTEN_PROPERTIES,
                         PANOSE_HANDWRITTEN_PROPERTY_VALUES),
    PANOSE_DECORATIVE: (PANOSE_DECORATIVE_PROPERTIES,
                        PANOSE_DECORATIVE_PROPERTY_VALUES),
    PANOSE_SYMBOL: (PANOSE_SYMBOL_PROPERTIES,
                    PANOSE_SYMBOL_PROPERTY_VALUES),
}


#######################################
### Embedding nonsense restrictions ###
#######################################

EMBEDDING_PERMISSIONS_MASK = 0x000F

EMBEDDING_INSTALLABLE = 0x0000
EMBEDDING_RESTRICTED = 0x0002
EMBEDDING_PREVIEW_AND_PRINT = 0x0004
EMBEDDING_EDITABLE = 0x0008

EMBEDDING_OBSOLETE_DRAFT_RESTRICTION = 0x0001

EMBEDDING_NO_SUBSETTING = 0x0100
EMBEDDING_BITMAP_ONLY = 0x0200


EMBEDDING_TEXTS = {
    EMBEDDING_INSTALLABLE: N_('embedding|Installable'),
    EMBEDDING_RESTRICTED: N_('No embedding'),
    EMBEDDING_PREVIEW_AND_PRINT: N_('embedding|Printable'),
    EMBEDDING_EDITABLE: N_('embedding|Editable'),

    EMBEDDING_OBSOLETE_DRAFT_RESTRICTION:
        N_('Non-valid obsolete restriction to embedding'),

    EMBEDDING_NO_SUBSETTING: N_('No subsetting'),
    EMBEDDING_BITMAP_ONLY: N_('Only bitmap embedding'),
}


EMBEDDING_DESCRIPTIONS = {
    EMBEDDING_INSTALLABLE: N_('Applications should allow the embedding or installation of this font — it carries no explicit restrictions on embedding it or on permanently installing it on remote systems or for other users.'),
    EMBEDDING_RESTRICTED: N_('Some applications may refuse to embed this font in documents — the font flags indicate no automatic permission has been granted to embed it or transfer it to third parties, if such actions have not been permitted through other means.'),
    EMBEDDING_PREVIEW_AND_PRINT: N_('Some applications may only allow to embed this font in read-only documents, such as PDF, and some viewers may retain the font only temporarily — the font flags indicate permissions to embed it in read-only documents, and to temporarily use it on remote systems for the purposes of viewing or printing, but do not include editing the documents or permanently installing the font.'),
    EMBEDDING_EDITABLE: N_('Applications should allow embedding this font in documents, but some viewers may retain the font only temporarily — the font flags indicate permissions to embed it, and to temporarily use it on remote systems for the purposes of viewing, printing or editing the documents in which it has been embedded, but they do not include permanently installing the font.'),

    EMBEDDING_OBSOLETE_DRAFT_RESTRICTION:
        N_('The font file flags are set to apply an invalid restriction to embedding that has been included in an early draft of the file format.'),

    EMBEDDING_NO_SUBSETTING: N_('Some appplications may refuse to subset the font when embeddeding — the permissions indicated by the flags apply to the full font, and do not explicitly allow subsets of it to be used for embedding.'),
    EMBEDDING_BITMAP_ONLY: N_('Some applications may refuse to embed the font outlines — the permissions indicated by the flags apply only to bitmaps contained in the font, not to the font outlines.'),
}

EMBEDDING_WARNING = N_("""The flags indicating the embedding rights are merely a numeric value inside the font file, which is used by some automated software systems. It may not represent the true legal rights that the user has for using this font.

For example, fonts that come with no legal permissions beyond what is permitted by law can still be marked as Installable, either in error, or to prevent the technical inconenience of automated restrictions, or because the font file has had unauthorized modifications. Conversely, unrestricted fonts released under permissive licenses have sometimes been distributed with the flags set to Restricted by third parties (see https://www.1001fonts.com/users/steffmann/). In addition, some jurisdictions may automatically provide rights not explicitly granted by these flags.""")


#################
### Functions ###
#################

# IBM

IBMFontClass = namedtuple('IBMFontClass',
                          ['genericfamily', 'class_id', 'subclass_id',
                                            'class_name', 'subclass_name'])


class _NoIbmClass(object):

    __slots__ = ()

    wrapped = IBMFontClass('', 0, 0, '', '')

    def __bool__(self):
        return False

    def __getitem__(self, pos):
        return self.wrapped[pos]

    def __len__(self):
        return len(self.wrapped)

    def __repr__(self):
        return 'NO_IBM_CLASS_DATA'

    @property
    def class_id(self):
        return 0

    @property
    def class_name(self):
        return ''

    subclass_id = class_id
    genericfamily = subclass_name = class_name

    @property
    def wrapper_object_for(self):
        """Provide the real object to our type checker."""
        return self.wrapped


NO_IBM_CLASS_DATA = _NoIbmClass()


def get_ibm_genericfamily(family_class: int) -> str:
    """Get the generic family for this IBM class"""
    firstbyte = family_class >> 8
    if firstbyte in IBM_SERIFS:
        return 'serif'
    elif firstbyte in IBM_SANS_SERIFS:
        return 'sans-serif'
    elif firstbyte in IBM_FANTASY_CLASSES:
        return 'fantasy'
    elif firstbyte in IBM_CURSIVE_CLASSES:
        return 'cursive'
    elif firstbyte in IBM_SYMBOLIC_CLASSES:
        return 'symbol'
    return ''


def get_ibm_class(family_class: int) -> IBMFontClass:
    """Parse the IBM class from integer's two bytes, and return
    IBMFontClass."""
    firstbyte = family_class >> 8
    lastbyte = family_class & 0xff

    class_name = IBM_CLASSES.get(firstbyte, '')
    subclass_name = IBM_GENERIC_SUBCLASSES.get(lastbyte)
    if subclass_name is None:
        subclass_name = IBM_SUBCLASSES.get(family_class, '')
    return IBMFontClass(get_ibm_genericfamily(family_class),
                        firstbyte, lastbyte,
                        class_name, subclass_name)


def extract_ibm_class(os2_table: bytes) -> IBMFontClass:
    """Extract the IBM class from the os2 table of the OpenType file."""
    return get_ibm_class(struct.unpack('>h', os2_table[30:32])[0])


def ibm_class_to_int(ibmclass: IBMFontClass) -> int:
    """Convert the IBM class back to integer."""
    return (ibmclass.class_id << 8) | ibmclass.subclass_id


# PANOSE


class PanoseProperty(namedtuple('_PanoseProperty',
                                'family pos fieldname value textual')):

    """A PANOSE property value at a given position (and for a given family)."""

    __slots__ = ()

    # For the family and subfamily properties
    @property
    def id(self) -> int:
        return self.value

    def text(self, translate: Callable=N_) -> str:
        """Get a single textual string representing the property value. Do not
        translate the result, pass the translation function to this method.
        You pass HTML-safe translating function."""
        if isinstance(self.textual, tuple):
            return '; '.join(map(translate, self.textual))
        return translate(self.textual)

    def texts(self, translate: Callable=N_) -> str:
        """Get an iterable of textual string representing the property value.
        You can translate the results, or pass the translation function to this
        method. You can pass HTML-safe translating function."""
        if isinstance(self.textual, tuple):
            return list(map(translate, self.textual))
        return [translate(self.textual)]

    _TextishType = Union[str, TupleOf[str]]

    def choices_raw(self, invalid: bool=False) -> MappingOf[int, _TextishType]:
        """Get a dictionary mapping the potential values to their names.
        The names can be either a tuple or string, so don't use this method.
        Use choices_text or choices_texts."""
        if invalid:
            result = dict((i, '%X' % (i, )) for i in range(16))
            result.update(PANOSE_GENERIC_VALUES)
        else:
            result = dict(PANOSE_GENERIC_VALUES)

        properties, propvalues = PANOSE_CLASS_PROPERTIES.get(self.family,
                                                             _dictpair)
        values = propvalues.get(self.pos)
        if values is None:
            values = PANOSE_GENERIC_PROPERTY_VALUES.get(self.pos, _emptydict)

        result.update(values)
        return result

    def choices_text(self, translate: Callable=N_,
                           sort: bool=True,
                           invalid: bool=True) -> MappingOf[int, str]:
        """Get a dictionary mapping the potential values to their names as
        textual strings. Do not translate the results, pass the translation
        function to this method. You pass HTML-safe translating function."""

        choices = self.choices_raw(invalid=invalid).items()
        if sort:
            result = OrderedDict()
            choices = sorted(choices)
        else:
            result = {}

        for value, textual in choices:
            if isinstance(textual, tuple):
                result[value] = '; '.join(map(translate, textual))
            else:
                result[value] = translate(textual)

        return result

    def choices_texts(self, translate: Callable=N_,
                            sort: bool=True,
                            invalid: bool=True) -> MappingOf[int, str]:
        """Get a dictionary mapping the potential values to their names as
        an iterable of textual strings. You can translate the results, or pass
        the translation function to this method. You pass HTML-safe translating
        function."""

        choices = self.choices_raw(invalid=invalid).items()
        if sort:
            result = OrderedDict()
            choices = sorted(choices)
        else:
            result = {}

        for value, textual in choices:
            if isinstance(textual, tuple):
                result[value] = list(map(translate, textual))
            else:
                result[value] = [translate(textual)]

        return result


_cached_panprops = {}
_emptydict = {}
_dictpair = (_emptydict, _emptydict)


def get_panose_property(family: int, pos: int, value: int,
                        cache: bool=True) -> PanoseProperty:
    """For the given PANOSE family, get the PANOSE property at the
    given byte position  with the given byte value. By default,
    this is cached."""
    key = family, pos, value
    if key in _cached_panprops:
        return _cached_panprops[key]

    properties, propvalues = PANOSE_CLASS_PROPERTIES.get(family, _dictpair)
    fieldname = properties.get(pos)
    values = propvalues.get(pos)
    if fieldname is None:
        fieldname = PANOSE_GENERIC_PROPERTIES.get(pos)
    if values is None:
        values = PANOSE_GENERIC_PROPERTY_VALUES.get(pos, _emptydict)

    textual = values.get(value)
    if textual is None:
        textual = PANOSE_GENERIC_VALUES.get(value)

    if fieldname is None:
        fieldname = str(pos + 1)
    if textual is None:
        textual = '%X' % (value, )

    result = PanoseProperty(family, pos, fieldname, value, textual)
    if cache:
        _cached_panprops[key] = result

    return result


PanoseFontClass = namedtuple('PanoseFontClass',
                             ['genericfamily', 'class_id', 'subclass_id',
                                               'class_name', 'subclass_name'])


PanoseNumeric = namedtuple('PanoseNumeric',
                           ['family', 'serif',
                            'weight', 'proportion', 'contrast',
                            'stroke_variation', 'arm_style',
                            'letterform', 'midline', 'xheight'])


class PanoseFontClass2(tuple):

    """The parsed PANOSE values, extended version."""

    __slots__ = ()

    @property
    def family(self) -> PanoseProperty:
        """The PANOSE family"""
        return self[PANOSE_FAMILY]

    @property
    def subfamily(self) -> PanoseProperty:
        """The PANOSE serif, tool, class, kind, or subfamily of the family."""
        return self[PANOSE_SUBFAMILY]

    serif = subfamily
    tool = subfamily
    class_ = subfamily
    kind = subfamily

    @property
    def weight(self) -> PanoseProperty:
        """The PANOSE weight"""
        return self[PANOSE_WEIGHT]

    # Compatibility with PanoseFontClass and IBMFontClass
    @property
    def class_id(self) -> int:
        """The integer PANOSE family"""
        return self.family.value

    @property
    def class_name(self) -> str:
        """The translatable PANOSE family text"""
        # Guaranteed to be non-tuple
        return self.family.textual

    @property
    def subclass_id(self) -> int:
        """The integer PANOSE serif, tool, class, kind, or subfamily of
        the family."""
        return self.subfamily.value

    @property
    def subclass_name(self) -> str:
        """The translatable PANOSE text for the serif, tool, class, kind, etc."""
        # Guaranteed to be non-tuple
        return self.subfamily.textual

    @property
    def genericfamily(self) -> str:
        """The generic family corresponding to the given PANOSE class."""
        return get_panose_genericfamily(self.family.value,
                                        self.subfamily.value)

    def monospace(self) -> bool:
        """Return true if monospace class"""
        if self.family.value == PANOSE_TEXT:
            return (self[PANOSE_TEXT_PROPORTION].value ==
                    PANOSE_TEXT_WIDTH_MONOSPACED)
        elif self.family.value == PANOSE_HANDWRITTEN:
            return (self[PANOSE_HANDWRITTEN_SPACING].value ==
                    PANOSE_HANDWRITTEN_MONOSPACED)
        elif self.family.value == PANOSE_DECORATIVE:
            return (self[PANOSE_DECORATIVE_ASPECT].value ==
                    PANOSE_DECORATIVE_ASPECT_MONOSPACED)
        elif self.family.value == PANOSE_SYMBOL:
            return (self[PANOSE_SYMBOL_SPACING].value ==
                    PANOSE_SYMBOL_MONOSPACED)

        return False

    def string(self) -> str:
        """Convert to hex string"""
        return ''.join(('%X' % (p.value,))[-1:] for p in self)

    def toints(self) -> SequenceOf[int]:
        """Convert to a list of integers."""
        return [p.value for p in self]

    @classmethod
    def fromints(cls, integers: SequenceOf[int]) -> 'PanoseFontClass2':
        """Construct from a list of integers."""
        if len(integers) != 10:
            raise ValueError("Ten numbers required: {!r}".format(integers))
        family = integers[0]
        return cls(get_panose_property(family, pos, value)
                   for pos, value in enumerate(integers))

    @classmethod
    def fromstring(cls, string: str) -> 'PanoseFontClass2':
        """Construct from a hexadecimal string."""
        return cls.fromints([int(v, 16) for v in string])

    @classmethod
    def extract(cls, os2_table: bytes) -> 'PanoseFontClass2':
        """Parse from the bytes of the os2 table of the OpenType font."""
        return cls.fromints(struct.unpack('B' * 10, os2_table[32:42]))

    def properties(self) -> SequenceOf[PanoseProperty]:
        """Return the non-class properties."""
        return self[2:]

    def __repr__(self):
        return '<PanoseFontClass2 %s>' % (self.string(), )


class _NoPanoseClass(object):

    __slots__ = ()

    wrapped = PanoseFontClass2.fromints([0] * 10)

    def __bool__(self):
        return False

    def __getitem__(self, pos):
        #if isinstance(pos, slice):
        #    return [self[i] for i in pos.indices(len(self))]
        #
        #if 0 <= pos < 10:
        #    return get_panose_property(0, pos, 0)
        #
        #raise IndexError('index out of range')

        return self.wrapped[pos]

    def __len__(self):
        #return 10

        return len(self.wrapped)

    def __repr__(self):
        return 'NO_PANOSE_DATA'

    @property
    def class_id(self):
        return 0

    @property
    def class_name(self):
        return ''

    subclass_id = class_id
    genericfamily = subclass_name = class_name

    @property
    def family(self):
        return self[PANOSE_FAMILY]

    @property
    def subfamily(self):
        return self[PANOSE_SUBFAMILY]

    serif = subfamily
    tool = subfamily
    class_ = subfamily
    kind = subfamily

    @property
    def weight(self):
        return self[PANOSE_WEIGHT]

    def properties(self):
        return self[2:]

    def string(self):
        return '0' * 10

    @property
    def wrapper_object_for(self):
        """Provide the real object to our type checker."""
        return self.wrapped


NO_PANOSE_DATA = _NoPanoseClass()


def get_panose_fields(family: int) -> SequenceOf[PanoseProperty]:
    """Get the PANOSE all fields for a given family."""
    return PanoseFontClass2.fromints([family] + [0] * 9)


def get_panose_genericfamily(family: int, serif: int) -> str:
    """Get the generic family corresponding to a given pair of family
    and serif (class, kind, tool)."""
    if family == PANOSE_TEXT:
        if serif in PANOSE_SERIFS:
            return N_('serif')
        elif serif in PANOSE_SANS_SERIFS:
            return N_('sans-serif')
    elif family == PANOSE_DECORATIVE:
        return N_('fantasy')
    elif family == PANOSE_HANDWRITTEN:
        return N_('cursive')
    elif family == PANOSE_SYMBOL:
        return N_('symbol')
    return ''


def get_panose_class(family: int, serif: int) -> PanoseFontClass:
    """Get basic PANOSE class information for a pari of family
    and serif."""
    class_name = PANOSE_CLASSES.get(family, '')
    subclass_name = PANOSE_GENERIC_SUBCLASSES.get(serif)
    if subclass_name is None:
        subclasses = PANOSE_CLASS_SUBCLASSES.get(family, None)
        if subclasses is None:
            subclass_name = ''
        else:
            subclass_name = subclasses.get(serif, '')

    return PanoseFontClass(get_panose_genericfamily(family, serif),
                           family, serif,
                           class_name, subclass_name)


def extract_panose_class(os2_table: bytes,
                         old_api: bool=False) -> PanoseFontClass2:
    """Extract the PANOSE class from the os2 table."""
    if not old_api:
        return PanoseFontClass2.extract(os2_table)
    panose = PanoseNumeric._make(struct.unpack('B' * 10, os2_table[32:42]))
    return get_panose_class(panose.family, panose.serif)


class EmbeddingInfo(object):

    """Font's embedding information."""

    __slots__ = ('flags', )

    def __init__(self, flags: int):
        self.flags = flags

    def _texts(self, names: MappingOf[int, str]=EMBEDDING_TEXTS) -> IteratorOf[str]:
        """Yield the embedding info texts using the given mapping of
        flags to texts."""
        if self.installable:
            yield names[EMBEDDING_INSTALLABLE]

        else:
            # If multiple bits are set, incorrectly, display the least
            # restrictive
            for flag in [EMBEDDING_EDITABLE,
                         EMBEDDING_PREVIEW_AND_PRINT,
                         EMBEDDING_RESTRICTED]:
                if self.flags & flag:
                    yield names[flag]
                    break

        for flag in [EMBEDDING_NO_SUBSETTING, EMBEDDING_BITMAP_ONLY]:
            if self.flags & flag:
                yield names[flag]
                break

    def texts(self) -> IteratorOf[str]:
        """Yield the emebedding info texts."""
        return self._texts(EMBEDDING_TEXTS)

    def descriptions(self) -> IteratorOf[str]:
        """Yield the emebedding descriptions."""
        return self._texts(EMBEDDING_DESCRIPTIONS)

    @property
    def permissions(self) -> int:
        """The permissions."""
        return self.flags & EMBEDDING_PERMISSIONS_MASK

    @property
    def installable(self) -> bool:
        """Can be installed on remote computers"""
        return bool(self.permissions == EMBEDDING_INSTALLABLE)

    @property
    def restricted(self) -> bool:
        """Cannot be copied to remote machines, embedded or modified
        without explicit permissions"""
        return self.permissions == EMBEDDING_RESTRICTED

    @property
    def preview_and_print(self) -> bool:
        """Can be embedded and sent to remote systems temporarily
        for the purposes of previewing and printing."""
        return self.permissions == EMBEDDING_PREVIEW_AND_PRINT

    @property
    def editable(self) -> bool:
        """Like preview and print, but can also be edited."""
        return self.permissions == EMBEDDING_EDITABLE

    @property
    def no_subsetting(self) -> bool:
        """Only the whole font can be embedded, no subsets"""
        return bool(self.flags & EMBEDDING_NO_SUBSETTING)

    @property
    def bitmap_only(self) -> bool:
        """Only bitmaps can be embedded, no outlines"""
        return bool(self.flags & EMBEDDING_BITMAP_ONLY)

    def can_preview_and_print(self) -> bool:
        """Return True if the font is preview and print or editable."""
        return self.preview_and_print or self.editable

    def can_embed_outline(self) -> bool:
        """Return True if embedding outlines is allowed."""
        return not self.bitmap_only

    def can_subset(self) -> bool:
        """Return True if subsetting is allowed."""
        return not self.no_subsetting


class _NoEmbeddingInfo(EmbeddingInfo):

    wrapped = EmbeddingInfo(0)

    def __init__(self):
        self.flags = 0

    def texts(self):
        yield N_("No information embedding restrictions")

    def descriptions(self):
        yield ''

    def __repr__(self):
        return 'NO_EMBEDDING_INFO'

    @property
    def wrapper_object_for(self):
        """Provide the real object to our type checker."""
        return self.wrapped


NO_EMBEDDING_INFO = _NoEmbeddingInfo()


def extract_embedding_info(os2_table: bytes) -> EmbeddingInfo:
    """Extract the embedding info from the os2 table of the OpenType font."""
    fstype = struct.unpack('>H', os2_table[8:10])
    return EmbeddingInfo(fstype[0])

