Skip to content

Commit 42a6014

Browse files
author
bors-servo
authored
Auto merge of #269 - jrmuizel:run, r=jdm
Add some minimal bindings for CTLine and CTRun <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/core-foundation-rs/269) <!-- Reviewable:end -->
2 parents 55a4d79 + 4288963 commit 42a6014

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

core-text/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ pub mod font_descriptor;
2525
pub mod font_manager;
2626
pub mod frame;
2727
pub mod framesetter;
28+
pub mod line;
29+
pub mod run;
30+
pub mod string_attributes;

core-text/src/line.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
use std::os::raw::c_void;
11+
use core_foundation::attributed_string::CFAttributedStringRef;
12+
use core_foundation::array::{CFArray, CFArrayRef};
13+
use core_foundation::base::{CFTypeID, TCFType};
14+
use run::CTRun;
15+
16+
#[repr(C)]
17+
pub struct __CTLine(c_void);
18+
19+
pub type CTLineRef = *const __CTLine;
20+
21+
declare_TCFType! {
22+
CTLine, CTLineRef
23+
}
24+
impl_TCFType!(CTLine, CTLineRef, CTLineGetTypeID);
25+
impl_CFTypeDescription!(CTLine);
26+
27+
impl CTLine {
28+
pub fn new_with_attributed_string(string: CFAttributedStringRef) -> Self {
29+
unsafe {
30+
let ptr = CTLineCreateWithAttributedString(string);
31+
CTLine::wrap_under_create_rule(ptr)
32+
}
33+
}
34+
35+
pub fn glyph_runs(&self) -> CFArray<CTRun> {
36+
unsafe {
37+
TCFType::wrap_under_get_rule(CTLineGetGlyphRuns(self.0))
38+
}
39+
}
40+
}
41+
42+
#[link(name = "CoreText", kind = "framework")]
43+
extern {
44+
fn CTLineGetTypeID() -> CFTypeID;
45+
fn CTLineGetGlyphRuns(line: CTLineRef) -> CFArrayRef;
46+
fn CTLineCreateWithAttributedString(string: CFAttributedStringRef) -> CTLineRef;
47+
}

core-text/src/run.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
use std::borrow::Cow;
11+
use std::os::raw::c_void;
12+
use std::slice;
13+
use std::ptr;
14+
use core_foundation::base::{CFIndex, CFTypeID, TCFType, CFType, CFRange};
15+
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
16+
use core_foundation::string::CFString;
17+
use core_graphics::font::CGGlyph;
18+
use core_graphics::geometry::CGPoint;
19+
20+
#[repr(C)]
21+
pub struct __CTRun(c_void);
22+
23+
pub type CTRunRef = *const __CTRun;
24+
25+
declare_TCFType! {
26+
CTRun, CTRunRef
27+
}
28+
impl_TCFType!(CTRun, CTRunRef, CTRunGetTypeID);
29+
impl_CFTypeDescription!(CTRun);
30+
31+
impl CTRun {
32+
pub fn attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
33+
unsafe {
34+
let attrs = CTRunGetAttributes(self.0);
35+
if attrs.is_null() {
36+
return None;
37+
}
38+
Some(TCFType::wrap_under_get_rule(attrs))
39+
}
40+
}
41+
pub fn glyph_count(&self) -> CFIndex {
42+
unsafe {
43+
CTRunGetGlyphCount(self.0)
44+
}
45+
}
46+
47+
pub fn glyphs(&self) -> Cow<[CGGlyph]> {
48+
unsafe {
49+
// CTRunGetGlyphsPtr can return null under some not understood circumstances.
50+
// If it does the Apple documentation tells us to allocate our own buffer and call
51+
// CTRunGetGlyphs
52+
let count = CTRunGetGlyphCount(self.0);
53+
let glyphs_ptr = CTRunGetGlyphsPtr(self.0);
54+
if glyphs_ptr != ptr::null() {
55+
Cow::from(slice::from_raw_parts(glyphs_ptr, count as usize))
56+
} else {
57+
let mut vec = Vec::with_capacity(count as usize);
58+
// "If the length of the range is set to 0, then the copy operation will continue
59+
// from the start index of the range to the end of the run"
60+
CTRunGetGlyphs(self.0, CFRange::init(0, 0), vec.as_mut_ptr());
61+
vec.set_len(count as usize);
62+
Cow::from(vec)
63+
}
64+
}
65+
}
66+
67+
pub fn positions(&self) -> Cow<[CGPoint]> {
68+
unsafe {
69+
// CTRunGetPositionsPtr can return null under some not understood circumstances.
70+
// If it does the Apple documentation tells us to allocate our own buffer and call
71+
// CTRunGetPositions
72+
let count = CTRunGetGlyphCount(self.0);
73+
let positions_ptr = CTRunGetPositionsPtr(self.0);
74+
if positions_ptr != ptr::null() {
75+
Cow::from(slice::from_raw_parts(positions_ptr, count as usize))
76+
} else {
77+
let mut vec = Vec::with_capacity(count as usize);
78+
// "If the length of the range is set to 0, then the copy operation will continue
79+
// from the start index of the range to the end of the run"
80+
CTRunGetPositions(self.0, CFRange::init(0, 0), vec.as_mut_ptr());
81+
vec.set_len(count as usize);
82+
Cow::from(vec)
83+
}
84+
}
85+
}
86+
87+
}
88+
89+
#[test]
90+
fn create_runs() {
91+
use core_foundation::attributed_string::CFMutableAttributedString;
92+
use string_attributes::*;
93+
use line::*;
94+
use font;
95+
let mut string = CFMutableAttributedString::new();
96+
string.replace_str(&CFString::new("Food"), CFRange::init(0, 0));
97+
let len = string.char_len();
98+
unsafe {
99+
string.set_attribute(CFRange::init(0, len), kCTFontAttributeName, font::new_from_name("Helvetica", 16.).unwrap());
100+
}
101+
let line = CTLine::new_with_attributed_string(string.as_concrete_TypeRef());
102+
let runs = line.glyph_runs();
103+
assert_eq!(runs.len(), 1);
104+
for run in runs.iter() {
105+
assert_eq!(run.glyph_count(), 4);
106+
let font = run.attributes().unwrap().get(CFString::new("NSFont")).downcast::<font::CTFont>().unwrap();
107+
assert_eq!(font.pt_size(), 16.);
108+
109+
let positions = run.positions();
110+
assert_eq!(positions.len(), 4);
111+
assert!(positions[0].x < positions[1].x);
112+
113+
let glyphs = run.glyphs();
114+
assert_eq!(glyphs.len(), 4);
115+
assert_ne!(glyphs[0], glyphs[1]);
116+
assert_eq!(glyphs[1], glyphs[2]);
117+
}
118+
}
119+
120+
#[link(name = "CoreText", kind = "framework")]
121+
extern {
122+
fn CTRunGetTypeID() -> CFTypeID;
123+
fn CTRunGetAttributes(run: CTRunRef) -> CFDictionaryRef;
124+
fn CTRunGetGlyphCount(run: CTRunRef) -> CFIndex;
125+
fn CTRunGetPositionsPtr(run: CTRunRef) -> *const CGPoint;
126+
fn CTRunGetPositions(run: CTRunRef, range: CFRange, buffer: *const CGPoint);
127+
fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph;
128+
fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph);
129+
}

core-text/src/string_attributes.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use core_foundation::string::CFStringRef;
2+
3+
extern {
4+
pub static kCTCharacterShapeAttributeName: CFStringRef;
5+
pub static kCTFontAttributeName: CFStringRef;
6+
pub static kCTKernAttributeName: CFStringRef;
7+
pub static kCTLigatureAttributeName: CFStringRef;
8+
pub static kCTForegroundColorAttributeName: CFStringRef;
9+
pub static kCTForegroundColorFromContextAttributeName: CFStringRef;
10+
pub static kCTParagraphStyleAttributeName: CFStringRef;
11+
pub static kCTStrokeWidthAttributeName: CFStringRef;
12+
pub static kCTStrokeColorAttributeName: CFStringRef;
13+
pub static kCTSuperscriptAttributeName: CFStringRef;
14+
pub static kCTUnderlineColorAttributeName: CFStringRef;
15+
pub static kCTUnderlineStyleAttributeName: CFStringRef;
16+
pub static kCTVerticalFormsAttributeName: CFStringRef;
17+
pub static kCTGlyphInfoAttributeName: CFStringRef;
18+
pub static kCTRunDelegateAttributeName: CFStringRef;
19+
}

0 commit comments

Comments
 (0)