From 7a8305dc163b1934df948aa252cbc99e69315f2f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 5 May 2012 16:32:11 -0700 Subject: [PATCH] Render to PNG file when using -o flag --- src/servo/engine.rs | 36 ++++++++++++++++++ src/servo/gfx/pngsink.rs | 2 + src/servo/opts.rs | 4 +- src/servo/servo.rc | 3 +- src/servo/servo.rs | 80 ++++++++++++++++++++++++++++------------ 5 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 src/servo/engine.rs diff --git a/src/servo/engine.rs b/src/servo/engine.rs new file mode 100644 index 00000000000..c20131797f4 --- /dev/null +++ b/src/servo/engine.rs @@ -0,0 +1,36 @@ +import gfx::renderer; + +enum msg { + load_url(str), + exit(comm::chan<()>) +} + +fn engine(sink: S) -> comm::chan { + + task::spawn_listener:: {|self_ch| + // The renderer + let renderer = renderer::renderer(sink); + + // The layout task + let layout = layout::layout::layout(renderer); + + // The content task + let content = content::content(layout); + + loop { + alt self_ch.recv() { + load_url(url) { content.send(content::parse(url)) } + exit(sender) { + content.send(content::exit); + layout.send(layout::layout::exit); + listen {|resp_ch| + renderer.send(renderer::exit(resp_ch)); + resp_ch.recv(); + } + sender.send(()); + break; + } + } + } + } +} diff --git a/src/servo/gfx/pngsink.rs b/src/servo/gfx/pngsink.rs index 8f3f8e4b229..653ab4a52e5 100644 --- a/src/servo/gfx/pngsink.rs +++ b/src/servo/gfx/pngsink.rs @@ -41,9 +41,11 @@ fn pngsink(output: chan<[u8]>) -> chan { loop { alt po.recv() { begin_drawing(sender) { + #debug("pngsink: begin_drawing"); sender.send(draw_target); } draw(sender, dt) { + #debug("pngsink: draw"); do_draw(sender, dt, output, cairo_surf); } exit { break } diff --git a/src/servo/opts.rs b/src/servo/opts.rs index a9ab9cbe887..d4ca2610705 100644 --- a/src/servo/opts.rs +++ b/src/servo/opts.rs @@ -12,7 +12,7 @@ type opts = { enum render_mode { screen, - file(str) + png(str) } fn from_cmdline_args(args: [str]) -> opts { @@ -36,7 +36,7 @@ fn from_cmdline_args(args: [str]) -> opts { }; let render_mode = alt getopts::opt_maybe_str(match, "o") { - some(output_file) { file(output_file) } + some(output_file) { png(output_file) } none { screen } }; diff --git a/src/servo/servo.rc b/src/servo/servo.rc index a90fdb52072..5d0eb0fb118 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -49,4 +49,5 @@ mod util { } mod content; -mod opts; \ No newline at end of file +mod opts; +mod engine; \ No newline at end of file diff --git a/src/servo/servo.rs b/src/servo/servo.rs index f8eff58fe46..c20d3208afb 100644 --- a/src/servo/servo.rs +++ b/src/servo/servo.rs @@ -11,41 +11,73 @@ fn main(args: [str]) { fn run(opts: opts::opts) { + alt opts.render_mode { + opts::screen { + run_pipeline_screen(opts.urls) + } + opts::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]) { + + // Use the platform thread as the renderer sink + import osmain::gfxsink; + // The platform event handler thread let osmain = osmain::osmain(); - // The renderer - let renderer = { - // Use the platform thread as the renderer sink - import osmain::gfxsink; - renderer::renderer(osmain) - }; - - // The layout task - let layout = layout::layout::layout(renderer); - - // The content task - let content = content::content(layout); + // Create a serve instance + let engine = engine::engine(osmain); // Send each file to render then wait for keypress - for opts.urls.each { |filename| - #debug["master: Sending filename `%s`", filename]; - content.send(content::parse(filename)); - #debug["master: Waiting for keypress"]; - listen {|key_ch| - osmain.send(platform::osmain::add_key_handler(key_ch)); + listen {|key_ch| + osmain.send(platform::osmain::add_key_handler(key_ch)); + + for urls.each { |filename| + #debug["master: Sending filename `%s`", filename]; + engine.send(engine::load_url(filename)); + #debug["master: Waiting for keypress"]; key_ch.recv(); } } // Shut everything down #debug["master: Shut down"]; - content.send(content::exit); - layout.send(layout::layout::exit); - - listen {|wait_ch| - renderer.send(gfx::renderer::exit(wait_ch)); - wait_ch.recv(); + listen {|resp_ch| + engine.send(engine::exit(resp_ch)); + resp_ch.recv(); } osmain.send(platform::osmain::exit); } + +fn run_pipeline_png(url: str, outfile: str) { + + // Use a PNG encoder as the graphics sink + import gfx::pngsink; + import pngsink::pngsink; + + listen {|pngdata| + let sink = pngsink::pngsink(pngdata); + let engine = engine::engine(sink); + engine.send(engine::load_url(url)); + alt io::buffered_file_writer(outfile) { + result::ok(writer) { + import io::writer; + writer.write(pngdata.recv()) + } + result::err(e) { fail e } + } + listen {|resp_ch| + engine.send(engine::exit(resp_ch)); + resp_ch.recv(); + } + sink.send(pngsink::exit); + } +}