def __init__( self, start: PointDef, start_parent: GraphicObject, end: PointDef, end_parent: Optional[GraphicObject] = None, ): """ Args: start: The position of the start-pedal mark relative to `start_parent`. start_parent: Anchor for the start-pedal mark, which must be in a staff or a staff itself. end: The position of the release-pedal mark relative to `end_parent`. end_parent: An optional anchor for the release-pedal mark. If provided, this must be in the same staff as `start_parent`. Otherwise, this defaults to `self`. """ ObjectGroup.__init__(self, start, start_parent) Spanner2D.__init__( self, end if isinstance(end, Point) else Point(*end), cast(Positioned, end_parent) if end_parent else self, ) StaffObject.__init__(self, self.parent) # Add opening pedal mark # (GraphicObject init handles registration with ObjectGroup) self.depress_mark = MusicText((GraphicUnit(0), GraphicUnit(0)), "keyboardPedalPed", parent=self) self.lift_mark = MusicText(self.end_pos, "keyboardPedalUp", parent=self.end_parent)
def __init__( self, pos_x: Unit, pitch: PitchDef, duration: BeatDef, parent: GraphicObject ): """ Args: pos_x (Unit): The x-axis position relative to `parent`. The y-axis position is calculated automatically based on `pitch` and contextual information in `self.staff`. pitch (Pitch or str): May be a `str` pitch representation. See `Pitch` for valid signatures. duration (Beat or init tuple): The logical duration of the notehead. This is used to determine the glyph style. parent (GraphicObject): Must either be a `Staff` or an object with an ancestor `Staff`. """ self._pitch = Pitch.from_def(pitch) self._duration = Beat.from_def(duration) # Use a temporary y-axis position before calculating it for real MusicText.__init__( self, (pos_x, ZERO), [self._glyphnames[self.duration.base_division]], parent, ) StaffObject.__init__(self, parent) self.y = self.staff.unit( self.staff_pos - map_between(self.staff, self.parent).y )
def __init__( self, start: PointDef, start_parent: GraphicObject, stop: PointDef, stop_parent: Optional[GraphicObject], direction: int = -1, ): """ Args: start: The starting point. start_parent: The parent for the starting position. Must be a staff or in one. stop: The stopping point. stop_parent: The parent for the ending position. If `None`, defaults to `self`. direction: The direction of the slur, where `-1` indicates curving upward, and `1` vice versa. """ Path.__init__(self, start, parent=start_parent, brush=Brush((0, 0, 0, 255))) StaffObject.__init__(self, self.parent) stop = Point.from_def(stop) Spanner2D.__init__(self, stop, stop_parent or self) self.direction = direction # Load relevant engraving defaults from music font engraving_defaults = self.staff.music_font.engraving_defaults self.midpoint_thickness = self.staff.unit( engraving_defaults["slurMidpointThickness"]) self.endpoint_thickness = self.staff.unit( engraving_defaults["slurEndpointThickness"]) self._draw_path()
def __init__( self, start: PointDef, start_parent: GraphicObject, stop: PointDef, stop_parent: GraphicObject, ): """ Args: start: The starting (left) position of the beam start_parent: The parent for the starting position. Must be a staff or in one. stop: The ending (right) position of the beam stop_parent: The parent for the ending position. Must be a staff or in one. """ Path.__init__(self, start, parent=start_parent) StaffObject.__init__(self, start_parent) self.beam_thickness = self.staff.music_font.engraving_defaults[ "beamThickness"] # Draw beam stop = Point.from_def(stop) self.line_to(stop.x, stop.y, stop_parent) self.line_to(stop.x, stop.y + self.beam_thickness, stop_parent) self.line_to(ZERO, self.beam_thickness, self) self.close_subpath()
def __init__( self, pos: PointDef, accidental_type: AccidentalType, parent: GraphicObject ): self._accidental_type = accidental_type canonical_name = self._canonical_names[self.accidental_type] MusicText.__init__(self, pos, [canonical_name], parent) StaffObject.__init__(self, parent)
def __init__( self, start: PointDef, start_parent: GraphicObject, stop: PointDef, stop_parent: Optional[GraphicObject], direction: int, width: Optional[Unit] = None, ): """ Args: start: The starting point. start_parent: The parent for the starting position. Must be a staff or in one. stop: The stopping point. stop_parent: The parent for the ending position. If `None`, defaults to `self`. direction: The direction of the hairpin, where `-1` means diminuendo (>) and `1` means crescendo (<). width: The width of the wide hairpin. Defaults to 1 staff unit. """ Path.__init__(self, start, parent=start_parent) StaffObject.__init__(self, start_parent) stop = Point.from_def(stop) Spanner2D.__init__(self, stop, stop_parent or self) self.direction = direction self.width = width if width is not None else self.staff.unit(1) self.thickness = self.staff.music_font.engraving_defaults[ "hairpinThickness"] self._draw_path()
def __init__(self, pos: PointDef, text: str, parent: GraphicObject): """ Args: pos: The object position text: A valid dynamic indicator string consisting of the letters: 'p, m, f, r, s, z, n' parent: The object parent. """ parsed_text = self._parse_dynamic_string(text) MusicText.__init__(self, pos, parsed_text, parent) StaffObject.__init__(self, parent)
def __init__( self, pos: PointDef, parent: Union[StaffObject, Staff], duration: BeatDef, ): pos = Point.from_def(pos) self._duration = Beat.from_def(duration) MusicText.__init__(self, pos, [self._glyphnames[self.duration.base_division]], parent) StaffObject.__init__(self, parent)
def __init__( self, pos: PointDef, text: Any, parent: Parent, font: Optional[MusicFont] = None, scale: float = 1, ): """ Args: pos: The position of the text. text (str, tuple, MusicChar, or list of these): The text to be used, represented as a either a `str` (glyph name), `tuple` (glyph name, alternate number), `MusicChar`, or a list of these. parent: The parent of the glyph. If no `font` is given, this must either be a `Staff` or an object which has a `Staff` as an ancestor. font: The music font to be used. If not specified, `parent` must be or have a `Staff` ancestor. scale: A hard scaling factor to be applied in addition to the size of the music font. """ if font is None: ancestor_staff = StaffObject.find_staff(parent) if ancestor_staff is None: raise ValueError( "MusicText must be given either a MusicFont or an ancestor staff" ) font = ancestor_staff.music_font self.music_chars = MusicText._resolve_music_chars(text, font) text = "".join(char.codepoint for char in self.music_chars) Text.__init__(self, pos, text, font, parent, scale=scale)
def __init__(self, start: PointDef, height: Unit, parent: GraphicObject): """ Args: start: Starting point for the stem height: The height of the stem, where positive extend downward. parent: """ Path.__init__(self, start, parent=parent) StaffObject.__init__(self, parent=parent) thickness = self.staff.music_font.engraving_defaults["stemThickness"] self.pen = Pen(thickness=thickness) self._height = height # Draw stem path self.line_to(self.staff.unit(0), self.height)
def __init__( self, pos: PointDef, parent: GraphicObject, length: Unit, indication: str ): """ Args: pos: parent: length: indication: A valid octave indication. Should be a valid entry in `OctaveLine.glyphs`. """ MusicText.__init__(self, pos, OctaveLine.glyphs[indication], parent) StaffObject.__init__(self, parent) open_paren_char = MusicChar(self.font, OctaveLine.glyphs["("]) close_paren_char = MusicChar(self.font, OctaveLine.glyphs[")"]) self.parenthesized_text = ( open_paren_char.codepoint + self.text + close_paren_char.codepoint ) self._length = length
def __init__(self, pos: PointDef, parent: GraphicObject, base_length: Unit): """ Args: pos: The position of the left edge of the notehead column. parent: The parent, which must be a staff or in one. base_length: The of the notehead this line is related to. The real length will be this plus a small extension defined in the `MusicFont`s engraving defaults. """ Path.__init__(self, pos, parent=parent) StaffObject.__init__(self, parent=parent) thickness = self.staff.music_font.engraving_defaults[ "legerLineThickness"] self.pen = Pen(thickness=thickness) extension = self.staff.music_font.engraving_defaults[ "legerLineExtension"] length = base_length + extension self.move_to(extension * -1, self.staff.unit(0)) self.line_to(length, self.staff.unit(0))
def __init__( self, pos_x: Unit, staff: Staff, key_signature_type: Union[KeySignatureType, str], ): """ Args: pos_x (Unit): The x position relative to the parent staff. staff (Staff): The parent staff key_signature_type (KeySignatureType or str): A description of the key signature. Any KeySignatureType may be used, or a str of one's name. """ ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff) StaffObject.__init__(self, staff) self._key_signature_type = ( key_signature_type if isinstance(key_signature_type, KeySignatureType) else KeySignatureType[key_signature_type.upper()]) self._create_pseudo_accidentals()
def __init__(self, staff: Staff, pos_x: Unit, clef_type: Union[ClefType, str]): """ Args: staff (Staff): pos_x (Unit): clef_type (ClefType or str): The type of clef. For convenience, any `str` of a `ClefType` enum name may be passed. Raises: KeyError: If the given `clef_type` is not a valid `ClefType` or `ClefType` enum name. """ if isinstance(clef_type, ClefType): self._clef_type = clef_type else: self._clef_type = ClefType[clef_type.upper()] MusicText.__init__(self, (pos_x, staff.unit(0)), self._canonical_names[self._clef_type], staff) StaffObject.__init__(self, staff) self.y = self.staff_position
def __init__( self, pos, pitch_letter, accidental_type, key_signature, music_font, scale, length, ): MusicText.__init__( self, pos, Accidental._canonical_names[accidental_type], key_signature, music_font, scale, ) StaffObject.__init__(self, key_signature) self._length = length self.pitch_letter = pitch_letter self.accidental_type = accidental_type
def __init__( self, pos_x: Unit, staff: Staff, pitches: Optional[list[PitchDef]], duration: BeatDef, stem_direction: Optional[int] = None, ): """ Args: pos_x: The horizontal position staff: The staff the object is attached to pitches: A list of pitch strings representing noteheads. An empty list or `None` indicates a rest. duration: The duration of the Chordrest stem_direction: An optional stem direction override where `1` points down and `-1` points up. If omitted, the direction is automatically calculated to point away from the furthest-out notehead. """ StaffObject.__init__(self, staff) ObjectGroup.__init__(self, Point(pos_x, staff.unit(0)), staff, None) self.duration = duration self._noteheads = set() self._accidentals = set() self._ledgers = set() self._dots = set() self._noteheads = set() self._stem_direction_override = stem_direction if pitches: for pitch in pitches: self._noteheads.add(Notehead(staff.unit(0), pitch, self.duration, self)) self.rest = None else: # TODO LOW support explicit rest Y positioning self.rest = Rest(Point(staff.unit(0), staff.unit(2)), self, duration) self._stem = None self._flag = None
def __init__( self, start: PointDef, parent: GraphicObject, end_x: Unit, text, end_parent: Optional[GraphicObject] = None, font: Optional[MusicFont] = None, scale: float = 1, ): """ Args: start (Point or init tuple): The starting point. parent (GraphicObject): The parent of the starting point. end_x (Unit): The end x position. text (str, tuple, MusicChar, or list of these): The text to be repeated over the spanner, represented as a str (glyph name), tuple (glyph name, alternate number), MusicChar, or a list of them. end_parent (GraphicObject): An optional parent of the end point. If omitted, the end position is relative to the main object. font (MusicFont): The music font to be used. If not specified, the font is taken from the ancestor staff. scale (float): A hard scaling factor to be applied in addition to the size of the music font. """ start = start if isinstance(start, Point) else Point(*start) # init the MusicText to ask it how wide a single # repetition of `text` is in order to calculate how many # repetitions are needed to cover the spanner. MusicText.__init__(self, start, text, parent, font, scale) StaffObject.__init__(self, parent) Spanner.__init__(self, end_x, end_parent or self) self.repeating_music_chars = self.music_chars self.repeating_text = self.text repetitions = self._repetitions_needed self.music_chars = self.music_chars * repetitions self._text = self.text * repetitions
def __init__(self, pos_x: Unit, staves: set[Staff]): """ Args: pos_x (Unit): Where this brace goes into effect staves (set(Staff)): The staves this brace spans """ MultiStaffObject.__init__(self, staves) StaffObject.__init__(self, self.highest_staff) # Calculate the height of the brace in highest_staff staff units scale = self.vertical_span / self.highest_staff.unit(4) if self.vertical_span > self.highest_staff.unit(50): text = ("brace", 4) elif self.vertical_span > self.highest_staff.unit(30): text = ("brace", 3) elif self.vertical_span > self.highest_staff.unit(15): text = ("brace", 2) elif self.vertical_span > self.highest_staff.unit(4): text = "brace" else: text = ("brace", 1) try: # Attempt to use size-specific optional glyph MusicText.__init__( self, (pos_x, self.vertical_span), text, self.highest_staff, scale=scale, ) except MusicFontGlyphNotFoundError: # Default to non-optional glyph MusicText.__init__( self, (pos_x, self.vertical_span), "brace", self.highest_staff, scale=scale, )
def __init__( self, start: PointDef, start_parent: GraphicObject, end_x: Unit, end_parent: Optional[GraphicObject] = None, half_lift_positions: Unit = None, ): """ Args: start (Point or init tuple): The starting position of the pedal line. start_parent (GraphicObject): An object either in a Staff or an actual Staff. end_x (Unit): The """ StaffObject.__init__(self, start_parent) pen = Pen(thickness=self.staff.music_font. engraving_defaults["pedalLineThickness"]) Path.__init__(self, start, pen, parent=start_parent) Spanner.__init__(self, end_x, end_parent or self) self.half_lift_positions = half_lift_positions self._draw_path()
def __init__(self, pos: PointDef, parent: GraphicObject, font: Optional[MusicFont] = None): MusicText.__init__(self, pos, [self._glyph_name], parent, font) StaffObject.__init__(self, parent)
def __init__(self, pos, parent): InvisibleObject.__init__(self, pos, parent) StaffObject.__init__(self, parent)
def __init__( self, start: PointDef, start_parent: GraphicObject, end_x: Unit, end_parent: Optional[GraphicObject] = None, indication: str = "8va", ): """ Args: start (Point or tuple init args): start_parent (GraphicObject): An object either in a Staff or a staff itself. This object will become the line's parent. end_x (Unit): The spanner end x position. The y position will be automatically calculated to be horizontal. end_parent (GraphicObject): An object either in a Staff or a staff itself. The root staff of this *must* be the same as the root staff of `start_parent`. If omitted, the stop point is relative to the start point. indication (str): A valid octave indication. currently supported indications are: - '15ma' (two octaves higher) - '8va' (one octave higher) - '8vb' (one octave lower) - '15mb' (two octaves lower) The default value is '8va'. """ ObjectGroup.__init__(self, start, start_parent) Spanner.__init__(self, end_x, end_parent or self) StaffObject.__init__(self, self.parent) self.transposition = Transposition(OctaveLine.intervals[indication]) self.line_text = _OctaveLineText( # No offset relative to ObjectGroup pos=ORIGIN, parent=self, length=self.length, indication=indication, ) # Vertically center the path relative to the text text_rect = self.line_text.bounding_rect # TODO LOW line needs some padding path_x = text_rect.width path_y = text_rect.height / -2 self.line_path = Path( pos=Point(path_x, path_y), pen=Pen( thickness=self.staff.music_font.engraving_defaults[ "octaveLineThickness" ], pattern=PenPattern.DASH, ), parent=self, ) # Drawn main line part self.line_path.line_to(self.end_pos.x, path_y, self.end_parent) pos_relative_to_staff = map_between(self.staff, self) # Draw end hook pointing toward the staff hook_direction = 1 if pos_relative_to_staff.y <= ZERO else -1 self.line_path.line_to( self.end_pos.x, (path_y + self.staff.unit(0.75 * hook_direction)), self.end_parent, )