PreviousUpNext

15.4.1479  src/lib/x-kit/xclient/pkg/window/pen.pkg

## pen.pkg
#
#  "A pen is similar to the graphics context provided by xlib.
#   The principal differences are that pens are immutable, do
#   not specify a font, and can specify clipping rectangles and
#   dashlists (which are handled separately in the X protocol)."
#           -- p16 http:://mythryl.org/pub/exene/1993-lib.ps
#              (John H Reppy's 1993 eXene library manual.)

# Compiled by:
#     src/lib/x-kit/xclient/xclient-internals.sublib



# Support for symbolic names for pen component values.

stipulate
    package rc  =  range_check;                                 # range_check           is from   src/lib/std/2d/range-check.pkg
    package dt  =  draw_types;                                  # draw_types            is from   src/lib/x-kit/xclient/pkg/window/draw-types.pkg
    package xt  =  xtypes;                                      # xtypes                is from   src/lib/x-kit/xclient/pkg/wire/xtypes.pkg
    package v2w =  value_to_wire;                               # value_to_wire         is from   src/lib/x-kit/xclient/pkg/wire/value-to-wire.pkg
    package xg  =  xgeometry;                                   # xgeometry             is from   src/lib/std/2d/xgeometry.pkg
    package rwv =  rw_vector;                                   # rw_vector             is from   src/lib/std/src/rw-vector.pkg
    package vec =  vector;                                      # vector                is from   src/lib/std/src/vector.pkg
herein


    package pen {

        include xgeometry;                                      # xgeometry             is from   src/lib/std/2d/xgeometry.pkg

        exception BAD_PEN_TRAIT;

        # These are the properties
        # distinguishing one pen from
        # another:
        #
        package p {
            #
            Pen_Trait
              = FUNCTION    xt::Graphics_Op
              | PLANE_MASK  xt::Plane_Mask
              | FOREGROUND  rgb8::Rgb8
              | BACKGROUND  rgb8::Rgb8
              | LINE_WIDTH  Int
              | LINE_STYLE_SOLID
              | LINE_STYLE_ON_OFF_DASH
              | LINE_STYLE_DOUBLE_DASH
              | CAP_STYLE_NOT_LAST
              | CAP_STYLE_BUTT
              | CAP_STYLE_ROUND
              | CAP_STYLE_PROJECTING
              | JOIN_STYLE_MITER
              | JOIN_STYLE_ROUND
              | JOIN_STYLE_BEVEL
              | FILL_STYLE_SOLID
              | FILL_STYLE_TILED
              | FILL_STYLE_STIPPLED
              | FILL_STYLE_OPAQUE_STIPPLED
              | FILL_RULE_EVEN_ODD
              | FILL_RULE_WINDING
              | ARC_MODE_CHORD
              | ARC_MODE_PIE_SLICE
              | CLIP_BY_CHILDREN
              | INCLUDE_INFERIORS
              #
              | RO_PIXMAP   dt::Ro_Pixmap
              | STIPPLE     dt::Ro_Pixmap
              | CLIP_MASK   dt::Ro_Pixmap
              | CLIP_MASK_NONE
              | CLIP_MASK_UNSORTED_BOXES  List( Box )
              | CLIP_MASK_YSORTED_BOXES   List( Box )
              | CLIP_MASK_YXSORTED_BOXES  List( Box )
              | CLIP_MASK_YXBANDED_BOXES  List( Box )
              | CLIP_ORIGIN       Point
              #
              | STIPPLE_ORIGIN    Point
              #
              | DASH_OFFSET       Int
              | DASH_FIXED        Int
              | DASH_LIST         List(Int)
              ;
        };

        stipulate

            include pen_guts;                           # pen_guts              is from   src/lib/x-kit/xclient/pkg/window/pen-guts.pkg


            fun check_list chkfn l
                =
                {   apply (fn x = { chkfn x; ();})
                          l;
                    l;
                };

            fun check_item chkfn
                =
                fn v =  if (chkfn v)   v;
                        else           raise exception BAD_PEN_TRAIT;
                        fi;

            check_card16 =  unt::from_int  o  (check_item  rc::valid16);
            check_card8  =  unt::from_int  o  (check_item  rc::valid8);

            check_point  =  check_item  xg::valid_point;
            check_box    =  check_item  xg::valid_box;

            check_boxes  =  check_list  check_box;
            check_card8s =  check_list  check_card8;


            # Map a pen trait to its slot and representation 
            #
            fun trait_to_rep (p::FUNCTION xt::OP_COPY)
                    =>
                    (0, IS_DEFAULT);

                trait_to_rep (p::FUNCTION gr_op)
                    =>
                    (0, IS_WIRE (v2w::graph_op_to_wire  gr_op));

                trait_to_rep (p::PLANE_MASK (xt::PLANEMASK mask))
                    =>
                    (1, IS_WIRE mask);

                trait_to_rep (p::FOREGROUND rgb8)
                    =>
                    {   i = rgb8::rgb8_to_int  rgb8;

                        i == 0   ??   (2, IS_DEFAULT)
                                 ::   (2, IS_WIRE (unt::from_int i));
                    };

                trait_to_rep (p::BACKGROUND rgb8)
                    =>
                    {   i = rgb8::rgb8_to_int  rgb8;

                        i == 1   ??   (3, IS_DEFAULT)
                                 ::   (3, IS_WIRE (unt::from_int i));
                    };
                
                trait_to_rep (p::LINE_WIDTH 0 ) => (4, IS_DEFAULT);
                trait_to_rep (p::LINE_WIDTH wd) => (4, IS_WIRE (check_card16 wd));

                trait_to_rep (p::LINE_STYLE_SOLID      ) => (5, IS_DEFAULT);
                trait_to_rep (p::LINE_STYLE_ON_OFF_DASH) => (5, IS_WIRE 0u1);
                trait_to_rep (p::LINE_STYLE_DOUBLE_DASH) => (5, IS_WIRE 0u2);

                trait_to_rep (p::CAP_STYLE_NOT_LAST  ) => (6, IS_WIRE 0u0);
                trait_to_rep (p::CAP_STYLE_BUTT      ) => (6, IS_DEFAULT);
                trait_to_rep (p::CAP_STYLE_ROUND     ) => (6, IS_WIRE 0u2);
                trait_to_rep (p::CAP_STYLE_PROJECTING) => (6, IS_WIRE 0u3);

                trait_to_rep (p::JOIN_STYLE_MITER) => (7, IS_DEFAULT);
                trait_to_rep (p::JOIN_STYLE_ROUND) => (7, IS_WIRE 0u1);
                trait_to_rep (p::JOIN_STYLE_BEVEL) => (7, IS_WIRE 0u2);

                trait_to_rep (p::FILL_STYLE_SOLID          ) => (8, IS_DEFAULT);
                trait_to_rep (p::FILL_STYLE_TILED          ) => (8, IS_WIRE 0u1);
                trait_to_rep (p::FILL_STYLE_STIPPLED       ) => (8, IS_WIRE 0u2);
                trait_to_rep (p::FILL_STYLE_OPAQUE_STIPPLED) => (8, IS_WIRE 0u3);

                trait_to_rep (p::FILL_RULE_EVEN_ODD) => (9, IS_DEFAULT);
                trait_to_rep (p::FILL_RULE_WINDING ) => (9, IS_WIRE 0u1);

                trait_to_rep (p::RO_PIXMAP (dt::RO_PIXMAP (dt::RW_PIXMAP { pixmap_id, ... } ))) => (10, IS_PIXMAP pixmap_id);
                trait_to_rep (p::STIPPLE   (dt::RO_PIXMAP (dt::RW_PIXMAP { pixmap_id, ... } ))) => (11, IS_PIXMAP pixmap_id);

                trait_to_rep (p::STIPPLE_ORIGIN pt) => (12, IS_POINT (check_point pt));

                trait_to_rep (p::CLIP_BY_CHILDREN ) => (13, IS_DEFAULT);
                trait_to_rep (p::INCLUDE_INFERIORS) => (13, IS_WIRE 0u1);

                trait_to_rep (p::CLIP_ORIGIN (POINT { col=>0, row=>0 } )) => (14, IS_DEFAULT);
                trait_to_rep (p::CLIP_ORIGIN pt)                          => (14, IS_POINT (check_point pt));

                trait_to_rep (p::CLIP_MASK_NONE) => (15, IS_DEFAULT);
                trait_to_rep (p::CLIP_MASK (dt::RO_PIXMAP (dt::RW_PIXMAP { pixmap_id, ... } ))) => (15, IS_PIXMAP pixmap_id);

                trait_to_rep (p::CLIP_MASK_UNSORTED_BOXES r) => (15, IS_BOXES (xt::UNSORTED_ORDER, check_boxes r));
                trait_to_rep (p::CLIP_MASK_YSORTED_BOXES  r) => (15, IS_BOXES (xt::YSORTED_ORDER,  check_boxes r));
                trait_to_rep (p::CLIP_MASK_YXSORTED_BOXES r) => (15, IS_BOXES (xt::YXSORTED_ORDER, check_boxes r));
                trait_to_rep (p::CLIP_MASK_YXBANDED_BOXES r) => (15, IS_BOXES (xt::YXBANDED_ORDER, check_boxes r));

                trait_to_rep (p::DASH_OFFSET 0)      => (16, IS_DEFAULT);
                trait_to_rep (p::DASH_OFFSET n)      => (16, IS_WIRE (check_card16 n));

                trait_to_rep (p::DASH_FIXED     4)   => (17, IS_DEFAULT);
                trait_to_rep (p::DASH_FIXED     n)   => (17, IS_WIRE (check_card8 n));
                trait_to_rep (p::DASH_LIST dashes)   => (17, IS_DASHES (check_card8s dashes));

                trait_to_rep (p::ARC_MODE_CHORD    ) => (18, IS_WIRE 0u0);
                trait_to_rep (p::ARC_MODE_PIE_SLICE) => (18, IS_DEFAULT);
            end;

            # Extract the non-default value mask
            # from a rw_vector of pen-guts:
            #
            fun extract_mask  vec
                =
                loop (0u0, 0, 0u1)
                where 

                    fun loop (m, i, b)
                        =
                        if (i < pen_slot_count)
                            #
                            case (rwv::get (vec, i))
                                #
                                IS_DEFAULT =>   loop (m, i+1, unt::(<<) (b, 0u1));
                                _          =>   loop (unt::bitwise_or (m, b), i+1, unt::(<<) (b, 0u1));
                            esac;
                        else
                            m;
                        fi;
                end;

            # Make a pen from a rw_vector of initial values
            # and a list of new values 
            #
            fun make_pen' (vec, trait_list)
                =
                {   fun update (slot, rep)
                        =
                        rwv::set (vec, slot, rep);

                    apply (fn trait = update (trait_to_rep  trait))
                          trait_list;

                    PEN { traits  =>  vec::tabulate (pen_slot_count, fn i = rwv::get (vec, i)),
                          bitmask =>  extract_mask vec
                        };
                };

        herein

            default_pen
                =
                pen_guts::default_pen;


            # Create a new drawing context
            # from a list of pen traits:
            #
            fun make_pen  traits
                =
                make_pen' (rwv::make_rw_vector (pen_slot_count, IS_DEFAULT),  traits);


            # Create a new pen from an existing
            # pen by functional update:
            #
            fun clone_pen (PEN { traits, ... }, new_traits)
                =
                make_pen' (rwv::tabulate (pen_slot_count, fn i = vec::get (traits, i)), new_traits);

        end;    # stipulate
    };          # package pen 

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext