auto merge of #1288 : ryanhc/servo/transparent_png, r=larsbergstrom

Modified to use libpng to read .png files. We use stb_image to read all other image files.
This requires updated submodule: https://github.com/mozilla-servo/rust-png/pull/13

This patch is for:
https://github.com/mozilla/servo/issues/1279
This commit is contained in:
bors-servo 2013-11-20 05:31:12 -08:00
commit 052a543f14
6 changed files with 58 additions and 36 deletions

View file

@ -15,6 +15,7 @@ extern mod extra;
extern mod geom = "rust-geom"; extern mod geom = "rust-geom";
extern mod layers = "rust-layers"; extern mod layers = "rust-layers";
extern mod stb_image; extern mod stb_image;
extern mod png;
extern mod servo_net (name = "net"); extern mod servo_net (name = "net");
extern mod servo_util (name = "util"); extern mod servo_util (name = "util");
extern mod style; extern mod style;

View file

@ -17,6 +17,7 @@ use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use geom::side_offsets::SideOffsets2D; use geom::side_offsets::SideOffsets2D;
use servo_net::image::base::Image; use servo_net::image::base::Image;
use png::{RGBA8, K8, KA8};
use servo_util::geometry::Au; use servo_util::geometry::Au;
use std::vec; use std::vec;
use std::libc::types::common::c99::uint16_t; use std::libc::types::common::c99::uint16_t;
@ -103,11 +104,17 @@ impl<'self> RenderContext<'self> {
pub fn draw_image(&self, bounds: Rect<Au>, image: Arc<~Image>) { pub fn draw_image(&self, bounds: Rect<Au>, image: Arc<~Image>) {
let image = image.get(); let image = image.get();
let size = Size2D(image.width as i32, image.height as i32); let size = Size2D(image.width as i32, image.height as i32);
let stride = image.width * 4; let pixel_width = match image.color_type {
RGBA8 => 4,
K8 => 1,
KA8 => 2,
_ => fail!(~"color type not supported"),
};
let stride = image.width * pixel_width;
self.draw_target.make_current(); self.draw_target.make_current();
let draw_target_ref = &self.draw_target; let draw_target_ref = &self.draw_target;
let azure_surface = draw_target_ref.create_source_surface_from_data(image.data, size, let azure_surface = draw_target_ref.create_source_surface_from_data(image.pixels, size,
stride as i32, B8G8R8A8); stride as i32, B8G8R8A8);
let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat),
Size2D(image.width as AzFloat, image.height as AzFloat)); Size2D(image.width as AzFloat, image.height as AzFloat));

View file

@ -359,7 +359,7 @@ pub fn run_compositor(compositor: &CompositorTask) {
let img = png::Image { let img = png::Image {
width: width as u32, width: width as u32,
height: height as u32, height: height as u32,
color_type: png::RGB8, color_type: png::RGBA8,
pixels: pixels, pixels: pixels,
}; };
let res = png::store_png(&img, &path); let res = png::store_png(&img, &path);

View file

@ -4,14 +4,19 @@
use std::vec; use std::vec;
use stb_image = stb_image::image; use stb_image = stb_image::image;
use png;
// FIXME: Images must not be copied every frame. Instead we should atomically // FIXME: Images must not be copied every frame. Instead we should atomically
// reference count them. // reference count them.
pub type Image = png::Image;
pub type Image = stb_image::Image<u8>; pub fn Image(width: u32, height: u32, color_type: png::ColorType, data: ~[u8]) -> Image {
png::Image {
pub fn Image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image { width: width,
stb_image::new_image(width, height, depth, data) height: height,
color_type: color_type,
pixels: data,
}
} }
static TEST_IMAGE: &'static [u8] = include_bin!("test.jpeg"); static TEST_IMAGE: &'static [u8] = include_bin!("test.jpeg");
@ -21,30 +26,38 @@ pub fn test_image_bin() -> ~[u8] {
} }
pub fn load_from_memory(buffer: &[u8]) -> Option<Image> { pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
// Can't remember why we do this. Maybe it's what cairo wants if png::is_png(buffer) {
static FORCE_DEPTH: uint = 4; match png::load_png_from_memory(buffer) {
Ok(png_image) => Some(png_image),
match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) { Err(_err) => None,
stb_image::ImageU8(image) => { }
assert!(image.depth == 4); } else {
// Do color space conversion :( // For non-png images, we use stb_image
let data = do vec::from_fn(image.width * image.height * 4) |i| { // Can't remember why we do this. Maybe it's what cairo wants
let color = i % 4; static FORCE_DEPTH: uint = 4;
let pixel = i / 4;
match color { match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) {
0 => image.data[pixel * 4 + 2], stb_image::ImageU8(image) => {
1 => image.data[pixel * 4 + 1], assert!(image.depth == 4);
2 => image.data[pixel * 4 + 0], // Do color space conversion :(
3 => 0xffu8, let data = do vec::from_fn(image.width * image.height * 4) |i| {
_ => fail!() let color = i % 4;
} let pixel = i / 4;
}; match color {
0 => image.data[pixel * 4 + 2],
assert!(image.data.len() == data.len()); 1 => image.data[pixel * 4 + 1],
2 => image.data[pixel * 4 + 0],
Some(Image(image.width, image.height, image.depth, data)) 3 => 0xffu8,
_ => fail!()
}
};
assert!(image.data.len() == data.len());
Some(Image(image.width as u32, image.height as u32, png::RGBA8, data))
}
stb_image::ImageF32(_image) => fail!(~"HDR images not implemented"),
stb_image::Error => None
} }
stb_image::ImageF32(_image) => fail!(~"HDR images not implemented"),
stb_image::Error => None
} }
} }

View file

@ -15,6 +15,7 @@ extern mod http;
extern mod servo_util (name = "util"); extern mod servo_util (name = "util");
extern mod stb_image; extern mod stb_image;
extern mod extra; extern mod extra;
extern mod png;
/// Image handling. /// Image handling.
/// ///

@ -1 +1 @@
Subproject commit bd3b394e35dee36989e3c80abd9bcc1f99affa27 Subproject commit 519c291139813bf6cda192a45745013d543c99fe