mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Use the high-level, safe Azure API in the PNG sink instead of the low-level, unsafe one
This commit is contained in:
parent
1533972c63
commit
350b26c1d4
1 changed files with 25 additions and 68 deletions
|
@ -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)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue