aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo/servo.rs
blob: b8e1b4e98a1d14f9d97eda805f8df64c04749202 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use comm::*;
use option::swap_unwrap;
use platform::osmain;
use osmain::{OSMain, AddKeyHandler};
use opts::{Opts, Screen, Png};
use engine::{EngineTask, EngineProto};

use url_to_str = std::net::url::to_str;
use util::url::make_url;

use pipes::{Port, Chan};

fn main(args: ~[~str]) {
    run(opts::from_cmdline_args(args))
}

#[allow(non_implicitly_copyable_typarams)]
fn run(opts: Opts) {
    match opts.render_mode {
      Screen => run_pipeline_screen(opts.urls),
      Png(outfile) => {
        assert opts.urls.is_not_empty();
        if opts.urls.len() > 1u {
            fail ~"servo asks that you stick to a single URL in PNG output mode"
        }
        run_pipeline_png(opts.urls.head(), outfile)
      }
    }
}

fn run_pipeline_screen(urls: ~[~str]) {

    // The platform event handler thread
    let osmain = OSMain();

    // Send each file to render then wait for keypress
    let (keypress_to_engine, keypress_from_osmain) = pipes::stream();
    osmain.send(AddKeyHandler(keypress_to_engine));

    // Create a serve instance
    let mut engine_task = Some(EngineTask(osmain));

    for urls.each |filename| {
        let url = make_url(*filename, None);
        #debug["master: Sending url `%s`", url_to_str(copy url)];
        engine_task =
            Some(EngineProto::client::LoadURL(swap_unwrap(&mut engine_task),
                                              url));
        #debug["master: Waiting for keypress"];

        match keypress_from_osmain.try_recv() {
          Some(*) => { }
          None => { #error("keypress stream closed unexpectedly") }
        };
    }

    // Shut everything down
    #debug["master: Shut down"];
    let engine_task = EngineProto::client::Exit(option::unwrap(engine_task));
    pipes::recv(engine_task);

    osmain.send(osmain::Exit);
}

fn run_pipeline_png(-url: ~str, outfile: ~str) {

    // Use a PNG encoder as the graphics compositor
    use gfx::png_compositor;
    use png_compositor::PngCompositor;
    use io::{Writer, buffered_file_writer};
    use resource::resource_task::ResourceTask;
    use resource::image_cache_task::SyncImageCacheTask;
    use engine::EngineTask_;

    listen(|pngdata_from_compositor| {
        let compositor = PngCompositor(pngdata_from_compositor);
        let resource_task = ResourceTask();
        // For the PNG pipeline we are using a synchronous image cache
        // so that all requests will be fullfilled before the first
        // render
        let image_cache_task = SyncImageCacheTask(resource_task);
        let engine_task = EngineTask_(compositor, resource_task, image_cache_task);
        let engine_task = EngineProto::client::LoadURL(engine_task, make_url(url, None));

        match buffered_file_writer(&Path(outfile)) {
          Ok(writer) => writer.write(pngdata_from_compositor.recv()),
          Err(e) => fail e
        }

        let engine_task = EngineProto::client::Exit(engine_task);
        pipes::recv(engine_task);
        compositor.send(png_compositor::Exit);
    })
}