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:
bors-servo
2018-11-14 17:42:48 -05:00
committed by GitHub
4 changed files with 198 additions and 0 deletions
+3
View File
@@ -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;
+47
View File
@@ -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;
}
+129
View File
@@ -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);
}
+19
View File
@@ -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;
}