mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +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
|
@ -72,7 +72,7 @@ impl FontHandleMethods for FontHandle {
|
|||
Some(s) => s.to_f64_px(),
|
||||
None => 0.0
|
||||
};
|
||||
match template.ctfont() {
|
||||
match template.ctfont(size) {
|
||||
Some(ref ctfont) => {
|
||||
Ok(FontHandle {
|
||||
font_data: template.clone(),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
use app_units::Au;
|
||||
use core_graphics::data_provider::CGDataProvider;
|
||||
use core_graphics::font::CGFont;
|
||||
use core_text;
|
||||
|
@ -9,6 +10,7 @@ use core_text::font::CTFont;
|
|||
use serde::de::{Error, Visitor};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
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
|
||||
/// `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
|
||||
/// harmless, however, because it can always be recreated.
|
||||
ctfont: CachedCTFont,
|
||||
|
@ -41,29 +43,38 @@ unsafe impl Sync for FontTemplateData {}
|
|||
impl FontTemplateData {
|
||||
pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> FontTemplateData {
|
||||
FontTemplateData {
|
||||
ctfont: CachedCTFont(Mutex::new(None)),
|
||||
ctfont: CachedCTFont(Mutex::new(HashMap::new())),
|
||||
identifier: identifier.to_owned(),
|
||||
font_data: font_data
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the Core Text font instance, instantiating it if necessary.
|
||||
pub fn ctfont(&self) -> Option<CTFont> {
|
||||
let mut ctfont = self.ctfont.lock().unwrap();
|
||||
if ctfont.is_none() {
|
||||
*ctfont = match self.font_data {
|
||||
pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
|
||||
let mut ctfonts = self.ctfont.lock().unwrap();
|
||||
let pt_size_key = Au::from_f64_px(pt_size);
|
||||
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) => {
|
||||
let fontprov = CGDataProvider::from_buffer(bytes);
|
||||
let cgfont_result = CGFont::from_data_provider(fontprov);
|
||||
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
|
||||
}
|
||||
}
|
||||
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
|
||||
|
@ -75,7 +86,7 @@ impl FontTemplateData {
|
|||
None => {}
|
||||
}
|
||||
|
||||
let path = Url::parse(&*self.ctfont()
|
||||
let path = Url::parse(&*self.ctfont(0.0)
|
||||
.expect("No Core Text font available!")
|
||||
.url()
|
||||
.expect("No URL for Core Text font!")
|
||||
|
@ -96,16 +107,16 @@ impl FontTemplateData {
|
|||
|
||||
/// Returns the native font that underlies this font template, if applicable.
|
||||
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)]
|
||||
pub struct CachedCTFont(Mutex<Option<CTFont>>);
|
||||
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);
|
||||
|
||||
impl Deref for CachedCTFont {
|
||||
type Target = Mutex<Option<CTFont>>;
|
||||
fn deref(&self) -> &Mutex<Option<CTFont>> {
|
||||
type Target = Mutex<HashMap<Au, CTFont>>;
|
||||
fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +137,7 @@ impl Deserialize for CachedCTFont {
|
|||
|
||||
#[inline]
|
||||
fn visit_none<E>(&mut self) -> Result<CachedCTFont, E> where E: Error {
|
||||
Ok(CachedCTFont(Mutex::new(None)))
|
||||
Ok(CachedCTFont(Mutex::new(HashMap::new())))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue