Skip to content

Commit f6d91e0

Browse files
author
bors-servo
authored
Auto merge of #2122 - jrmuizel:font-data, r=glennw
Support serializing NativeFontHandle on macOS This fixes #2051 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2122) <!-- Reviewable:end -->
2 parents 23d1358 + 7bd05c0 commit f6d91e0

File tree

6 files changed

+223
-58
lines changed

6 files changed

+223
-58
lines changed

Cargo.lock

Lines changed: 20 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webrender/src/platform/macos/font.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ fn new_ct_font_with_variations(cg_font: &CGFont, size: f64, variations: &[FontVa
247247

248248
val = val.max(min_val).min(max_val);
249249
if val != def_val {
250-
vals.push((name, CFNumber::from_f64(val)));
250+
vals.push((name, CFNumber::from(val)));
251251
}
252252
}
253253
if vals.is_empty() {

wrench/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ osmesa-src = { git = "https://github.com/servo/osmesa-src", optional = true }
2727
webrender = {path = "../webrender", features=["debugger","profiler"]}
2828
serde = {version = "1.0", features = ["derive"] }
2929

30+
[target.'cfg(target_os = "macos")'.dependencies]
31+
core-graphics = "0.12.4"
32+
core-foundation = "0.4"
33+
3034
[features]
3135
headless = [ "osmesa-sys", "osmesa-src" ]
3236
logging = [ "env_logger" ]

wrench/src/cgfont_to_data.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
6+
use core_foundation::data::CFData;
7+
use core_graphics::font::CGFont;
8+
use std;
9+
use std::io::Cursor;
10+
use std::io::Read;
11+
use std::io::Write;
12+
13+
14+
fn calc_table_checksum<D: Read>(mut data: D) -> u32 {
15+
let mut sum: u32 = 0;
16+
17+
while let Ok(x) = data.read_u32::<BigEndian>() {
18+
sum = sum.wrapping_add(x);
19+
}
20+
// read the remaining bytes
21+
let mut buf: [u8; 4] = [0; 4];
22+
data.read(&mut buf).unwrap();
23+
// if there was nothing left in buf we'll just read a 0
24+
// which won't affect the checksum
25+
sum = sum.wrapping_add(BigEndian::read_u32(&buf));
26+
sum
27+
}
28+
29+
fn max_pow_2_less_than(a: u16) -> u16 {
30+
let x = 1;
31+
let mut shift = 0;
32+
while (x << (shift + 1)) < a {
33+
shift += 1;
34+
}
35+
shift
36+
}
37+
38+
struct TableRecord {
39+
tag: u32,
40+
checksum: u32,
41+
offset: u32,
42+
length: u32,
43+
data: CFData
44+
}
45+
46+
const CFF_TAG: u32 = 0x43464620; // 'CFF '
47+
const HEAD_TAG: u32 = 0x68656164; // 'head'
48+
const OTTO_TAG: u32 = 0x4f54544f; // 'OTTO'
49+
const TRUE_TAG: u32 = 0x00010000;
50+
51+
pub fn font_to_data(font: CGFont) -> Result<Vec<u8>, std::io::Error> {
52+
// We'll reconstruct a TTF font from the tables we can get from the CGFont
53+
let mut cff = false;
54+
let tags = font.copy_table_tags();
55+
let count = tags.len() as u16;
56+
57+
let mut records = Vec::new();
58+
let mut offset: u32 = 0;
59+
offset += 4 * 3;
60+
offset += 4 * 4 * (count as u32);
61+
for tag in tags.iter() {
62+
if tag == CFF_TAG {
63+
cff = true;
64+
}
65+
let data = font.copy_table_for_tag(tag).unwrap();
66+
let length = data.len() as u32;
67+
let checksum;
68+
if tag == HEAD_TAG {
69+
// we need to skip the checksum field
70+
checksum = calc_table_checksum(&data.bytes()[0..2])
71+
.wrapping_add(calc_table_checksum(&data.bytes()[3..]))
72+
} else {
73+
checksum = calc_table_checksum(data.bytes());
74+
}
75+
records.push(TableRecord { tag, offset, data, length, checksum } );
76+
offset += length;
77+
// 32 bit align the tables
78+
offset = (offset + 3) & !3;
79+
}
80+
81+
let mut buf = Vec::new();
82+
if cff {
83+
buf.write_u32::<BigEndian>(OTTO_TAG)?;
84+
} else {
85+
buf.write_u32::<BigEndian>(TRUE_TAG)?;
86+
}
87+
88+
buf.write_u16::<BigEndian>(count)?;
89+
buf.write_u16::<BigEndian>((1 << max_pow_2_less_than(count)) * 16)?;
90+
buf.write_u16::<BigEndian>(max_pow_2_less_than(count))?;
91+
buf.write_u16::<BigEndian>(count * 16 - ((1 << max_pow_2_less_than(count)) * 16))?;
92+
93+
// write table record entries
94+
for r in &records {
95+
buf.write_u32::<BigEndian>(r.tag)?;
96+
buf.write_u32::<BigEndian>(r.checksum)?;
97+
buf.write_u32::<BigEndian>(r.offset)?;
98+
buf.write_u32::<BigEndian>(r.length)?;
99+
}
100+
101+
// write tables
102+
let mut check_sum_adjustment_offset = 0;
103+
for r in &records {
104+
if r.tag == 0x68656164 {
105+
check_sum_adjustment_offset = buf.len() + 2 * 4;
106+
}
107+
buf.write(r.data.bytes())?;
108+
// 32 bit align the tables
109+
while buf.len() & 3 != 0 {
110+
buf.push(0);
111+
}
112+
}
113+
114+
let mut c = Cursor::new(buf);
115+
c.set_position(check_sum_adjustment_offset as u64);
116+
// clear the checksumAdjust field before checksumming the whole font
117+
c.write_u32::<BigEndian>(0)?;
118+
let sum = 0xb1b0afba_u32.wrapping_sub(calc_table_checksum(&c.get_mut()[..]));
119+
// set checkSumAdjust to the computed checksum
120+
c.set_position(check_sum_adjustment_offset as u64);
121+
c.write_u32::<BigEndian>(sum)?;
122+
123+
Ok(c.into_inner())
124+
}

wrench/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ extern crate bincode;
88
extern crate byteorder;
99
#[macro_use]
1010
extern crate clap;
11+
#[cfg(target_os = "macos")]
12+
extern crate core_foundation;
13+
#[cfg(target_os = "macos")]
14+
extern crate core_graphics;
1115
extern crate crossbeam;
1216
#[cfg(target_os = "windows")]
1317
extern crate dwrote;
@@ -46,6 +50,8 @@ mod wrench;
4650
mod yaml_frame_reader;
4751
mod yaml_frame_writer;
4852
mod yaml_helper;
53+
#[cfg(target_os = "macos")]
54+
mod cgfont_to_data;
4955

5056
use binary_frame_reader::BinaryFrameReader;
5157
use gleam::gl;

0 commit comments

Comments
 (0)