mirror of https://github.com/KLayout/klayout.git
Merge branch 'master' into issue-1249
This commit is contained in:
commit
4e3c106b27
|
|
@ -1552,15 +1552,19 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo
|
|||
m_alt_ac = ac_from_buttons (buttons);
|
||||
|
||||
// drag the vertex or edge/segment
|
||||
if (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && (m_selection.begin ()->second.size () == 1 /*p*/ || m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/)) {
|
||||
if (is_single_point_selection () || is_single_edge_selection ()) {
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
|
||||
// for a single selected point or edge, m_start is the original position and we snap the target -
|
||||
// thus, we can bring the point on grid or to an object's edge or vertex
|
||||
snap_details = snap2 (p);
|
||||
m_current = snap_details.snapped_point;
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
m_current = m_start + snap (p - m_start);
|
||||
} else {
|
||||
m_current = snap_details.snapped_point;
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1601,6 +1605,17 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo
|
|||
return false;
|
||||
}
|
||||
|
||||
static db::DPoint
|
||||
projected_to_edge (const db::DEdge &edge, const db::DPoint &p)
|
||||
{
|
||||
if (edge.is_degenerate ()) {
|
||||
return edge.p1 ();
|
||||
} else {
|
||||
db::DVector v = edge.d () * (1.0 / edge.length ());
|
||||
return edge.p1 () + v * db::sprod (p - edge.p1 (), v);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
|
|
@ -1674,8 +1689,12 @@ PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
|
||||
if (is_single_point_selection ()) {
|
||||
// for a single selected point we use the original point as the start location which
|
||||
// allows bringing a to grid
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = single_selected_point ();
|
||||
} else if (is_single_edge_selection ()) {
|
||||
// for an edge selection use the point projected to edge as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = projected_to_edge (single_selected_edge (), p);
|
||||
} else {
|
||||
m_current = m_start = p;
|
||||
}
|
||||
|
|
@ -1863,8 +1882,12 @@ PartialService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
|
||||
if (is_single_point_selection ()) {
|
||||
// for a single selected point we use the original point as the start location which
|
||||
// allows bringing a to grid
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = single_selected_point ();
|
||||
} else if (is_single_edge_selection ()) {
|
||||
// for an edge selection use the point projected to edge as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = projected_to_edge (single_selected_edge (), p);
|
||||
} else {
|
||||
m_current = m_start = p;
|
||||
}
|
||||
|
|
@ -2390,6 +2413,28 @@ PartialService::is_single_point_selection () const
|
|||
return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 1 /*p*/);
|
||||
}
|
||||
|
||||
db::DEdge
|
||||
PartialService::single_selected_edge () const
|
||||
{
|
||||
// build the transformation variants cache and
|
||||
// use only the first one of the explicit transformations
|
||||
// TODO: clarify how this can be implemented in a more generic form or leave it thus.
|
||||
TransformationVariants tv (view ());
|
||||
const std::vector<db::DCplxTrans> *tv_list = tv.per_cv_and_layer (m_selection.begin ()->first.cv_index (), m_selection.begin ()->first.layer ());
|
||||
|
||||
const lay::CellView &cv = view ()->cellview (m_selection.begin ()->first.cv_index ());
|
||||
db::ICplxTrans gt (cv.context_trans () * m_selection.begin ()->first.trans ());
|
||||
db::CplxTrans tt = (*tv_list)[0] * db::CplxTrans (cv->layout ().dbu ()) * gt;
|
||||
|
||||
return tt * *m_selection.begin ()->second.begin ();
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::is_single_edge_selection () const
|
||||
{
|
||||
return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/);
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::select (const db::DBox &box, SelectionMode mode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -363,7 +363,9 @@ private:
|
|||
void resize_markers (size_t n, bool transient);
|
||||
void resize_inst_markers (size_t n, bool transient);
|
||||
bool is_single_point_selection () const;
|
||||
bool is_single_edge_selection () const;
|
||||
db::DPoint single_selected_point () const;
|
||||
db::DEdge single_selected_edge () const;
|
||||
bool handle_guiding_shape_changes ();
|
||||
void transform_selection (const db::DTrans &move_trans);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,27 +21,41 @@ import unittest
|
|||
import os
|
||||
import sys
|
||||
|
||||
def compare(pb1, pb2):
|
||||
|
||||
if pb1.width() != pb2.width() or pb1.height() != pb2.height():
|
||||
return False
|
||||
|
||||
for x in range(0, pb1.width()):
|
||||
for y in range(0, pb1.height()):
|
||||
if pb1.pixel(x, y) != pb2.pixel(x, y):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class LAYPixelBufferTests(unittest.TestCase):
|
||||
|
||||
def test_4(self):
|
||||
pb = pya.PixelBuffer(10, 20)
|
||||
pb.transparent = True
|
||||
pb.fill(0xf0010203)
|
||||
def test_1(self):
|
||||
|
||||
png = pb.to_png_data()
|
||||
pb = pya.PixelBuffer(10, 20)
|
||||
pb.transparent = True
|
||||
pb.fill(0xf0010203)
|
||||
|
||||
# some range because implementations may differ
|
||||
self.assertGreater(len(png), 20)
|
||||
self.assertLess(len(png), 200)
|
||||
pb_copy = pya.PixelBuffer.from_png_data(png)
|
||||
self.assertEqual(pb, pb_copy)
|
||||
png = pb.to_png_data()
|
||||
|
||||
ut_testtmp = os.getenv("TESTTMP", ".")
|
||||
tmp = os.path.join(ut_testtmp, "tmp.png")
|
||||
# some range because implementations may differ
|
||||
self.assertGreater(len(png), 20)
|
||||
self.assertLess(len(png), 200)
|
||||
pb_copy = pya.PixelBuffer.from_png_data(png)
|
||||
self.assertEqual(pb, pb_copy)
|
||||
|
||||
pb.write_png(tmp)
|
||||
pb_copy = pya.PixelBuffer.read_png(tmp)
|
||||
self.assertEqual(pb, pb_copy)
|
||||
ut_testtmp = os.getenv("TESTTMP", ".")
|
||||
tmp = os.path.join(ut_testtmp, "tmp.png")
|
||||
|
||||
pb.write_png(tmp)
|
||||
pb_copy = pya.PixelBuffer.read_png(tmp)
|
||||
self.assertEqual(compare(pb, pb_copy), True)
|
||||
|
||||
|
||||
# run unit tests
|
||||
|
|
|
|||
Loading…
Reference in New Issue