Release v0.6.17: constrained pencil strokes and snippet editor states
This commit is contained in:
@@ -24,6 +24,105 @@ int main()
|
||||
require(c.pencilCursor!=nullptr,"pencil drawing cursor loads");
|
||||
require(c.freehand && !c.pointer && ks::toolCursor(c)==c.pencilCursor,
|
||||
"new screenshot editor starts with the pencil tool");
|
||||
{
|
||||
BYTE savedKeys[256]{},keys[256]{}; GetKeyboardState(savedKeys);
|
||||
std::copy(savedKeys,savedKeys+256,keys); keys[VK_SHIFT]=0; SetKeyboardState(keys);
|
||||
auto mouse=[&](UINT message,POINT p,bool shift=false) {
|
||||
int x=c.view.left+MulDiv(p.x,c.view.right-c.view.left,c.image->width);
|
||||
int y=c.view.top+MulDiv(p.y,c.view.bottom-c.view.top,c.image->height);
|
||||
SendMessageW(window,message,(message==WM_LBUTTONUP?0:MK_LBUTTON)|(shift?MK_SHIFT:0),MAKELPARAM(x,y));
|
||||
};
|
||||
mouse(WM_LBUTTONDOWN,{40,40},true);
|
||||
mouse(WM_MOUSEMOVE,{100,50},true);
|
||||
require(c.stroke.to.x==100 && c.stroke.to.y==40,"Shift constrains pencil horizontally");
|
||||
mouse(WM_MOUSEMOVE,{100,90},true);
|
||||
require(c.stroke.to.x==100 && c.stroke.to.y==40 && c.stroke.points.size()==2,
|
||||
"50 pixel deviation keeps the current axis");
|
||||
mouse(WM_MOUSEMOVE,{100,91},true);
|
||||
require(c.stroke.to.x==100 && c.stroke.to.y==91 && c.stroke.points.size()==3 && c.stroke.points[1].y==40,
|
||||
"51 pixel deviation turns vertically and preserves the horizontal segment");
|
||||
mouse(WM_MOUSEMOVE,{70,140});
|
||||
require(c.stroke.to.x==70 && c.stroke.to.y==140 && c.stroke.points.size()==4,
|
||||
"releasing Shift resumes freehand in the same stroke");
|
||||
SendMessageW(window,WM_KEYDOWN,VK_SHIFT,0);
|
||||
mouse(WM_MOUSEMOVE,{140,150},true);
|
||||
require(c.stroke.to.x==140 && c.stroke.to.y==140 && c.stroke.points[3].x==70,
|
||||
"pressing Shift mid-stroke anchors at the last drawn point");
|
||||
SendMessageW(window,WM_KEYUP,VK_SHIFT,0);
|
||||
SendMessageW(window,WM_KEYDOWN,VK_SHIFT,0);
|
||||
mouse(WM_MOUSEMOVE,{150,200},true);
|
||||
mouse(WM_LBUTTONUP,{150,210},true);
|
||||
SetKeyboardState(savedKeys);
|
||||
require(c.marks.size()==1 && c.marks[0].to.x==140 && c.marks[0].to.y==210,
|
||||
"repressing Shift without mouse movement starts a new segment and constrains mouse-up");
|
||||
SendMessageW(window,WM_COMMAND,12,0);
|
||||
require(c.marks.empty(),"mixed freehand and constrained segments undo as one stroke");
|
||||
SendMessageW(window,WM_COMMAND,18,0);
|
||||
require(c.marks.size()==1 && c.marks[0].points.size()==6,"redo preserves constrained stroke geometry");
|
||||
c.marks.clear(); c.selected=-1;
|
||||
for(int sx:{-1,1}) for(int sy:{-1,1}) {
|
||||
mouse(WM_LBUTTONDOWN,{160,120},true);
|
||||
mouse(WM_MOUSEMOVE,{160+sx,120},true);
|
||||
for(int step=2;step<=90;++step)
|
||||
mouse(WM_MOUSEMOVE,{160+sx*step,120+sy*step},true);
|
||||
require(c.stroke.points.size()==2 && c.stroke.to.x==160+sx*90 && c.stroke.to.y==120+sy*90,
|
||||
"smooth diagonal after one-pixel horizontal jitter stays diagonal without stairs");
|
||||
mouse(WM_LBUTTONUP,{160+sx*90,120+sy*90},true);
|
||||
c.marks.clear(); c.selected=-1;
|
||||
mouse(WM_LBUTTONDOWN,{160-sx*40,120-sy*70},true);
|
||||
mouse(WM_MOUSEMOVE,{160,120-sy*70},true);
|
||||
for(int step=1;step<=90;++step)
|
||||
mouse(WM_MOUSEMOVE,{160+sx*step,120-sy*70+sy*step},true);
|
||||
require(c.stroke.points.size()==3 && c.strokeAxis>=3 &&
|
||||
std::abs(c.stroke.to.x-c.stroke.points[1].x)==std::abs(c.stroke.to.y-c.stroke.points[1].y),
|
||||
"smooth turn from horizontal into diagonal uses raw mouse direction without stairs");
|
||||
mouse(WM_LBUTTONUP,{160+sx*90,120-sy*70+sy*90},true);
|
||||
c.marks.clear(); c.selected=-1;
|
||||
}
|
||||
for(int sx:{-1,1}) for(int sy:{-1,1}) {
|
||||
mouse(WM_LBUTTONDOWN,{160,120},true);
|
||||
mouse(WM_MOUSEMOVE,{160+sx*60,120+sy*50},true);
|
||||
require(c.stroke.to.x==160+sx*55 && c.stroke.to.y==120+sy*55,
|
||||
"Shift snaps to exact 45 degree diagonals in all four directions");
|
||||
mouse(WM_LBUTTONUP,{160+sx*60,120+sy*50},true);
|
||||
c.marks.clear(); c.selected=-1;
|
||||
}
|
||||
mouse(WM_LBUTTONDOWN,{40,40},true);
|
||||
mouse(WM_MOUSEMOVE,{100,40},true);
|
||||
mouse(WM_MOUSEMOVE,{160,100},true);
|
||||
require(c.stroke.points.size()==3 && c.stroke.to.x==160 && c.stroke.to.y==100 &&
|
||||
c.stroke.points[1].x==100 && c.stroke.points[1].y==40,
|
||||
"large deviation turns a horizontal segment diagonally without losing its corner");
|
||||
mouse(WM_MOUSEMOVE,{200,100},true);
|
||||
require(c.stroke.to.x==180 && c.stroke.to.y==120 && c.stroke.points.size()==3,
|
||||
"small perpendicular deviation keeps the diagonal axis");
|
||||
mouse(WM_MOUSEMOVE,{260,120},true);
|
||||
require(c.stroke.to.x==260 && c.stroke.to.y==120 && c.stroke.points.size()==4,
|
||||
"diagonal deviation beyond 50 pixels turns back to horizontal");
|
||||
mouse(WM_LBUTTONUP,{260,120},true);
|
||||
c.marks.clear(); c.selected=-1;
|
||||
for(int sx:{-1,1}) for(int sy:{-1,1}) {
|
||||
POINT start{sx>0?310L:9L,120};
|
||||
mouse(WM_LBUTTONDOWN,start,true);
|
||||
mouse(WM_MOUSEMOVE,{start.x+sx*8,start.y+sy*8},true);
|
||||
mouse(WM_MOUSEMOVE,{sx>0?319L:0L,start.y+sy*25},true);
|
||||
auto end=c.stroke.to;
|
||||
require(end.x>=0 && end.x<320 && end.y>=0 && end.y<240 &&
|
||||
std::abs(end.x-start.x)==std::abs(end.y-start.y),
|
||||
"diagonal stays at 45 degrees and inside image boundaries");
|
||||
mouse(WM_LBUTTONUP,{sx>0?319L:0L,start.y+sy*25},true);
|
||||
c.marks.clear(); c.selected=-1;
|
||||
}
|
||||
keys[VK_CONTROL]=0x80; SetKeyboardState(keys);
|
||||
mouse(WM_LBUTTONDOWN,{40,40});
|
||||
mouse(WM_MOUSEMOVE,{100,70});
|
||||
mouse(WM_LBUTTONUP,{120,90});
|
||||
SetKeyboardState(savedKeys);
|
||||
require(c.marks.size()==1 && c.marks[0].points[1].x==100 && c.marks[0].points[1].y==70 &&
|
||||
c.marks[0].to.x==120 && c.marks[0].to.y==90,
|
||||
"Ctrl keeps its existing drawing behavior without constraining the pencil");
|
||||
c.marks.clear(); c.selected=-1;
|
||||
}
|
||||
for(int size:{32,48,64,96}) {
|
||||
auto cursor=(HCURSOR)LoadImageW(app.instance,MAKEINTRESOURCEW(IDC_SCREENSHOT_PENCIL),IMAGE_CURSOR,size,size,0);
|
||||
ICONINFO info{};
|
||||
|
||||
Reference in New Issue
Block a user