Пример #1
0
def stems(name):
    """Draws note stem primitives for stem and note composites."""
    print 'drawing ...'
    long_stem_length = helpers.configvalue('Stems', 'long stem length')
    x, y = 0, long_stem_length / 2
    stem_width = helpers.configvalue('Stems', 'stem thickness')
    stem_height = long_stem_length / 2
    metrics = Point(stem_width / 2, 0)

    # Handle long stem in Beamed groups of notes.
    if name in {'uniE204', 'uniE205'}:
        # Get metrics based on noteheadBlack.
        note_index = f.FindGlyph(data.beamed_notes['uniE1F0'][1])
        note_glyph = f.glyphs[note_index]
        glyph_width = note_glyph.width
        x = glyph_width - stem_width
        retraction = helpers.configvalue('Stems', 'stem retraction')
        y += retraction / 2
        stem_height -= retraction / 2
        metrics = Point(glyph_width, 0)

        # Handle short stem in Beamed groups of notes.
        if name == 'uniE204':
            short_stem_length = helpers.configvalue('Stems', 'short stem length')
            diff = (long_stem_length - short_stem_length) / 2
            y -= diff
            stem_height -= diff

    # Draw and append glyph.
    parent_glyph = Glyph()
    registration = Point(x, y)
    tools.draw_rectangle(parent_glyph, registration, stem_width, stem_height)
    helpers.append_glyph(parent_glyph, name, metrics)
Пример #2
0
def barlines(glyphdata):
    """builds composites in Barlines and Repeats ranges.

    Special spacing parameters are required to build composites involving
    repeat dots."""
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        bbox_widths = []
        separations = []
        components = []

        for i, parent in enumerate(parents):
            complete = helpers.check_complete(parent)
            if not complete:
                if not config.getboolean('Global', 'draw missing'):
                    helpers.print_incomplete(child)
                    break
                makers.barlines(parent)
                complete = True

            # Get bounding boxes.
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            bbox_width = parent_glyph.GetBoundingRect().width
            bbox_widths.append(bbox_width)

            # Set separation parameters.
            separation = helpers.configvalue('Barlines', 'barline separation')
            if parents[i] == 'uniE044' or parents[i - 1] == 'uniE044':
                separation = helpers.configvalue(
                    'Repeats', 'repeat barline dot separation')

            if parent == 'uniE044':
                if i in {1, 3, 6} or i == len(parents) - 1:
                    separation = -bbox_width

            if i == 0:
                separation = 0
            separations.append(separation)

            # Set shifts for repeat dots.
            dx, dy = sum(bbox_widths[:-1] + separations), 0
            if parent == 'uniE044':
                dy = SPACE * 1.5 if i % 2 == 1 else SPACE * 2.5

            # Append components.
            components.append(Component(parent_index, Point(dx, dy)))

            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)

        if child and complete:
            new_width = sum(bbox_widths + separations)
            metrics = Point(new_width, 0)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #3
0
def time_ligatures(glyphdata):
    """Builds recommended ligatures in Time Signatures range.

    Target name and numerator/denominator is determined by ligature name
    (underscore and ctrl character).
    """
    for child in glyphdata:
        if helpers.check_excluded(child):
            continue

        components = []
        shifts = []

        parents = child.split('_')
        complete = True
        for i, parent in enumerate(parents):
            complete = helpers.check_complete(parent)
            if not complete:
                break
            helpers.decompose(parent)

            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            dx, dy = 0, 0
            if parent in data.ctrl_char:
                continue
            # Set vertical shift values for denominator and numerator.
            dy = SPACE if parents[i - 1] == 'uniE09F' else SPACE * 3
            if len(parents) <= 4:
                continue
            # Set horizontal shifts and spacing for ligatures
            # with double digit numerator.
            shifts.append(parent_glyph.width)
            if i == 3:
                dx = shifts[0]
            elif i == 5:
                glyph_width = sum(shifts[:2])
                glyph_center = parent_glyph.width / 2
                dx = glyph_width / 2 - glyph_center

                components.append(Component(parent_index, Point(dx, dy)))

        if not complete:
            helpers.print_incomplete(child)
        else:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)

            metrics = parent_glyph.GetMetrics()
            if len(parents) > 4:
                metrics = Point(glyph_width, 0)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #4
0
def coupler_dot(name):
    """Draws coupler dot for accordion registrations."""
    print 'drawing ...'
    glyph = Glyph()
    radius = helpers.configvalue('Accordion', 'coupler dot radius')
    x = y = radius
    width = radius * 2
    registration = Point(x, y)
    tools.draw_circle(glyph, registration, radius)
    metrics = Point(width, 0)
    helpers.append_glyph(glyph, name, metrics)
Пример #5
0
def augmentation_dot(name):
    """Draws augmentation dot for Individual Notes range."""
    print 'drawing ...'
    radius = helpers.configvalue('Notes', 'augmentation dot radius')
    x, y = radius, 0
    width = radius * 2
    registration = Point(x, y)
    glyph = Glyph()
    tools.draw_circle(glyph, registration, radius)
    metrics = Point(width, 0)
    helpers.append_glyph(glyph, name, metrics)
Пример #6
0
def note_beam(name):
    """Draws beam for Beamed group of notes range."""
    print 'drawing ...'
    short_stem_length = helpers.configvalue('Stems', 'short stem length')
    beam_thickness = helpers.configvalue('Beams', 'beam thickness')
    beam_length = helpers.configvalue('Beams', 'beam length')

    x, y = 0, short_stem_length - beam_thickness / 2
    height, width = beam_thickness / 2, beam_length
    metrics = Point(width, 0)

    # Draw lines and append glyph.
    glyph = Glyph()
    registration = Point(x, y)
    tools.draw_rectangle(glyph, registration, width, height)
    helpers.append_glyph(glyph, name, metrics)
Пример #7
0
def mirror_time(glyphdata):
    """Builds composites in Turned and Reversed time signatures ranges.

    Requires unencoded timeSigVerticalStroke component to retain cutTimeCommon
    as composite.
    """
    for parent, child in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        stroke = helpers.configvalue('Time Signatures', 'cut time stroke')
        complete = helpers.check_complete(parent)
        if complete and parent == 'uniE08B':
            complete = helpers.check_complete(stroke)
        helpers.decompose(parent)

        if not complete:
            helpers.print_incomplete(child)
        else:
            new_glyph = Glyph()
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            # Turn.
            dx, dy, sx, sy = parent_glyph.width, parent_glyph.height, -1, -1
            if glyphdata == data.reversed_time:
                # Reverse.
                dx, dy, sx, sy = parent_glyph.width, 0, -1, 1
            new_glyph.components.append(
                Component(parent_index, Point(dx, dy), Point(sx, sy)))

            # Append component if cut time is component.
            if parent == 'uniE08B' and parent_glyph.components:
                stroke_index = f.FindGlyph(stroke)
                stroke_glyph = f.glyphs[stroke_index]

                for c in parent_glyph.components:
                    if c.index == stroke_index:
                        dx = (parent_glyph.width + stroke_glyph.width) * 0.5
                    new_glyph.components.append(
                        Component(c.index, Point(dx, dy), Point(sx, sy)))

            metrics = parent_glyph.GetMetrics()
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #8
0
def stems(glyphdata):
    """Builds composites in Stems range.

    Dedicated technique components are found in Tremolos and various
    instrument-specific ranges.
    """
    for child, parent in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        complete = helpers.check_complete(parent)
        if not complete:
            if (config.getboolean('Global', 'draw missing')
                    and parent == 'uniE210'):
                makers.stems(parent)
                complete = True
            elif child:
                helpers.print_incomplete(child)
            else:
                helpers.print_incomplete(parent)
            break
        else:
            helpers.decompose(parent)
            stem_index = f.FindGlyph(glyphdata[None])
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            new_glyph = Glyph()
            dx, dy = 0, 0
            # append stem component.
            new_glyph.components.append(Component(stem_index, Point(dx, dy)))

            # Set parameters for symbols and append.
            dx = helpers.configvalue('Stems', 'stem thickness') / 2
            dy = SPACE * 2
            # Centre double sharp on left sidebearing.
            if parent == 'uniE263':
                dx -= parent_glyph.width / 2
            new_glyph.components.append(Component(parent_index, Point(dx, dy)))

            stem_glyph = f.glyphs[stem_index]
            metrics = stem_glyph.GetMetrics()
            if child:
                helpers.handle_replaced(child)
                helpers.append_glyph(new_glyph, child, metrics)
Пример #9
0
def flags(glyphdata):
    """Builds composite glyphs in Flags range.

    Additionally builds straight flags, as well as short flag and small flags
    (for small staff) stylistic sets.
    """
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        components = []

        complete = True
        for i, parent in enumerate(parents):
            complete = helpers.check_complete(parent)
            if not complete:
                continue
            helpers.decompose(parent)

            spacing = helpers.configvalue('Flags', 'internal flag spacing')
            suffix = helpers.configvalue('Set Suffixes', 'straight flags')
            if helpers.configvalue('Include', 'straight flags'):
                if parent.endswith(suffix):
                    spacing = helpers.configvalue('Flags',
                                                  'straight flag spacing')
            shifts = range(-spacing, spacing * len(parents), spacing)
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            dx, dy = 0, 0
            for n, dy in enumerate(shifts):
                if 'uniE251' in parent or parent == 'uniE241' + '.' + suffix:
                    dy = -dy
                if i == n:
                    components.append(Component(parent_index, Point(dx, dy)))

        if not complete:
            helpers.print_incomplete(child)
        else:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)
            metrics = parent_glyph.GetMetrics()
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #10
0
def staves(glyphdata):
    """builds composites in Staves range.

    Determines baseline from number of components required.
    """
    for parent, children in glyphdata.iteritems():
        complete = helpers.check_complete(parent)
        if not complete and config.getboolean('Global', 'draw missing'):
            makers.staves(parent, children)
            complete = True
        helpers.decompose(parent)

        if not children:
            continue
        for child in children:
            if helpers.check_excluded(child) or not complete:
                helpers.print_incomplete(child)
                continue

            # Determine base y values for initial components
            # in glyphs with odd vs. even number of lines.
            num_of_lines = children.index(child) + 2
            baseline = SPACE / 2 if num_of_lines % 2 == 0 else 0
            glyph_height = SPACE * num_of_lines / 2

            # Generate shift values for subsequent components.
            shifts = range(baseline, glyph_height, SPACE)
            new_glyph = Glyph()
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]

            # Append components with + and - shift values to new glyph.
            dx, dy = 0, 0
            for dy in shifts:
                new_glyph.components.append(
                    Component(parent_index, Point(dx, dy)))
                if dy > 0:
                    new_glyph.components.append(
                        Component(parent_index, Point(dx, -dy)))

            metrics = parent_glyph.GetMetrics()
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #11
0
def cut_time(glyphdata):
    """Builds cut time composites in Time signature related ranges.

    Covers both Time signature and Time signatures supplement ranges.
    Requires unencoded timeSigVerticalStroke component.
    """
    for parent, child in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        stroke = helpers.configvalue('Time Signatures', 'cut time stroke')
        l_suffix = helpers.configvalue('Set Suffixes', 'large time signatures')
        n_suffix = helpers.configvalue('Set Suffixes',
                                       'large narrow time signatures')
        if parent.endswith(l_suffix):
            stroke += l_suffix
        elif parent.endswith(n_suffix):
            stroke += n_suffix

        complete = helpers.check_complete(parent)
        if complete:
            complete = helpers.check_complete(stroke)

        if not complete:
            helpers.print_incomplete(child)
        else:
            new_glyph = Glyph()
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            dx, dy = 0, 0
            new_glyph.components.append(Component(parent_index, Point(dx, dy)))

            # Get index of cut time stroke glyph,
            # and center in main parent glyph.
            stroke_index = f.FindGlyph(stroke)
            parent_width = parent_glyph.GetBoundingRect().width
            parent_center = parent_width / 2
            dx, dy = parent_center, 0
            new_glyph.components.append(Component(stroke_index, Point(dx, dy)))

            metrics = parent_glyph.GetMetrics()
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #12
0
def dynamics(name):
    """Draws dynamic hairpin and niente circle

    Determines vertical registration of hairpin from range x-height,
    in additon to user specs.
    """
    glyph = Glyph()
    if name == 'uniE53E':
        width = helpers.configvalue('Dynamics', 'hairpin length')
        aperture = helpers.configvalue('Dynamics', 'hairpin aperture')
        thickness = helpers.configvalue('Dynamics', 'hairpin line thickness')
        offset = helpers.configvalue('Dynamics', 'hairpin height adjustment')

        # Base x-height/hairpin height on n, m, r, z or s (in that order).
        x_heights = ('uniE526', 'uniE521', 'uniE523', 'uniE525', 'uniE524')
        for item in x_heights:
            if f.has_key(item):
                l_height = helpers.get_bbox(item).height / 2 + offset
                break
            else:
                l_height = SPACE / 2 + offset
        r_height = aperture / 2
        x, y = 0, l_height + offset
        registration = Point(x, y)

        tools.draw_slash(glyph, registration, width, 0, r_height, thickness)
        tools.draw_slash(glyph, registration, width, 0, -r_height, thickness)

    else:
        # Draw niente circle.
        radius = helpers.configvalue('Dynamics', 'niente radius')
        thickness = helpers.configvalue('Dynamics', 'niente line thickness')
        width = radius * 2
        x, y = radius + thickness / 2, 0
        registration = Point(x, y)
        tools.draw_circle_frame(glyph, registration, radius, thickness)

    glyph.RemoveOverlap()
    metrics = Point(width, 0)
    helpers.append_glyph(glyph, name, metrics)
Пример #13
0
def ranks(name):
    """Draws empty ranks for accordion registration."""
    def partition(glyph, radius, width, position, thickness):
        """Draws partition lines for ranks."""
        diff = thickness / 2 + radius - width / 2
        x, y = diff, position
        height = thickness / 2
        registration = Point(x, y)
        tools.draw_rectangle(glyph, registration, width, height)
        glyph.RemoveOverlap()

    print 'drawing ...'
    glyph = Glyph()
    width = 0
    thickness = helpers.configvalue('Accordion', 'ranks line thickness')
    if name != 'uniE8C9':
        radius = helpers.configvalue('Accordion', 'round ranks radius')
        width = radius * 2
        overshoot = helpers.configvalue('Accordion', 'round ranks overshoot')
        x = radius + thickness / 2
        y = x + overshoot
        registration = Point(x, y)
        tools.draw_circle_frame(glyph, registration, radius, thickness)
    else:
        width = helpers.configvalue('Accordion', 'square ranks width')
        height = helpers.configvalue('Accordion', 'square ranks height')
        x, y = 0, (height + thickness) / 2
        registration = Point(x, y)
        radius = width / 2
        tools.draw_rect_frame(glyph, registration, width, height, thickness)

    for position, length in helpers.compile_part_data(name):
        partition(glyph, radius, length, position, thickness)

    metrics = Point(width + thickness, 0)
    helpers.append_glyph(glyph, name, metrics)
Пример #14
0
def tuplet_bracket(name):
    """Draws tuplet bracket for Beamed group of notes range."""
    print 'drawing ...'
    # Horizontal stroke
    bracket_height = helpers.configvalue('Beams', 'tuplet height')
    hook_length = helpers.configvalue('Beams', 'tuplet bracket hook length')
    bracket_thickness = helpers.configvalue('Beams', 'tuplet bracket thickness')
    beam_length = helpers.configvalue('Beams', 'beam length')

    x, y = 0, bracket_height + hook_length
    horizontal_width = beam_length - bracket_thickness
    height = bracket_thickness / 2
    glyph = Glyph()
    registration = Point(x, y)
    tools.draw_rectangle(glyph, registration, horizontal_width, height)

    # Vertical stroke
    x, y = 0, bracket_height + hook_length / 2
    vertical_width, height = bracket_thickness, hook_length / 2
    registration = Point(x, y)
    tools.draw_rectangle(glyph, registration, vertical_width, height)
    glyph.RemoveOverlap()
    metrics = Point(horizontal_width, 0)
    helpers.append_glyph(glyph, name, metrics)
Пример #15
0
def staves(name, value):
    """Draws staff parents and leger line glyphs for Staves range."""
    # Define staffline dimensions.
    print 'drawing ...'
    x = 0
    y = width = helpers.configvalue('Staves', 'medium staff line width')
    height = helpers.configvalue('Staves', 'staff line thickness') / 2
    if name == 'uniE016':
        width = helpers.configvalue('Staves', 'wide staff line width')
    elif name == 'uniE01C':
        width = helpers.configvalue('Staves', 'narrow staff line width')
    metrics = Point(width, 0)

    # Define leger line dimensions.
    if not value:
        leger_extension = helpers.configvalue('Staves', 'leger line extension')
        x, y = -leger_extension, 0
        ext = leger_extension * 2
        height = helpers.configvalue('Staves', 'leger line thickness') / 2
        if name == 'uniE022':
            sidebearing = helpers.configvalue('Staves',
                                              'narrow leger line width')
        elif name == 'uniE023':
            sidebearing = helpers.configvalue('Staves',
                                              'medium leger line width')
        else:
            sidebearing = helpers.configvalue('Staves',
                                              'wide leger line width')
        width = sidebearing + ext
        metrics = Point(sidebearing, 0)

    # Draw lines and append parent glyphs.
    parent_glyph = Glyph()
    registration = Point(x, y)
    tools.draw_rectangle(parent_glyph, registration, width, height)
    helpers.append_glyph(parent_glyph, name, metrics)
Пример #16
0
def octaves(glyphdata):
    """Builds composite glyphs in Octaves and Octaves supplement ranges.

    Requires additional (unencoded) letters to build 'loco' and 'bassa' glyphs.
    """
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        complete = True
        parent_widths = []
        components = []

        for i, parent in enumerate(parents):
            # Define names of unencoded letters according to spec.
            if parent == 'octaveC':
                parent = helpers.configvalue('Octaves', 'c')
            elif parent == 'octaveL':
                parent = helpers.configvalue('Octaves', 'l')
            elif parent == 'octaveO':
                parent = helpers.configvalue('Octaves', 'o')
            elif parent == 'octaveS':
                parent = helpers.configvalue('Octaves', 's')

            complete = helpers.check_complete(parent)
            if not complete:
                break
            helpers.decompose(parent)

            # Define shift, spacing and kerning for fraction glyphs acc. to spec.
            spacing = helpers.configvalue('Octaves', 'component spacing')
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]

            # Define horizontal shifts.
            dx = dy = 0
            parent_widths.append(parent_glyph.width + spacing)
            dx = sum(parent_widths[:-1])
            new_width = sum(parent_widths)

            # Define vertical shift for superscript.
            number_bbox = helpers.get_bbox('uniE510')
            letter_bbox = helpers.get_bbox('uniEC91')
            super_height = (number_bbox.ur.y - letter_bbox.ur.y +
                            number_bbox.ll.y + helpers.configvalue(
                                'Octaves', 'superscript height adjustment'))
            super_kern = helpers.configvalue('Octaves', 'superscript kern')

            if child in {
                    'uniE511', 'uniE515', 'uniE518', 'uniEC92', 'uniEC94',
                    'uniEC96', 'uniEC98'
            }:
                if parent in {'uniEC91', 'uniEC93', 'uniEC95', 'uniEC97'}:
                    dx += super_kern
                    dy = super_height
                    new_width += super_kern

            components.append(Component(parent_index, Point(dx, dy)))

        if complete:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)

            metrics = Point(new_width, 0)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
        else:
            helpers.print_incomplete(child)
Пример #17
0
def barlines(name):
    """Draws parent barline glyphs for Barlines and Repeats ranges."""
    def dashed_barline(glyph, registration, height):
        """Draws dashed barline.

        Superimposes reversed gap sized squares, separated by dash length,
        over full-length barline and removes overlap.

        Indexes in loop are understood as 1/4 increments, since square's
        origin point is midpoint.
        """
        width = helpers.configvalue('Barlines', 'dashed barline thickness')
        dash = helpers.configvalue('Barlines', 'dashed barline dash length')
        gap = helpers.configvalue('Barlines', 'dashed barline gap length')

        # Draw normal barline for dashes.
        tools.draw_rectangle(glyph, registration, width, height)

        # Draw gaps and remove overlap.
        unit, stop = dash + gap, height * 2 - dash
        for quarter, _ in enumerate(range(0, stop, unit)):
            diff = dash - gap
            init = quarter * 4
            start_height = init + 3
            gap_height = gap / 2
            x, y = 0, start_height * gap_height + diff * (quarter + 1)
            registration = Point(x, y)
            tools.draw_rectangle(glyph, registration, width, -gap_height)
            # -gap_height == rev. contour.
            glyph.RemoveOverlap()

    def dotted_barline(glyph, registration, height):
        """Draws dotted barline.

        Draws dots and spaces according to user specifications.
        Rounds gap values to fit staff hight (4 spaces).
        """
        radius = x = y = helpers.configvalue('Barlines',
                                             'dotted barline dot radius')
        dot = width = radius * 2
        gap = dot + helpers.configvalue('Barlines',
                                        'dotted barline gap length')
        unit, height = dot + gap, height * 2
        for num, _ in enumerate(range(0, height, unit)):
            num_of_units = height / unit
            num_of_gaps = gap * num_of_units
            num_of_dots = dot * (num_of_units + 1)
            diff = (num_of_gaps + num_of_dots - height) / num_of_units
            x = y = radius
            registration = Point(x, y + (unit - diff) * num)
            tools.draw_circle(glyph, registration, radius)

    # Define and draw barline and dot elements acc. to spec.
    print 'drawing ...'
    x, y = 0, SPACE * 2
    height = y
    width = helpers.configvalue('Barlines', 'thin barline thickness')
    if name == 'uniE034':  # barlineHeavy
        width = helpers.configvalue('Barlines', 'thick barline thickness')
    elif name == 'uniE038':  # barlineShort
        y = SPACE * 3
        height = SPACE
    elif name == 'uniE039':  # barlineTick
        y = SPACE * 4
        height = SPACE * 0.5
    elif name == 'uniE044':  # repeatDot
        x, y = helpers.configvalue('Repeats', 'repeat dot radius'), 0
        width = x * 2
    parent_glyph = Glyph()
    registration = Point(x, y)

    if name == 'uniE036':  # barlineDashed
        dashed_barline(parent_glyph, registration, height)
        width = helpers.configvalue('Barlines', 'dashed barline thickness')
    elif name == 'uniE037':  # barlineDotted
        dotted_barline(parent_glyph, registration, height)
        width = helpers.configvalue('Barlines',
                                    'dotted barline dot radius') * 2
    elif name == 'uniE044':  # repeat dot
        tools.draw_circle(parent_glyph, registration,
                          helpers.configvalue('Repeats',
                                              'repeat dot radius'))
    else:  # everything else
        tools.draw_rectangle(parent_glyph, registration, width, height)
    metrics = Point(width, 0)
    helpers.append_glyph(parent_glyph, name, metrics)
Пример #18
0
def tremolos(glyphdata):
    """Builds slash and separation dot composites in Tremolos range.

    Determines baseline of slash composites based on number of components
    required, and builds from there.
    Special spcing parameters are used for tremoloDivisiDots6 to split dots
    into to two rows of three.

    Drawing of parents is not yet implemented in [makers].
    """
    for parent, children in glyphdata.iteritems():
        complete = helpers.check_complete(parent)
        helpers.decompose(parent)
        if not children:
            continue

        for child in children:
            if helpers.check_excluded(child):
                continue

            if not complete:
                helpers.print_incomplete(child)
                continue

            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            bbox = parent_glyph.GetBoundingRect()
            dot_spacing = helpers.configvalue('Tremolos', 'divisi dot spacing')
            num_of_comps = children.index(child) + 2

            # Define base values for divisi dots.
            if parent == 'uniE4A2':
                baseline = 0
                separation = bbox.height + dot_spacing
                glyph_span = separation * num_of_comps
                # Set up tremoloDivisiDots6 for double two rows of 3 dots.
                if child == 'uniE231':
                    num_of_comps += -2

            # Define base y values for initial comps with
            # odd/even number of trem slashes.
            else:
                baseline = bbox.height / 2 if num_of_comps % 2 == 0 else 0
                spacing = helpers.configvalue('Tremolos',
                                              'tremolo slash spacing')
                separation = bbox.height + spacing
                glyph_span = separation * num_of_comps / 2

                if parent == 'uniE225':
                    spacing = helpers.configvalue('Tremolos',
                                                  'fingered tremolo spacing')
                    separation = bbox.height + spacing

            shifts = range(baseline, glyph_span, separation)
            new_glyph = Glyph()
            for shift in shifts:

                # Append trem slash comps with + and - shift values.
                if parent != 'uniE4A2':
                    dx, dy = 0, shift
                    new_glyph.components.append(
                        Component(parent_index, Point(dx, dy)))
                    if shift > 0:
                        new_glyph.components.append(
                            Component(parent_index, Point(dx, -dy)))
                    metrics = parent_glyph.GetMetrics()

                # Append divisi dot components with 2x3 for 'uniE231'.
                else:
                    dx, dy = shift, 0
                    if child != 'uniE231':
                        new_glyph.components.append(
                            Component(parent_index, Point(dx, dy)))
                    else:
                        new_glyph.components.append(
                            Component(parent_index, Point(dx, dy)))
                        dy = dot_spacing + bbox.height
                        new_glyph.components.append(
                            Component(parent_index, Point(dx, dy)))
                    metrics = Point(glyph_span - dot_spacing, 0)

            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #19
0
def dynamics(glyphdata):
    """Builds composites in Dynamics range.

    Uses sidebearings and any kerning pairs to space components.
    A global spacing setting for entire range is also available in config.
    """

    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        complete = True
        parent_widths = []
        components = []

        for i, parent in enumerate(parents):
            complete = helpers.check_complete(parent)
            if not complete:
                if not config.getboolean('Global', 'draw missing'):
                    helpers.print_incomplete(parent)
                    break
                elif parent in {'uniE53E', 'uniE541'}:
                    makers.dynamics(parent)
                    complete = True
                else:
                    helpers.print_incomplete(child)
                    break

            helpers.decompose(parent)
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            width = parent_glyph.width
            dx = dy = 0

            # Define shifts for letters based on width, spacing and kerning.
            if 'uniE53E' not in parents:
                spacing = helpers.configvalue('Dynamics', 'component spacing')
                left = parents[i - 1]
                right = parents[i]
                # Exclude kerning for leftmost component
                kerning = 0 if i == 0 else helpers.get_kerning(left, right)
                parent_widths.append(width + spacing + kerning)

                dx = sum(parent_widths[:-1]) + kerning
                # Exclude spacing for rightmost component
                width = sum(parent_widths) - spacing
                components.append(Component(parent_index, Point(dx, dy)))

            elif child == 'uniE53F':
                dx, sx, sy = width, -1, 1
                components.append(
                    Component(parent_index, Point(dx, dy), Point(sx, sy)))
            elif i == 0:
                components.append(Component(parent_index, Point(dx, dy)))
            else:
                spacing = helpers.configvalue('Dynamics', 'hairpin spacing')
                width = width * 2 + spacing
                dx, sx, sy = width, -1, 1
                components.append(
                    Component(parent_index, Point(dx, dy), Point(sx, sy)))

        if child and complete:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)
            metrics = Point(width, 0)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #20
0
def indv_notes(glyphdata):
    """Builds composites in Individual notes range.

    Duplicates functionality of flags() which is not ideal, but difficult to
    avoid when parameters are different.
    """
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        components = []

        complete = True
        for i, parent in enumerate(parents):
            long_stem_length = helpers.configvalue('Stems', 'long stem length')
            complete = helpers.check_complete(parent)
            if not complete:
                if not config.getboolean('Global', 'draw missing'):
                    break
                if parent not in {'uniE210', 'uniE1E7'}:
                    continue
                # Draw/append stem according to spec.
                elif parent == 'uniE210':
                    makers.stems(parent)
                # Draw/append augmentation dot according to spec.
                else:
                    makers.augmentation_dot(parent)
                complete = True

            if not complete:
                continue
            helpers.decompose(parent)

            # Define parameters for notehead and append to list.
            if parent in {
                    'uniE0A0', 'uniE0A1', 'uniE0A2', 'uniE0A3', 'uniE0A4'
            }:
                note_index = f.FindGlyph(parent)
                note_glyph = f.glyphs[note_index]
                metrics = Point(note_glyph.width, 0)
                dx, dy = 0, 0
                components.append(Component(note_index, Point(dx, dy)))

            # Define parameters for stem.
            elif parent == 'uniE210':
                note_bbox = note_glyph.GetBoundingRect()
                stem_index = f.FindGlyph('uniE210')
                stem_glyph = f.glyphs[stem_index]
                stem_bbox = stem_glyph.GetBoundingRect()
                dx, dy = note_glyph.width - stem_glyph.width, 0

                # Handle downstem notes and append to list.
                if child in {
                        'uniE1D4', 'uniE1D6', 'uniE1D8', 'uniE1DA', 'uniE1DC',
                        'uniE1DE', 'uniE1E0', 'uniE1E2', 'uniE1E4', 'uniE1E6'
                }:
                    dx, dy = stem_glyph.width, -long_stem_length
                components.append(Component(stem_index, Point(dx, dy)))

            # Define parameters for flags.
            elif parent in {
                    'uniE240', 'uniE241', 'uniE250', 'uniE242', 'uniE243',
                    'uniE251'
            }:
                flag_spacing = helpers.configvalue('Flags',
                                                   'internal flag spacing')
                flag_index = f.FindGlyph(parent)
                flag_glyph = f.glyphs[flag_index]
                glyph_width = (note_glyph.width + flag_glyph.width -
                               stem_glyph.width * 2)
                metrics = Point(glyph_width, 0)
                dx, dy = (note_glyph.width - stem_glyph.width * 2,
                          long_stem_length - flag_spacing * 2)
                shifts = range(dy, dy + flag_spacing * len(parents),
                               flag_spacing)

                # Generate vertical shifts and append to list.
                for n, dy in enumerate(shifts):
                    if parent in {'uniE241', 'uniE243', 'uniE251'}:
                        dx, dy = 0, -dy
                        metrics = Point(note_glyph.width, 0)
                    if i == n:
                        components.append(Component(flag_index, Point(dx, dy)))

        if not complete:
            helpers.print_incomplete(child)
        elif child:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #21
0
def beamed_notes(glyphdata):
    """Builds composites in Beamed groups of notes range.

    Scales number in Tuplets range to 70%.
    Mirrors tuplet bracket.
    """
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        components = []

        complete = True
        for i, parent in enumerate(parents):
            if not parent:
                continue
            complete = helpers.check_complete(parent)
            if not complete:
                if not config.getboolean('Global', 'draw missing'):
                    break
                elif parent in {
                        'uniE204', 'uniE205', 'uniE1E7', 'uniE1F7', 'uniE1FE'
                }:
                    # Draw/append stem according to spec.
                    if parent in {'uniE204', 'uniE205'}:
                        makers.stems(parent)
                    elif parent == 'uniE1E7':
                        makers.augmentation_dot(parent)
                    elif parent == 'uniE1F7':
                        makers.note_beam(parent)
                    elif parent == 'uniE1FE':
                        makers.tuplet_bracket(parent)
                    complete = True

            if not complete:
                continue
            helpers.decompose(parent)
            # Initialize components at origin and 100% scale.
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            parent_bbox = parent_glyph.GetBoundingRect()
            dx, dy, sx, sy = 0, 0, 1, 1

            # Scale tuplet nums to 72% and move in line
            # with parent bracket and move tall version up.
            long_stem_length = helpers.configvalue('Stems', 'long stem length')
            short_stem_length = helpers.configvalue('Stems',
                                                    'short stem length')
            tuplet_height = helpers.configvalue('Beams', 'tuplet height')
            hook_length = helpers.configvalue('Beams',
                                              'tuplet bracket hook length')
            diff = long_stem_length - short_stem_length
            if child in {'uniE1FF', 'uniE202'}:
                bbox_center = parent_bbox.height / 2
                sx = sy = 0.72
                dy = tuplet_height + hook_length - (bbox_center * 0.72)

            # Reverse tuplet brackets horizontally.
            elif child in {'uniE200', 'uniE203'}:
                dx, sx, sy = parent_glyph.width, -1, 1

            # Move bracket and number for long stem
            # up according to separation.
            if child in {'uniE201', 'uniE202', 'uniE203'}:
                dy += diff

            # Define parameters for beams.
            if parent == 'uniE1F7':
                beam_index = f.FindGlyph(parent)
                beam_glyph = f.glyphs[beam_index]
                beam_thickness = helpers.configvalue('Beams', 'beam thickness')
                beam_spacing = helpers.configvalue('Beams', 'beam spacing')
                separation = beam_thickness + beam_spacing

                # Set vertical shift for long short stem
                # and different number of beams.
                if 'uniE205' in parents or child in {
                        'uniE1F8', 'uniE1FA', 'uniE1FB'
                }:
                    if parents.count('uniE1F7') == 1:
                        dy = separation
                    elif parents.count('uniE1F7') == 3:
                        dy = -separation
                elif parents.count('uniE1F7') == 2:
                    dy = -separation

                # Generate shifts and append to list.
                number_of_beams = parents.count('uniE1F7')
                shifts = range(dy, dy + separation * number_of_beams,
                               separation)
                for n, dy in enumerate(shifts):
                    if i - 2 == n:
                        components.append(Component(beam_index, Point(dx, dy)))

            # Define parameters for beamed notes and append to list.
            elif ('uniE1F7' in parents and 'uniE204' in parents
                  or 'uniE1F7' in parents and 'uniE205' in parents):
                diff = beam_glyph.width - parent_glyph.width
                dx = diff
                components.append(Component(parent_index, Point(dx, dy)))

            # Append the rest.
            else:
                components.append(
                    Component(parent_index, Point(dx, dy), Point(sx, sy)))

        if not complete:
            helpers.print_incomplete(child)
        else:
            new_glyph = Glyph()
            for item in components:
                new_glyph.components.append(item)
            helpers.handle_replaced(child)
            metrics = parent_glyph.GetMetrics()
            if 'uniE883' in parents:
                metrics = Point(parent_bbox.width * 0.72, 0)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #22
0
def accordion_reg(glyphdata):
    """Builds registration composites in Accordion range.

    Placement schemes are defined by 'codes' derived from descriptions in
    SMuFL documentation. Reference values are given in comments below.
    """

    # for parent_data, child_data in glyphdata:
    for parent, value in glyphdata[0].iteritems():
        complete = helpers.check_complete(parent)
        if not complete:
            if not config.getboolean('Global', 'draw missing'):
                continue
            if parent == 'uniE8CA':
                makers.coupler_dot(parent)
            else:
                makers.ranks(parent)
            complete = True
        helpers.decompose(parent)

    for child, values in glyphdata[1].iteritems():
        if helpers.check_excluded(child):
            continue

        components = []
        parent = values[0]
        placement = values[1:]

        if not complete:
            helpers.print_incomplete(child)
            continue

        for i, value in enumerate(placement):
            # Calculates offsets for dot placement from reference values.
            # Reference values provided in comments.
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            parent_bbox = parent_glyph.GetBoundingRect()

            dot_index = f.FindGlyph('uniE8CA')
            dot_glyph = f.glyphs[dot_index]
            dot_bbox = dot_glyph.GetBoundingRect()

            x, y = parent_bbox.width / 2, parent_bbox.height / 2
            if value == 'stop4':
                y = parent_bbox.height / 1.219
                # 'stop4' = top of round ranks 3 (780/640)
            elif value in {'upper8', 'master'}:
                x = parent_bbox.width / 1.3
                # 'upper8'/'master' = mid right of round ranks 2/3/4 (780/600)
            elif value == 'lower8':
                x = parent_bbox.width / 4.333
                # 'lower8' = mid left of round ranks 3 (780/180)
            elif value == 'stop16':
                y = parent_bbox.height / 5.571
                # 'stop16' = bottom of round ranks 3 (780/140)
            elif value == 'soprano':
                y = parent_bbox.height / 1.1624
                # 'soprano' = top of ranks 4 (780/671)
            elif value == 'alto':
                y = parent_bbox.height / 1.612
                # 'alto' = upper mid of ranks 4 (780/484)
            elif value == 'tenor':
                y = parent_bbox.height / 2.635
                # 'tenor' = lower mid of ranks 4 (780/296)
            elif value == 'bass':
                y = parent_bbox.height / 7.156
                # 'bass' = bottom of ranks 4 (780/109)
            elif value == 'stop8b':
                y = parent_bbox.height / 1.352
                # 'stop8b' = top of ranks 2 (780/577)
            elif value == 'stop16b':
                y = parent_bbox.height / 3.842
                # 'stop16b' = bottom of ranks 2 (780/203)
            elif value in {'stop8c', 'left8stop', 'right8stop'}:
                y = parent_bbox.height / 5.555
                # 'stop8c' = bottom of square ranks 3 (750/135)
            elif value == 'stop2':
                y = parent_bbox.height / 1.22
                # 'stop2' = top of square ranks 3 (750/615)
            elif value == 'left8stop':
                x = parent_bbox.width / 3.079
                # 'left8stop' = bottom left half of square ranks 3 (625/203)
                # (x = parent_bbox.width / 3 with 3% compensation <--> for
                # 'left8stop' and 'right8stop')
            elif value == 'right8stop':
                x = parent_bbox.width / 1.481
                # 'right8stop' = bottom right half of square ranks 3 (625/422)

            # Adjust to dot center base and overshoot of round ranks glyphs.
            x -= dot_bbox.width / 2
            y -= dot_bbox.height / 2
            if parent != 'uniE8C9':
                y += helpers.configvalue('Accordion', 'round ranks overshoot')

            components.append(Component(dot_index, Point(x, y)))
            if i == 0:
                components.append(Component(parent_index, Point(0, 0)))

        new_glyph = Glyph()
        for item in components:
            new_glyph.components.append(item)

        metrics = parent_glyph.GetMetrics()
        if child:
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)
Пример #23
0
def fraction_time(glyphdata):
    """Builds Time signature fraction composites.

    Scales regular numerals to 50%.
    Fraction slash is kept at 100%, according to Bravura scaling factor.
    Option to build from dedicated numerals should perhaps be implemented.
    """
    for child, parents in glyphdata.iteritems():
        if helpers.check_excluded(child):
            continue

        parent_widths = []

        new_glyph = Glyph()
        for i, parent in enumerate(parents):
            complete = helpers.check_complete(parent)
            if not complete:
                break
            helpers.decompose(parent)

            # Define scale, shift, spacing and
            # kerning for fraction glyphs acc. to spec.
            sidebearings = helpers.configvalue('Time Signatures',
                                               'fraction sidebearings')
            spacing = helpers.configvalue('Time Signatures',
                                          'fraction spacing')
            one_kern = helpers.configvalue('Time Signatures',
                                           'fraction one kern')
            four_kern = helpers.configvalue('Time Signatures',
                                            'fraction four kern')
            parent_index = f.FindGlyph(parent)
            parent_glyph = f.glyphs[parent_index]
            parent_width = parent_glyph.width
            sx = sy = 1  # 1 = 100% (x, y)
            dx = dy = 0
            num_factor = 0.5
            # num_factor reflects current scaling factor
            # of slash vs. numerals in Bravura.
            if i == 1:
                dx = parent_widths[i - 1] - parent_width / 2 + spacing
            else:
                parent_width = parent_glyph.width * num_factor + sidebearings
                sx, sy = sx * num_factor, sy * num_factor
                if i == 0:
                    dx, dy = sidebearings, SPACE / 2
                    if parent == 'uniE081':
                        parent_width += one_kern
                else:
                    dx, dy = parent_widths[0] + spacing * 2, -SPACE / 2
                    if parent == 'uniE084':
                        dx += four_kern
                        parent_width += four_kern

            parent_widths.append(parent_width)
            new_glyph.components.append(
                Component(parent_index, Point(dx, dy), Point(sx, sy)))
        if not complete:
            helpers.print_incomplete(child)
        else:
            new_width = parent_widths[0] + parent_widths[2] + spacing * 2
            metrics = Point(new_width, 0)
            helpers.handle_replaced(child)
            helpers.append_glyph(new_glyph, child, metrics)