add `Tools->Grab screen area` function (unix only)

This commit is contained in:
stefan schippers 2024-03-20 03:53:56 +01:00
parent 6405ac4c09
commit 61b1c0b368
9 changed files with 172 additions and 5 deletions

View File

@ -122,6 +122,7 @@ LeftButton Double click Terminate Polygon placement
- BackSpace Back to parent schematic
- Delete Delete selected objects
- Insert Insert element from library
- Print Scrn Grab screen area
- Escape Abort, redraw, unselect
ctrl Enter Confirm closing dialog boxes
- Down Move down

View File

@ -840,6 +840,8 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
Return various global variables used in the program </pre>
<li><kbd> go_back</kbd></li><pre>
Go up one level (pop) in hierarchy </pre>
<li><kbd> grabscreen</kbd></li><pre>
grab root window </pre>
<li><kbd> hash_file file [skip_path_lines]</kbd></li><pre>
Do a simple hash of 'file'
'skip_path_lines' is an integer (default: 0) passed to hash_file() </pre>
@ -860,13 +862,17 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
'inst' can be an instance name or number </pre>
<li><kbd> hilight_netname net</kbd></li><pre>
Highlight net name 'net' </pre>
<li><kbd> image [invert|white_transp|black_transp|transp_white|transp_black|write_back]</kbd></li><pre>
<li><kbd> image [invert|white_transp|black_transp|transp_white|transp_black|write_back|</kbd></li><pre>
blend_white|blend_black]
Apply required changes to selected images
invert: invert colors
white_transp: transform white to transparent color (alpha=0) after invert.
black_transp: transform black to transparent color (alpha=0) after invert.
transp_white: transform white to transparent color (alpha=0) after invert.
transp_black: transform black to transparent color (alpha=0) after invert.</pre>
transp_black: transform black to transparent color (alpha=0) after invert.
blend_white: blend with white background and remove alpha
blend_black: blend with black background and remove alpha
write_back: write resulting image back into `image_data` attribute</pre>
<li><kbd> instance sym_name x y rot flip [prop] [n]</kbd></li><pre>
Place a new instance of symbol 'sym_name' at position x,y,
rotation and flip set to 'rot', 'flip'

View File

@ -1736,6 +1736,130 @@ static void end_shape_point_edit()
}
}
#if defined(__unix__) && HAS_CAIRO==1
static int grabscreen(const char *winpath, int event, int mx, int my, KeySym key,
int button, int aux, int state)
{
static int grab_state = 0;
static int x1, y1, x2, y2;
int rmx, rmy, wmx, wmy;
unsigned int msq;
Window rw, cw;
XSetWindowAttributes winattr;
XGCValues gcv;
static GC gc = NULL;
static Window clientwin = 0;
static int first_motion = 1;
static int displayh = 0, displayw = 0;
static unsigned long white = 0;
if(grab_state == 0 && event == ButtonPress && button == Button1) {
unsigned long gcvm = GCFunction | GCForeground;
white = WhitePixel(display, screen_number);
displayh = DisplayHeight(display, screen_number);
displayw = DisplayWidth(display, screen_number);
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
gcv.function = GXxor;
gcv.foreground = white;
gc = XCreateGC(display, rw, gcvm, &gcv);
winattr.override_redirect = True;
clientwin = XCreateWindow(display, rw, 0, 0, displayw, displayh, 0, screendepth,
InputOutput, visual, CWOverrideRedirect, &winattr);
XMapRaised(display,clientwin);
x1 = rmx;
y1 = rmy;
dbg(1, "grabscreen(): got point1: %d %d\n", x1, y1);
grab_state = 1;
}
if(grab_state == 1 && event == MotionNotify) {
static int xx1, xx2, yy1, yy2;
xx1 = x1; yy1 = y1; xx2 = x2; yy2 = y2;
INT_RECTORDER(xx1, yy1, xx2, yy2);
dbg(1, "Motion: %d %d %d %d\n", xx1, yy1, xx2, yy2);
if(!first_motion) {
XDrawRectangle(display, clientwin, gc, xx1 - 1, yy1 - 1, xx2 - xx1 + 2, yy2 - yy1 + 2);
}
first_motion = 0;
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
x2 = xx2 = rmx;
y2 = yy2 = rmy;
xx1 = x1; yy1 = y1;
INT_RECTORDER(xx1, yy1, xx2, yy2);
XDrawRectangle(display, clientwin, gc, xx1 - 1, yy1 - 1, xx2 - xx1 + 2, yy2 - yy1 + 2);
}
if(grab_state == 1 && event == ButtonRelease) {
int grab_w = 0, grab_h = 0;
cairo_surface_t *sfc = NULL, *subsfc = NULL;
png_to_byte_closure_t closure;
char *encoded_data = NULL;
size_t olength;
char *prop = NULL;
grab_state = 0;
first_motion = 1;
xctx->ui_state &= ~GRABSCREEN;
XQueryPointer(display, xctx->window, &rw, &cw , &rmx, &rmy, &wmx, &wmy, &msq);
x2 = rmx;
y2 = rmy;
INT_RECTORDER(x1, y1, x2, y2);
tcleval("grab release [xschem get current_win_path]");
if(x2 - x1 > 10 && y2 -y1 > 10) {
grab_w = (x2 - x1 + 1);
grab_h = (y2 - y1 + 1);
dbg(1, "grabscreen(): grab area: %d %d - %d %d\n", x1, y1, x2, y2);
dbg(1, "grabscreen(): root w=%d, h=%d\n", displayw, displayh);
sfc = cairo_xlib_surface_create(display, rw, visual, displayw, displayh);
if(!sfc || cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) {
dbg(0, "grabscreen(): failure creating sfc\n");
XFreeGC(display, gc);
XDestroyWindow(display, clientwin);
return 0;
}
dbg(1, "sfc: w=%d, h=%d\n",
cairo_xlib_surface_get_width(sfc),
cairo_xlib_surface_get_height(sfc));
subsfc = cairo_surface_create_for_rectangle(sfc, x1, y1, grab_w, grab_h);
if(!subsfc || cairo_surface_status(subsfc) != CAIRO_STATUS_SUCCESS) {
dbg(0, "grabscreen(): failure creating subsfc\n");
cairo_surface_destroy(sfc);
XFreeGC(display, gc);
XDestroyWindow(display, clientwin);
return 0;
}
closure.buffer = NULL;
closure.size = 0;
closure.pos = 0;
cairo_surface_write_to_png_stream(subsfc, png_writer, &closure);
cairo_surface_destroy(subsfc);
cairo_surface_destroy(sfc);
closure.size = closure.pos;
dbg(1, "closure.size = %ld\n", closure.size);
encoded_data = base64_encode((unsigned char *)closure.buffer, closure.size, &olength, 0);
dbg(1, "olength = %ld\n", olength);
my_free(_ALLOC_ID_, &closure.buffer);
my_mstrcat(_ALLOC_ID_, &prop, "flags=image,unscaled\nalpha=0.8\nimage_data=", encoded_data, NULL);
my_free(_ALLOC_ID_, &encoded_data);
storeobject(-1, xctx->mousex_snap, xctx->mousey_snap, xctx->mousex_snap + grab_w, xctx->mousey_snap + grab_h,
xRECT, GRIDLAYER, SELECTED, prop);
my_free(_ALLOC_ID_, &prop);
xctx->need_reb_sel_arr=1;
rebuild_selected_array();
move_objects(START,0,0,0);
xctx->ui_state |= START_SYMPIN;
}
XFreeGC(display, gc);
XDestroyWindow(display, clientwin);
}
return 1;
}
#endif
/* main window callback */
/* mx and my are set to the mouse coord. relative to window */
/* winpath: set to .drw or sub windows .x1.drw, .x2.drw, ... */
@ -1854,6 +1978,12 @@ int rstate; /* (reduced state, without ShiftMask) */
}
dbg(1, "key=%d EQUAL_MODMASK=%d, SET_MODMASK=%d\n", key, SET_MODMASK, EQUAL_MODMASK);
#if defined(__unix__) && HAS_CAIRO==1
if(xctx->ui_state & GRABSCREEN) {
grabscreen(winpath, event, mx, my, key, button, aux, state);
} else
#endif
switch(event)
{
@ -2708,6 +2838,13 @@ int rstate; /* (reduced state, without ShiftMask) */
}
break;
}
#if defined(__unix__) && HAS_CAIRO==1
if(key == XK_Print) {
xctx->ui_state |= GRABSCREEN;
tcleval("grab set -global [xschem get current_win_path]");
break;
}
#endif
if(key=='Q' && rstate == 0) /* edit attributes in editor */
{
if(xctx->semaphore >= 2) break;

View File

@ -4049,7 +4049,7 @@ static cairo_surface_t *get_surface_from_file(const char *filename, const char *
}
filesize = (size_t)buf.st_size;
if(filesize > 0) {
fd = fopen(filename, "r");
fd = fopen(filename, fopen_read_mode);
if(fd) {
size_t bytes_read;
filedata = my_malloc(_ALLOC_ID_, filesize);

View File

@ -63,6 +63,7 @@ LeftButton Double click Terminate Polygon placement
- BackSpace Back to parent schematic
- Delete Delete selected objects
- Insert Insert element from library
- Print Scrn Grab screen area
- Escape Abort, redraw, unselect
ctrl Enter Confirm closing dialog boxes
- Down Move down

View File

@ -1907,6 +1907,18 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if((xctx->semaphore == 0)) go_back(1);
Tcl_ResetResult(interp);
}
/* grabscreen
* grab root window */
else if(!strcmp(argv[1], "grabscreen"))
{
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
#if defined(__unix__) && HAS_CAIRO==1
xctx->ui_state |= GRABSCREEN;
tcleval("grab set -global [xschem get current_win_path]");
#endif
Tcl_ResetResult(interp);
}
else { cmd_found = 0;}
break;
case 'h': /*----------------------------------------------*/
@ -5397,7 +5409,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(argc > 2 && atoi(argv[2]) == 2) {
Tcl_ResetResult(interp);
}
else if(argc > 3 && atoi(argv[2]) == 3) {
else if(argc > 2 && atoi(argv[2]) == 3) {
Tcl_ResetResult(interp);
}
}

View File

@ -2551,6 +2551,7 @@ int Tcl_AppInit(Tcl_Interp *inter)
tcleval(name);
}
}
if(debug_var==-10) debug_var=0;
/* */
/* EXECUTE xschem.tcl */
/* */
@ -2594,7 +2595,6 @@ int Tcl_AppInit(Tcl_Interp *inter)
cadlayers=tclgetintvar("cadlayers");
fix_broken_tiled_fill = tclgetboolvar("fix_broken_tiled_fill");
fix_mouse_coord = tclgetboolvar("fix_mouse_coord");
if(debug_var==-10) debug_var=0;
my_snprintf(tmp, S(tmp), "%.16g",CADGRID);
tclvareval("set_ne cadgrid ", tmp, NULL);
my_snprintf(tmp, S(tmp), "%.16g",CADSNAP);

View File

@ -229,6 +229,7 @@ extern char win_temp_dir[PATH_MAX];
#define START_SYMPIN 16384U
#define GRAPHPAN 32768U /* bit 15 */
#define MENUSTART 65536U /* bit 16 */
#define GRABSCREEN 131072 /* bit 17 */
#define SELECTED 1U /* used in the .sel field for selected objs. */
#define SELECTED1 2U /* first point selected... */
@ -349,6 +350,13 @@ extern char win_temp_dir[PATH_MAX];
if(y2 < y1) {xxtmp = y1; y1 = y2; y2 = xxtmp;} \
}
#define INT_RECTORDER(x1,y1,x2,y2) { \
int xxtmp; \
if(x2 < x1) {xxtmp = x1; x1 = x2; x2 = xxtmp;} \
if(y2 < y1) {xxtmp = y1; y1 = y2; y2 = xxtmp;} \
}
#define LINE_OUTSIDE(xa,ya,xb,yb,x1,y1,x2,y2) \
(xa>=x2 || xb<=x1 || ( (ya<yb)? (ya>=y2 || yb<=y1) : (yb>=y2 || ya<=y1) ) )

View File

@ -7736,6 +7736,8 @@ proc build_widgets { {topwin {} } } {
$topwin.menubar.tools.menu add command -label "Insert circle" -command "xschem circle" -accelerator Ctrl+Shift+C
toolbar_add ToolInsertCircle "xschem circle" "Insert Circle" $topwin
$topwin.menubar.tools.menu add command -label "Insert JPG/PNG image" -command "xschem add_image"
$topwin.menubar.tools.menu add command -label "Grab screen area" -command "xschem grabscreen" \
-accelerator {Print Scrn}
$topwin.menubar.tools.menu add command -label "Search" -accelerator Ctrl+F -command property_search
toolbar_add ToolSearch property_search "Search" $topwin
$topwin.menubar.tools.menu add command -label "Align to Grid" -accelerator Alt+U -command "xschem align"