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 -->
This commit is contained in:
@@ -25,3 +25,6 @@ pub mod font_descriptor;
|
||||
pub mod font_manager;
|
||||
pub mod frame;
|
||||
pub mod framesetter;
|
||||
pub mod line;
|
||||
pub mod run;
|
||||
pub mod string_attributes;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::os::raw::c_void;
|
||||
use core_foundation::attributed_string::CFAttributedStringRef;
|
||||
use core_foundation::array::{CFArray, CFArrayRef};
|
||||
use core_foundation::base::{CFTypeID, TCFType};
|
||||
use run::CTRun;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CTLine(c_void);
|
||||
|
||||
pub type CTLineRef = *const __CTLine;
|
||||
|
||||
declare_TCFType! {
|
||||
CTLine, CTLineRef
|
||||
}
|
||||
impl_TCFType!(CTLine, CTLineRef, CTLineGetTypeID);
|
||||
impl_CFTypeDescription!(CTLine);
|
||||
|
||||
impl CTLine {
|
||||
pub fn new_with_attributed_string(string: CFAttributedStringRef) -> Self {
|
||||
unsafe {
|
||||
let ptr = CTLineCreateWithAttributedString(string);
|
||||
CTLine::wrap_under_create_rule(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn glyph_runs(&self) -> CFArray<CTRun> {
|
||||
unsafe {
|
||||
TCFType::wrap_under_get_rule(CTLineGetGlyphRuns(self.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreText", kind = "framework")]
|
||||
extern {
|
||||
fn CTLineGetTypeID() -> CFTypeID;
|
||||
fn CTLineGetGlyphRuns(line: CTLineRef) -> CFArrayRef;
|
||||
fn CTLineCreateWithAttributedString(string: CFAttributedStringRef) -> CTLineRef;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::os::raw::c_void;
|
||||
use std::slice;
|
||||
use std::ptr;
|
||||
use core_foundation::base::{CFIndex, CFTypeID, TCFType, CFType, CFRange};
|
||||
use core_foundation::dictionary::{CFDictionary, CFDictionaryRef};
|
||||
use core_foundation::string::CFString;
|
||||
use core_graphics::font::CGGlyph;
|
||||
use core_graphics::geometry::CGPoint;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CTRun(c_void);
|
||||
|
||||
pub type CTRunRef = *const __CTRun;
|
||||
|
||||
declare_TCFType! {
|
||||
CTRun, CTRunRef
|
||||
}
|
||||
impl_TCFType!(CTRun, CTRunRef, CTRunGetTypeID);
|
||||
impl_CFTypeDescription!(CTRun);
|
||||
|
||||
impl CTRun {
|
||||
pub fn attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
|
||||
unsafe {
|
||||
let attrs = CTRunGetAttributes(self.0);
|
||||
if attrs.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(TCFType::wrap_under_get_rule(attrs))
|
||||
}
|
||||
}
|
||||
pub fn glyph_count(&self) -> CFIndex {
|
||||
unsafe {
|
||||
CTRunGetGlyphCount(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn glyphs(&self) -> Cow<[CGGlyph]> {
|
||||
unsafe {
|
||||
// CTRunGetGlyphsPtr can return null under some not understood circumstances.
|
||||
// If it does the Apple documentation tells us to allocate our own buffer and call
|
||||
// CTRunGetGlyphs
|
||||
let count = CTRunGetGlyphCount(self.0);
|
||||
let glyphs_ptr = CTRunGetGlyphsPtr(self.0);
|
||||
if glyphs_ptr != ptr::null() {
|
||||
Cow::from(slice::from_raw_parts(glyphs_ptr, count as usize))
|
||||
} else {
|
||||
let mut vec = Vec::with_capacity(count as usize);
|
||||
// "If the length of the range is set to 0, then the copy operation will continue
|
||||
// from the start index of the range to the end of the run"
|
||||
CTRunGetGlyphs(self.0, CFRange::init(0, 0), vec.as_mut_ptr());
|
||||
vec.set_len(count as usize);
|
||||
Cow::from(vec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn positions(&self) -> Cow<[CGPoint]> {
|
||||
unsafe {
|
||||
// CTRunGetPositionsPtr can return null under some not understood circumstances.
|
||||
// If it does the Apple documentation tells us to allocate our own buffer and call
|
||||
// CTRunGetPositions
|
||||
let count = CTRunGetGlyphCount(self.0);
|
||||
let positions_ptr = CTRunGetPositionsPtr(self.0);
|
||||
if positions_ptr != ptr::null() {
|
||||
Cow::from(slice::from_raw_parts(positions_ptr, count as usize))
|
||||
} else {
|
||||
let mut vec = Vec::with_capacity(count as usize);
|
||||
// "If the length of the range is set to 0, then the copy operation will continue
|
||||
// from the start index of the range to the end of the run"
|
||||
CTRunGetPositions(self.0, CFRange::init(0, 0), vec.as_mut_ptr());
|
||||
vec.set_len(count as usize);
|
||||
Cow::from(vec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_runs() {
|
||||
use core_foundation::attributed_string::CFMutableAttributedString;
|
||||
use string_attributes::*;
|
||||
use line::*;
|
||||
use font;
|
||||
let mut string = CFMutableAttributedString::new();
|
||||
string.replace_str(&CFString::new("Food"), CFRange::init(0, 0));
|
||||
let len = string.char_len();
|
||||
unsafe {
|
||||
string.set_attribute(CFRange::init(0, len), kCTFontAttributeName, font::new_from_name("Helvetica", 16.).unwrap());
|
||||
}
|
||||
let line = CTLine::new_with_attributed_string(string.as_concrete_TypeRef());
|
||||
let runs = line.glyph_runs();
|
||||
assert_eq!(runs.len(), 1);
|
||||
for run in runs.iter() {
|
||||
assert_eq!(run.glyph_count(), 4);
|
||||
let font = run.attributes().unwrap().get(CFString::new("NSFont")).downcast::<font::CTFont>().unwrap();
|
||||
assert_eq!(font.pt_size(), 16.);
|
||||
|
||||
let positions = run.positions();
|
||||
assert_eq!(positions.len(), 4);
|
||||
assert!(positions[0].x < positions[1].x);
|
||||
|
||||
let glyphs = run.glyphs();
|
||||
assert_eq!(glyphs.len(), 4);
|
||||
assert_ne!(glyphs[0], glyphs[1]);
|
||||
assert_eq!(glyphs[1], glyphs[2]);
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreText", kind = "framework")]
|
||||
extern {
|
||||
fn CTRunGetTypeID() -> CFTypeID;
|
||||
fn CTRunGetAttributes(run: CTRunRef) -> CFDictionaryRef;
|
||||
fn CTRunGetGlyphCount(run: CTRunRef) -> CFIndex;
|
||||
fn CTRunGetPositionsPtr(run: CTRunRef) -> *const CGPoint;
|
||||
fn CTRunGetPositions(run: CTRunRef, range: CFRange, buffer: *const CGPoint);
|
||||
fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph;
|
||||
fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use core_foundation::string::CFStringRef;
|
||||
|
||||
extern {
|
||||
pub static kCTCharacterShapeAttributeName: CFStringRef;
|
||||
pub static kCTFontAttributeName: CFStringRef;
|
||||
pub static kCTKernAttributeName: CFStringRef;
|
||||
pub static kCTLigatureAttributeName: CFStringRef;
|
||||
pub static kCTForegroundColorAttributeName: CFStringRef;
|
||||
pub static kCTForegroundColorFromContextAttributeName: CFStringRef;
|
||||
pub static kCTParagraphStyleAttributeName: CFStringRef;
|
||||
pub static kCTStrokeWidthAttributeName: CFStringRef;
|
||||
pub static kCTStrokeColorAttributeName: CFStringRef;
|
||||
pub static kCTSuperscriptAttributeName: CFStringRef;
|
||||
pub static kCTUnderlineColorAttributeName: CFStringRef;
|
||||
pub static kCTUnderlineStyleAttributeName: CFStringRef;
|
||||
pub static kCTVerticalFormsAttributeName: CFStringRef;
|
||||
pub static kCTGlyphInfoAttributeName: CFStringRef;
|
||||
pub static kCTRunDelegateAttributeName: CFStringRef;
|
||||
}
|
||||
Reference in New Issue
Block a user