Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 59 additions & 21 deletions webrender/src/platform/macos/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions, GlyphOptions};
use webrender_traits::{ColorU, FontKey, FontRenderMode, GlyphDimensions};
use webrender_traits::{GlyphOptions, SubpixelOffset};

pub type NativeFontHandle = CGFont;

Expand Down Expand Up @@ -69,23 +70,47 @@ fn supports_subpixel_aa() -> bool {
data[0] != data[1] || data[1] != data[2]
}

fn get_glyph_metrics(ct_font: &CTFont, glyph: CGGlyph) -> GlyphMetrics {
fn get_glyph_metrics(ct_font: &CTFont,
glyph: CGGlyph,
x_subpixel: SubpixelOffset,
y_subpixel: SubpixelOffset) -> GlyphMetrics {
let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

let rasterized_left = bounds.origin.x.floor() as i32;
let rasterized_width =
(bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
let rasterized_descent = (-bounds.origin.y).ceil() as i32;
let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;

GlyphMetrics {
rasterized_ascent: rasterized_ascent,
rasterized_descent: rasterized_descent,
rasterized_left: rasterized_left,
rasterized_width: rasterized_width,
rasterized_height: rasterized_height,
}
let x_offset :f64 = SubpixelOffset::into(x_subpixel);
let y_offset :f64 = SubpixelOffset::into(y_subpixel);

// First round out to pixel boundaries
// CG Origin is bottom left
let mut left = bounds.origin.x.floor() as i32;
let mut bottom = bounds.origin.y.floor() as i32;
let mut right = (bounds.origin.x
+ bounds.size.width
+ x_offset).ceil() as i32;
let mut top = (bounds.origin.y
+ bounds.size.height
+ y_offset).ceil() as i32;

// Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
// Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
// is not currently known, as CG dilates the outlines by some percentage.
// This is taken from Skia.
left -= 1;
bottom -= 1;
right += 1;
top += 1;

let width = right - left;
let height = top - bottom;

let metrics = GlyphMetrics {
rasterized_left: left,
rasterized_width: width as u32,
rasterized_height: height as u32,
rasterized_ascent: top,
rasterized_descent: -bottom,
};

metrics
}

impl FontContext {
Expand Down Expand Up @@ -141,10 +166,12 @@ impl FontContext {
pub fn get_glyph_dimensions(&mut self,
font_key: FontKey,
size: Au,
character: u32) -> Option<GlyphDimensions> {
character: u32,
x_subpixel: SubpixelOffset,
y_subpixel: SubpixelOffset) -> Option<GlyphDimensions> {
self.get_ct_font(font_key, size).and_then(|ref ct_font| {
let glyph = character as CGGlyph;
let metrics = get_glyph_metrics(ct_font, glyph);
let metrics = get_glyph_metrics(ct_font, glyph, x_subpixel, y_subpixel);
if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
None
} else {
Expand All @@ -161,6 +188,7 @@ impl FontContext {
#[allow(dead_code)]
fn print_glyph_data(&mut self, data: &Vec<u8>, width: usize, height: usize) {
// Rust doesn't have step_by support on stable :(
println!("Width: {:?} height: {:?}", width, height);
for i in 0..height {
let current_height = i * width * 4;

Expand All @@ -181,11 +209,13 @@ impl FontContext {
color: ColorU,
character: u32,
render_mode: FontRenderMode,
x_suboffset: SubpixelOffset,
y_suboffset: SubpixelOffset,
glyph_options: Option<GlyphOptions>) -> Option<RasterizedGlyph> {
match self.get_ct_font(font_key, size) {
Some(ref ct_font) => {
let glyph = character as CGGlyph;
let metrics = get_glyph_metrics(ct_font, glyph);
let metrics = get_glyph_metrics(ct_font, glyph, x_suboffset, y_suboffset);
if metrics.rasterized_width == 0 || metrics.rasterized_height == 0 {
return Some(RasterizedGlyph::blank())
}
Expand Down Expand Up @@ -234,14 +264,22 @@ impl FontContext {
cg_context.set_allows_font_subpixel_positioning(true);
cg_context.set_should_subpixel_position_fonts(true);

// Don't quantize because we're doing it already.
cg_context.set_allows_font_subpixel_quantization(false);
cg_context.set_should_subpixel_quantize_fonts(false);

cg_context.set_allows_font_smoothing(smooth);
cg_context.set_should_smooth_fonts(smooth);
cg_context.set_allows_antialiasing(antialias);
cg_context.set_should_antialias(antialias);

let x_offset :f64 = SubpixelOffset::into(x_suboffset);
let y_offset :f64 = SubpixelOffset::into(y_suboffset);

// CG Origin is bottom left, WR is top left. Need -y offset
let rasterization_origin = CGPoint {
x: -metrics.rasterized_left as f64,
y: metrics.rasterized_descent as f64,
x: -metrics.rasterized_left as f64 + x_offset,
y: metrics.rasterized_descent as f64 - y_offset,
};

// Always draw black text on a white background
Expand Down
6 changes: 5 additions & 1 deletion webrender/src/platform/unix/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ impl FontContext {
pub fn get_glyph_dimensions(&self,
font_key: FontKey,
size: Au,
character: u32) -> Option<GlyphDimensions> {
character: u32,
x_subpixel: SubpixelOffset,
y_subpixel: SubpixelOffset) -> Option<GlyphDimensions> {
self.load_glyph(font_key, size, character).and_then(|slot| {
let metrics = unsafe { &(*slot).metrics };
if metrics.width == 0 || metrics.height == 0 {
Expand All @@ -136,6 +138,8 @@ impl FontContext {
color: ColorU,
character: u32,
render_mode: FontRenderMode,
x_suboffset: SubpixelOffset,
y_suboffset: SubpixelOffset,
glyph_options: Option<GlyphOptions>) -> Option<RasterizedGlyph> {
let mut glyph = None;

Expand Down
37 changes: 29 additions & 8 deletions webrender/src/prim_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use webrender_traits::{FontKey, FontRenderMode, WebGLContextId};
use webrender_traits::{device_length, DeviceIntRect, DeviceIntSize};
use webrender_traits::{DeviceRect, DevicePoint, DeviceSize};
use webrender_traits::{LayerRect, LayerSize, LayerPoint};
use webrender_traits::LayerToWorldTransform;
use webrender_traits::{GlyphOptions};
use webrender_traits::{LayerToWorldTransform, GlyphOptions};
use tiling::{AuxiliaryListsMap, StackingContext};

pub const CLIP_DATA_GPU_SIZE: usize = 5;
pub const MASK_DATA_GPU_SIZE: usize = 1;
Expand Down Expand Up @@ -292,6 +292,7 @@ pub struct TextRunPrimitiveCpu {
pub render_mode: FontRenderMode,
pub resource_address: GpuStoreAddress,
pub glyph_options: Option<GlyphOptions>,
pub stackingcontext_index: usize,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -718,7 +719,9 @@ impl PrimitiveStore {

pub fn resolve_primitives(&mut self,
resource_cache: &ResourceCache,
device_pixel_ratio: f32) -> Vec<DeferredResolve> {
device_pixel_ratio: f32,
layer_store: &Vec<StackingContext>,
auxiliary_lists_map: &AuxiliaryListsMap) -> Vec<DeferredResolve> {
let mut deferred_resolves = Vec::new();

for prim_index in self.prims_to_resolve.drain(..) {
Expand All @@ -735,14 +738,22 @@ impl PrimitiveStore {
PrimitiveKind::RadialGradient=> {}
PrimitiveKind::TextRun => {
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
let sc_index = text.stackingcontext_index;

let font_size_dp = text.logical_font_size.scale_by(device_pixel_ratio);

let dest_rects = self.gpu_resource_rects.get_slice_mut(text.resource_address,
text.glyph_range.length);

let layer = &layer_store[sc_index];
let auxiliary_lists = auxiliary_lists_map.get(&layer.pipeline_id)
.expect("No auxiliary lists?");
let src_glyphs = auxiliary_lists.glyph_instances(&text.glyph_range);

let texture_id = resource_cache.get_glyphs(text.font_key,
font_size_dp,
text.color,
&text.glyph_indices,
src_glyphs,
text.render_mode,
text.glyph_options, |index, uv0, uv1| {
let dest_rect = &mut dest_rects[index];
Expand Down Expand Up @@ -878,7 +889,8 @@ impl PrimitiveStore {
resource_cache: &mut ResourceCache,
layer_transform: &LayerToWorldTransform,
device_pixel_ratio: f32,
auxiliary_lists: &AuxiliaryLists) -> bool {
auxiliary_lists: &AuxiliaryLists,
stackingcontext_index: usize) -> bool {

let metadata = &mut self.cpu_metadata[prim_index.0];
let mut prim_needs_resolve = false;
Expand Down Expand Up @@ -918,7 +930,10 @@ impl PrimitiveStore {
}
PrimitiveKind::TextRun => {
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
text.stackingcontext_index = stackingcontext_index;

let font_size_dp = text.logical_font_size.scale_by(device_pixel_ratio);
let src_glyphs = auxiliary_lists.glyph_instances(&text.glyph_range);
prim_needs_resolve = true;

if text.cache_dirty {
Expand All @@ -927,18 +942,24 @@ impl PrimitiveStore {

debug_assert!(metadata.gpu_data_count == text.glyph_range.length as i32);
debug_assert!(text.glyph_indices.is_empty());
let src_glyphs = auxiliary_lists.glyph_instances(&text.glyph_range);

let dest_glyphs = self.gpu_data16.get_slice_mut(metadata.gpu_data_address,
text.glyph_range.length);
let mut glyph_key = GlyphKey::new(text.font_key,
font_size_dp,
text.color,
src_glyphs[0].index);
src_glyphs[0].index,
src_glyphs[0].x,
src_glyphs[0].y,
text.render_mode,
text.glyph_options);
let mut local_rect = LayerRect::zero();
let mut actual_glyph_count = 0;

for src in src_glyphs {
glyph_key.index = src.index;
glyph_key.set_x_offset(src.x);
glyph_key.set_y_offset(src.y);

let dimensions = match resource_cache.get_glyph_dimensions(&glyph_key) {
None => continue,
Expand Down Expand Up @@ -999,7 +1020,7 @@ impl PrimitiveStore {
resource_cache.request_glyphs(text.font_key,
font_size_dp,
text.color,
&text.glyph_indices,
src_glyphs,
text.render_mode,
text.glyph_options);
}
Expand Down
Loading