mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
gfx: Clamp the font size we supply to Core Text to 0.01pt.
Core Text treats a font size of 0.0 as 12.0, which is obviously not what we want. Improves Twitter. Improves Reddit /r/rust. Closes #10492.
This commit is contained in:
parent
b214205ba9
commit
18fbf8cf30
6 changed files with 70 additions and 17 deletions
|
@ -38,7 +38,7 @@ fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFo
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
|
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
|
||||||
let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont();
|
let cgfont = template.ctfont(pt_size.to_f64_px()).as_ref().unwrap().copy_to_CGFont();
|
||||||
ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px())
|
ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl FontHandleMethods for FontHandle {
|
||||||
Some(s) => s.to_f64_px(),
|
Some(s) => s.to_f64_px(),
|
||||||
None => 0.0
|
None => 0.0
|
||||||
};
|
};
|
||||||
match template.ctfont() {
|
match template.ctfont(size) {
|
||||||
Some(ref ctfont) => {
|
Some(ref ctfont) => {
|
||||||
Ok(FontHandle {
|
Ok(FontHandle {
|
||||||
font_data: template.clone(),
|
font_data: template.clone(),
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
use core_graphics::data_provider::CGDataProvider;
|
use core_graphics::data_provider::CGDataProvider;
|
||||||
use core_graphics::font::CGFont;
|
use core_graphics::font::CGFont;
|
||||||
use core_text;
|
use core_text;
|
||||||
|
@ -9,6 +10,7 @@ use core_text::font::CTFont;
|
||||||
use serde::de::{Error, Visitor};
|
use serde::de::{Error, Visitor};
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -26,7 +28,7 @@ pub struct FontTemplateData {
|
||||||
/// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
|
/// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
|
||||||
/// `font_data` fields.
|
/// `font_data` fields.
|
||||||
///
|
///
|
||||||
/// When sending a `FontTemplateData` instance across processes, this will be set to `None` on
|
/// When sending a `FontTemplateData` instance across processes, this will be cleared out on
|
||||||
/// the other side, because `CTFont` instances cannot be sent across processes. This is
|
/// the other side, because `CTFont` instances cannot be sent across processes. This is
|
||||||
/// harmless, however, because it can always be recreated.
|
/// harmless, however, because it can always be recreated.
|
||||||
ctfont: CachedCTFont,
|
ctfont: CachedCTFont,
|
||||||
|
@ -41,29 +43,38 @@ unsafe impl Sync for FontTemplateData {}
|
||||||
impl FontTemplateData {
|
impl FontTemplateData {
|
||||||
pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> FontTemplateData {
|
pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> FontTemplateData {
|
||||||
FontTemplateData {
|
FontTemplateData {
|
||||||
ctfont: CachedCTFont(Mutex::new(None)),
|
ctfont: CachedCTFont(Mutex::new(HashMap::new())),
|
||||||
identifier: identifier.to_owned(),
|
identifier: identifier.to_owned(),
|
||||||
font_data: font_data
|
font_data: font_data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the Core Text font instance, instantiating it if necessary.
|
/// Retrieves the Core Text font instance, instantiating it if necessary.
|
||||||
pub fn ctfont(&self) -> Option<CTFont> {
|
pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
|
||||||
let mut ctfont = self.ctfont.lock().unwrap();
|
let mut ctfonts = self.ctfont.lock().unwrap();
|
||||||
if ctfont.is_none() {
|
let pt_size_key = Au::from_f64_px(pt_size);
|
||||||
*ctfont = match self.font_data {
|
if !ctfonts.contains_key(&pt_size_key) {
|
||||||
|
// If you pass a zero font size to one of the Core Text APIs, it'll replace it with
|
||||||
|
// 12.0. We don't want that! (Issue #10492.)
|
||||||
|
let clamped_pt_size = pt_size.max(0.01);
|
||||||
|
let ctfont = match self.font_data {
|
||||||
Some(ref bytes) => {
|
Some(ref bytes) => {
|
||||||
let fontprov = CGDataProvider::from_buffer(bytes);
|
let fontprov = CGDataProvider::from_buffer(bytes);
|
||||||
let cgfont_result = CGFont::from_data_provider(fontprov);
|
let cgfont_result = CGFont::from_data_provider(fontprov);
|
||||||
match cgfont_result {
|
match cgfont_result {
|
||||||
Ok(cgfont) => Some(core_text::font::new_from_CGFont(&cgfont, 0.0)),
|
Ok(cgfont) => {
|
||||||
|
Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
|
||||||
|
}
|
||||||
Err(_) => None
|
Err(_) => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => core_text::font::new_from_name(&*self.identifier, 0.0).ok(),
|
None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(),
|
||||||
|
};
|
||||||
|
if let Some(ctfont) = ctfont {
|
||||||
|
ctfonts.insert(pt_size_key, ctfont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctfont.as_ref().map(|ctfont| (*ctfont).clone())
|
ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a clone of the data in this font. This may be a hugely expensive
|
/// Returns a clone of the data in this font. This may be a hugely expensive
|
||||||
|
@ -75,7 +86,7 @@ impl FontTemplateData {
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = Url::parse(&*self.ctfont()
|
let path = Url::parse(&*self.ctfont(0.0)
|
||||||
.expect("No Core Text font available!")
|
.expect("No Core Text font available!")
|
||||||
.url()
|
.url()
|
||||||
.expect("No URL for Core Text font!")
|
.expect("No URL for Core Text font!")
|
||||||
|
@ -96,16 +107,16 @@ impl FontTemplateData {
|
||||||
|
|
||||||
/// Returns the native font that underlies this font template, if applicable.
|
/// Returns the native font that underlies this font template, if applicable.
|
||||||
pub fn native_font(&self) -> Option<CGFont> {
|
pub fn native_font(&self) -> Option<CGFont> {
|
||||||
self.ctfont().map(|ctfont| ctfont.copy_to_CGFont())
|
self.ctfont(0.0).map(|ctfont| ctfont.copy_to_CGFont())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CachedCTFont(Mutex<Option<CTFont>>);
|
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);
|
||||||
|
|
||||||
impl Deref for CachedCTFont {
|
impl Deref for CachedCTFont {
|
||||||
type Target = Mutex<Option<CTFont>>;
|
type Target = Mutex<HashMap<Au, CTFont>>;
|
||||||
fn deref(&self) -> &Mutex<Option<CTFont>> {
|
fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +137,7 @@ impl Deserialize for CachedCTFont {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_none<E>(&mut self) -> Result<CachedCTFont, E> where E: Error {
|
fn visit_none<E>(&mut self) -> Result<CachedCTFont, E> where E: Error {
|
||||||
Ok(CachedCTFont(Mutex::new(None)))
|
Ok(CachedCTFont(Mutex::new(HashMap::new())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2423,6 +2423,18 @@
|
||||||
"url": "/_mozilla/css/inline_element_border_a.html"
|
"url": "/_mozilla/css/inline_element_border_a.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/inline_font_size_zero_a.html": [
|
||||||
|
{
|
||||||
|
"path": "css/inline_font_size_zero_a.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/inline_font_size_zero_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/inline_font_size_zero_a.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/inline_hypothetical_box_a.html": [
|
"css/inline_hypothetical_box_a.html": [
|
||||||
{
|
{
|
||||||
"path": "css/inline_hypothetical_box_a.html",
|
"path": "css/inline_hypothetical_box_a.html",
|
||||||
|
@ -8923,6 +8935,18 @@
|
||||||
"url": "/_mozilla/css/inline_element_border_a.html"
|
"url": "/_mozilla/css/inline_element_border_a.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/inline_font_size_zero_a.html": [
|
||||||
|
{
|
||||||
|
"path": "css/inline_font_size_zero_a.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/inline_font_size_zero_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/inline_font_size_zero_a.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/inline_hypothetical_box_a.html": [
|
"css/inline_hypothetical_box_a.html": [
|
||||||
{
|
{
|
||||||
"path": "css/inline_hypothetical_box_a.html",
|
"path": "css/inline_hypothetical_box_a.html",
|
||||||
|
|
9
tests/wpt/mozilla/tests/css/inline_font_size_zero_a.html
Normal file
9
tests/wpt/mozilla/tests/css/inline_font_size_zero_a.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<link rel="match" href="inline_font_size_zero_ref.html">
|
||||||
|
<div style="width: 600px; font-size: 0;">
|
||||||
|
<div style="display: inline-block; width: 200px; background: blue; height: 50px;"></div>
|
||||||
|
<div style="display: inline-block; width: 400px; background: green; height: 50px;"></div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<div style="width: 600px;">
|
||||||
|
<div style="display: inline-block; width: 200px; background: blue; height: 50px;"></div><!--
|
||||||
|
--><div style="display: inline-block; width: 400px; background: green; height: 50px;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue