Honor print media in PDF export
This commit is contained in:
1 parent
c1dbec078b
commit
703d334df7
12 files changed
+856
-181
No files matched your search
@@ -16,6 +16,6 @@ pub use obscura_render::{
|
||||
screenshot_png, screenshot_png_scrolled, screenshot_png_scrolled_at_animation_time,
|
||||
screenshot_png_scrolled_at_animation_time_with_surface_color,
|
||||
validate_capture_region, AnimationSample, AnimationSampleMode, AnimationSampleTime,
|
||||
CaptureError, CaptureRegion, ImageRequestProfile,
|
||||
CaptureError, CaptureRegion, CssMediaType, ImageRequestProfile,
|
||||
MAX_CAPTURE_DIMENSION, MAX_CAPTURE_PIXELS,
|
||||
};
|
||||
@@ -141,6 +141,11 @@ pub struct ObscuraState {
|
||||
/// DOM/style/viewport changes clear this value but retain resource bytes.
|
||||
#[cfg(feature = "render")]
|
||||
pub prepared_render: Option<obscura_render::PreparedRender>,
|
||||
/// CSS media type selected for the next retained layout. Live pages use
|
||||
/// screen; PDF export switches to print for one synchronous capture and
|
||||
/// restores screen before returning.
|
||||
#[cfg(feature = "render")]
|
||||
pub render_media: obscura_render::CssMediaType,
|
||||
/// Explicit document-timeline sample used by the next style/layout flush.
|
||||
/// Captures set this to either deterministic T=0 or live document time.
|
||||
#[cfg(feature = "render")]
|
||||
@@ -235,6 +240,8 @@ impl ObscuraState {
|
||||
#[cfg(feature = "render")]
|
||||
prepared_render: None,
|
||||
#[cfg(feature = "render")]
|
||||
render_media: obscura_render::CssMediaType::Screen,
|
||||
#[cfg(feature = "render")]
|
||||
animation_sample: obscura_render::AnimationSample::default(),
|
||||
#[cfg(feature = "render")]
|
||||
animation_timeline: obscura_render::AnimationTimelineState::default(),
|
||||
@@ -3426,6 +3433,7 @@ pub(crate) fn ensure_prepared_render(
|
||||
) -> Option<&obscura_render::PreparedRender> {
|
||||
let base_url = document_base_url(state);
|
||||
let viewport = state.viewport;
|
||||
let render_media = state.render_media;
|
||||
let animation_sample = state.animation_sample;
|
||||
let incompatible = state.prepared_render.as_ref().is_some_and(|prepared| {
|
||||
prepared.viewport() != viewport
|
||||
@@ -3440,7 +3448,7 @@ pub(crate) fn ensure_prepared_render(
|
||||
.animation_timeline
|
||||
.materialize_start_candidates(dom);
|
||||
}
|
||||
let previous = (!incompatible)
|
||||
let previous = (!incompatible && render_media == obscura_render::CssMediaType::Screen)
|
||||
.then(|| state.prepared_render.take())
|
||||
.flatten();
|
||||
let mutations = std::mem::take(&mut state.pending_style_mutations);
|
||||
@@ -3471,16 +3479,29 @@ pub(crate) fn ensure_prepared_render(
|
||||
&mut state.animation_timeline,
|
||||
)
|
||||
})?,
|
||||
None => obscura_render::prepare_dom_with_dynamic_fonts_and_stylesheet_cache_with_animation_state(
|
||||
dom,
|
||||
viewport,
|
||||
base_url.as_deref(),
|
||||
&mut state.render_resources,
|
||||
&state.dynamic_fonts,
|
||||
&mut state.stylesheet_cache,
|
||||
animation_sample,
|
||||
&mut state.animation_timeline,
|
||||
)?,
|
||||
None => match render_media {
|
||||
obscura_render::CssMediaType::Screen => obscura_render::prepare_dom_with_dynamic_fonts_and_stylesheet_cache_with_animation_state(
|
||||
dom,
|
||||
viewport,
|
||||
base_url.as_deref(),
|
||||
&mut state.render_resources,
|
||||
&state.dynamic_fonts,
|
||||
&mut state.stylesheet_cache,
|
||||
animation_sample,
|
||||
&mut state.animation_timeline,
|
||||
)?,
|
||||
obscura_render::CssMediaType::Print => obscura_render::prepare_dom_with_dynamic_fonts_and_stylesheet_cache_for_media_with_animation_state(
|
||||
dom,
|
||||
viewport,
|
||||
base_url.as_deref(),
|
||||
&mut state.render_resources,
|
||||
&state.dynamic_fonts,
|
||||
&mut state.stylesheet_cache,
|
||||
render_media,
|
||||
animation_sample,
|
||||
&mut state.animation_timeline,
|
||||
)?,
|
||||
},
|
||||
}
|
||||
};
|
||||
if animation_sample.mode == obscura_render::AnimationSampleMode::DocumentTime {
|
||||
|
||||
@@ -493,6 +493,24 @@ impl ObscuraJsRuntime {
|
||||
true
|
||||
}
|
||||
|
||||
/// Select the CSS media type for the next synchronous render flush.
|
||||
/// Changing media invalidates geometry and the compiled stylesheet key but
|
||||
/// leaves the live DOM, scroll offsets, and resource bytes untouched.
|
||||
#[cfg(feature = "render")]
|
||||
pub fn set_render_media(
|
||||
&self,
|
||||
media: obscura_render::CssMediaType,
|
||||
) -> obscura_render::CssMediaType {
|
||||
let mut state = self.state.borrow_mut();
|
||||
let previous = state.render_media;
|
||||
if previous != media {
|
||||
state.render_media = media;
|
||||
state.prepared_render = None;
|
||||
state.resolved_scroll = None;
|
||||
}
|
||||
previous
|
||||
}
|
||||
|
||||
#[cfg(feature = "render")]
|
||||
pub fn animation_sample_time(&self) -> obscura_render::AnimationSampleTime {
|
||||
self.state.borrow().animation_sample.time
|
||||
|
||||
Reference in new issue
Block a user