mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Decode HTML Image
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
This commit is contained in:
parent
781fda5b6d
commit
5daf5c55e3
3 changed files with 90 additions and 17 deletions
|
@ -41,7 +41,6 @@ use crate::resource_thread::CoreResourceThreadPool;
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg {
|
fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg {
|
||||||
// decode
|
|
||||||
let image = load_from_memory(bytes, cors);
|
let image = load_from_memory(bytes, cors);
|
||||||
DecoderMsg { key, image }
|
DecoderMsg { key, image }
|
||||||
}
|
}
|
||||||
|
@ -571,6 +570,25 @@ impl ImageCache for ImageCacheImpl {
|
||||||
cache_result
|
cache_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decode(
|
||||||
|
&self,
|
||||||
|
url: ServoUrl,
|
||||||
|
origin: ImmutableOrigin,
|
||||||
|
cors_setting: Option<CorsSettings>,
|
||||||
|
) -> Option<Image> {
|
||||||
|
let mut store: std::sync::MutexGuard<'_, ImageCacheStore> = self.store.lock().unwrap();
|
||||||
|
|
||||||
|
let result = store
|
||||||
|
.pending_loads
|
||||||
|
.get_cached(url.clone(), origin.clone(), cors_setting);
|
||||||
|
match result {
|
||||||
|
CacheResult::Hit(key, pl) => {
|
||||||
|
return decode_bytes_sync(key, &pl.bytes.as_slice(), pl.cors_status).image
|
||||||
|
},
|
||||||
|
CacheResult::Miss(_) => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a new listener for the given pending image id. If the image is already present,
|
/// Add a new listener for the given pending image id. If the image is already present,
|
||||||
/// the responder will still receive the expected response.
|
/// the responder will still receive the expected response.
|
||||||
fn add_listener(&self, id: PendingImageId, listener: ImageResponder) {
|
fn add_listener(&self, id: PendingImageId, listener: ImageResponder) {
|
||||||
|
|
|
@ -920,6 +920,53 @@ impl HTMLImageElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Step 2-2.2 of https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode
|
||||||
|
fn decode_image_data_sync(&self, promise: &Rc<Promise>) {
|
||||||
|
let document = document_from_node(self);
|
||||||
|
let window = document.window();
|
||||||
|
let elem = self.upcast::<Element>();
|
||||||
|
let src = elem.get_url_attribute(&local_name!("src"));
|
||||||
|
let base_url = document.base_url();
|
||||||
|
|
||||||
|
let image_cache = window.image_cache();
|
||||||
|
|
||||||
|
if let Ok(img_url) = base_url.join(&src) {
|
||||||
|
// Step 2.1
|
||||||
|
let available = match self.current_request.borrow().state {
|
||||||
|
State::Unavailable => false,
|
||||||
|
State::PartiallyAvailable => false,
|
||||||
|
State::CompletelyAvailable => true,
|
||||||
|
State::Broken => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 2.2
|
||||||
|
if document.is_fully_active() || !available {
|
||||||
|
let decode_result: Option<Image> = image_cache.decode(
|
||||||
|
img_url.clone(),
|
||||||
|
window.origin().immutable().clone(),
|
||||||
|
cors_setting_for_element(self.upcast()),
|
||||||
|
);
|
||||||
|
|
||||||
|
match decode_result {
|
||||||
|
Some(_) => {
|
||||||
|
promise.resolve_native(&());
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
promise.reject_native(&DOMException::new(
|
||||||
|
&self.global(),
|
||||||
|
DOMErrorName::EncodingError,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
promise.reject_native(&DOMException::new(
|
||||||
|
&self.global(),
|
||||||
|
DOMErrorName::EncodingError,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#update-the-image-data>
|
/// <https://html.spec.whatwg.org/multipage/#update-the-image-data>
|
||||||
pub fn update_the_image_data(&self) {
|
pub fn update_the_image_data(&self) {
|
||||||
let document = document_from_node(self);
|
let document = document_from_node(self);
|
||||||
|
@ -1349,6 +1396,11 @@ pub enum ImageElementMicrotask {
|
||||||
elem: DomRoot<HTMLImageElement>,
|
elem: DomRoot<HTMLImageElement>,
|
||||||
generation: u32,
|
generation: u32,
|
||||||
},
|
},
|
||||||
|
DecodeTask {
|
||||||
|
elem: DomRoot<HTMLImageElement>,
|
||||||
|
#[ignore_malloc_size_of = "promises are hard"]
|
||||||
|
promise: Rc<Promise>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MicrotaskRunnable for ImageElementMicrotask {
|
impl MicrotaskRunnable for ImageElementMicrotask {
|
||||||
|
@ -1370,13 +1422,20 @@ impl MicrotaskRunnable for ImageElementMicrotask {
|
||||||
} => {
|
} => {
|
||||||
elem.react_to_environment_changes_sync_steps(*generation);
|
elem.react_to_environment_changes_sync_steps(*generation);
|
||||||
},
|
},
|
||||||
|
&ImageElementMicrotask::DecodeTask {
|
||||||
|
ref elem,
|
||||||
|
ref promise,
|
||||||
|
} => {
|
||||||
|
elem.decode_image_data_sync(promise);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter_realm(&self) -> JSAutoRealm {
|
fn enter_realm(&self) -> JSAutoRealm {
|
||||||
match self {
|
match self {
|
||||||
&ImageElementMicrotask::StableStateUpdateImageDataTask { ref elem, .. } |
|
&ImageElementMicrotask::StableStateUpdateImageDataTask { ref elem, .. } |
|
||||||
&ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } => enter_realm(&**elem),
|
&ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } |
|
||||||
|
&ImageElementMicrotask::DecodeTask { ref elem, .. } => enter_realm(&**elem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1615,22 +1674,11 @@ impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
let promise = Promise::new(&self.global());
|
let promise = Promise::new(&self.global());
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
let document = document_from_node(self);
|
let task = ImageElementMicrotask::DecodeTask {
|
||||||
let ready = match self.current_request.borrow().state {
|
elem: DomRoot::from_ref(self),
|
||||||
State::Unavailable => false,
|
promise: promise.clone(),
|
||||||
State::PartiallyAvailable => false,
|
|
||||||
State::CompletelyAvailable => true,
|
|
||||||
State::Broken => false,
|
|
||||||
};
|
};
|
||||||
|
ScriptThread::await_stable_state(Microtask::ImageElement(task));
|
||||||
if document.is_fully_active() && ready && self.current_request.borrow().image.is_some() {
|
|
||||||
promise.reject_native(&DOMException::new(
|
|
||||||
&self.global(),
|
|
||||||
DOMErrorName::EncodingError,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
promise.resolve_native(&());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
promise
|
promise
|
||||||
|
|
|
@ -119,6 +119,13 @@ pub trait ImageCache: Sync + Send {
|
||||||
use_placeholder: UsePlaceholder,
|
use_placeholder: UsePlaceholder,
|
||||||
) -> ImageCacheResult;
|
) -> ImageCacheResult;
|
||||||
|
|
||||||
|
fn decode(
|
||||||
|
&self,
|
||||||
|
url: ServoUrl,
|
||||||
|
origin: ImmutableOrigin,
|
||||||
|
cors_setting: Option<CorsSettings>,
|
||||||
|
) -> Option<Image>;
|
||||||
|
|
||||||
/// Add a listener for the provided pending image id, eventually called by
|
/// Add a listener for the provided pending image id, eventually called by
|
||||||
/// ImageCacheStore::complete_load.
|
/// ImageCacheStore::complete_load.
|
||||||
/// If only metadata is available, Available(ImageOrMetadataAvailable) will
|
/// If only metadata is available, Available(ImageOrMetadataAvailable) will
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue