From 7f00bbf441e344e1215198bb4c12f57926a0a2a0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 30 Nov 2015 16:39:49 -0800 Subject: [PATCH] Support serialization of `CGFont` objects. Due to API limitations, this will only serialize native fonts, not Web fonts. Specifically, there is no way I know of to fetch the `CGDataProvider` associated with a `CGFont`. This isn't a problem for Servo, however, because Servo knows which fonts are Web fonts and stores their byte data separately. --- Cargo.toml | 2 ++ src/font.rs | 43 +++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 1 + 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6e0bf06..42299d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,5 @@ license = "MIT / Apache-2.0" [dependencies] libc = "0.2" core-foundation = "0.2" +serde = "0.6" + diff --git a/src/font.rs b/src/font.rs index 8fcf21f..0cb89fc 100644 --- a/src/font.rs +++ b/src/font.rs @@ -8,9 +8,12 @@ // except according to those terms. use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::string::{CFString, CFStringRef}; use data_provider::{CGDataProvider, CGDataProviderRef}; use libc; +use serde::de::{self, Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer}; use std::mem; use std::ptr; @@ -28,6 +31,22 @@ pub struct CGFont { unsafe impl Send for CGFont {} unsafe impl Sync for CGFont {} +impl Serialize for CGFont { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + let postscript_name = self.postscript_name().to_string(); + postscript_name.serialize(serializer) + } +} + +impl Deserialize for CGFont { + fn deserialize(deserializer: &mut D) -> Result where D: Deserializer { + let postscript_name: String = try!(Deserialize::deserialize(deserializer)); + CGFont::from_name(&CFString::new(&*postscript_name)).map_err(|err| { + de::Error::syntax("Couldn't find a font with that PostScript name!") + }) + } +} + impl Clone for CGFont { #[inline] fn clone(&self) -> CGFont { @@ -92,15 +111,35 @@ impl CGFont { } } } + + pub fn from_name(name: &CFString) -> Result { + unsafe { + let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef()); + if font_ref != ptr::null() { + Ok(TCFType::wrap_under_create_rule(font_ref)) + } else { + Err(()) + } + } + } + + pub fn postscript_name(&self) -> CFString { + unsafe { + let string_ref = CGFontCopyPostScriptName(self.obj); + TCFType::wrap_under_create_rule(string_ref) + } + } } #[link(name = "ApplicationServices", kind = "framework")] extern { - - // TODO: basically nothing has bindings (even commented-out) besides what we use. + // TODO: basically nothing has bindings (even commented-out) besides what we use. fn CGFontCreateWithDataProvider(provider: CGDataProviderRef) -> CGFontRef; + fn CGFontCreateWithFontName(name: CFStringRef) -> CGFontRef; fn CGFontGetTypeID() -> CFTypeID; + fn CGFontCopyPostScriptName(font: CGFontRef) -> CFStringRef; + // These do the same thing as CFRetain/CFRelease, except // gracefully handle a NULL argument. We don't use them. //fn CGFontRetain(font: CGFontRef); diff --git a/src/lib.rs b/src/lib.rs index 03d2c90..a7d45ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ extern crate libc; extern crate core_foundation; +extern crate serde; pub mod base; pub mod color_space;