Use the high-level, safe Azure API in the PNG sink instead of the low-level, unsafe one

This commit is contained in:
Patrick Walton 2012-08-09 17:33:48 -07:00
parent 1533972c63
commit 350b26c1d4

View file

@ -12,14 +12,15 @@ import azure::AzDrawTargetRef;
import azure_bg = azure::bindgen; import azure_bg = azure::bindgen;
import azure_bg::{AzCreateDrawTargetForCairoSurface, AzReleaseDrawTarget}; import azure_bg::{AzCreateDrawTargetForCairoSurface, AzReleaseDrawTarget};
import azure::cairo; import azure::cairo;
import cairo::{CAIRO_FORMAT_ARGB32, cairo_surface_t, cairo_status_t, import azure::azure_hl::DrawTarget;
CAIRO_STATUS_SUCCESS}; import azure::cairo_hl::ImageSurface;
import cairo::{CAIRO_FORMAT_ARGB32, cairo_surface_t, cairo_status_t, CAIRO_STATUS_SUCCESS};
import cairo_bg = cairo::bindgen; import cairo_bg = cairo::bindgen;
import cairo_bg::{cairo_image_surface_create, cairo_surface_destroy, import cairo_bg::{cairo_image_surface_create, cairo_surface_destroy,
cairo_surface_write_to_png_stream}; cairo_surface_write_to_png_stream};
import renderer::{Renderer, Sink, RenderMsg}; import renderer::{Renderer, Sink, RenderMsg};
import task::spawn_listener; import task::spawn_listener;
import comm::chan; import comm::{chan, port};
import unsafe::reinterpret_cast; import unsafe::reinterpret_cast;
import vec_from_buf = vec::unsafe::from_buf; import vec_from_buf = vec::unsafe::from_buf;
import ptr::addr_of; import ptr::addr_of;
@ -48,84 +49,40 @@ impl chan<Msg> : Sink {
} }
fn PngSink(output: chan<~[u8]>) -> PngSink { fn PngSink(output: chan<~[u8]>) -> PngSink {
spawn_listener::<Msg>(|po| { do spawn_listener |po: port<Msg>| {
let cairo_surf = cairo_image_surface_create( let cairo_surface = ImageSurface(CAIRO_FORMAT_ARGB32, 800, 600);
CAIRO_FORMAT_ARGB32, 800 as c_int, 600 as c_int let draw_target = DrawTarget(cairo_surface);
);
assert cairo_surf.is_not_null();
let draw_target = AzCreateDrawTargetForCairoSurface(cairo_surf);
assert draw_target.is_not_null();
loop { loop {
match po.recv() { match po.recv() {
BeginDrawing(sender) => { BeginDrawing(sender) => {
#debug("pngsink: begin_drawing"); debug!("pngsink: begin_drawing");
sender.send(draw_target); sender.send(draw_target.azure_draw_target);
} }
Draw(sender, dt) => { Draw(sender, dt) => {
#debug("pngsink: draw"); debug!("pngsink: draw");
do_draw(sender, dt, output, cairo_surf); do_draw(sender, dt, output, cairo_surface);
} }
Exit => { break } Exit => break
} }
} }
}
AzReleaseDrawTarget(draw_target);
cairo_surface_destroy(cairo_surf);
})
} }
fn do_draw(sender: pipes::chan<AzDrawTargetRef>, fn do_draw(sender: pipes::chan<AzDrawTargetRef>, dt: AzDrawTargetRef, output: chan<~[u8]>,
dt: AzDrawTargetRef, cairo_surface: ImageSurface) {
output: chan<~[u8]>, let buffer = io::mem_buffer();
cairo_surf: *cairo_surface_t) { cairo_surface.write_to_png_stream(&buffer);
let @{ buf: buffer, pos: _ } <- buffer;
output.send(vec::from_mut(dvec::unwrap(move buffer)));
listen(|data_ch: chan<~[u8]>| {
extern fn write_fn(closure: *c_void,
data: *c_uchar,
len: c_uint)
-> cairo_status_t unsafe {
let p: *chan<~[u8]> = reinterpret_cast(closure);
let data_ch = *p;
// Convert from *c_uchar to *u8
let data = reinterpret_cast(data);
let len = len as uint;
// Copy to a vector
let data = vec_from_buf(data, len);
data_ch.send(data);
return CAIRO_STATUS_SUCCESS;
}
let closure = addr_of(data_ch);
unsafe {
cairo_surface_write_to_png_stream(
cairo_surf, write_fn, reinterpret_cast(closure));
}
// Collect the entire image into a single vector
let mut result = ~[];
while data_ch.peek() {
result += data_ch.recv();
}
// Send the PNG image away
output.send(result);
});
// Send the next draw target to the renderer // Send the next draw target to the renderer
sender.send(dt); sender.send(dt);
} }
#[test] #[test]
fn sanity_check() { fn sanity_check() {
listen(|self_channel| { do listen |self_channel| {
let sink = PngSink(self_channel); let sink = PngSink(self_channel);
let renderer = Renderer(sink); let renderer = Renderer(sink);
@ -136,5 +93,5 @@ fn sanity_check() {
exit_response_from_engine.recv(); exit_response_from_engine.recv();
sink.send(Exit) sink.send(Exit)
}) }
} }