コード例 #1
0
ファイル: test_spanner_2d.py プロジェクト: ajyoon/brown
 def end_y_settable(self):
     spanner = MockSpanner2D(
         Point(Unit(0), Unit(1)), None, Point(Unit(2), Unit(3)), None
     )
     assert spanner.end_pos == Point(Unit(2), Unit(3))
     spanner.end_y = Unit(10)
     assert spanner.end_pos == Point(Unit(2), Unit(10))
コード例 #2
0
 def test_shape(self):
     beam = Beam(
         (Mm(1), Mm(2)),
         self.left_parent,
         (Mm(3), Mm(4)),
         self.right_parent,
     )
     thickness = beam.beam_thickness
     assert len(beam.elements) == 5
     assert_path_els_equal(beam.elements[0],
                           MoveTo(Point(Mm(0), Mm(0)), beam))
     assert_path_els_equal(beam.elements[1],
                           LineTo(Point(Mm(3), Mm(4)), self.right_parent))
     assert_path_els_equal(
         beam.elements[2],
         LineTo(
             Point(Mm(3),
                   Mm(4) + thickness),
             self.right_parent,
         ),
     )
     assert_path_els_equal(
         beam.elements[3],
         LineTo(
             Point(Mm(0), thickness),
             beam,
         ),
     )
     assert_path_els_equal(
         beam.elements[4],
         MoveTo(
             Point(Mm(0), Mm(0)),
             beam,
         ),
     )
コード例 #3
0
    def _render_in_flowable(self):
        """Render the object to the scene, dispatching partial rendering calls
        when needed if an object flows across a break in the flowable.

        Returns: None
        """
        # Calculate position within flowable
        pos_in_flowable = descendant_pos(self, self.flowable)

        remaining_x = self.length + self.flowable.dist_to_line_end(
            pos_in_flowable.x)
        if remaining_x < ZERO:
            self._render_complete(
                canvas_pos_of(self),
                self.flowable.dist_to_line_start(pos_in_flowable.x),
                pos_in_flowable.x,
            )
            return

        # Render before break
        first_line_i = self.flowable.last_break_index_at(pos_in_flowable.x)
        current_line = self.flowable.layout_controllers[first_line_i]
        render_start_pos = canvas_pos_of(self)
        first_line_length = self.flowable.dist_to_line_end(
            pos_in_flowable.x) * -1
        render_end_pos = Point(render_start_pos.x + first_line_length,
                               render_start_pos.y)
        self._render_before_break(
            pos_in_flowable.x,
            render_start_pos,
            render_end_pos,
            self.flowable.dist_to_line_start(pos_in_flowable.x),
        )

        # Iterate through remaining length
        for current_line_i in range(first_line_i + 1,
                                    len(self.flowable.layout_controllers)):
            current_line = self.flowable.layout_controllers[current_line_i]
            if remaining_x > current_line.length:
                # Render spanning continuation
                line_pos = canvas_pos_of(current_line)
                render_start_pos = Point(line_pos.x,
                                         line_pos.y + pos_in_flowable.y)
                render_end_pos = Point(
                    render_start_pos.x + current_line.length,
                    render_start_pos.y)
                self._render_spanning_continuation(self.length - remaining_x,
                                                   render_start_pos,
                                                   render_end_pos)
                remaining_x -= current_line.length
            else:
                break

        # Render end
        render_start_pos = self.flowable.map_to_canvas(
            Point(current_line.flowable_x, pos_in_flowable.y))
        render_end_pos = Point(render_start_pos.x + remaining_x,
                               render_start_pos.y)
        self._render_after_break(self.length - remaining_x, render_start_pos,
                                 render_end_pos)
コード例 #4
0
    def test_hairpin_points_diagonal_different_parents(self):
        # For reference...
        # self.left_parent = MockStaffObject((Unit(0), Unit(0)), self.staff)
        # self.right_parent = MockStaffObject((Unit(10), Unit(2)), self.staff)
        cresc = Hairpin(
            (Unit(10), Unit(2)),
            self.left_parent,
            (Unit(4), Unit(4)),
            self.right_parent,
            1,
            Unit(2),
        )
        # Spanner line slope should be Unit(1)
        points = cresc._find_hairpin_points()
        assert_almost_equal(points[0].x, points[4].y)
        assert_almost_equal(points[0].y, points[4].x)
        assert points[2] == Point(Unit(10), Unit(2))
        assert points[3] == self.left_parent

        dim = Hairpin(
            (Unit(0), Unit(0)),
            self.left_parent,
            (Unit(-6), Unit(2)),
            self.right_parent,
            -1,
            Unit(2),
        )
        # Spanner line slope should be Unit(1)
        points = dim._find_hairpin_points()
        assert_almost_equal(points[0].x, points[4].y)
        assert_almost_equal(points[0].y, points[4].x)
        assert points[2] == Point(Unit(-6), Unit(2))
        assert points[3] == self.right_parent
コード例 #5
0
ファイル: test_spanner_2d.py プロジェクト: ajyoon/brown
 def test_length_with_parents(self):
     parent_1 = InvisibleObject((Unit(1), Unit(2)), None)
     parent_2 = InvisibleObject((Unit(11), Unit(12)), None)
     spanner = MockSpanner2D(
         Point(Unit(1), Unit(2)), parent_1, Point(Unit(4), Unit(5)), parent_2
     )
     # math.sqrt(((15-2)**2) + ((17-4)**2))
     assert_almost_equal(spanner.spanner_2d_length, Unit(18.384776310850235))
コード例 #6
0
 def test__eq__(self):
     p1 = Point(Unit(5), Unit(6))
     p2 = Point(Unit(5), Unit(6))
     p3 = Point(Unit(5), Unit(1234))
     p4 = Point(Unit(1234), Unit(6))
     assert p1 == p2
     assert p1 != p3
     assert p1 != p4
コード例 #7
0
ファイル: test_spanner_2d.py プロジェクト: ajyoon/brown
 def test_length_no_parents(self):
     spanner = MockSpanner2D(
         Point(Unit(1), Unit(2)),
         neoscore.document.pages[0],
         Point(Unit(5), Unit(7)),
         neoscore.document.pages[0],
     )
     # math.sqrt(((5-1)**2) + ((7-2)**2))
     assert_almost_equal(spanner.spanner_2d_length, Unit(6.4031242374328485))
コード例 #8
0
ファイル: test_spanner_2d.py プロジェクト: ajyoon/brown
 def test_length_with_self_parent(self):
     parent = MockSpanner2D(
         Point(Unit(1), Unit(2)), None, Point(Unit(0), Unit(0)), None
     )
     spanner = MockSpanner2D(
         Point(Unit(3), Unit(7)), parent, Point(Unit(4), Unit(5)), None
     )
     # math.sqrt((4**2) + (5**2))
     assert_almost_equal(spanner.spanner_2d_length, Unit(6.4031242374328485))
コード例 #9
0
ファイル: test_chordrest.py プロジェクト: ajyoon/brown
 def test_rhythm_dot_positions_with_rest(self):
     chord = Chordrest(Mm(1), self.staff, None, Beat(7, 16))
     dots = list(chord.rhythm_dot_positions)
     dots.sort(key=lambda d: d.x)
     assert_almost_equal(
         dots[0], Point(self.staff.unit(1.326), self.staff.unit(1.5))
     )
     assert_almost_equal(
         dots[1], Point(self.staff.unit(1.826), self.staff.unit(1.5))
     )
コード例 #10
0
    def test_map_between(self):
        source = InvisibleObject((Unit(5), Unit(6)),
                                 neoscore.document.pages[1])
        destination = InvisibleObject((Unit(99), Unit(90)),
                                      neoscore.document.pages[4])
        relative_pos = map_between(source, destination)

        page_1_pos = canvas_pos_of(neoscore.document.pages[1])
        page_4_pos = canvas_pos_of(neoscore.document.pages[4])

        expected = (page_4_pos + Point(Unit(99), Unit(90))) - (
            page_1_pos + Point(Unit(5), Unit(6)))
        assert_almost_equal(relative_pos, expected)
コード例 #11
0
ファイル: flowable.py プロジェクト: ajyoon/brown
    def _generate_layout_controllers(self) -> list[NewLine]:
        """Generate automatic layout controllers.

        The generated controllers are stored in `self.layout_controllers`
        in sorted order according to ascending x position
        """
        live_page_width = neoscore.document.paper.live_width
        live_page_height = neoscore.document.paper.live_height
        # local progress of layout generation; when the entire flowable has
        # been covered, this will be equal to `self.width`
        x_progress = ZERO
        # Current position on the page relative to the top left corner
        # of the live page area
        pos_x = self.pos.x
        pos_y = self.pos.y
        current_page = 0
        # Attach initial line controller
        layout_controllers = [
            NewLine(self.pos, neoscore.document.pages[current_page],
                    x_progress, self.height)
        ]
        while True:
            x_progress += live_page_width - pos_x
            pos_y = pos_y + self.height + self.y_padding
            if x_progress >= self.length:
                # End of breakable width - Done.
                break
            if pos_y > live_page_height:
                # Page break - No y offset
                pos_x = ZERO
                pos_y = ZERO
                current_page += 1
                layout_controllers.append(
                    NewLine(
                        Point(pos_x, pos_y),
                        neoscore.document.pages[current_page],
                        x_progress,
                        self.height,
                    ))
            else:
                # Line break - self.y_padding as y offset
                pos_x = ZERO
                layout_controllers.append(
                    NewLine(
                        Point(pos_x, pos_y),
                        neoscore.document.pages[current_page],
                        x_progress,
                        self.height,
                        self.y_padding,
                    ))
        return layout_controllers
コード例 #12
0
    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)
コード例 #13
0
 def test_map_between_where_src_parent_is_dest(self):
     destination = InvisibleObject((Unit(3), Unit(10)),
                                   neoscore.document.pages[0])
     source = InvisibleObject((Unit(1), Unit(2)), destination)
     relative_pos = map_between(source, destination)
     expected = Point(Unit(-1), Unit(-2))
     assert_almost_equal(relative_pos, expected)
コード例 #14
0
 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()
コード例 #15
0
    def _render_occurrence(self, pos: Point, local_start_x: Unit,
                           shift_for_clef: bool):
        """Render one appearance of one key signature accidental.

        Much of the positioning code needs to be performed
        per-occurrence because key signatures can have different
        appearances when clefs change.

        Ideally there should be a way to cache/centralize much of this
        work.

        """
        staff_pos_in_flowable = map_between(self.flowable, self.staff)
        pos_x_in_staff = local_start_x - staff_pos_in_flowable.x
        clef = self.staff.active_clef_at(pos_x_in_staff)
        if clef is None:
            return
        clef_type = clef.clef_type
        pos_tuple = _KeySignatureAccidental.positions[
            self.accidental_type][clef_type][self.pitch_letter]
        visual_pos_x = self.staff.unit(pos_tuple[0]) + pos.x
        visual_pos_y = self.staff.unit(pos_tuple[1]) + pos.y
        if shift_for_clef:
            visual_pos_x += self._padded_clef_width(clef)
        self._render_slice(Point(visual_pos_x, visual_pos_y))
コード例 #16
0
 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()
コード例 #17
0
 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()
コード例 #18
0
ファイル: test_document.py プロジェクト: ajyoon/brown
 def test_page_origin_at_first_page(self):
     left_margin = Mm(13)
     top_margin = Mm(21)
     test_paper = Paper(Mm(200), Mm(250), top_margin, Mm(10), Mm(20),
                        left_margin, Mm(0))
     test_doc = Document(test_paper)
     found = test_doc.page_origin(0)
     assert_almost_equal(found, Point(left_margin, top_margin))
コード例 #19
0
ファイル: test_path.py プロジェクト: ajyoon/brown
 def test_move_to_with_parent(self):
     path = Path(ORIGIN)
     parent = InvisibleObject((Unit(100), Unit(50)))
     path.move_to(Unit(10), Unit(11), parent)
     assert len(path.elements) == 1
     assert_path_els_equal(
         path.elements[0], MoveTo(Point(Unit(10), Unit(11)), parent)
     )
コード例 #20
0
ファイル: test_path.py プロジェクト: ajyoon/brown
 def test_init(self):
     mock_parent = InvisibleObject(ORIGIN, parent=None)
     test_pen = Pen("#eeeeee")
     test_brush = Brush("#dddddd")
     path = Path((Unit(5), Unit(6)), test_pen, test_brush, mock_parent)
     assert path.pos == Point(Unit(5), Unit(6))
     assert path.pen == test_pen
     assert path.brush == test_brush
コード例 #21
0
ファイル: test_flowable.py プロジェクト: ajyoon/brown
 def test_init(self):
     test_flowable = Flowable((Mm(10), Mm(11)), Mm(1000), Mm(100), Mm(5))
     assert test_flowable.pos == Point(Mm(10), Mm(11))
     assert test_flowable.x == Mm(10)
     assert test_flowable.y == Mm(11)
     assert test_flowable.length == Mm(1000)
     assert test_flowable.height == Mm(100)
     assert test_flowable.y_padding == Mm(5)
コード例 #22
0
ファイル: test_flowable.py プロジェクト: ajyoon/brown
 def test_generate_layout_controllers_with_only_one_line(self):
     test_flowable = Flowable((Mm(9), Mm(11)), Mm(100), Mm(50), Mm(5))
     test_flowable._generate_layout_controllers()
     assert len(test_flowable.layout_controllers) == 1
     assert test_flowable.layout_controllers[0].flowable_x == Mm(0)
     assert test_flowable.layout_controllers[0].pos == Point(Mm(9), Mm(11))
     assert test_flowable.layout_controllers[
         0].page == neoscore.document.pages[0]
コード例 #23
0
 def test_map_between_with_common_parent(self):
     parent = InvisibleObject((Unit(5), Unit(6)),
                              neoscore.document.pages[0])
     source = InvisibleObject((Unit(1), Unit(2)), parent)
     destination = InvisibleObject((Unit(3), Unit(10)), parent)
     relative_pos = map_between(source, destination)
     expected = Point(Unit(2), Unit(8))
     assert_almost_equal(relative_pos, expected)
コード例 #24
0
def qt_point_to_point(qt_point: Union[QPoint, QPointF]) -> Point:
    """Create a Point from a QPoint or QPointF

    Args:
        qt_point: The source point

    Returns: Point
    """
    return Point(GraphicUnit(qt_point.x()), GraphicUnit(qt_point.y()))
コード例 #25
0
ファイル: path.py プロジェクト: ajyoon/brown
    def cubic_to(
        self,
        control_1_x: Unit,
        control_1_y: Unit,
        control_2_x: Unit,
        control_2_y: Unit,
        end_x: Unit,
        end_y: Unit,
        control_1_parent: Optional[Parent] = None,
        control_2_parent: Optional[Parent] = None,
        end_parent: Optional[Parent] = None,
    ):
        """Draw a cubic bezier curve from the current position to a new point.

        If the path is empty, this will add two elements, an initial
        `MoveTo(Point(Unit(0), Unit(0)), self)` and the requested
        `CurveTo`.

        Args:
            control_1_x: The x coordinate of the first control point.
            control_1_y: The y coordinate of the first control point.
            control_2_x: The x coordinate of the second control point.
            control_2_y: The y coordinate of the second control point.
            end_x: The x coordinate of the curve target.
            end_y: The y coordinate of the curve target.
            control_1_parent: An optional parent for
                the first control point. Defaults to `self`.
            control_2_parent: An optional parent for
                the second control point. Defaults to `self`.
            end_parent: An optional parent for the
                curve target. Defaults to `self`.
        """
        c1 = ControlPoint(
            Point(control_1_x, control_1_y),
            control_1_parent or self,
        )
        c2 = ControlPoint(
            Point(control_2_x, control_2_y),
            control_2_parent or self,
        )
        if not len(self.elements):
            # Needed to ensure bounding rect / length calculations are correct
            self.elements.append(MoveTo(Point(Unit(0), Unit(0)), self))
        self.elements.append(CurveTo(c1, c2, Point(end_x, end_y), end_parent or self))
コード例 #26
0
ファイル: test_path.py プロジェクト: ajyoon/brown
 def test_cubic_to_with_no_parents(self):
     path = Path((Unit(5), Unit(6)))
     path.cubic_to(Unit(10), Unit(11), ZERO, Unit(1), Unit(5), Unit(6))
     assert len(path.elements) == 2
     assert_path_els_equal(path.elements[0], MoveTo(ORIGIN, path))
     assert_path_els_equal(
         path.elements[1],
         CurveTo(
             ControlPoint(Point(Unit(10), Unit(11)), path),
             ControlPoint(Point(ZERO, Unit(1)), path),
             Point(Unit(5), Unit(6)),
             path,
         ),
     )
     resolved_els = path._resolve_path_elements()
     assert resolved_els == [
         ResolvedMoveTo(ZERO, ZERO),
         ResolvedCurveTo(Unit(10), Unit(11), ZERO, Unit(1), Unit(5), Unit(6)),
     ]
コード例 #27
0
ファイル: chordrest.py プロジェクト: ajyoon/brown
    def _create_stem(self):
        """Create a Stem and stores it in `self.stem`.

        Returns: None
        """
        self._stem = Stem(
            Point(self.staff.unit(0), self.furthest_notehead.staff_pos),
            self.stem_height,
            self,
        )
コード例 #28
0
ファイル: flowable.py プロジェクト: ajyoon/brown
    def map_to_canvas(self, local_point: Point) -> Point:
        """Convert a local point to its position in the canvas.

        Args:
            local_point: A position in the flowable's local space.
        """
        line = self.last_break_at(local_point.x)
        line_canvas_pos = canvas_pos_of(line)
        return line_canvas_pos + Point(local_point.x - line.flowable_x,
                                       local_point.y)
コード例 #29
0
ファイル: test_path.py プロジェクト: ajyoon/brown
 def test_line_to(self):
     path = Path((Unit(5), Unit(6)))
     path.line_to(Unit(10), Unit(12))
     assert len(path.elements) == 2
     assert_path_els_equal(path.elements[0], MoveTo(ORIGIN, path))
     assert_path_els_equal(path.elements[1], LineTo(Point(Unit(10), Unit(12)), path))
     resolved_els = path._resolve_path_elements()
     assert resolved_els == [
         ResolvedMoveTo(ZERO, ZERO),
         ResolvedLineTo(Unit(10), Unit(12)),
     ]
コード例 #30
0
ファイル: path.py プロジェクト: ajyoon/brown
    def line_to(self, x: Unit, y: Unit, parent: Optional[Parent] = None):
        """Draw a path from the current position to a new point.

        A point parent may be passed as well, anchored the target point to
        a separate GraphicObject. In this case, the coordinates passed will be
        considered relative to the parent.

        If the path is empty, this will add two elements, an initial
        `MoveTo(Point(Unit(0), Unit(0)), self)` and the requested
        `LineTo`.

        Args:
            x: The end x position
            y: The end y position
            parent: An optional parent, whose position the target coordinate
                will be relative to.
        """
        if not len(self.elements):
            # Needed to ensure bounding rect / length calculations are correct
            self.elements.append(MoveTo(Point(Unit(0), Unit(0)), self))
        self.elements.append(LineTo(Point(x, y), parent or self))