diff --git a/demo3/shaders/post.fs.glsl b/demo3/shaders/post.fs.glsl index 4eaf5c57..2d383914 100644 --- a/demo3/shaders/post.fs.glsl +++ b/demo3/shaders/post.fs.glsl @@ -63,15 +63,13 @@ float convolve7Tap(vec4 alpha0, vec3 alpha1) { void main() { // Apply defringing if necessary. - vec3 fgColor; - if (uKernel.w == 0.0) { - fgColor = texture(uSource, vTexCoord).rgb; - } else { + vec4 fgColor = texture(uSource, vTexCoord); + if (uKernel.w != 0.0) { vec4 alphaLeft, alphaRight; float alphaCenter; sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uFramebufferSize.x); - fgColor = + fgColor.rgb = vec3(convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy)), convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz), convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw)); @@ -79,8 +77,8 @@ void main() { // Apply gamma correction if necessary. if (uGammaCorrectionBGColor.a > 0.0) - fgColor = gammaCorrect(fgColor); + fgColor.rgb = gammaCorrect(fgColor.rgb); // Finish. - oFragColor = vec4(fgColor, 1.0); + oFragColor = fgColor; } diff --git a/demo3/src/main.rs b/demo3/src/main.rs index 0a6f1b63..deeca445 100644 --- a/demo3/src/main.rs +++ b/demo3/src/main.rs @@ -22,7 +22,7 @@ use pathfinder_gl::renderer::Renderer; use pathfinder_renderer::builder::{RenderOptions, RenderTransform, SceneBuilder}; use pathfinder_renderer::gpu_data::BuiltScene; use pathfinder_renderer::paint::ColorU; -use pathfinder_renderer::post::DEFRINGING_KERNEL_CORE_GRAPHICS; +use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS}; use pathfinder_renderer::scene::Scene; use pathfinder_renderer::z_buffer::ZBuffer; use pathfinder_svg::SceneExt; @@ -56,6 +56,8 @@ const EFFECTS_WINDOW_HEIGHT: i32 = BUTTON_HEIGHT * 3 + PADDING * 4; const SWITCH_SIZE: i32 = SWITCH_HALF_SIZE * 2 + 1; const SWITCH_HALF_SIZE: i32 = 96; +const APPROX_FONT_SIZE: f32 = 16.0; + static EFFECTS_PNG_NAME: &'static str = "demo-effects"; static OPEN_PNG_NAME: &'static str = "demo-open"; @@ -132,7 +134,12 @@ fn main() { let count = if frame_counter == 0 { 2 } else { 1 }; for _ in 0..count { scene_thread_proxy.sender.send(MainToSceneMsg::Build(BuildOptions { - perspective + perspective, + stem_darkening_font_size: if demo_ui.stem_darkening_effect_enabled { + Some(APPROX_FONT_SIZE * scale_factor as f32) + } else { + None + }, })).unwrap(); } @@ -208,6 +215,7 @@ fn main() { tile_time } = scene_thread_proxy.receiver.recv().unwrap(); unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::ClearColor(BACKGROUND_COLOR.r as f32 / 255.0, BACKGROUND_COLOR.g as f32 / 255.0, BACKGROUND_COLOR.b as f32 / 255.0, @@ -306,6 +314,7 @@ enum MainToSceneMsg { struct BuildOptions { perspective: Option, + stem_darkening_font_size: Option, } enum SceneToMainMsg { @@ -376,7 +385,13 @@ fn build_scene(scene: &Scene, build_options: BuildOptions, jobs: Option) None => RenderTransform::Transform2D(Transform2DF32::default()), Some(perspective) => RenderTransform::Perspective(perspective), }, - dilation: Point2DF32::default(), + dilation: match build_options.stem_darkening_font_size { + None => Point2DF32::default(), + Some(font_size) => { + let (x, y) = (STEM_DARKENING_FACTORS[0], STEM_DARKENING_FACTORS[1]); + Point2DF32::new(x, y).scale(font_size) + } + }, }; let built_objects = panic::catch_unwind(|| { diff --git a/gl/src/device.rs b/gl/src/device.rs index bc6eda9c..67f9311c 100644 --- a/gl/src/device.rs +++ b/gl/src/device.rs @@ -86,6 +86,12 @@ impl Framebuffer { } Framebuffer { gl_framebuffer, texture } } + + pub fn bind(&self) { + unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, self.gl_framebuffer); + } + } } impl Drop for Framebuffer { diff --git a/gl/src/renderer.rs b/gl/src/renderer.rs index e8cca8f5..feb514d0 100644 --- a/gl/src/renderer.rs +++ b/gl/src/renderer.rs @@ -18,7 +18,6 @@ use pathfinder_renderer::paint::{ColorU, ObjectShader}; use pathfinder_renderer::post::DefringingKernel; use pathfinder_renderer::tiles::{TILE_HEIGHT, TILE_WIDTH}; use std::collections::VecDeque; -use std::ptr; use std::time::Duration; static QUAD_VERTEX_POSITIONS: [u8; 8] = [0, 0, 1, 0, 1, 1, 0, 1]; @@ -216,7 +215,7 @@ impl Renderer { fn draw_batch_fills(&mut self, batch: &Batch) { unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, self.mask_framebuffer.gl_framebuffer); + self.mask_framebuffer.bind(); gl::Viewport(0, 0, MASK_FRAMEBUFFER_WIDTH as GLint, MASK_FRAMEBUFFER_HEIGHT as GLint); // TODO(pcwalton): Only clear the appropriate portion? gl::ClearColor(0.0, 0.0, 0.0, 0.0); @@ -265,9 +264,7 @@ impl Renderer { FILL_COLORS_TEXTURE_HEIGHT as GLfloat); // FIXME(pcwalton): Fill this in properly! gl::Uniform2f(self.mask_tile_program.view_box_origin_uniform.location, 0.0, 0.0); - gl::BlendEquation(gl::FUNC_ADD); - gl::BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA, gl::ONE, gl::ONE); - gl::Enable(gl::BLEND); + self.enable_blending(); gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, batch.mask_tiles.len() as GLint); gl::Disable(gl::BLEND); } @@ -340,8 +337,9 @@ impl Renderer { color.a as f32 / 255.0); } } - gl::Disable(gl::BLEND); + self.enable_blending(); gl::DrawArrays(gl::TRIANGLE_FAN, 0, 4); + gl::Disable(gl::BLEND); } } @@ -371,20 +369,34 @@ impl Renderer { return; } - if let Some(ref existing_framebuffer) = self.postprocess_source_framebuffer { - if existing_framebuffer.texture.size == self.main_framebuffer_size { - return; + match self.postprocess_source_framebuffer { + Some(ref existing_framebuffer) if + existing_framebuffer.texture.size == self.main_framebuffer_size => {} + _ => { + self.postprocess_source_framebuffer = + Some(Framebuffer::new(Texture::new_rgba(&self.main_framebuffer_size))); } - } + }; - self.postprocess_source_framebuffer = - Some(Framebuffer::new(Texture::new_rgba(&self.main_framebuffer_size))); + unsafe { + self.postprocess_source_framebuffer.as_ref().unwrap().bind(); + gl::ClearColor(0.0, 0.0, 0.0, 0.0); + gl::Clear(gl::COLOR_BUFFER_BIT); + } } fn postprocessing_needed(&self) -> bool { self.postprocess_options.defringing_kernel.is_some() || self.postprocess_options.gamma_correction_bg_color.is_some() } + + fn enable_blending(&self) { + unsafe { + gl::BlendEquation(gl::FUNC_ADD); + gl::BlendFuncSeparate(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA, gl::ONE, gl::ONE); + gl::Enable(gl::BLEND); + } + } } #[derive(Clone, Copy, Default)] diff --git a/renderer/src/post.rs b/renderer/src/post.rs index ec1af3e4..d70e721c 100644 --- a/renderer/src/post.rs +++ b/renderer/src/post.rs @@ -25,3 +25,11 @@ pub static DEFRINGING_KERNEL_FREETYPE: DefringingKernel = DefringingKernel([ 0.0, 0.031372549, 0.301960784, 0.337254902 ]); +/// Should match macOS 10.13 High Sierra. +pub static STEM_DARKENING_FACTORS: [f32; 2] = [0.0121, 0.0121 * 1.25]; + +/// Should match macOS 10.13 High Sierra. +pub const MAX_STEM_DARKENING_AMOUNT: [f32; 2] = [0.3, 0.3]; + +/// This value is a subjective cutoff. Above this ppem value, no stem darkening is performed. +pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;