vncrec 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +16 -0
 - data/.rspec +4 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +36 -0
 - data/Rakefile +8 -0
 - data/bin/vncrec +80 -0
 - data/examples/exit.rb +8 -0
 - data/examples/mp4.rb +10 -0
 - data/examples/mp4audio.rb +11 -0
 - data/ext/enchex_c/ReadRect.c +215 -0
 - data/ext/enchex_c/extconf.rb +5 -0
 - data/lib/vncrec.rb +6 -0
 - data/lib/vncrec/constants.rb +10 -0
 - data/lib/vncrec/recorder.rb +286 -0
 - data/lib/vncrec/rfb/enchex.rb +115 -0
 - data/lib/vncrec/rfb/encraw.rb +33 -0
 - data/lib/vncrec/rfb/enczrle.rb +202 -0
 - data/lib/vncrec/rfb/proxy.rb +200 -0
 - data/lib/vncrec/version.rb +3 -0
 - data/lib/vncrec/writers.rb +209 -0
 - data/spec/executable_spec.rb +40 -0
 - data/spec/recorder_spec.rb +338 -0
 - data/spec/spec_helper.rb +171 -0
 - data/spec/writers_spec.rb +121 -0
 - data/vncrec.gemspec +34 -0
 - metadata +165 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 44f235ad8e44ea1bab090676b4b011ba3eb53993
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 314f906e6b36542cc0c8ed42b61fe14c0de4dc31
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: bcab87f697e3d8ea4da518a1e2bde030235b83016d1c6c48a327168f365d75f4c962589f037fcc4465b5faa09eb88ae4b77b2470fdfe1185fb35c4677ae529a6
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: ee53667bcbfc8f44e2e86304cd82932d3f095090dedfeabf59618f42680fb942fac35d69dc3b2c93e3aba33f3e0f8e875a6e318f916ad43b0dfa95a81e9fc30a
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2015 slowness pc
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 6 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 7 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 8 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 9 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 10 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 14 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 19 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 20 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 21 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 22 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            VNCRec
         
     | 
| 
      
 2 
     | 
    
         
            +
            ===========
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            VNCRec is a gem that provides you 
         
     | 
| 
      
 5 
     | 
    
         
            +
            tools to record VNC session.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ##Usage
         
     | 
| 
      
 8 
     | 
    
         
            +
            There is a binary called `vncrec`, which is a recorder tool.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            With no host specified, it will listen on
         
     | 
| 
      
 11 
     | 
    
         
            +
            given port (5900 by default) for connection
         
     | 
| 
      
 12 
     | 
    
         
            +
            from VNC server (they refer to that mode as
         
     | 
| 
      
 13 
     | 
    
         
            +
            _reverse connection_). This is intended to
         
     | 
| 
      
 14 
     | 
    
         
            +
            be used when you want to record remote
         
     | 
| 
      
 15 
     | 
    
         
            +
            desktop and you don't know if it's available.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Call `vncrec -h` for list of available options.
         
     | 
| 
      
 18 
     | 
    
         
            +
            To stop recording send `SIGINT` (press ^C).
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            You can also use `VNCRec::Recorder` class in your ruby code.
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 'vncrec'
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            r = VNCRec::Recorder.new(filename: "myvncsession.mp4")
         
     | 
| 
      
 26 
     | 
    
         
            +
            r.run
         
     | 
| 
      
 27 
     | 
    
         
            +
            # loop do 
         
     | 
| 
      
 28 
     | 
    
         
            +
            #   sleep 100
         
     | 
| 
      
 29 
     | 
    
         
            +
            # end
         
     | 
| 
      
 30 
     | 
    
         
            +
            ```
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            If you have FFmpeg installed, file extension is passed just through to it, so
         
     | 
| 
      
 33 
     | 
    
         
            +
            you can specify encoder you want by passing .mp4 or .flv, etc. If no filename
         
     | 
| 
      
 34 
     | 
    
         
            +
            specified, `vncrec` assumes raw. There is also a way to 
         
     | 
| 
      
 35 
     | 
    
         
            +
            record raw video by specifying filename with extension .raw. This way FFmpeg is 
         
     | 
| 
      
 36 
     | 
    
         
            +
            not required.
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/vncrec
    ADDED
    
    | 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'vncrec'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            options = VNCRec::Recorder::DEFAULTS
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            OptionParser.new do |opts|
         
     | 
| 
      
 10 
     | 
    
         
            +
              opts.on('--pix_fmt F', 'Specify pixel format. List available with --pix_fmts') do |d|
         
     | 
| 
      
 11 
     | 
    
         
            +
                options[:pix_fmt] = d.dup
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
              opts.on('--pix_fmts', 'List available pix_fmts') do
         
     | 
| 
      
 14 
     | 
    
         
            +
                puts 'Available pixel formats:'
         
     | 
| 
      
 15 
     | 
    
         
            +
                puts "bgr8\t8 bits color palette"
         
     | 
| 
      
 16 
     | 
    
         
            +
                puts "bgra\t32 bits color palette"
         
     | 
| 
      
 17 
     | 
    
         
            +
                puts
         
     | 
| 
      
 18 
     | 
    
         
            +
                exit 0
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
              opts.on('--debug', 'Enable debugger, gem pry-debugger required') do
         
     | 
| 
      
 21 
     | 
    
         
            +
                require 'pry-byebug'
         
     | 
| 
      
 22 
     | 
    
         
            +
                options[:debug] = true
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              opts.on('-e ENC', '--encoding', 'Specify encoding') do |e|
         
     | 
| 
      
 25 
     | 
    
         
            +
                name = "ENC_#{e.upcase}".to_sym
         
     | 
| 
      
 26 
     | 
    
         
            +
                if VNCRec.constants.index(name)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  options[:encoding] = VNCRec.const_get(name)
         
     | 
| 
      
 28 
     | 
    
         
            +
                else
         
     | 
| 
      
 29 
     | 
    
         
            +
                  puts 'Unsupported encoding type. Pass option --encodings to see a list of available encodings.'
         
     | 
| 
      
 30 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
              opts.on('--encodings', 'Print list of available encodings') do
         
     | 
| 
      
 34 
     | 
    
         
            +
                puts 'Available encodings are:'
         
     | 
| 
      
 35 
     | 
    
         
            +
                puts "\traw"
         
     | 
| 
      
 36 
     | 
    
         
            +
                puts "\thextile"
         
     | 
| 
      
 37 
     | 
    
         
            +
                puts "\tzrle(not yet supported)"
         
     | 
| 
      
 38 
     | 
    
         
            +
                puts
         
     | 
| 
      
 39 
     | 
    
         
            +
                exit
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
              opts.on('-g GEOM', '--geometry GEOM', 'Screen resolution, <X>x<Y>') do |opt|
         
     | 
| 
      
 42 
     | 
    
         
            +
                unless opt =~ /\d+x\d+/
         
     | 
| 
      
 43 
     | 
    
         
            +
                  puts 'Unknown screen resolution format, use <x>x<y>'
         
     | 
| 
      
 44 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
                options[:geometry] = opt
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
              opts.on('-h', '--help', 'Display this message') do
         
     | 
| 
      
 49 
     | 
    
         
            +
                puts opts
         
     | 
| 
      
 50 
     | 
    
         
            +
                exit
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
              opts.on('--logging', 'Enable logging to stderr') do
         
     | 
| 
      
 53 
     | 
    
         
            +
                options[:logging] = true
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
              opts.on('-o NAME', '--output', 'Specify filename to write to. Special name is "stdout"') do |f|
         
     | 
| 
      
 56 
     | 
    
         
            +
                options[:filename] = f.to_s
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
              opts.on('-p PORT', '--port', 'Choose port to listen on') do |p|
         
     | 
| 
      
 59 
     | 
    
         
            +
                options[:port] = p.to_i
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
              opts.on('-r RATE', '--framerate <rate>', 'Specify framerate') do |r|
         
     | 
| 
      
 62 
     | 
    
         
            +
                options[:fps] = r.to_i
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
              opts.on('-s', '--server SERVER', 'Specify host address') do |s|
         
     | 
| 
      
 65 
     | 
    
         
            +
                options[:host] = s
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end.parse!
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            v = VNCRec::Recorder.new(options)
         
     | 
| 
      
 70 
     | 
    
         
            +
            v.on_exit << ->() { exit }
         
     | 
| 
      
 71 
     | 
    
         
            +
            Signal.trap('INT') { v.running? ? v.stop : exit }
         
     | 
| 
      
 72 
     | 
    
         
            +
            Signal.trap('USR1') do
         
     | 
| 
      
 73 
     | 
    
         
            +
              puts v.filesize
         
     | 
| 
      
 74 
     | 
    
         
            +
              $stdout.flush
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            v.run
         
     | 
| 
      
 78 
     | 
    
         
            +
            loop do
         
     | 
| 
      
 79 
     | 
    
         
            +
              sleep 100
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/exit.rb
    ADDED
    
    
    
        data/examples/mp4.rb
    ADDED
    
    
| 
         @@ -0,0 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'vncrec'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            VNCRec::Recorder.new(
         
     | 
| 
      
 7 
     | 
    
         
            +
              encoding: VNCRec::EncHextile,
         
     | 
| 
      
 8 
     | 
    
         
            +
              filename: 'file.mp4',
         
     | 
| 
      
 9 
     | 
    
         
            +
              ffmpeg_ia_opts: '-i /path/to/audio/file.mp3',
         
     | 
| 
      
 10 
     | 
    
         
            +
              ffmpeg_out_opts: '-map 0 -vcodec libx264 -preset ultrafast -map 1 -acodec mp3'
         
     | 
| 
      
 11 
     | 
    
         
            +
            )
         
     | 
| 
         @@ -0,0 +1,215 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include <ruby.h>
         
     | 
| 
      
 2 
     | 
    
         
            +
            #include <ruby/io.h>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <fcntl.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            #include <math.h>
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            int my_readbyte(VALUE io){
         
     | 
| 
      
 8 
     | 
    
         
            +
              return NUM2INT( rb_funcall(io, rb_intern("readbyte"),0));
         
     | 
| 
      
 9 
     | 
    
         
            +
            }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            char *my_read(VALUE io, long nbytes){
         
     | 
| 
      
 12 
     | 
    
         
            +
              char * result = (char*)malloc(nbytes+1);
         
     | 
| 
      
 13 
     | 
    
         
            +
              VALUE nbytes_v = INT2NUM(nbytes);
         
     | 
| 
      
 14 
     | 
    
         
            +
              VALUE rstr = rb_funcall(io, rb_intern("read"), 1,nbytes_v);
         
     | 
| 
      
 15 
     | 
    
         
            +
              memcpy(
         
     | 
| 
      
 16 
     | 
    
         
            +
                  result,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  RSTRING_PTR(rstr),
         
     | 
| 
      
 18 
     | 
    
         
            +
                  RSTRING_LEN(rstr)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  );
         
     | 
| 
      
 20 
     | 
    
         
            +
              return result;
         
     | 
| 
      
 21 
     | 
    
         
            +
            }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            VALUE mVNC = Qnil;
         
     | 
| 
      
 24 
     | 
    
         
            +
            VALUE mEncHextile = Qnil;
         
     | 
| 
      
 25 
     | 
    
         
            +
            VALUE mRFB = Qnil;
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            void Init_enchex_c();
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            static VALUE read_rect_c(VALUE self,VALUE io, VALUE _x, VALUE _y, VALUE _w, VALUE _h, VALUE bitspp, VALUE fb, VALUE fbw, VALUE fbh);
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            void Init_enchex_c() {
         
     | 
| 
      
 32 
     | 
    
         
            +
              mVNC = rb_define_module("VNCRec");
         
     | 
| 
      
 33 
     | 
    
         
            +
              mRFB = rb_define_module_under(mVNC, "RFB");
         
     | 
| 
      
 34 
     | 
    
         
            +
              mEncHextile = rb_define_module_under(mRFB, "EncHextile");
         
     | 
| 
      
 35 
     | 
    
         
            +
              rb_define_module_function(mEncHextile, "read_rect", read_rect_c, 9);
         
     | 
| 
      
 36 
     | 
    
         
            +
            }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            void _read_subrect_c(int rx, int ry, int rw, int rh, int tx, int ty, char *fg, VALUE io, char* fb, int fbw, int fbh, int bpp){
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              unsigned char xy, wh;
         
     | 
| 
      
 41 
     | 
    
         
            +
              xy = my_readbyte(io);
         
     | 
| 
      
 42 
     | 
    
         
            +
              wh = my_readbyte(io);
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              if(!fb)
         
     | 
| 
      
 45 
     | 
    
         
            +
                return;
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              unsigned char stx = (xy & 0xF0) >> 4;
         
     | 
| 
      
 48 
     | 
    
         
            +
              unsigned char stw = ((wh & 0xF0) >> 4) + 1;
         
     | 
| 
      
 49 
     | 
    
         
            +
              unsigned char sty = (xy & 0x0F);
         
     | 
| 
      
 50 
     | 
    
         
            +
              unsigned char sth = (wh & 0x0F) + 1;
         
     | 
| 
      
 51 
     | 
    
         
            +
              rw *= bpp;
         
     | 
| 
      
 52 
     | 
    
         
            +
              rx *= bpp;
         
     | 
| 
      
 53 
     | 
    
         
            +
              tx *= bpp;
         
     | 
| 
      
 54 
     | 
    
         
            +
              stx *= bpp;
         
     | 
| 
      
 55 
     | 
    
         
            +
              stw *= bpp;
         
     | 
| 
      
 56 
     | 
    
         
            +
              char *fg_row = (char*)malloc(stw);
         
     | 
| 
      
 57 
     | 
    
         
            +
              int k,l;
         
     | 
| 
      
 58 
     | 
    
         
            +
              for(k = 0; k < stw; k+=bpp){
         
     | 
| 
      
 59 
     | 
    
         
            +
                for(l = 0; l < bpp; l++){
         
     | 
| 
      
 60 
     | 
    
         
            +
                  fg_row[k+l] = fg[l];
         
     | 
| 
      
 61 
     | 
    
         
            +
                }
         
     | 
| 
      
 62 
     | 
    
         
            +
              }
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              int i;
         
     | 
| 
      
 65 
     | 
    
         
            +
              for (i = 0; i < sth; i++) {
         
     | 
| 
      
 66 
     | 
    
         
            +
                register int row_begin = fbw*(ry+ty+sty+i) + rx + tx + stx;
         
     | 
| 
      
 67 
     | 
    
         
            +
                memcpy(&fb[row_begin], fg_row, stw);
         
     | 
| 
      
 68 
     | 
    
         
            +
              }
         
     | 
| 
      
 69 
     | 
    
         
            +
              free(fg_row);
         
     | 
| 
      
 70 
     | 
    
         
            +
            }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            void _read_subrect_c_raw(int rx, int ry, int rw, int rh, int tx, int ty, int tw, int th, VALUE io, char* fb, int fbw, int fbh, int bpp){
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              rw *= bpp;
         
     | 
| 
      
 75 
     | 
    
         
            +
              rx *= bpp;
         
     | 
| 
      
 76 
     | 
    
         
            +
              tw *= bpp;
         
     | 
| 
      
 77 
     | 
    
         
            +
              tx *= bpp;
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              int trow;
         
     | 
| 
      
 80 
     | 
    
         
            +
              char *data = my_read(io, tw*th);
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              if(!fb){
         
     | 
| 
      
 83 
     | 
    
         
            +
                return;
         
     | 
| 
      
 84 
     | 
    
         
            +
              }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              for (trow = 0; trow < th; trow++) {
         
     | 
| 
      
 87 
     | 
    
         
            +
                register int row_begin = fbw*(ry+ty+trow) + rx + tx;
         
     | 
| 
      
 88 
     | 
    
         
            +
                memcpy( &fb[row_begin], &data[trow*tw],tw);
         
     | 
| 
      
 89 
     | 
    
         
            +
              }
         
     | 
| 
      
 90 
     | 
    
         
            +
              free(data);
         
     | 
| 
      
 91 
     | 
    
         
            +
            }
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            void _fill_tile_bg(int rx, int ry, int rw, int rh, int tx, int ty, int tw, int th, char*bg, VALUE io, char* fb, int fbw, int fbh, int bpp){
         
     | 
| 
      
 94 
     | 
    
         
            +
              if(!fb)
         
     | 
| 
      
 95 
     | 
    
         
            +
                return;
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              rw *= bpp;
         
     | 
| 
      
 98 
     | 
    
         
            +
              rx *= bpp;
         
     | 
| 
      
 99 
     | 
    
         
            +
              tw *=bpp;
         
     | 
| 
      
 100 
     | 
    
         
            +
              tx *= bpp;
         
     | 
| 
      
 101 
     | 
    
         
            +
              int trow;
         
     | 
| 
      
 102 
     | 
    
         
            +
              char *bg_row = (char*)malloc(tw);
         
     | 
| 
      
 103 
     | 
    
         
            +
              int k,l;
         
     | 
| 
      
 104 
     | 
    
         
            +
              for(k = 0; k < tw; k+=bpp){
         
     | 
| 
      
 105 
     | 
    
         
            +
                for(l = 0; l < bpp; l++){
         
     | 
| 
      
 106 
     | 
    
         
            +
                  bg_row[k+l] = bg[l];
         
     | 
| 
      
 107 
     | 
    
         
            +
                }
         
     | 
| 
      
 108 
     | 
    
         
            +
              }
         
     | 
| 
      
 109 
     | 
    
         
            +
              register int base_row_begin = fbw*(ry+ty) + rx + tx;
         
     | 
| 
      
 110 
     | 
    
         
            +
              for (trow = 0; trow < th; trow++) {
         
     | 
| 
      
 111 
     | 
    
         
            +
                register int row_begin = base_row_begin + fbw*trow;
         
     | 
| 
      
 112 
     | 
    
         
            +
                memcpy(&fb[row_begin], bg_row, tw);
         
     | 
| 
      
 113 
     | 
    
         
            +
              }
         
     | 
| 
      
 114 
     | 
    
         
            +
              free(bg_row);
         
     | 
| 
      
 115 
     | 
    
         
            +
            }
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            static VALUE read_rect_c(VALUE self,VALUE io, VALUE _x, VALUE _y, VALUE _w, VALUE _h, VALUE bitspp, VALUE _fb, VALUE _fbw, VALUE _fbh){
         
     | 
| 
      
 118 
     | 
    
         
            +
              int w = NUM2INT(_w);
         
     | 
| 
      
 119 
     | 
    
         
            +
              int h = NUM2INT(_h);
         
     | 
| 
      
 120 
     | 
    
         
            +
              int rx = NUM2INT(_x);
         
     | 
| 
      
 121 
     | 
    
         
            +
              int ry = NUM2INT(_y);
         
     | 
| 
      
 122 
     | 
    
         
            +
              int fbw = NUM2INT(_fbw);
         
     | 
| 
      
 123 
     | 
    
         
            +
              int fbh = NUM2INT(_fbh);
         
     | 
| 
      
 124 
     | 
    
         
            +
              int bpp = (float)NUM2INT(bitspp) / 8.0;
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
              int tiles_row_num = ceil((float)h/16.0);
         
     | 
| 
      
 128 
     | 
    
         
            +
              int tiles_col_num = ceil((float)w/16.0);
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
              char *fb;
         
     | 
| 
      
 131 
     | 
    
         
            +
              int fbsize = fbw*fbh;
         
     | 
| 
      
 132 
     | 
    
         
            +
              if(ry > fbh || rx * bpp > fbw)
         
     | 
| 
      
 133 
     | 
    
         
            +
                fb = NULL; // skip
         
     | 
| 
      
 134 
     | 
    
         
            +
              else
         
     | 
| 
      
 135 
     | 
    
         
            +
                fb = (char*)malloc(fbsize);
         
     | 
| 
      
 136 
     | 
    
         
            +
              if(fb)
         
     | 
| 
      
 137 
     | 
    
         
            +
                memcpy(fb,RSTRING(_fb)->as.heap.ptr,RSTRING(_fb)->as.heap.len);
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
              int last_tile_w = w % 16;
         
     | 
| 
      
 140 
     | 
    
         
            +
              int last_tile_h = h % 16;
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
              char prev_tile_bg[4];
         
     | 
| 
      
 143 
     | 
    
         
            +
              char prev_tile_fg[4];
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
              int i,j;
         
     | 
| 
      
 146 
     | 
    
         
            +
              int tw, th;
         
     | 
| 
      
 147 
     | 
    
         
            +
              int ty, tx;
         
     | 
| 
      
 148 
     | 
    
         
            +
              int ti,tj,tk;
         
     | 
| 
      
 149 
     | 
    
         
            +
              unsigned char subenc;
         
     | 
| 
      
 150 
     | 
    
         
            +
              for (i = 0; i < tiles_row_num; i++) {
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                if ((i == tiles_row_num-1) && (last_tile_h > 0))
         
     | 
| 
      
 153 
     | 
    
         
            +
                  th = last_tile_h;
         
     | 
| 
      
 154 
     | 
    
         
            +
                else
         
     | 
| 
      
 155 
     | 
    
         
            +
                  th = 16;
         
     | 
| 
      
 156 
     | 
    
         
            +
                ty = 16 * i;
         
     | 
| 
      
 157 
     | 
    
         
            +
                for (j = 0; j < tiles_col_num; j++) {
         
     | 
| 
      
 158 
     | 
    
         
            +
                  
         
     | 
| 
      
 159 
     | 
    
         
            +
                  if ((j == tiles_col_num-1) && (last_tile_w > 0))
         
     | 
| 
      
 160 
     | 
    
         
            +
                    tw = last_tile_w;
         
     | 
| 
      
 161 
     | 
    
         
            +
                  else
         
     | 
| 
      
 162 
     | 
    
         
            +
                    tw = 16;
         
     | 
| 
      
 163 
     | 
    
         
            +
                  tx = 16 * j;
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                  subenc = my_readbyte(io);
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                  if(subenc & 1){ //raw
         
     | 
| 
      
 168 
     | 
    
         
            +
                    _read_subrect_c_raw(rx,ry,w,h,tx,ty,tw,th,io,fb,fbw,fbh,bpp);
         
     | 
| 
      
 169 
     | 
    
         
            +
                  }
         
     | 
| 
      
 170 
     | 
    
         
            +
                  if(subenc & 2){//background specified
         
     | 
| 
      
 171 
     | 
    
         
            +
                    for (tk = 0; tk < bpp; tk++) {
         
     | 
| 
      
 172 
     | 
    
         
            +
                      prev_tile_bg[tk] = my_readbyte(io);
         
     | 
| 
      
 173 
     | 
    
         
            +
                    }
         
     | 
| 
      
 174 
     | 
    
         
            +
                  }
         
     | 
| 
      
 175 
     | 
    
         
            +
                  if(!(subenc & 1)){//should not refill raw
         
     | 
| 
      
 176 
     | 
    
         
            +
                    for (ti = 0; ti < th; ti++) {
         
     | 
| 
      
 177 
     | 
    
         
            +
                      for(tj = 0; tj < tw; tj++){
         
     | 
| 
      
 178 
     | 
    
         
            +
                        _fill_tile_bg(rx,ry,w,h,tx,ty,tw,th,prev_tile_bg,io,fb,fbw,fbh,bpp);
         
     | 
| 
      
 179 
     | 
    
         
            +
                      }
         
     | 
| 
      
 180 
     | 
    
         
            +
                    }
         
     | 
| 
      
 181 
     | 
    
         
            +
                  }
         
     | 
| 
      
 182 
     | 
    
         
            +
                  if(subenc & 4){//foreground specified
         
     | 
| 
      
 183 
     | 
    
         
            +
                    for (tk = 0; tk < bpp; tk++) {
         
     | 
| 
      
 184 
     | 
    
         
            +
                      prev_tile_fg[tk] = my_readbyte(io);
         
     | 
| 
      
 185 
     | 
    
         
            +
                    }
         
     | 
| 
      
 186 
     | 
    
         
            +
                  }
         
     | 
| 
      
 187 
     | 
    
         
            +
                  if(subenc & 8){//any subrect
         
     | 
| 
      
 188 
     | 
    
         
            +
                    size_t subrects_number = my_readbyte(io);
         
     | 
| 
      
 189 
     | 
    
         
            +
                    size_t subrect;
         
     | 
| 
      
 190 
     | 
    
         
            +
                    char fg[4];
         
     | 
| 
      
 191 
     | 
    
         
            +
                    for (subrect = 0; subrect < subrects_number; subrect++) {
         
     | 
| 
      
 192 
     | 
    
         
            +
                      if(subenc & 16){//subrect colored
         
     | 
| 
      
 193 
     | 
    
         
            +
                        for (tk = 0; tk < bpp; tk++) {
         
     | 
| 
      
 194 
     | 
    
         
            +
                          fg[tk] = my_readbyte(io);
         
     | 
| 
      
 195 
     | 
    
         
            +
                        }
         
     | 
| 
      
 196 
     | 
    
         
            +
                        _read_subrect_c(rx,ry,w,h,tx,ty, fg, io, fb, fbw, fbh, bpp);
         
     | 
| 
      
 197 
     | 
    
         
            +
                      }else{
         
     | 
| 
      
 198 
     | 
    
         
            +
                        _read_subrect_c(rx,ry,w,h,tx,ty, prev_tile_fg, io, fb, fbw, fbh, bpp);
         
     | 
| 
      
 199 
     | 
    
         
            +
                      }
         
     | 
| 
      
 200 
     | 
    
         
            +
                    }
         
     | 
| 
      
 201 
     | 
    
         
            +
                  }
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                } //for j
         
     | 
| 
      
 204 
     | 
    
         
            +
              }//for i
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
              if(fb) {
         
     | 
| 
      
 207 
     | 
    
         
            +
                for (i = 0; i < fbh; i++) {
         
     | 
| 
      
 208 
     | 
    
         
            +
                  rb_str_update(_fb, i*fbw, fbw,
         
     | 
| 
      
 209 
     | 
    
         
            +
                      rb_str_new(&fb[i * fbw], fbw));
         
     | 
| 
      
 210 
     | 
    
         
            +
                }
         
     | 
| 
      
 211 
     | 
    
         
            +
                free(fb);
         
     | 
| 
      
 212 
     | 
    
         
            +
              }
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
              return Qtrue;
         
     | 
| 
      
 215 
     | 
    
         
            +
            }
         
     |