use super::*;
pub(crate) fn attach_canvas_context(
canvas: &HtmlCanvasElement,
) -> Result<CanvasRenderingContext2d, JsValue> {
let lookup: Result<Option<Object>, JsValue> = canvas.get_context(CANVAS_CONTEXT_ID_2D);
let context_object: Object = match lookup {
Ok(Some(object)) => object,
Ok(None) => {
return Err(backend_error(
ERROR_CANVAS_UNAVAILABLE,
ERROR_CANVAS_UNAVAILABLE.to_string(),
));
}
Err(reason) => return Err(backend_error(ERROR_CANVAS_UNAVAILABLE, describe(&reason))),
};
match context_object.dyn_into() {
Ok(context) => Ok(context),
Err(_) => Err(backend_error(
ERROR_CANVAS_UNAVAILABLE,
ERROR_CANVAS_UNAVAILABLE.to_string(),
)),
}
}
pub(crate) fn allocate_canvas_surface(
width: u32,
height: u32,
) -> Result<(ImageData, Uint8ClampedArray), JsValue> {
let expected: usize = match surface_rgba_length(width, height) {
Some(bytes) => bytes,
None => {
return Err(backend_error(
ERROR_DIMENSION_OVERFLOW,
format!("{width}x{height} overflows the addressable byte count"),
));
}
};
let length: u32 = match u32::try_from(expected) {
Ok(elements) => elements,
Err(_) => {
return Err(backend_error(
ERROR_DIMENSION_OVERFLOW,
format!("{width}x{height} needs {expected} bytes, over one typed array"),
));
}
};
let backing: Uint8ClampedArray = Uint8ClampedArray::new_with_length(length);
let image: ImageData =
match ImageData::new_with_js_u8_clamped_array_and_sh(&backing, width, height) {
Ok(value) => value,
Err(reason) => return Err(backend_error(ERROR_CANVAS_IMAGE_DATA, describe(&reason))),
};
Ok((image, backing))
}
pub(crate) fn surface_rgba_length(width: u32, height: u32) -> Option<usize> {
(width as usize)
.checked_mul(height as usize)?
.checked_mul(4)
}