PreviousUpNext

15.4.1614  src/lib/x-kit/xclient/src/window/cs-pixmap.pkg

## cs-pixmap.pkg                        "cs" == "client-side"
#
#   Client-side rectangular arrays of pixels,
#   Support for copying back and forth between them
#   and server-side windows makes them useful for
#   specifying icons, tiling patterns and other
#   client-originated image data intended for X display.
#
# See also:
#     src/lib/x-kit/xclient/src/window/ro-pixmap-old.pkg
#     src/lib/x-kit/xclient/src/window/window-old.pkg
#     src/lib/x-kit/xclient/src/window/rw-pixmap-old.pkg

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



#
# TODO                  XXX SUCKO FIXME
#   - support a left-pad
#   - support Z format



###                  "Science is what we understand well enough to explain
###                   to a computer.  Art is everything else we do."
###
###                                          -- Donald Knuth

stipulate
    include package   threadkit;                        # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
    package byt =  byte;                                # byte                          is from   src/lib/std/src/byte.pkg
    package v1u =  vector_of_one_byte_unts;             # vector_of_one_byte_unts       is from   src/lib/std/src/vector-of-one-byte-unts.pkg
    package s1u =  vector_slice_of_one_byte_unts;       # vector_slice_of_one_byte_unts is from   src/lib/std/src/vector-slice-of-one-byte-unts.pkg
    package w8  =  one_byte_unt;                        # one_byte_unt                  is from   src/lib/std/one-byte-unt.pkg
    package g2d =  geometry2d;                          # geometry2d                    is from   src/lib/std/2d/geometry2d.pkg
    package w2v =  wire_to_value;                       # wire_to_value                 is from   src/lib/x-kit/xclient/src/wire/wire-to-value.pkg
    package v2w =  value_to_wire;                       # value_to_wire                 is from   src/lib/x-kit/xclient/src/wire/value-to-wire.pkg
    package xt  =  xtypes;                              # xtypes                        is from   src/lib/x-kit/xclient/src/wire/xtypes.pkg
    package xtr =  xlogger;                             # xlogger                       is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
    #
    package di  =  xserver_ximp;                        # xserver_ximp                  is from   src/lib/x-kit/xclient/src/window/xserver-ximp.pkg
    package w2x =  windowsystem_to_xserver;             # windowsystem_to_xserver       is from   src/lib/x-kit/xclient/src/window/windowsystem-to-xserver.pkg
#   package dt  =  draw_types;                          # draw_types                    is from   src/lib/x-kit/xclient/src/window/draw-types.pkg
    package dy  =  display;                             # display                       is from   src/lib/x-kit/xclient/src/wire/display.pkg
    package sn  =  xsession_junk;                       # xsession_junk                 is from   src/lib/x-kit/xclient/src/window/xsession-junk.pkg
    package wpm =  rw_pixmap;                           # rw_pixmap                     is from   src/lib/x-kit/xclient/src/window/rw-pixmap.pkg
#   package x2s =  xclient_to_sequencer;                # xclient_to_sequencer          is from   src/lib/x-kit/xclient/src/wire/xclient-to-sequencer.pkg
    package pn  =  pen;                                 # pen                           is from   src/lib/x-kit/xclient/src/window/pen.pkg
    #
    trace =  xtr::log_if  xtr::io_logging 0;            # Conditionally write strings to tracing.log or whatever.
herein


    package   cs_pixmap
    : (weak)  Cs_Pixmap                                 # Cs_Pixmap                     is from   src/lib/x-kit/xclient/src/window/cs-pixmap.api
    {
        exception BAD_CS_PIXMAP_DATA;

        v1uextract =    s1u::to_vector
                        o
                        s1u::make_slice;

        Cs_Pixmap = CS_PIXMAP { size:  g2d::Size,
                                data:  List(  List(  v1u::Vector ) )
                              };

        # Two cs_pixmaps   are the same
        # iff their fields are the same:
        #
        fun same_cs_pixmap
            ( CS_PIXMAP { size => size1, data => data1 },
              CS_PIXMAP { size => size2, data => data2 }
            )
            =
            if (not (g2d::size::eq (size1, size2)))
                #
                FALSE;
            else
                same_planes (data1, data2)
                where
                    fun same_plane ([], []) =>   TRUE;
                        same_plane (_,  []) =>   FALSE;
                        same_plane ([], _ ) =>   FALSE;

                        same_plane ( scanline1 ! rest1,
                                     scanline2 ! rest2
                                   )
                            =>
                            scanline1 == scanline2
                            and
                            same_plane (rest1, rest2);
                    end;

                    fun same_planes ([], []) =>   TRUE;
                        same_planes (_,  []) =>   FALSE;
                        same_planes ([], _ ) =>   FALSE;

                        same_planes ( plane1 ! rest1,
                                      plane2 ! rest2
                                    )
                            =>
                            same_plane (plane1, plane2)
                            and
                            same_planes (rest1, rest2);
                    end;
                end;
            fi;

        #
        fun string_to_data (wid, s)                                                                                             # Map a row of data coded as  a string to a bit representation.
            =                                                                                                                   # The data may be either encoded in hex (with a preceding "0x")
            case (string::explode s)                                                                                            # or in binary (with a preceeding "0b").
                #
                ('0' ! 'x' ! r)
                    =>
                    make_row (nbytes, r, [])
                    where
                        nbytes = ((wid + 7) / 8);   #  # of bytes per line 

                        fun cvt_char c
                            =
                            if (char::is_digit c)
                                #
                                byte::char_to_byte c - byte::char_to_byte '0';
                            else
                                if (char::is_hex_digit c)
                                    #
                                    char::is_upper c
                                    ??  byte::char_to_byte c - byte::char_to_byte 'A'
                                    ::  byte::char_to_byte c - byte::char_to_byte 'a';
                                else
                                    raise exception BAD_CS_PIXMAP_DATA;
                                fi;
                            fi;

                        fun make_row (0, [], l) =>  v1u::from_list (reverse l);
                            make_row (0,  _, _) =>  raise exception BAD_CS_PIXMAP_DATA;

                            make_row (i, d1 ! d0 ! r, l)
                                =>
                                make_row (i - 1, r,
                                  w8::bitwise_or (w8::(<<) (cvt_char d1, 0u4), cvt_char d0) ! l);

                            make_row _
                                =>
                                raise exception BAD_CS_PIXMAP_DATA;
                        end;
                    end;

                ('0' ! 'b' ! r)
                    =>
                    make_row (wid, 0ux80, r, 0u0, [])
                    where
                        fun make_row (0, _, [], b, l)
                                =>
                                v1u::from_list (reverse (b ! l));

                            make_row (_, _, [], _, _)
                                =>
                                raise exception BAD_CS_PIXMAP_DATA;

                            make_row (i, 0u0, l1, b, l2)
                               =>
                               make_row (i, 0ux80, l1, 0u0, b ! l2);

                            make_row (i, m, '0' ! r, b, l)
                               =>
                               make_row (i - 1, w8::(>>) (m, 0u1), r, b, l);

                            make_row (i, m, '1' ! r, b, l)
                               =>
                               make_row (i - 1, w8::(>>) (m, 0u1), r, w8::bitwise_or (m, b), l);

                            make_row _
                                =>
                                raise exception BAD_CS_PIXMAP_DATA;
                        end;
                    end;

                _   => raise exception BAD_CS_PIXMAP_DATA;
            esac;


        reverse_bits =  byt::reverse_byte_bits;                                                                                 # Reverse the bit-order of a byte 


        # Routines to re-order bits and bytes to the server's format (stolen from
        # XPutImage::c in Xlib).  We represent data in the following format:
        #
        #   scan-line unit = 1 byte
        #   byte-order     = MSB first (doen't matter for 1-byte scan units)
        #   bit-order      = MSB first (bit 0 is leftmost on display)
        #
        # This is the "1Mm" format of XPutImagec in Xlib.  The relevant lines
        # in the conversion table are:
        #
        #         1Mm 2Mm 4Mm 1Ml 2Ml 4Ml 1Lm 2Lm 4Lm 1Ll 2Ll 4Ll
        #   1Mm:   n   n   n   R   S   L   n   s   l   R   R   R
        #   1Ml:   R   R   R   n   s   l   R   S   L   n   n   n
        #
        #   legend:
        #               n   no changes
        #               s   reverse 8-bit units within 16-bit units
        #               l   reverse 8-bit units within 32-bit units
        #               R   reverse bits within 8-bit units
        #               S   s+R
        #               L   l+R

        fun no_swap x = x;

        fun swap_bits data
            =
            v1u::from_list
                (v1u::fold_backward (\\ (b, l) = reverse_bits b ! l)
                                    []
                                    data
                );

        fun explode_v data
            =
            v1u::fold_backward  (!)  []  data;

        fun swap_two_bytes s
            =
            v1u::from_list (swap (explode_v s))
            where
                fun swap (a ! b ! r) =>  b ! a ! (swap r);
                    swap [] =>  [];
                    swap _  =>  xgripe::impossible "[swap_two_bytes: bad image data]";
                end;
            end;

        fun swap_four_bytes s
            =
            v1u::from_list (swap (explode_v s))
            where
                fun swap (a ! b ! c ! d ! r) =>  d ! c ! b ! a ! (swap r);
                    swap [] =>  [];
                    swap _  =>  xgripe::impossible "[swap_four_bytes: bad image data]";
                end;
            end;

        fun swap_bits_and_two_bytes s
            =
            v1u::from_list (swap (explode_v s))
            where
                fun swap (a ! b ! r) =>  (reverse_bits b) ! (reverse_bits a) ! (swap r);
                    swap [] =>  [];
                    swap _  =>  xgripe::impossible "[swap_bits_and_two_bytes: bad image data]";
                end;
            end;

        fun swap_bits_and_four_bytes  s
            =
            v1u::from_list (swap (explode_v s))
            where
                fun swap (a ! b ! c ! d ! r)
                        =>
                        (reverse_bits d) ! (reverse_bits c) ! (reverse_bits b) ! (reverse_bits a) ! (swap r);

                    swap [] =>   [];
                    swap _  =>   xgripe::impossible "[swap_bits_and_four_bytes: bad image data]";
                end;
            end;

        fun swap_func (xt::RAW08, xt::MSBFIRST, xt::MSBFIRST) =>  no_swap;
            swap_func (xt::RAW16, xt::MSBFIRST, xt::MSBFIRST) =>  no_swap;
            swap_func (xt::RAW32, xt::MSBFIRST, xt::MSBFIRST) =>  no_swap;
            swap_func (xt::RAW08, xt::MSBFIRST, xt::LSBFIRST) =>  swap_bits;
            swap_func (xt::RAW16, xt::MSBFIRST, xt::LSBFIRST) =>  swap_bits_and_two_bytes;
            swap_func (xt::RAW32, xt::MSBFIRST, xt::LSBFIRST) =>  swap_bits_and_four_bytes;
            swap_func (xt::RAW08, xt::LSBFIRST, xt::MSBFIRST) =>  no_swap;
            swap_func (xt::RAW16, xt::LSBFIRST, xt::MSBFIRST) =>  swap_two_bytes;
            swap_func (xt::RAW32, xt::LSBFIRST, xt::MSBFIRST) =>  swap_four_bytes;
            swap_func (xt::RAW08, xt::LSBFIRST, xt::LSBFIRST) =>  swap_bits;
            swap_func (xt::RAW16, xt::LSBFIRST, xt::LSBFIRST) =>  swap_bits;
            swap_func (xt::RAW32, xt::LSBFIRST, xt::LSBFIRST) =>  swap_bits;
        end;

        fun pad_to_bits xt::RAW08 =>   0u8;
            pad_to_bits xt::RAW16 =>  0u16;
            pad_to_bits xt::RAW32 =>  0u32;
        end;

        fun round_down (nbytes, pad)
            =
            unt::to_int_x(
              unt::bitwise_and (unt::from_int nbytes, unt::bitwise_not((pad_to_bits pad) - 0u1)));

        fun round_up (nbytes, pad)
            =
            {   bits = (pad_to_bits pad) - 0u1;
                #
                unt::to_int_x (unt::bitwise_and (unt::from_int nbytes + bits, unt::bitwise_not bits));
            };

        # Pad and re-order image data as necessary
        # to match the server's format.
        #
        stipulate
            #
            pad1 = v1u::from_fn (1, \\ _ = 0u0);
            pad2 = v1u::from_fn (2, \\ _ = 0u0);
            pad3 = v1u::from_fn (3, \\ _ = 0u0);

        herein

            fun adjust_image_data (dpy_info: dy::Xdisplay)
                =
                {
                    fun extra (v, m)
                        =
                        unt::bitwise_and (unt::from_int (v1u::length v), m);

                    pad_scan_line
                        =
                        case dpy_info.bitmap_scanline_pad
                            #
                            xt::RAW08
                                =>
                                \\ s = s;

                            xt::RAW16
                                =>
                                \\ s =
                                    if (extra (s, 0u1) == 0u0)  s;
                                    else                        v1u::cat [s, pad1];
                                    fi;

                            xt::RAW32
                                =>
                                \\ s =  case (extra (s, 0u3))
                                            #
                                            0u0 => s;
                                            0u1 => v1u::cat [s, pad3];
                                            0u2 => v1u::cat [s, pad2];
                                            _   => v1u::cat [s, pad1];
                                        esac;


                        esac;

                    swapfn =    swap_func
                                  (
                                    dpy_info.bitmap_scanline_unit,
                                    dpy_info.image_byte_order,
                                    dpy_info.bitmap_bit_order
                                  );

                    \\ data =   map (\\ s = swapfn (pad_scan_line s))
                                    data;
                };
        end;

        # Copy rectangle from clientside window
        # into server-side offscreen window.
        #
        # It wouldn't take much to generalize
        # this to all drawables & pens. Additional
        # efficiency could be gained by having the
        # extract_row function extract rows already
        # padded correctly for the display when possible. XXX BUGGO FIXME
        #
        fun copy_from_clientside_pixmap_to_pixmap pm { from=>CS_PIXMAP { size, data }, from_box, to_point }
            =
            case (g2d::box::intersection (from_box, g2d::box::make (g2d::point::zero, size)))                   # Clip from_box to clientside window.
                #
                NULL => ();                                                                                     # No intersection so nothing to do.
                #
                THE from_box'
                    =>
                    put_sub_image (from_box', g2d::point::add (to_point, delta))
                    where
                        delta =     g2d::point::subtract
                                      ( g2d::box::upperleft  from_box',
                                        g2d::box::upperleft  from_box
                                      );

                        depth =  list::length data;

                        pm  ->  { pixmap_id, screen, per_depth_imps => { windowsystem_to_xserver, ... }: sn::Per_Depth_Imps, ... }: sn::Rw_Pixmap;

                        screen ->  { xsession=>{ xdisplay as (dpy_info: dy::Xdisplay), ... }: sn::Xsession, ... }: sn::Screen ;

                        scanline_pad  =  dpy_info.bitmap_scanline_pad;
                        scanline_unit =  dpy_info.bitmap_scanline_unit;

                        # Minimum no. of 4-byte words needed for PutImage.
                        # There should be a function in XRequest to provide this.       XXX SUCKO FIXME
                        #
                        request_size = 6;

                        # Number of image bytes per request:
                        #
                        available = (int::min (dpy_info.max_request_length, 65536) - request_size) * 4;

                        fun copy_from_clientside_pixmap_to_pixmap_request (r as { col, row, wide, high }, to_point)
                            =
                            {
                                left_pad    =   unt::to_int_x
                                                  (
                                                    unt::bitwise_and
                                                      (
                                                        unt::from_int  col,
                                                        pad_to_bits scanline_unit   - 0u1
                                                      )
                                                  );

                                byte_offset = (col - left_pad) / 8;

                                num_bytes   = round_up (wide + left_pad, xt::RAW08) / 8;

                                adjust      = adjust_image_data xdisplay;

                                # Given the list of data for a plane, extract a list of substrings
                                # corresponding to given rectangle, to the nearest byte.
                                #
                                fun extract_box (rows:  List( v1u::Vector ))
                                    =
                                    {
                                        fun skip (0, r) => r;
                                            skip (i, _ ! r) => skip (i - 1, r);
                                            skip (i, []) => xgripe::impossible "cs_pixmap_old: extract_box (skip)";
                                        end;


                                        fun extract_row (0, _)
                                                =>
                                                [];

                                            extract_row (i, my_row ! rest)
                                                =>
                                                if (   byte_offset == 0
                                                   and num_bytes == v1u::length my_row
                                                   )

                                                     my_row ! (extract_row (i - 1, rest));
                                                else
                                                     (v1uextract (my_row, byte_offset, THE num_bytes))
                                                     !
                                                     (extract_row (i - 1, rest));
                                                fi;

                                            extract_row (i,[])
                                                =>
                                                xgripe::impossible "cs_pixmap_old: extract_row";
                                        end;

                                        extract_row (high, skip (row, rows));
                                    };

                                xdata =  map  extract_box  data;

                                windowsystem_to_xserver.draw_ops
                                  [
                                    {
                                      to  => pixmap_id,
                                      pen => pn::default_pen,
                                      op  => w2x::x::PUT_IMAGE
                                              [ 
                                                {
                                                  to_point,
                                                  size => { wide, high },
                                                  depth,
                                                  lpad => left_pad,
                                                  format => xt::XYPIXMAP,
                      /*** THIS SHOULD BE
                                                  data => v1u::cat (list::cat (map adjust xdata))
                      ***/
                                                  data => v1u::cat (map (v1u::cat o adjust) xdata)
                                                }
                                              ] 
                                    }
                                  ];
                            };                                                                                                          # fun copy_from_clientside_pixmap_to_pixmap_request

                        # Decompose copy_from_clientside_pixmap_to_pixmap
                        # into multiple requests smaller than max size.
                        #
                        # First try to use as many rows as possible;
                        # if there is only one row left and it is
                        # still too large, decompose by columns:
                        #
                        fun put_sub_image (r as { col, row, wide, high }, pt as { col=>dx, row=>dy } )
                            =
                            {   left_pad
                                    =
                                    unt::to_int_x (unt::bitwise_and (unt::from_int col,  pad_to_bits scanline_unit - 0u1));

                                bytes_per_row
                                    =
                                    (round_up (wide + left_pad, scanline_pad) / 8) * depth;

                                if ((bytes_per_row * high) <= available)
                                    #
                                    copy_from_clientside_pixmap_to_pixmap_request (r, pt);
                                else
                                    if (high > 1)
                                        #
                                        high' = int::max (1, available / bytes_per_row);

                                        put_sub_image ({ col, row, wide, high=>high' }, pt);
                                        put_sub_image ({ col, row=>row+high', wide, high=>high-high' }, { col=>dx, row=>dy+high' } );
                                    else
                                        wide' = round_down (available * 8, scanline_pad) - left_pad;

                                        put_sub_image ({ col, row, wide=>wide', high=>1 }, pt);
                                        put_sub_image ({ col=>col+wide', row, wide=>wide-wide', high=>1 }, { col=>dx+wide', row=>dy } );
                                    fi;
                                fi;
                            };
                    end;                                                                                                                # fun copy_from_clientside_pixmap_to_pixmap 
            esac;       


        #  Create image data from an ascii representation 
        #
        fun make_clientside_pixmap_from_ascii (wide, p0 ! rest)
                =>
                {   fun mk (n, [],    l) =>   (n, reverse l);
                        mk (n, s ! r, l) =>   mk (n+1, r, string_to_data (wide, s) ! l);
                    end;

                    (mk (0, p0, []))
                        ->
                        (high, plane0);

                    fun check data
                        =
                        {   (mk (0, data,[]))
                                ->
                                (h, plane);

                            if (h == high)    plane;
                            else              raise exception  BAD_CS_PIXMAP_DATA;
                            fi;
                        };

                    CS_PIXMAP {
                        size =>   { wide, high },
                        data =>   plane0 ! (map check rest)
                    };
               };

            make_clientside_pixmap_from_ascii (wide, [])
                =>
                raise exception BAD_CS_PIXMAP_DATA;
        end;



        # Create a server-side offscreen window from
        # data in a client-side window:
        #
        fun make_readwrite_pixmap_from_clientside_pixmap
                screen
                (cs_pixmap_old as CS_PIXMAP { size, data } )
            =
            pixmap
            where
                depth = length data;

                pixmap
                    =
                    wpm::make_readwrite_pixmap
                        screen
                        (size, depth);

                copy_from_clientside_pixmap_to_pixmap
                    pixmap
                    {
                      from     =>  cs_pixmap_old, 
                      from_box =>  g2d::box::make (g2d::point::zero, size), 
                      to_point =>  g2d::point::zero
                    };
            end;


        # Create an pixmap from ascii data:
        #
        fun make_readwrite_pixmap_from_ascii_data
                screen
                (wide, ascii_rep)
            =
            make_readwrite_pixmap_from_clientside_pixmap
                screen
                (make_clientside_pixmap_from_ascii (wide, ascii_rep));



        stipulate

            # Create a client-side window from
            # a server-side offscreen window.
            #
            # This should be better integrated with
            # the draw_imp to avoid a possible race
            # condition: We need to be sure the
            # draw_imp flush has occurred before we
            # ask for the clientside window.    XXX BUGGO FIXME
            #
            fun make_clientside_pixmap_from_pixmap_or_window
                (
                  box,                                          # Get the pixelmap pixel contents from this part of
                  pixmap_or_window_id as xid,                   # this server-side pixmap or window.
#                  per_depth_imps,
                  screen
                )
                =
                {   (g2d::box::size  box)     ->  size as our_size;
#                    per_depth_imps ->  { depth, to_screen_drawimp, ... }: sn::Per_Depth_Imps;

                    (sn::xsession_of_screen  screen)
                        ->
                        { xdisplay, windowsystem_to_xserver, ... }: sn::Xsession;


                    # Avoid a race condition by flushing
                    # from the draw_imp any buffered draw
                    # commands for this drawable before
                    # sending our GetImage request to the
                    # X server:
                    #

# trace  {. sprintf "XYZZY calling dt::flush_drawimp  -- cs_pixmap_old::make_clientside_pixmap_from_pixmap_or_window   pixmap_or_window_id x=%x  (drawimp thread_id d=%d)" (unt::to_int u) (dt::drawimp_thread_id_of to_screen_drawimp); };
#                   dt::flush_drawimp  to_screen_drawimp;
# trace  {. sprintf "XYZZY done    dt::flush_drawimp  -- cs_pixmap_old::make_clientside_pixmap_from_pixmap_or_window   pixmap_or_window_id x=%x  (drawimp thread_id d=%d)" (unt::to_int u) (dt::drawimp_thread_id_of to_screen_drawimp); };

                    all_planes =  unt::bitwise_not  0u0;

log::note_on_stderr {. "calling v2w::encode_get_image     -- make_clientside_pixmap_from_pixmap_or_window() in cs-pixmap.pkg\n"; };
                    msg =   v2w::encode_get_image
                              { 
                                drawable   =>  pixmap_or_window_id, 
                                box,
                                plane_mask =>  xt::PLANEMASK all_planes, 
                                format     =>  xt::XYPIXMAP
                              };
# trace  {. sprintf "XYZZY calling GetImage, string == %s -- cs_pixmap_old::make_clientside_pixmap_from_pixmap_or_window" (xok::bytes_to_hex msg); };

log::note_on_stderr {. "sending get-image request and reading reply...   -- make_clientside_pixmap_from_pixmap_or_window() in cs-pixmap.pkg\n"; };
                    my { depth, data, visualid }
                        = 
                        w2v::decode_get_image_reply
                            (
                            block_until_mailop_fires                                    # XXX SUCKO FIXME
#                           ========================
                                (
#                               xok::send_xrequest_and_read_reply  xdisplay.xsocket  msg
                                windowsystem_to_xserver.xclient_to_sequencer.send_xrequest_and_read_reply    msg
                                )
                            );
log::note_on_stderr {. "sent get-image request and read reply...   -- make_clientside_pixmap_from_pixmap_or_window() in cs-pixmap.pkg\n"; };

# trace  {. sprintf "XYZZY done    GetImage, string == %s -- cs_pixmap_old::make_clientside_pixmap_from_pixmap_or_window" (xok::bytes_to_hex msg); };

                    swapfn =    swap_func
                                  (
                                    xdisplay.bitmap_scanline_unit,
                                    xdisplay.image_byte_order,
                                    xdisplay.bitmap_bit_order
                                  );

                    lines_per_plane = our_size.high;

                    bytes_per_line  = round_up (our_size.wide, xdisplay.bitmap_scanline_pad) / 8;
                    bytes_per_plane = bytes_per_line * lines_per_plane;

log::note_on_stderr {. sprintf "depth d=%d   lines_per_plane d=%d   bytes_per_line d=%d   bytes_per_plane d=%d   -- make_clientside_pixmap_from_pixmap_or_window() in cs-pixmap.pkg\n"   depth   lines_per_plane   bytes_per_line   bytes_per_plane; };

                    fun do_line start
                        =
                        swapfn (v1uextract (data, start, THE bytes_per_line));

                    fun make_line (i, start)
                        =
                        i == lines_per_plane
                         ?? []
                         :: (do_line start) ! (make_line (i+1, start+bytes_per_line));

                    fun make_plane (i, start)
                        =
                        i == depth
                         ?? []
                         :: (make_line (0, start)) ! (make_plane (i+1, start+bytes_per_plane));

                    CS_PIXMAP { size, data=>make_plane (0, 0) };
                };                                                                                                              # fun make_clientside_pixmap_from_pixmap_or_window

        herein

            # Create a client-side pixmap from
            # a server-side offscreen window.
            #
            fun make_clientside_pixmap_from_readwrite_pixmap ({ pixmap_id, size, screen, per_depth_imps }: sn::Rw_Pixmap)
                =
                {   # Before attempting to read back pixels
                    # from the X server we want to be sure that
                    # any relevant draw commands have been flushed
                    # from the relevant draw-imp.  For a RW_PIXMAP
                    # that means to_screen_drawimp:
                    #
                    per_depth_imps ->  { windowsystem_to_xserver, ... }: sn::Per_Depth_Imps;

#                   dt::flush_drawimp  to_screen_drawimp;

                    box = g2d::box::make (g2d::point::zero, size);      # Copy all of pixmap.
                    #
                    make_clientside_pixmap_from_pixmap_or_window (box, pixmap_id, screen);
                };

            # Create a client-side window from part of
            # a server-side onscreen window.  The underlying
            # GetImage X call is snarky:
            #
            #   o The window must be entirely onscreen.
            #   o Any parts of it obscured by non-descendents      come back undefined.
            #   o Any parts of it obscured by different-depth kids come back undefined.
            #
            # According to he docs on p57 of http://mythryl.org/pub/exene/X-protocol-R6.pdf
            #
            #    "This request is not general-purpose in the same sense
            #     as other graphics-related requests.  It is intended
            #     specifically for rudimentary hardcopy support." 
            #
            fun make_clientside_pixmap_from_window (box, window as { window_id, screen, windowsystem_to_xserver, ... }: sn::Window  )
                =
                {   # Before attempting to read back pixels
                    # from the X server we want to be sure that
                    # any relevant draw commands have been flushed
                    # from the relevant draw-imp.  For a WINDOW
                    # that means to_hostwindow_drawimp:
                    #
#                   dt::flush_drawimp  to_hostwindow_drawimp;

# per_depth_imps   -> { depth, to_screen_drawimp, ... }: sn::Per_Depth_Imps;
# trace {. sprintf "XYZZY make_clientside_pixmap_from_window: window.id x=%x   drawimp_thread_id_of window d=%d PER_DEPTH_IMPS.to_screen_drawimp.thread_id d=%d" (dt::id_of_window window) (draw::drawimp_thread_id_of (dt::drawable_of_window  window)) (dt::drawimp_thread_id_of to_screen_drawimp); };
                    make_clientside_pixmap_from_pixmap_or_window    (box, window_id, screen);
                };

        end;

        fun make_clientside_pixmap_from_readonly_pixmap (sn::RO_PIXMAP pm)
            =
            make_clientside_pixmap_from_readwrite_pixmap   pm;

    };                                                                  # package cs_pixmap_old

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext