зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #4524 - gfx: Implement `font-stretch` per CSS3-FONTS § 3.3 in the Core Text font backend (from pcwalton:font-stretch); r=glennw
r? @glennw Source-Repo: https://github.com/servo/servo Source-Revision: 3736396c63ad3f84349132ea9c0bb0f5fc045f01
This commit is contained in:
Родитель
39a22519e3
Коммит
c36f083a85
|
@ -10,7 +10,7 @@ use std::rc::Rc;
|
|||
use std::cell::RefCell;
|
||||
use servo_util::cache::HashCache;
|
||||
use servo_util::smallvec::{SmallVec, SmallVec8};
|
||||
use style::computed_values::{font_variant, font_weight};
|
||||
use style::computed_values::{font_stretch, font_variant, font_weight};
|
||||
use style::style_structs::Font as FontStyle;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -37,6 +37,7 @@ pub trait FontHandleMethods {
|
|||
fn face_name(&self) -> String;
|
||||
fn is_italic(&self) -> bool;
|
||||
fn boldness(&self) -> font_weight::T;
|
||||
fn stretchiness(&self) -> font_stretch::T;
|
||||
|
||||
fn glyph_index(&self, codepoint: char) -> Option<GlyphId>;
|
||||
fn glyph_h_advance(&self, GlyphId) -> Option<FractionalPixel>;
|
||||
|
|
|
@ -140,7 +140,9 @@ impl FontContext {
|
|||
// so they will never be released. Find out a good time to drop them.
|
||||
|
||||
let desc = FontTemplateDescriptor::new(style.font_weight,
|
||||
style.font_style == font_style::T::italic || style.font_style == font_style::T::oblique);
|
||||
style.font_stretch,
|
||||
style.font_style == font_style::T::italic ||
|
||||
style.font_style == font_style::T::oblique);
|
||||
let mut fonts = SmallVec8::new();
|
||||
|
||||
for family in style.font_family.iter() {
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
* 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 style::computed_values::font_weight;
|
||||
use font::FontHandleMethods;
|
||||
use platform::font_context::FontContextHandle;
|
||||
use platform::font::FontHandle;
|
||||
use platform::font_template::FontTemplateData;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
use std::sync::{Arc, Weak};
|
||||
use font::FontHandleMethods;
|
||||
use style::computed_values::{font_stretch, font_weight};
|
||||
|
||||
/// Describes how to select a font from a given family.
|
||||
/// This is very basic at the moment and needs to be
|
||||
|
@ -18,13 +18,17 @@ use font::FontHandleMethods;
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct FontTemplateDescriptor {
|
||||
pub weight: font_weight::T,
|
||||
pub stretch: font_stretch::T,
|
||||
pub italic: bool,
|
||||
}
|
||||
|
||||
impl FontTemplateDescriptor {
|
||||
pub fn new(weight: font_weight::T, italic: bool) -> FontTemplateDescriptor {
|
||||
#[inline]
|
||||
pub fn new(weight: font_weight::T, stretch: font_stretch::T, italic: bool)
|
||||
-> FontTemplateDescriptor {
|
||||
FontTemplateDescriptor {
|
||||
weight: weight,
|
||||
stretch: stretch,
|
||||
italic: italic,
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +37,8 @@ impl FontTemplateDescriptor {
|
|||
impl PartialEq for FontTemplateDescriptor {
|
||||
fn eq(&self, other: &FontTemplateDescriptor) -> bool {
|
||||
self.weight.is_bold() == other.weight.is_bold() &&
|
||||
self.italic == other.italic
|
||||
self.stretch == other.stretch &&
|
||||
self.italic == other.italic
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +49,8 @@ pub struct FontTemplate {
|
|||
identifier: String,
|
||||
descriptor: Option<FontTemplateDescriptor>,
|
||||
weak_ref: Option<Weak<FontTemplateData>>,
|
||||
strong_ref: Option<Arc<FontTemplateData>>, // GWTODO: Add code path to unset the strong_ref for web fonts!
|
||||
// GWTODO: Add code path to unset the strong_ref for web fonts!
|
||||
strong_ref: Option<Arc<FontTemplateData>>,
|
||||
is_valid: bool,
|
||||
}
|
||||
|
||||
|
@ -82,8 +88,10 @@ impl FontTemplate {
|
|||
}
|
||||
|
||||
/// Get the data for creating a font if it matches a given descriptor.
|
||||
pub fn get_if_matches(&mut self, fctx: &FontContextHandle,
|
||||
requested_desc: &FontTemplateDescriptor) -> Option<Arc<FontTemplateData>> {
|
||||
pub fn get_if_matches(&mut self,
|
||||
fctx: &FontContextHandle,
|
||||
requested_desc: &FontTemplateDescriptor)
|
||||
-> Option<Arc<FontTemplateData>> {
|
||||
// The font template data can be unloaded when nothing is referencing
|
||||
// it (via the Weak reference to the Arc above). However, if we have
|
||||
// already loaded a font, store the style information about it separately,
|
||||
|
@ -97,42 +105,42 @@ impl FontTemplate {
|
|||
None
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if self.is_valid {
|
||||
let data = self.get_data();
|
||||
let handle: Result<FontHandle, ()> = FontHandleMethods::new_from_template(fctx, data.clone(), None);
|
||||
match handle {
|
||||
Ok(handle) => {
|
||||
let actual_desc = FontTemplateDescriptor::new(handle.boldness(),
|
||||
handle.is_italic());
|
||||
let desc_match = actual_desc == *requested_desc;
|
||||
None if self.is_valid => {
|
||||
let data = self.get_data();
|
||||
let handle: Result<FontHandle, ()> =
|
||||
FontHandleMethods::new_from_template(fctx, data.clone(), None);
|
||||
match handle {
|
||||
Ok(handle) => {
|
||||
let actual_desc = FontTemplateDescriptor::new(handle.boldness(),
|
||||
handle.stretchiness(),
|
||||
handle.is_italic());
|
||||
let desc_match = actual_desc == *requested_desc;
|
||||
|
||||
self.descriptor = Some(actual_desc);
|
||||
self.is_valid = true;
|
||||
if desc_match {
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(()) => {
|
||||
self.is_valid = false;
|
||||
debug!("Unable to create a font from template {}", self.identifier);
|
||||
self.descriptor = Some(actual_desc);
|
||||
self.is_valid = true;
|
||||
if desc_match {
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Err(()) => {
|
||||
self.is_valid = false;
|
||||
debug!("Unable to create a font from template {}", self.identifier);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the data for creating a font.
|
||||
pub fn get(&mut self) -> Option<Arc<FontTemplateData>> {
|
||||
match self.is_valid {
|
||||
true => Some(self.get_data()),
|
||||
false => None
|
||||
if self.is_valid {
|
||||
Some(self.get_data())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,14 +153,13 @@ impl FontTemplate {
|
|||
None => None,
|
||||
};
|
||||
|
||||
match maybe_data {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
assert!(self.strong_ref.is_none());
|
||||
let template_data = Arc::new(FontTemplateData::new(self.identifier.as_slice(), None));
|
||||
self.weak_ref = Some(template_data.downgrade());
|
||||
template_data
|
||||
}
|
||||
if let Some(data) = maybe_data {
|
||||
return data
|
||||
}
|
||||
|
||||
assert!(self.strong_ref.is_none());
|
||||
let template_data = Arc::new(FontTemplateData::new(self.identifier.as_slice(), None));
|
||||
self.weak_ref = Some(template_data.downgrade());
|
||||
template_data
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use servo_util::str::c_str_to_string;
|
|||
use platform::font_context::FontContextHandle;
|
||||
use text::glyph::GlyphId;
|
||||
use text::util::{float_to_fixed, fixed_to_float};
|
||||
use style::computed_values::font_weight;
|
||||
use style::computed_values::{font_stretch, font_weight};
|
||||
use platform::font_template::FontTemplateData;
|
||||
|
||||
use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name};
|
||||
|
@ -161,6 +161,10 @@ impl FontHandleMethods for FontHandle {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn stretchiness(&self) -> font_stretch::T {
|
||||
// TODO(pcwalton): Implement this.
|
||||
font_stretch::T::normal
|
||||
}
|
||||
|
||||
fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
|
||||
assert!(!self.face.is_null());
|
||||
|
|
|
@ -15,7 +15,7 @@ use servo_util::geometry::{Au, px_to_pt};
|
|||
use servo_util::geometry;
|
||||
use platform::macos::font_context::FontContextHandle;
|
||||
use text::glyph::GlyphId;
|
||||
use style::computed_values::font_weight;
|
||||
use style::computed_values::{font_stretch, font_weight};
|
||||
use platform::font_template::FontTemplateData;
|
||||
|
||||
use core_foundation::base::CFIndex;
|
||||
|
@ -111,6 +111,21 @@ impl FontHandleMethods for FontHandle {
|
|||
return font_weight::T::Weight900;
|
||||
}
|
||||
|
||||
fn stretchiness(&self) -> font_stretch::T {
|
||||
let normalized = self.ctfont.all_traits().normalized_width(); // [-1.0, 1.0]
|
||||
match (normalized + 1.0) / 2.0 * 9.0 { // [0.0, 9.0]
|
||||
v if v < 1.0 => font_stretch::T::ultra_condensed,
|
||||
v if v < 2.0 => font_stretch::T::extra_condensed,
|
||||
v if v < 3.0 => font_stretch::T::condensed,
|
||||
v if v < 4.0 => font_stretch::T::semi_condensed,
|
||||
v if v < 5.0 => font_stretch::T::normal,
|
||||
v if v < 6.0 => font_stretch::T::semi_expanded,
|
||||
v if v < 7.0 => font_stretch::T::expanded,
|
||||
v if v < 8.0 => font_stretch::T::extra_expanded,
|
||||
_ => font_stretch::T::ultra_expanded,
|
||||
}
|
||||
}
|
||||
|
||||
fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
|
||||
let characters: [UniChar; 1] = [codepoint as UniChar];
|
||||
let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph];
|
||||
|
|
|
@ -127,6 +127,7 @@ partial interface CSSStyleDeclaration {
|
|||
[TreatNullAs=EmptyString] attribute DOMString font;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontFamily;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontSize;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontStretch;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontStyle;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontVariant;
|
||||
[TreatNullAs=EmptyString] attribute DOMString fontWeight;
|
||||
|
|
|
@ -1149,6 +1149,9 @@ pub mod longhands {
|
|||
}
|
||||
</%self:longhand>
|
||||
|
||||
${single_keyword("font-stretch",
|
||||
"normal ultra-condensed extra-condensed condensed semi-condensed semi-expanded expanded extra-expanded ultra-expanded")}
|
||||
|
||||
// CSS 2.1, Section 16 - Text
|
||||
|
||||
${new_style_struct("InheritedText", is_inherited=True)}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-size: 36pt;
|
||||
font-family: "Helvetica Neue";
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
#a {
|
||||
font-stretch: normal;
|
||||
}
|
||||
#b {
|
||||
font-stretch: condensed;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id=a>Felis silvestris catus</div>
|
||||
<div id=b>Felis silvestris catus</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче