## gui-displaylist.pkg
#
# Our cross-platform drawing language for the Mythryl widget set.
#
# Draw_Op is intended to be the cross-platform-portable
# subset of windowsystem_to_xserver::x::Op # windowsystem_to_xserver is from
src/lib/x-kit/xclient/src/window/windowsystem-to-xserver.pkg#
# The intent is that guiboss_to_guishim should define a
# rendering model which is highly compatible with X
# (Mythryl's prime target) but able to be supported
# with reasonable effort on other platforms.
# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublibstipulate
package r64 = rgb; # rgb is from
src/lib/x-kit/xclient/src/color/rgb.pkg package g2d = geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg package mtx = rw_matrix; # rw_matrix is from
src/lib/std/src/rw-matrix.pkg package r8 = rgb8; # rgb8 is from
src/lib/x-kit/xclient/src/color/rgb8.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkgherein
package gui_displaylist {
#
Put_Text = TO_LEFT_OF_POINT
| TO_RIGHT_OF_POINT
# Default.
| CENTERED_ON_POINT
;
Draw_Op
= POINTS List( g2d::Point ) # Unaffected by LINE_THICKNESS; use 360 degree FILLED_ARCS for fat points.
| PATH List( g2d::Point )
# Draws a sequence of line segments connecting given points.
| POLYGON List( g2d::Point )
# Like PATH, but additionally draws a line segment connectings last point back to first point.
| FILLED_POLYGON List( g2d::Point )
| LINES List( g2d::Line )
| BOXES List( g2d::Box )
| FILLED_BOXES List( g2d::Box )
| ARCS List( g2d::Arc )
# NB: ARCS can draw circles and X-Y oriented ellipses (and parts thereof). For other ellipses see ellipse.pkg below.
| FILLED_ARCS List( g2d::Arc )
#
| TEXT (g2d::Point, String)
#
| IMAGE { from_box: Null_Or( g2d::Box ),
# Take this subrectangle (default: all)
from: mtx::Rw_Matrix( r8::Rgb8 ), # from this pixel array
to_point: g2d::Point # and write it to this point in window.
}
| COPY_BOX { to_point: g2d::Point,
# So terminal widgets can scroll text up, etc. Contents of screen area in given box are copied to given point.
from_box: g2d::Box
}
| COPY_FROM_RW_PIXMAP { from_id: Id,
# 'from_id' should be guiboss_to_rw_pixmap.id for some gtg::Guiboss_To_Rw_Pixmap value obtained via guiboss_to_guishim.make_rw_pixmap.
to_point: g2d::Point,
from_box: g2d::Box
}
#
| COLOR (r64::Rgb, List(Draw_Op))
| LINE_THICKNESS (Int, List(Draw_Op))
# Affects lines and arcs. A thickness of zero draws the fastest, thinnest lines supported by host. Use thickness 1 for pretty lines and joints.
| PUT_TEXT (Put_Text, List(Draw_Op))
| CLIP_TO (g2d::Box, List(Draw_Op))
| FONT (List(String), List(Draw_Op))
# X fontnames like "fixed" or "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1" -- see Note[1] or (eg) /usr/share/fonts/X11/misc/fonts.alias
# # TEXTs will be drawn in first font in FONT list which is found on X server. The best fonts are optional, hence the list: put best-first, most-common last.
#
; # Additional drawing support is provided by higher-level packages which generate Draw_Op-level results, for example:
#
src/lib/x-kit/draw/ellipse.pkg #
src/lib/x-kit/draw/beta2-spline.pkg Gui_Displaylist = List( Draw_Op );
fun find_all_points_in_gui_displaylist (d: Gui_Displaylist) # Used mainly to generate pointlists to be handed to g2d::bounding_box or g2d::convex_hull, for mouseclick hit-testing etc via g2d::point_in_polygon.
=
do_ops (d, [])
where
fun do_box (box: g2d::Box) = g2d::box::to_points box;
fun do_line (point1, point2) = [ point1, point2 ];
fun do_arc ({ row, col, high, wide, ... }: g2d::Arc) #
=
do_box { row, col, high, wide }; # XXX QUERO FIXME is this anywhere close to sane?
fun do_image { to_point as { row, col }: g2d::Point,
from_box: Null_Or( g2d::Box ),
from: mtx::Rw_Matrix( r8::Rgb8 )
}
=
{ my (high, wide)
=
case from_box
#
NULL => (mtx::rowscols from);
THE { high, wide, ... } => (high, wide);
esac;
#
do_box { row, col, high, wide };
};
fun do_boxes (boxes) = list::cat (map do_box boxes);
fun do_lines (lines) = list::cat (map do_line lines);
fun do_arcs (arcs) = list::cat (map do_arc arcs);
fun do_copybox { to_point: g2d::Point, from_box: g2d::Box }
=
{ from_box -> { row, col, high, wide };
to_box = { row => to_point.row, col => to_point.col, high, wide };
do_boxes [ from_box, to_box ];
};
fun do_copy_from_rw_pixmap { to_point as { row, col }: g2d::Point, from_box as { high, wide, ... }: g2d::Box, from_id: Id }
=
do_boxes [ { row, col, high, wide } ];
fun do_ops ([], result) => result;
do_ops (op ! rest, result) => do_ops (rest, do_op op @ result);
end
also
fun do_op (POINTS p) => p;
do_op (PATH p) => p;
do_op (POLYGON p) => p;
do_op (FILLED_POLYGON p) => p;
#
do_op (LINES l) => do_lines l;
do_op (BOXES b) => do_boxes b;
do_op (FILLED_BOXES b) => do_boxes b;
do_op (ARCS a) => do_arcs a;
do_op (FILLED_ARCS a) => do_arcs a;
#
do_op (TEXT (p, _ )) => [ p ]; # XXX SUCKO FIXME We should really compute the bounding box for the string here.
do_op (IMAGE a) => do_image a;
do_op (COPY_BOX a) => do_copybox a;
do_op (COPY_FROM_RW_PIXMAP a) => do_copy_from_rw_pixmap a;
#
do_op (FONT (_, ops)) => (do_ops (ops, []));
do_op (COLOR (_, ops)) => (do_ops (ops, []));
do_op (LINE_THICKNESS (_, ops)) => (do_ops (ops, []));
do_op (PUT_TEXT (_, ops)) => (do_ops (ops, []));
do_op (CLIP_TO (box, ops)) => (do_box box) @ (do_ops (ops, []));
end;
end;
# Sample call looks like:
#
# fg = pp::prettyprint_to_string [] {. gd::prettyprint_gui_displaylist #pp displaylist; };
# print ("\narrowbutton: foreground:\n" + fg + "\n");
#
fun prettyprint_gui_displaylist
#
(pp: pp::Prettyprinter)
(gd: Gui_Displaylist)
=
pp::listx pp do_op "" gd
where
fun point_to_string { row, col } = sprintf "{ row => %d, col => %d }" row col;
fun line_to_string (p1, p2) = sprintf "(%s, %s)" (point_to_string p1) (point_to_string p2);
fun box_to_string { row, col, high, wide } = sprintf "{ row => %d, col => %d, high => %d, wide => %d }" row col high wide;
fun arc_to_string { row, col, high, wide, start_angle, fill_angle } = sprintf "{ row => %d, col => %d, high => %d, wide => %d, start_angle => %f, fill_angle => %f }" row col high wide start_angle fill_angle;
fun do_op (POINTS p) => pp::listx pp (\\ pt = pp.lit (point_to_string pt)) "POINTS" p;
do_op (PATH p) => pp::listx pp (\\ pt = pp.lit (point_to_string pt)) "PATH" p;
do_op (POLYGON p) => pp::listx pp (\\ pt = pp.lit (point_to_string pt)) "POLYGON" p;
do_op (FILLED_POLYGON p) => pp::listx pp (\\ pt = pp.lit (point_to_string pt)) "FILLED_POLYGON" p;
#
do_op (LINES l) => pp::listx pp (\\ pt = pp.lit (line_to_string pt)) "LINES" l;
do_op (BOXES b) => pp::listx pp (\\ pt = pp.lit ( box_to_string pt)) "BOXES" b;
do_op (FILLED_BOXES b) => pp::listx pp (\\ pt = pp.lit ( box_to_string pt)) "FILLED_BOXES" b;
do_op (ARCS a) => pp::listx pp (\\ pt = pp.lit ( arc_to_string pt)) "ARCS" a;
do_op (FILLED_ARCS a) => pp::listx pp (\\ pt = pp.lit ( arc_to_string pt)) "FILLED_ARCS" a;
#
do_op (TEXT (p, t)) => pp.lit (sprintf "(TEXT (%s,\"%s\"))" (point_to_string p) t);
do_op (IMAGE a) => pp.lit "<IMAGE>";
do_op (COPY_BOX r) => pp.lit (sprintf "(COPY_BOX { to_point => %s, from_box => %s }" (point_to_string r.to_point) (box_to_string r.from_box));
do_op (COPY_FROM_RW_PIXMAP r) => pp.lit (sprintf "(COPY_FROM_RW_PIXMAP { to_point => %s, from_box => %s, from_id }" (point_to_string r.to_point) (box_to_string r.from_box));
#
do_op (FONT (_, ops)) => pp::listx pp do_op "FONT" ops;
do_op (COLOR (_, ops)) => pp::listx pp do_op "COLOR" ops;
do_op (LINE_THICKNESS (_, ops)) => pp::listx pp do_op "LINE_THICKNESS" ops;
do_op (PUT_TEXT (_, ops)) => pp::listx pp do_op "PUT_TEXT" ops;
do_op (CLIP_TO (box, ops)) => pp::listx pp do_op "CLIP_TO" ops;
end;
end;
};
end;
###########################################################################################
# Note[1]
# As of X11R7.5 standard short fontnames include:
#
# fixed -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
# variable -*-helvetica-bold-r-normal-*-*-120-*-*-*-*-iso8859-1
# 5x7 -misc-fixed-medium-r-normal--7-70-75-75-c-50-iso8859-1
# 5x8 -misc-fixed-medium-r-normal--8-80-75-75-c-50-iso8859-1
# 6x9 -misc-fixed-medium-r-normal--9-90-75-75-c-60-iso8859-1
# 6x10 -misc-fixed-medium-r-normal--10-100-75-75-c-60-iso8859-1
# 6x12 -misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso8859-1
# 6x13 -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
# 6x13bold -misc-fixed-bold-r-semicondensed--13-120-75-75-c-60-iso8859-1
# 7x13 -misc-fixed-medium-r-normal--13-120-75-75-c-70-iso8859-1
# 7x13bold -misc-fixed-bold-r-normal--13-120-75-75-c-70-iso8859-1
# 7x13euro -misc-fixed-medium-r-normal--13-120-75-75-c-70-iso8859-15
# 7x13eurobold -misc-fixed-bold-r-normal--13-120-75-75-c-70-iso8859-15
# 7x14 -misc-fixed-medium-r-normal--14-130-75-75-c-70-iso8859-1
# 7x14bold -misc-fixed-bold-r-normal--14-130-75-75-c-70-iso8859-1
# 8x13 -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1
# 8x13bold -misc-fixed-bold-r-normal--13-120-75-75-c-80-iso8859-1
# 8x16 -sony-fixed-medium-r-normal--16-120-100-100-c-80-iso8859-1
# 9x15 -misc-fixed-medium-r-normal--15-140-75-75-c-90-iso8859-1
# 9x15bold -misc-fixed-bold-r-normal--15-140-75-75-c-90-iso8859-1
# 10x20 -misc-fixed-medium-r-normal--20-200-75-75-c-100-iso8859-1
# 12x24 -sony-fixed-medium-r-normal--24-170-100-100-c-120-iso8859-1
# ...