diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /third_party/rust/core-text | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/core-text')
-rw-r--r-- | third_party/rust/core-text/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/core-text/COPYRIGHT | 5 | ||||
-rw-r--r-- | third_party/rust/core-text/Cargo.toml | 36 | ||||
-rw-r--r-- | third_party/rust/core-text/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | third_party/rust/core-text/LICENSE-MIT | 25 | ||||
-rw-r--r-- | third_party/rust/core-text/README.md | 3 | ||||
-rw-r--r-- | third_party/rust/core-text/src/font.rs | 744 | ||||
-rw-r--r-- | third_party/rust/core-text/src/font_collection.rs | 131 | ||||
-rw-r--r-- | third_party/rust/core-text/src/font_descriptor.rs | 404 | ||||
-rw-r--r-- | third_party/rust/core-text/src/font_manager.rs | 72 | ||||
-rw-r--r-- | third_party/rust/core-text/src/frame.rs | 93 | ||||
-rw-r--r-- | third_party/rust/core-text/src/framesetter.rs | 94 | ||||
-rw-r--r-- | third_party/rust/core-text/src/lib.rs | 35 | ||||
-rw-r--r-- | third_party/rust/core-text/src/line.rs | 113 | ||||
-rw-r--r-- | third_party/rust/core-text/src/run.rs | 152 | ||||
-rw-r--r-- | third_party/rust/core-text/src/string_attributes.rs | 19 |
16 files changed, 2128 insertions, 0 deletions
diff --git a/third_party/rust/core-text/.cargo-checksum.json b/third_party/rust/core-text/.cargo-checksum.json new file mode 100644 index 0000000000..057b261191 --- /dev/null +++ b/third_party/rust/core-text/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"26a527860e530d18a5ce446ffb595f63a178504506fb4a283993402295053afe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"98d25015857a430aac32f34bdc979a1a66e672a0ea42c5f92dd9cfe23c1fccfd","src/font.rs":"17d957510eee8d96ef2bc1b5bc97491917ac0336ad3dbf48416dda3685cef579","src/font_collection.rs":"02de0ce2a61683314897a521d31ab9cc572a8b10ceda2ac47181fbe18bf4f235","src/font_descriptor.rs":"43a2fec6bca9689d8172f363ab20ce8c633696974e1653cad2e072e3af776528","src/font_manager.rs":"6e5056a42868187e1f4e696c181ca247423308652d3c68867c708616031876e4","src/frame.rs":"ed1e2aad7be9dafc3e9729f2caecefd4214a9552f834932a414239146142069a","src/framesetter.rs":"13e34b4111cee5f023aa05e2220d2a6f102e96fd18c51a356992bffd6c9fc7c1","src/lib.rs":"1c662e51874eb43ff52a8a1af131d1b2fd84095c3d949a271dc895bf56fd0fc6","src/line.rs":"02fab7f07c3f6a003a7c35ffeb3d37546ae58e4da7fe05f26e520f283397a602","src/run.rs":"b86e9b9b39effe4a79c6002880d95f214742d448029a3111e288734abe75b827","src/string_attributes.rs":"ea0f854d64097d3626a03002323e2276e28affae7a698aaadd89dd6b744dd80f"},"package":"99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"}
\ No newline at end of file diff --git a/third_party/rust/core-text/COPYRIGHT b/third_party/rust/core-text/COPYRIGHT new file mode 100644 index 0000000000..8b7291ad28 --- /dev/null +++ b/third_party/rust/core-text/COPYRIGHT @@ -0,0 +1,5 @@ +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. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. diff --git a/third_party/rust/core-text/Cargo.toml b/third_party/rust/core-text/Cargo.toml new file mode 100644 index 0000000000..a674dc3327 --- /dev/null +++ b/third_party/rust/core-text/Cargo.toml @@ -0,0 +1,36 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "core-text" +version = "19.2.0" +authors = ["The Servo Project Developers"] +description = "Bindings to the Core Text framework." +license = "MIT/Apache-2.0" +repository = "https://github.com/servo/core-foundation-rs" +[package.metadata.docs.rs] +default-target = "x86_64-apple-darwin" +[dependencies.core-foundation] +version = "0.9" + +[dependencies.core-graphics] +version = "0.22.0" + +[dependencies.foreign-types] +version = "0.3" + +[dependencies.libc] +version = "0.2" + +[features] +default = ["mountainlion"] +mountainlion = [] diff --git a/third_party/rust/core-text/LICENSE-APACHE b/third_party/rust/core-text/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/third_party/rust/core-text/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/core-text/LICENSE-MIT b/third_party/rust/core-text/LICENSE-MIT new file mode 100644 index 0000000000..807526f57f --- /dev/null +++ b/third_party/rust/core-text/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2012-2013 Mozilla Foundation + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/core-text/README.md b/third_party/rust/core-text/README.md new file mode 100644 index 0000000000..312fe3325d --- /dev/null +++ b/third_party/rust/core-text/README.md @@ -0,0 +1,3 @@ +# core-text-rs + +[![Build Status](https://travis-ci.com/servo/core-text-rs.svg?branch=master)](https://travis-ci.com/servo/core-text-rs) diff --git a/third_party/rust/core-text/src/font.rs b/third_party/rust/core-text/src/font.rs new file mode 100644 index 0000000000..ebe6d580f5 --- /dev/null +++ b/third_party/rust/core-text/src/font.rs @@ -0,0 +1,744 @@ +// 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. + +#![allow(non_upper_case_globals)] + +use font_descriptor; +use font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontOrientation}; +use font_descriptor::{CTFontSymbolicTraits, CTFontTraits, SymbolicTraitAccessors, TraitAccessors}; +use font_manager::create_font_descriptor; + +use core_foundation::array::{CFArray, CFArrayRef}; +use core_foundation::base::{CFIndex, CFOptionFlags, CFType, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::data::{CFData, CFDataRef}; +use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; +use core_foundation::number::CFNumber; +use core_foundation::string::{CFString, CFStringRef, UniChar}; +use core_foundation::url::{CFURL, CFURLRef}; +use core_graphics::base::CGFloat; +use core_graphics::context::CGContext; +use core_graphics::font::{CGGlyph, CGFont}; +use core_graphics::geometry::{CGAffineTransform, CGPoint, CGRect, CGSize}; +use core_graphics::path::CGPath; + +use foreign_types::ForeignType; +use libc::{self, size_t}; +use std::os::raw::c_void; +use std::ptr; + +type CGContextRef = *mut <CGContext as ForeignType>::CType; +type CGFontRef = *mut <CGFont as ForeignType>::CType; +type CGPathRef = *mut <CGPath as ForeignType>::CType; + +pub type CTFontUIFontType = u32; +// kCTFontNoFontType: CTFontUIFontType = -1; +pub const kCTFontUserFontType: CTFontUIFontType = 0; +pub const kCTFontUserFixedPitchFontType: CTFontUIFontType = 1; +pub const kCTFontSystemFontType: CTFontUIFontType = 2; +pub const kCTFontEmphasizedSystemFontType: CTFontUIFontType = 3; +pub const kCTFontSmallSystemFontType: CTFontUIFontType = 4; +pub const kCTFontSmallEmphasizedSystemFontType: CTFontUIFontType = 5; +pub const kCTFontMiniSystemFontType: CTFontUIFontType = 6; +pub const kCTFontMiniEmphasizedSystemFontType: CTFontUIFontType = 7; +pub const kCTFontViewsFontType: CTFontUIFontType = 8; +pub const kCTFontApplicationFontType: CTFontUIFontType = 9; +pub const kCTFontLabelFontType: CTFontUIFontType = 10; +pub const kCTFontMenuTitleFontType: CTFontUIFontType = 11; +pub const kCTFontMenuItemFontType: CTFontUIFontType = 12; +pub const kCTFontMenuItemMarkFontType: CTFontUIFontType = 13; +pub const kCTFontMenuItemCmdKeyFontType: CTFontUIFontType = 14; +pub const kCTFontWindowTitleFontType: CTFontUIFontType = 15; +pub const kCTFontPushButtonFontType: CTFontUIFontType = 16; +pub const kCTFontUtilityWindowTitleFontType: CTFontUIFontType = 17; +pub const kCTFontAlertHeaderFontType: CTFontUIFontType = 18; +pub const kCTFontSystemDetailFontType: CTFontUIFontType = 19; +pub const kCTFontEmphasizedSystemDetailFontType: CTFontUIFontType = 20; +pub const kCTFontToolbarFontType: CTFontUIFontType = 21; +pub const kCTFontSmallToolbarFontType: CTFontUIFontType = 22; +pub const kCTFontMessageFontType: CTFontUIFontType = 23; +pub const kCTFontPaletteFontType: CTFontUIFontType = 24; +pub const kCTFontToolTipFontType: CTFontUIFontType = 25; +pub const kCTFontControlContentFontType: CTFontUIFontType = 26; + +pub type CTFontTableTag = u32; +// TODO: create bindings for enum with 'chars' values + +pub type CTFontTableOptions = u32; +pub const kCTFontTableOptionsNoOptions: CTFontTableOptions = 0; +pub const kCTFontTableOptionsExcludeSynthetic: CTFontTableOptions = 1 << 0; + +pub type CTFontOptions = CFOptionFlags; +pub const kCTFontOptionsDefault: CTFontOptions = 0; +pub const kCTFontOptionsPreventAutoActivation: CTFontOptions = 1 << 0; +pub const kCTFontOptionsPreferSystemFont: CTFontOptions = 1 << 2; + +#[repr(C)] +pub struct __CTFont(c_void); + +pub type CTFontRef = *const __CTFont; + +declare_TCFType! { + CTFont, CTFontRef +} +impl_TCFType!(CTFont, CTFontRef, CTFontGetTypeID); +impl_CFTypeDescription!(CTFont); + +unsafe impl Send for CTFont {} +unsafe impl Sync for CTFont {} + +pub fn new_from_CGFont(cgfont: &CGFont, pt_size: f64) -> CTFont { + unsafe { + let font_ref = CTFontCreateWithGraphicsFont(cgfont.as_ptr() as *mut _, + pt_size as CGFloat, + ptr::null(), + ptr::null()); + CTFont::wrap_under_create_rule(font_ref) + } +} + +pub fn new_from_CGFont_with_variations(cgfont: &CGFont, + pt_size: f64, + variations: &CFDictionary<CFString, CFNumber>) + -> CTFont { + unsafe { + let font_desc = font_descriptor::new_from_variations(variations); + let font_ref = CTFontCreateWithGraphicsFont(cgfont.as_ptr() as *mut _, + pt_size as CGFloat, + ptr::null(), + font_desc.as_concrete_TypeRef()); + CTFont::wrap_under_create_rule(font_ref) + } +} + +pub fn new_from_descriptor(desc: &CTFontDescriptor, pt_size: f64) -> CTFont { + unsafe { + let font_ref = CTFontCreateWithFontDescriptor(desc.as_concrete_TypeRef(), + pt_size as CGFloat, + ptr::null()); + CTFont::wrap_under_create_rule(font_ref) + } +} + +pub fn new_from_buffer(buffer: &[u8]) -> Result<CTFont, ()> { + let ct_font_descriptor = create_font_descriptor(buffer)?; + Ok(new_from_descriptor(&ct_font_descriptor, 16.0)) +} + +pub fn new_from_name(name: &str, pt_size: f64) -> Result<CTFont, ()> { + unsafe { + let name: CFString = name.parse().unwrap(); + let font_ref = CTFontCreateWithName(name.as_concrete_TypeRef(), + pt_size as CGFloat, + ptr::null()); + if font_ref.is_null() { + Err(()) + } else { + Ok(CTFont::wrap_under_create_rule(font_ref)) + } + } +} + +impl CTFont { + // Properties + pub fn symbolic_traits(&self) -> CTFontSymbolicTraits { + unsafe { + CTFontGetSymbolicTraits(self.0) + } + } +} + +impl CTFont { + // Creation methods + pub fn copy_to_CGFont(&self) -> CGFont { + unsafe { + let cgfont_ref = CTFontCopyGraphicsFont(self.0, ptr::null_mut()); + CGFont::from_ptr(cgfont_ref as *mut _) + } + } + + pub fn copy_descriptor(&self) -> CTFontDescriptor { + unsafe { + let desc = CTFontCopyFontDescriptor(self.0); + CTFontDescriptor::wrap_under_create_rule(desc) + } + } + + pub fn clone_with_font_size(&self, size: f64) -> CTFont { + unsafe { + let font_ref = CTFontCreateCopyWithAttributes(self.0, + size as CGFloat, + ptr::null(), + ptr::null()); + CTFont::wrap_under_create_rule(font_ref) + } + } + + pub fn clone_with_symbolic_traits(&self, + trait_value: CTFontSymbolicTraits, + trait_mask: CTFontSymbolicTraits) + -> Option<CTFont> { + unsafe { + let font_ref = CTFontCreateCopyWithSymbolicTraits(self.0, + 0.0, + ptr::null(), + trait_value, + trait_mask); + if font_ref.is_null() { + None + } else { + Some(CTFont::wrap_under_create_rule(font_ref)) + } + } + } + + // Names + pub fn family_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontFamilyNameKey); + value.expect("Fonts should always have a family name.") + } + } + + pub fn face_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontSubFamilyNameKey); + value.expect("Fonts should always have a face name.") + } + } + + pub fn unique_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontUniqueNameKey); + value.expect("Fonts should always have a unique name.") + } + } + + pub fn postscript_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontPostScriptNameKey); + value.expect("Fonts should always have a PostScript name.") + } + } + + pub fn display_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontFullNameKey); + value.expect("Fonts should always have a PostScript name.") + } + } + + pub fn style_name(&self) -> String { + unsafe { + let value = get_string_by_name_key(self, kCTFontStyleNameKey); + value.expect("Fonts should always have a style name.") + } + } + + pub fn all_traits(&self) -> CTFontTraits { + unsafe { + CTFontTraits::wrap_under_create_rule(CTFontCopyTraits(self.0)) + } + } + + // Font metrics + pub fn ascent(&self) -> CGFloat { + unsafe { + CTFontGetAscent(self.0) + } + } + + pub fn descent(&self) -> CGFloat { + unsafe { + CTFontGetDescent(self.0) + } + } + + pub fn underline_thickness(&self) -> CGFloat { + unsafe { + CTFontGetUnderlineThickness(self.0) + } + } + + pub fn underline_position(&self) -> CGFloat { + unsafe { + CTFontGetUnderlinePosition(self.0) + } + } + + pub fn slant_angle(&self) -> CGFloat { + unsafe { + CTFontGetSlantAngle(self.0) + } + } + + pub fn cap_height(&self) -> CGFloat { + unsafe { + CTFontGetCapHeight(self.0) + } + } + + pub fn bounding_box(&self) -> CGRect { + unsafe { + CTFontGetBoundingBox(self.0) + } + } + + pub fn leading(&self) -> CGFloat { + unsafe { + CTFontGetLeading(self.0) + } + } + + pub fn units_per_em(&self) -> libc::c_uint { + unsafe { + CTFontGetUnitsPerEm(self.0) + } + } + + pub fn x_height(&self) -> CGFloat { + unsafe { + CTFontGetXHeight(self.0) + } + } + + pub fn pt_size(&self) -> CGFloat { + unsafe { + CTFontGetSize(self.0) + } + } + + pub fn get_glyph_with_name(&self, glyph_name: &str) -> CGGlyph { + let glyph_name = CFString::new(glyph_name); + unsafe { + CTFontGetGlyphWithName(self.0, glyph_name.as_concrete_TypeRef()) + } + } + + pub unsafe fn get_glyphs_for_characters(&self, + characters: *const UniChar, + glyphs: *mut CGGlyph, + count: CFIndex) + -> bool { + CTFontGetGlyphsForCharacters(self.0, characters, glyphs, count) + } + + pub unsafe fn get_advances_for_glyphs(&self, + orientation: CTFontOrientation, + glyphs: *const CGGlyph, + advances: *mut CGSize, + count: CFIndex) + -> f64 { + CTFontGetAdvancesForGlyphs(self.0, orientation, glyphs, advances, count) as f64 + } + + pub unsafe fn get_vertical_translations_for_glyphs(&self, + orientation: CTFontOrientation, + glyphs: *const CGGlyph, + translations: *mut CGSize, + count: CFIndex) { + CTFontGetVerticalTranslationsForGlyphs(self.0, + orientation, + glyphs, + translations, + count) + } + + pub fn get_font_table(&self, tag: u32) -> Option<CFData> { + unsafe { + let result = CTFontCopyTable(self.0, + tag as CTFontTableTag, + kCTFontTableOptionsExcludeSynthetic); + if result.is_null() { + None + } else { + Some(CFData::wrap_under_create_rule(result)) + } + } + } + + pub fn get_available_font_tables(&self) -> Option<CFArray<CTFontTableTag>> { + unsafe { + let result = CTFontCopyAvailableTables(self.0, kCTFontTableOptionsExcludeSynthetic); + if result.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(result)) + } + } + } + + pub fn get_bounding_rects_for_glyphs(&self, orientation: CTFontOrientation, glyphs: &[CGGlyph]) + -> CGRect { + unsafe { + CTFontGetBoundingRectsForGlyphs(self.as_concrete_TypeRef(), + orientation, + glyphs.as_ptr(), + ptr::null_mut(), + glyphs.len() as CFIndex) + } + } + + pub fn draw_glyphs(&self, glyphs: &[CGGlyph], positions: &[CGPoint], context: CGContext) { + assert_eq!(glyphs.len(), positions.len()); + unsafe { + CTFontDrawGlyphs(self.as_concrete_TypeRef(), + glyphs.as_ptr(), + positions.as_ptr(), + glyphs.len() as size_t, + context.as_ptr()) + } + } + + pub fn url(&self) -> Option<CFURL> { + unsafe { + let result = CTFontCopyAttribute(self.0, kCTFontURLAttribute); + if result.is_null() { + None + } else { + Some(CFURL::wrap_under_create_rule(result as CFURLRef)) + } + } + } + + pub fn get_variation_axes(&self) -> Option<CFArray<CFDictionary<CFString, CFType>>> { + unsafe { + let axes = CTFontCopyVariationAxes(self.0); + if axes.is_null() { + return None; + } + Some(TCFType::wrap_under_create_rule(axes)) + } + } + + pub fn create_path_for_glyph(&self, glyph: CGGlyph, matrix: &CGAffineTransform) + -> Result<CGPath, ()> { + unsafe { + let path = CTFontCreatePathForGlyph(self.0, glyph, matrix); + if path.is_null() { + Err(()) + } else { + Ok(CGPath::from_ptr(path)) + } + } + } + + #[inline] + pub fn glyph_count(&self) -> CFIndex { + unsafe { + CTFontGetGlyphCount(self.0) + } + } +} + +// Helper methods +fn get_string_by_name_key(font: &CTFont, name_key: CFStringRef) -> Option<String> { + unsafe { + let result = CTFontCopyName(font.as_concrete_TypeRef(), name_key); + if result.is_null() { + None + } else { + Some(CFString::wrap_under_create_rule(result).to_string()) + } + } +} + +pub fn debug_font_names(font: &CTFont) { + fn get_key(font: &CTFont, key: CFStringRef) -> String { + get_string_by_name_key(font, key).unwrap() + } + + unsafe { + println!("kCTFontFamilyNameKey: {}", get_key(font, kCTFontFamilyNameKey)); + println!("kCTFontSubFamilyNameKey: {}", get_key(font, kCTFontSubFamilyNameKey)); + println!("kCTFontStyleNameKey: {}", get_key(font, kCTFontStyleNameKey)); + println!("kCTFontUniqueNameKey: {}", get_key(font, kCTFontUniqueNameKey)); + println!("kCTFontFullNameKey: {}", get_key(font, kCTFontFullNameKey)); + println!("kCTFontPostScriptNameKey: {}", get_key(font, kCTFontPostScriptNameKey)); + } +} + +pub fn debug_font_traits(font: &CTFont) { + let sym = font.symbolic_traits(); + println!("kCTFontItalicTrait: {}", sym.is_italic()); + println!("kCTFontBoldTrait: {}", sym.is_bold()); + println!("kCTFontExpandedTrait: {}", sym.is_expanded()); + println!("kCTFontCondensedTrait: {}", sym.is_condensed()); + println!("kCTFontMonoSpaceTrait: {}", sym.is_monospace()); + + let traits = font.all_traits(); + println!("kCTFontWeightTrait: {}", traits.normalized_weight()); + println!("kCTFontWidthTrait: {}", traits.normalized_width()); +// println!("kCTFontSlantTrait: {}", traits.normalized_slant()); +} + +#[cfg(feature = "mountainlion")] +pub fn cascade_list_for_languages(font: &CTFont, language_pref_list: &CFArray<CFString>) -> CFArray<CTFontDescriptor> { + unsafe { + let font_collection_ref = + CTFontCopyDefaultCascadeListForLanguages(font.as_concrete_TypeRef(), + language_pref_list.as_concrete_TypeRef()); + CFArray::wrap_under_create_rule(font_collection_ref) + } +} + +#[link(name = "CoreText", kind = "framework")] +extern { + /* + * CTFont.h + */ + + /* Name Specifier Constants */ + //static kCTFontCopyrightNameKey: CFStringRef; + static kCTFontFamilyNameKey: CFStringRef; + static kCTFontSubFamilyNameKey: CFStringRef; + static kCTFontStyleNameKey: CFStringRef; + static kCTFontUniqueNameKey: CFStringRef; + static kCTFontFullNameKey: CFStringRef; + //static kCTFontVersionNameKey: CFStringRef; + static kCTFontPostScriptNameKey: CFStringRef; + //static kCTFontTrademarkNameKey: CFStringRef; + //static kCTFontManufacturerNameKey: CFStringRef; + //static kCTFontDesignerNameKey: CFStringRef; + //static kCTFontDescriptionNameKey: CFStringRef; + //static kCTFontVendorURLNameKey: CFStringRef; + //static kCTFontDesignerURLNameKey: CFStringRef; + //static kCTFontLicenseNameKey: CFStringRef; + //static kCTFontLicenseURLNameKey: CFStringRef; + //static kCTFontSampleTextNameKey: CFStringRef; + //static kCTFontPostScriptCIDNameKey: CFStringRef; + + //static kCTFontVariationAxisIdentifierKey: CFStringRef; + //static kCTFontVariationAxisMinimumValueKey: CFStringRef; + //static kCTFontVariationAxisMaximumValueKey: CFStringRef; + //static kCTFontVariationAxisDefaultValueKey: CFStringRef; + //static kCTFontVariationAxisNameKey: CFStringRef; + + //static kCTFontFeatureTypeIdentifierKey: CFStringRef; + //static kCTFontFeatureTypeNameKey: CFStringRef; + //static kCTFontFeatureTypeExclusiveKey: CFStringRef; + //static kCTFontFeatureTypeSelectorsKey: CFStringRef; + //static kCTFontFeatureSelectorIdentifierKey: CFStringRef; + //static kCTFontFeatureSelectorNameKey: CFStringRef; + //static kCTFontFeatureSelectorDefaultKey: CFStringRef; + //static kCTFontFeatureSelectorSettingKey: CFStringRef; + + static kCTFontURLAttribute: CFStringRef; + + // N.B. Unlike most Cocoa bindings, this extern block is organized according + // to the documentation's Functions By Task listing, because there so many functions. + + /* Creating Fonts */ + fn CTFontCreateWithName(name: CFStringRef, size: CGFloat, matrix: *const CGAffineTransform) -> CTFontRef; + //fn CTFontCreateWithNameAndOptions + fn CTFontCreateWithFontDescriptor(descriptor: CTFontDescriptorRef, size: CGFloat, + matrix: *const CGAffineTransform) -> CTFontRef; + //fn CTFontCreateWithFontDescriptorAndOptions + #[cfg(test)] + fn CTFontCreateUIFontForLanguage(uiType: CTFontUIFontType, size: CGFloat, language: CFStringRef) -> CTFontRef; + fn CTFontCreateCopyWithAttributes(font: CTFontRef, size: CGFloat, matrix: *const CGAffineTransform, + attributes: CTFontDescriptorRef) -> CTFontRef; + fn CTFontCreateCopyWithSymbolicTraits(font: CTFontRef, + size: CGFloat, + matrix: *const CGAffineTransform, + symTraitValue: CTFontSymbolicTraits, + symTraitMask: CTFontSymbolicTraits) + -> CTFontRef; + //fn CTFontCreateCopyWithFamily + //fn CTFontCreateForString + + /* Getting Font Data */ + fn CTFontCopyFontDescriptor(font: CTFontRef) -> CTFontDescriptorRef; + fn CTFontCopyAttribute(font: CTFontRef, attribute: CFStringRef) -> CFTypeRef; + fn CTFontGetSize(font: CTFontRef) -> CGFloat; + //fn CTFontGetMatrix + fn CTFontGetSymbolicTraits(font: CTFontRef) -> CTFontSymbolicTraits; + fn CTFontCopyTraits(font: CTFontRef) -> CFDictionaryRef; + + /* Getting Font Names */ + //fn CTFontCopyPostScriptName(font: CTFontRef) -> CFStringRef; + //fn CTFontCopyFamilyName(font: CTFontRef) -> CFStringRef; + //fn CTFontCopyFullName(font: CTFontRef) -> CFStringRef; + //fn CTFontCopyDisplayName(font: CTFontRef) -> CFStringRef; + fn CTFontCopyName(font: CTFontRef, nameKey: CFStringRef) -> CFStringRef; + //fn CTFontCopyLocalizedName(font: CTFontRef, nameKey: CFStringRef, + // language: *CFStringRef) -> CFStringRef; + #[cfg(feature = "mountainlion")] + fn CTFontCopyDefaultCascadeListForLanguages(font: CTFontRef, languagePrefList: CFArrayRef) -> CFArrayRef; + + + /* Working With Encoding */ + //fn CTFontCopyCharacterSet + //fn CTFontGetStringEncoding + //fn CTFontCopySupportedLanguages + + /* Getting Font Metrics */ + fn CTFontGetAscent(font: CTFontRef) -> CGFloat; + fn CTFontGetDescent(font: CTFontRef) -> CGFloat; + fn CTFontGetLeading(font: CTFontRef) -> CGFloat; + fn CTFontGetUnitsPerEm(font: CTFontRef) -> libc::c_uint; + fn CTFontGetGlyphCount(font: CTFontRef) -> CFIndex; + fn CTFontGetBoundingBox(font: CTFontRef) -> CGRect; + fn CTFontGetUnderlinePosition(font: CTFontRef) -> CGFloat; + fn CTFontGetUnderlineThickness(font: CTFontRef) -> CGFloat; + fn CTFontGetSlantAngle(font: CTFontRef) -> CGFloat; + fn CTFontGetCapHeight(font: CTFontRef) -> CGFloat; + fn CTFontGetXHeight(font: CTFontRef) -> CGFloat; + + /* Getting Glyph Data */ + fn CTFontCreatePathForGlyph(font: CTFontRef, glyph: CGGlyph, matrix: *const CGAffineTransform) + -> CGPathRef; + fn CTFontGetGlyphWithName(font: CTFontRef, glyphName: CFStringRef) -> CGGlyph; + fn CTFontGetBoundingRectsForGlyphs(font: CTFontRef, + orientation: CTFontOrientation, + glyphs: *const CGGlyph, + boundingRects: *mut CGRect, + count: CFIndex) + -> CGRect; + fn CTFontGetAdvancesForGlyphs(font: CTFontRef, + orientation: CTFontOrientation, + glyphs: *const CGGlyph, + advances: *mut CGSize, + count: CFIndex) + -> libc::c_double; + fn CTFontGetVerticalTranslationsForGlyphs(font: CTFontRef, + orientation: CTFontOrientation, + glyphs: *const CGGlyph, + translations: *mut CGSize, + count: CFIndex); + + /* Working With Font Variations */ + fn CTFontCopyVariationAxes(font: CTFontRef) -> CFArrayRef; + //fn CTFontCopyVariation + + /* Getting Font Features */ + //fn CTFontCopyFeatures + //fn CTFontCopyFeatureSettings + + /* Working with Glyphs */ + fn CTFontGetGlyphsForCharacters(font: CTFontRef, characters: *const UniChar, glyphs: *mut CGGlyph, count: CFIndex) -> bool; + fn CTFontDrawGlyphs(font: CTFontRef, + glyphs: *const CGGlyph, + positions: *const CGPoint, + count: size_t, + context: CGContextRef); + //fn CTFontGetLigatureCaretPositions + + /* Converting Fonts */ + fn CTFontCopyGraphicsFont(font: CTFontRef, attributes: *mut CTFontDescriptorRef) + -> CGFontRef; + fn CTFontCreateWithGraphicsFont(graphicsFont: CGFontRef, size: CGFloat, + matrix: *const CGAffineTransform, + attributes: CTFontDescriptorRef) -> CTFontRef; + //fn CTFontGetPlatformFont + //fn CTFontCreateWithPlatformFont + //fn CTFontCreateWithQuickdrawInstance + + /* Getting Font Table Data */ + fn CTFontCopyAvailableTables(font: CTFontRef, options: CTFontTableOptions) -> CFArrayRef; + fn CTFontCopyTable(font: CTFontRef, table: CTFontTableTag, options: CTFontTableOptions) -> CFDataRef; + + fn CTFontGetTypeID() -> CFTypeID; +} + +#[test] +fn copy_font() { + use std::io::Read; + let mut f = std::fs::File::open("/System/Library/Fonts/ZapfDingbats.ttf").unwrap(); + let mut font_data = Vec::new(); + f.read_to_end(&mut font_data).unwrap(); + let desc = crate::font_manager::create_font_descriptor(&font_data).unwrap(); + let font = new_from_descriptor(&desc, 12.); + drop(desc); + let desc = font.copy_descriptor(); + drop(font); + let font = new_from_descriptor(&desc, 14.); + assert_eq!(font.family_name(), "Zapf Dingbats"); +} + +#[cfg(test)] +fn macos_version() -> (i32, i32, i32) { + use std::io::Read; + + // This is the same approach that Firefox uses for detecting versions + let file = "/System/Library/CoreServices/SystemVersion.plist"; + let mut f = std::fs::File::open(file).unwrap(); + let mut system_version_data = Vec::new(); + f.read_to_end(&mut system_version_data).unwrap(); + + use core_foundation::propertylist; + let (list, _) = propertylist::create_with_data(core_foundation::data::CFData::from_buffer(&system_version_data), propertylist::kCFPropertyListImmutable).unwrap(); + let k = unsafe { propertylist::CFPropertyList::wrap_under_create_rule(list) }; + + let dict = unsafe { std::mem::transmute::<_, CFDictionary<CFType, CFType>>(k.downcast::<CFDictionary>().unwrap()) }; + + let version = dict.find(&CFString::new("ProductVersion").as_CFType()) + .as_ref().unwrap() + .downcast::<CFString>().unwrap() + .to_string(); + + match version.split(".").map(|x| x.parse().unwrap()).collect::<Vec<_>>()[..] { + [a, b, c] => (a, b, c), + [a, b] => (a, b, 0), + _ => panic!() + } +} + +#[test] +fn copy_system_font() { + let small = unsafe { + CTFont::wrap_under_create_rule( + CTFontCreateUIFontForLanguage(kCTFontSystemDetailFontType, 19., std::ptr::null()) + ) + }; + let big = small.clone_with_font_size(20.); + + // ensure that we end up with different fonts for the different sizes before 10.15 + if macos_version() < (10, 15, 0) { + assert_ne!(big.url(), small.url()); + } else { + assert_eq!(big.url(), small.url()); + } + + let ps = small.postscript_name(); + let desc = small.copy_descriptor(); + + // check that we can construct a new vesion by descriptor + let ctfont = new_from_descriptor(&desc, 20.); + assert_eq!(big.postscript_name(), ctfont.postscript_name()); + + // on newer versions of macos we can't construct by name anymore + if macos_version() < (10, 13, 0) { + let ui_font_by_name = new_from_name(&small.postscript_name(), 19.).unwrap(); + assert_eq!(ui_font_by_name.postscript_name(), small.postscript_name()); + + let ui_font_by_name = new_from_name(&small.postscript_name(), 20.).unwrap(); + assert_eq!(ui_font_by_name.postscript_name(), small.postscript_name()); + + let ui_font_by_name = new_from_name(&big.postscript_name(), 20.).unwrap(); + assert_eq!(ui_font_by_name.postscript_name(), big.postscript_name()); + } + + // but we can still construct the CGFont by name + let cgfont = CGFont::from_name(&CFString::new(&ps)).unwrap(); + let cgfont = new_from_CGFont(&cgfont, 0.); + println!("{:?}", cgfont); + let desc = cgfont.copy_descriptor(); + let matching = unsafe { crate::font_descriptor::CTFontDescriptorCreateMatchingFontDescriptor(desc.as_concrete_TypeRef(), std::ptr::null()) }; + let matching = unsafe { CTFontDescriptor::wrap_under_create_rule(matching) }; + + println!("{:?}", cgfont.copy_descriptor()); + assert!(desc.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_some()); + + println!("{:?}", matching); + println!("{:?}", matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute"))); + + assert!(matching.attributes().find(CFString::from_static_string("NSFontSizeAttribute")).is_none()); + + assert_eq!(small.postscript_name(), cgfont.postscript_name()); +}
\ No newline at end of file diff --git a/third_party/rust/core-text/src/font_collection.rs b/third_party/rust/core-text/src/font_collection.rs new file mode 100644 index 0000000000..8f3f2c5619 --- /dev/null +++ b/third_party/rust/core-text/src/font_collection.rs @@ -0,0 +1,131 @@ +// 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 font_descriptor; +use font_descriptor::{CTFontDescriptor, CTFontDescriptorCreateMatchingFontDescriptors}; +use font_manager::{CTFontManagerCopyAvailableFontFamilyNames, CTFontManagerCopyAvailablePostScriptNames}; + +use core_foundation::array::{CFArray, CFArrayRef}; +use core_foundation::base::{CFTypeID, TCFType}; +use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; +use core_foundation::number::CFNumber; +use core_foundation::set::CFSet; +use core_foundation::string::{CFString, CFStringRef}; + +use std::os::raw::c_void; + +#[repr(C)] +pub struct __CTFontCollection(c_void); + +pub type CTFontCollectionRef = *const __CTFontCollection; + +declare_TCFType! { + CTFontCollection, CTFontCollectionRef +} +impl_TCFType!(CTFontCollection, CTFontCollectionRef, CTFontCollectionGetTypeID); +impl_CFTypeDescription!(CTFontCollection); + + +impl CTFontCollection { + pub fn get_descriptors(&self) -> Option<CFArray<CTFontDescriptor>> { + // surprise! this function follows the Get rule, despite being named *Create*. + // So we have to addRef it to avoid CTFontCollection from double freeing it later. + unsafe { + let font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(self.0); + if font_descriptors.is_null() { + // This returns null if there are no matching font descriptors. + None + } else { + Some(CFArray::wrap_under_get_rule(font_descriptors)) + } + } + } +} + +pub fn new_from_descriptors(descs: &CFArray<CTFontDescriptor>) -> CTFontCollection { + unsafe { + let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption); + let value = CFNumber::from(1i64); + let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]); + let font_collection_ref = + CTFontCollectionCreateWithFontDescriptors(descs.as_concrete_TypeRef(), + options.as_concrete_TypeRef()); + CTFontCollection::wrap_under_create_rule(font_collection_ref) + } +} + +pub fn create_for_all_families() -> CTFontCollection { + unsafe { + let key = CFString::wrap_under_get_rule(kCTFontCollectionRemoveDuplicatesOption); + let value = CFNumber::from(1i64); + let options = CFDictionary::from_CFType_pairs(&[ (key.as_CFType(), value.as_CFType()) ]); + let font_collection_ref = + CTFontCollectionCreateFromAvailableFonts(options.as_concrete_TypeRef()); + CTFontCollection::wrap_under_create_rule(font_collection_ref) + } +} + +pub fn create_for_family(family: &str) -> Option<CTFontCollection> { + use font_descriptor::kCTFontFamilyNameAttribute; + + unsafe { + let family_attr = CFString::wrap_under_get_rule(kCTFontFamilyNameAttribute); + let family_name: CFString = family.parse().unwrap(); + let specified_attrs = CFDictionary::from_CFType_pairs(&[ + (family_attr.clone(), family_name.as_CFType()) + ]); + + let wildcard_desc: CTFontDescriptor = + font_descriptor::new_from_attributes(&specified_attrs); + let mandatory_attrs = CFSet::from_slice(&[ family_attr.as_CFType() ]); + let matched_descs = CTFontDescriptorCreateMatchingFontDescriptors( + wildcard_desc.as_concrete_TypeRef(), + mandatory_attrs.as_concrete_TypeRef()); + if matched_descs.is_null() { + return None; + } + let matched_descs = CFArray::wrap_under_create_rule(matched_descs); + // I suppose one doesn't even need the CTFontCollection object at this point. + // But we stick descriptors into and out of it just to provide a nice wrapper API. + Some(new_from_descriptors(&matched_descs)) + } +} + +pub fn get_family_names() -> CFArray<CFString> { + unsafe { + CFArray::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames()) + } +} + +pub fn get_postscript_names() -> CFArray<CFString> { + unsafe { + CFArray::wrap_under_create_rule(CTFontManagerCopyAvailablePostScriptNames()) + } +} + +extern { + /* + * CTFontCollection.h + */ + + static kCTFontCollectionRemoveDuplicatesOption: CFStringRef; + + //fn CTFontCollectionCreateCopyWithFontDescriptors(original: CTFontCollectionRef, + // descriptors: CFArrayRef, + // options: CFDictionaryRef) -> CTFontCollectionRef; + fn CTFontCollectionCreateFromAvailableFonts(options: CFDictionaryRef) -> CTFontCollectionRef; + // this stupid function doesn't actually do any wildcard expansion; + // it just chooses the best match. Use + // CTFontDescriptorCreateMatchingDescriptors instead. + fn CTFontCollectionCreateMatchingFontDescriptors(collection: CTFontCollectionRef) -> CFArrayRef; + fn CTFontCollectionCreateWithFontDescriptors(descriptors: CFArrayRef, + options: CFDictionaryRef) -> CTFontCollectionRef; + //fn CTFontCollectionCreateMatchingFontDescriptorsSortedWithCallback; + fn CTFontCollectionGetTypeID() -> CFTypeID; +} diff --git a/third_party/rust/core-text/src/font_descriptor.rs b/third_party/rust/core-text/src/font_descriptor.rs new file mode 100644 index 0000000000..c70495c829 --- /dev/null +++ b/third_party/rust/core-text/src/font_descriptor.rs @@ -0,0 +1,404 @@ +// 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. + +#![allow(non_upper_case_globals)] + +use core_foundation::array::CFArrayRef; +use core_foundation::base::{CFType, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; +use core_foundation::number::{CFNumber, CFNumberRef}; +use core_foundation::set::CFSetRef; +use core_foundation::string::{CFString, CFStringRef}; +use core_foundation::url::{CFURL, CFURLRef}; +use core_graphics::base::CGFloat; + +use std::os::raw::c_void; +use std::path::PathBuf; + +/* +* CTFontTraits.h +*/ +// actually, these are extern enums +pub type CTFontFormat = u32; +pub const kCTFontFormatUnrecognized: CTFontFormat = 0; +pub const kCTFontFormatOpenTypePostScript: CTFontFormat = 1; +pub const kCTFontFormatOpenTypeTrueType: CTFontFormat = 2; +pub const kCTFontFormatTrueType: CTFontFormat = 3; +pub const kCTFontFormatPostScript: CTFontFormat = 4; +pub const kCTFontFormatBitmap: CTFontFormat = 5; + +pub const kCTFontClassMaskShift: u32 = 28; + +pub type CTFontSymbolicTraits = u32; +pub const kCTFontItalicTrait: CTFontSymbolicTraits = 1 << 0; +pub const kCTFontBoldTrait: CTFontSymbolicTraits = 1 << 1; +pub const kCTFontExpandedTrait: CTFontSymbolicTraits = 1 << 5; +pub const kCTFontCondensedTrait: CTFontSymbolicTraits = 1 << 6; +pub const kCTFontMonoSpaceTrait: CTFontSymbolicTraits = 1 << 10; +pub const kCTFontVerticalTrait: CTFontSymbolicTraits = 1 << 11; +pub const kCTFontUIOptimizedTrait: CTFontSymbolicTraits = 1 << 12; +pub const kCTFontColorGlyphsTrait: CTFontSymbolicTraits = 1 << 13; +pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = 15 << kCTFontClassMaskShift; + +pub trait SymbolicTraitAccessors { + fn is_italic(&self) -> bool; + fn is_bold(&self) -> bool; + fn is_expanded(&self) -> bool; + fn is_condensed(&self) -> bool; + fn is_monospace(&self) -> bool; + fn is_vertical(&self) -> bool; +} + +impl SymbolicTraitAccessors for CTFontSymbolicTraits { + fn is_italic(&self) -> bool { (*self & kCTFontItalicTrait) != 0 } + fn is_bold(&self) -> bool { (*self & kCTFontBoldTrait) != 0 } + fn is_expanded(&self) -> bool { (*self & kCTFontExpandedTrait) != 0 } + fn is_condensed(&self) -> bool { (*self & kCTFontCondensedTrait) != 0 } + fn is_monospace(&self) -> bool { (*self & kCTFontMonoSpaceTrait) != 0 } + fn is_vertical(&self) -> bool { (*self & kCTFontVerticalTrait) != 0 } +} + +pub type CTFontStylisticClass = u32; +pub const kCTFontUnknownClass: CTFontStylisticClass = 0 << kCTFontClassMaskShift; +pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = 1 << kCTFontClassMaskShift; +pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = 2 << kCTFontClassMaskShift; +pub const kCTFontModernSerifsClass: CTFontStylisticClass = 3 << kCTFontClassMaskShift; +pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = 4 << kCTFontClassMaskShift; +pub const kCTFontSlabSerifsClass: CTFontStylisticClass = 5 << kCTFontClassMaskShift; +pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = 7 << kCTFontClassMaskShift; +pub const kCTFontSansSerifClass: CTFontStylisticClass = 8 << kCTFontClassMaskShift; +pub const kCTFontOrnamentalsClass: CTFontStylisticClass = 9 << kCTFontClassMaskShift; +pub const kCTFontScriptsClass: CTFontStylisticClass = 10 << kCTFontClassMaskShift; +pub const kCTFontSymbolicClass: CTFontStylisticClass = 12 << kCTFontClassMaskShift; + +pub trait StylisticClassAccessors { + fn is_serif(&self) -> bool; + fn is_sans_serif(&self) -> bool; + fn is_script(&self) -> bool; + fn is_fantasy(&self) -> bool; + fn is_symbols(&self) -> bool; +} + +impl StylisticClassAccessors for CTFontStylisticClass { + fn is_serif(&self) -> bool { + let any_serif_class = kCTFontOldStyleSerifsClass + | kCTFontTransitionalSerifsClass + | kCTFontModernSerifsClass + | kCTFontClarendonSerifsClass + | kCTFontSlabSerifsClass + | kCTFontFreeformSerifsClass; + + (*self & any_serif_class) != 0 + } + + fn is_sans_serif(&self) -> bool { + (*self & kCTFontSansSerifClass) != 0 + } + + fn is_script(&self) -> bool { + (*self & kCTFontScriptsClass) != 0 + } + + fn is_fantasy(&self) -> bool { + (*self & kCTFontOrnamentalsClass) != 0 + } + + fn is_symbols(&self) -> bool { + (*self & kCTFontSymbolicClass) != 0 + } +} + +pub type CTFontAttributes = CFDictionary; + +pub type CTFontTraits = CFDictionary<CFString, CFType>; + +pub trait TraitAccessors { + fn symbolic_traits(&self) -> CTFontSymbolicTraits; + fn normalized_weight(&self) -> f64; + fn normalized_width(&self) -> f64; + fn normalized_slant(&self) -> f64; +} + +trait TraitAccessorPrivate { + fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber; +} + +impl TraitAccessorPrivate for CTFontTraits { + fn extract_number_for_key(&self, key: CFStringRef) -> CFNumber { + let cftype = self.get(key); + cftype.downcast::<CFNumber>().unwrap() + } + +} + +impl TraitAccessors for CTFontTraits { + fn symbolic_traits(&self) -> CTFontSymbolicTraits { + unsafe { + let number = self.extract_number_for_key(kCTFontSymbolicTrait); + number.to_i64().unwrap() as u32 + } + } + + fn normalized_weight(&self) -> f64 { + unsafe { + let number = self.extract_number_for_key(kCTFontWeightTrait); + number.to_f64().unwrap() + } + } + + fn normalized_width(&self) -> f64 { + unsafe { + let number = self.extract_number_for_key(kCTFontWidthTrait); + number.to_f64().unwrap() + } + } + + fn normalized_slant(&self) -> f64 { + unsafe { + let number = self.extract_number_for_key(kCTFontSlantTrait); + number.to_f64().unwrap() + } + } +} + +/* +* CTFontDescriptor.h +*/ +pub type CTFontOrientation = u32; +pub const kCTFontDefaultOrientation: CTFontOrientation = 0; +pub const kCTFontHorizontalOrientation: CTFontOrientation = 1; +pub const kCTFontVerticalOrientation: CTFontOrientation = 2; + +pub type CTFontPriority = u32; +pub const kCTFontPrioritySystem: CTFontPriority = 10000; +pub const kCTFontPriorityNetwork: CTFontPriority = 20000; +pub const kCTFontPriorityComputer: CTFontPriority = 30000; +pub const kCTFontPriorityUser: CTFontPriority = 40000; +pub const kCTFontPriorityDynamic: CTFontPriority = 50000; +pub const kCTFontPriorityProcess: CTFontPriority = 60000; + +#[repr(C)] +pub struct __CTFontDescriptor(c_void); + +pub type CTFontDescriptorRef = *const __CTFontDescriptor; + +declare_TCFType! { + CTFontDescriptor, CTFontDescriptorRef +} +impl_TCFType!(CTFontDescriptor, CTFontDescriptorRef, CTFontDescriptorGetTypeID); +impl_CFTypeDescription!(CTFontDescriptor); + +// "Font objects (CTFont, CTFontDescriptor, and associated objects) can be used +// simultaneously by multiple operations, work queues, or threads." +unsafe impl Send for CTFontDescriptor {} +unsafe impl Sync for CTFontDescriptor {} + +impl CTFontDescriptor { + fn get_string_attribute(&self, attribute: CFStringRef) -> Option<String> { + unsafe { + let value = CTFontDescriptorCopyAttribute(self.0, attribute); + if value.is_null() { + return None + } + + let value = CFType::wrap_under_create_rule(value); + assert!(value.instance_of::<CFString>()); + let s = CFString::wrap_under_get_rule(value.as_CFTypeRef() as CFStringRef); + Some(s.to_string()) + } + } + +} + +impl CTFontDescriptor { + pub fn family_name(&self) -> String { + unsafe { + let value = self.get_string_attribute(kCTFontFamilyNameAttribute); + value.expect("A font must have a non-null family name.") + } + } + + pub fn font_name(&self) -> String { + unsafe { + let value = self.get_string_attribute(kCTFontNameAttribute); + value.expect("A font must have a non-null name.") + } + } + + pub fn style_name(&self) -> String { + unsafe { + let value = self.get_string_attribute(kCTFontStyleNameAttribute); + value.expect("A font must have a non-null style name.") + } + } + + pub fn display_name(&self) -> String { + unsafe { + let value = self.get_string_attribute(kCTFontDisplayNameAttribute); + value.expect("A font must have a non-null display name.") + } + } + + pub fn font_format(&self) -> Option<CTFontFormat> { + unsafe { + let value = CTFontDescriptorCopyAttribute(self.0, kCTFontFormatAttribute); + if value.is_null() { + return None; + } + + let value = CFType::wrap_under_create_rule(value); + assert!(value.instance_of::<CFNumber>()); + let format = CFNumber::wrap_under_get_rule(value.as_CFTypeRef() as CFNumberRef); + format.to_i32().map(|x| x as CTFontFormat) + } + } + + pub fn font_path(&self) -> Option<PathBuf> { + unsafe { + let value = CTFontDescriptorCopyAttribute(self.0, kCTFontURLAttribute); + if value.is_null() { + return None; + } + + let value = CFType::wrap_under_create_rule(value); + assert!(value.instance_of::<CFURL>()); + let url = CFURL::wrap_under_get_rule(value.as_CFTypeRef() as CFURLRef); + url.to_path() + } + } + + pub fn traits(&self) -> CTFontTraits { + unsafe { + let value = CTFontDescriptorCopyAttribute(self.0, kCTFontTraitsAttribute); + assert!(!value.is_null()); + let value = CFType::wrap_under_create_rule(value); + assert!(value.instance_of::<CFDictionary>()); + CFDictionary::wrap_under_get_rule(value.as_CFTypeRef() as CFDictionaryRef) + } + } + + pub fn create_copy_with_attributes(&self, attr: CFDictionary) -> Result<CTFontDescriptor, ()> { + unsafe { + let desc = CTFontDescriptorCreateCopyWithAttributes(self.as_concrete_TypeRef(), + attr.as_concrete_TypeRef()); + if desc.is_null() { + return Err(()); + } + Ok(CTFontDescriptor::wrap_under_create_rule(desc)) + } + } + + pub fn attributes(&self) -> CFDictionary<CFString, CFType> { + unsafe { + let attrs = CTFontDescriptorCopyAttributes(self.as_concrete_TypeRef()); + CFDictionary::wrap_under_create_rule(attrs) + } + } +} + +pub fn new_from_attributes(attributes: &CFDictionary<CFString, CFType>) -> CTFontDescriptor { + unsafe { + let result: CTFontDescriptorRef = + CTFontDescriptorCreateWithAttributes(attributes.as_concrete_TypeRef()); + CTFontDescriptor::wrap_under_create_rule(result) + } +} + +pub fn new_from_variations(variations: &CFDictionary<CFString, CFNumber>) -> CTFontDescriptor { + unsafe { + let var_key = CFString::wrap_under_get_rule(kCTFontVariationAttribute); + let var_val = CFType::wrap_under_get_rule(variations.as_CFTypeRef()); + let attributes = CFDictionary::from_CFType_pairs(&[(var_key, var_val)]); + new_from_attributes(&attributes) + } +} + +pub fn new_from_postscript_name(name: &CFString) -> CTFontDescriptor { + unsafe { + let result: CTFontDescriptorRef = + CTFontDescriptorCreateWithNameAndSize(name.as_concrete_TypeRef(), 0.0); + CTFontDescriptor::wrap_under_create_rule(result) + } +} + +pub fn debug_descriptor(desc: &CTFontDescriptor) { + println!("family: {}", desc.family_name()); + println!("name: {}", desc.font_name()); + println!("style: {}", desc.style_name()); + println!("display: {}", desc.display_name()); + println!("path: {:?}", desc.font_path()); + desc.show(); +} + +extern { + /* + * CTFontTraits.h + */ + + // font trait constants + pub static kCTFontSymbolicTrait: CFStringRef; + pub static kCTFontWeightTrait: CFStringRef; + pub static kCTFontWidthTrait: CFStringRef; + pub static kCTFontSlantTrait: CFStringRef; + + /* + * CTFontDescriptor.h + */ + + // font attribute constants. Note that the name-related attributes + // here are somewhat flaky. Servo creates CTFont instances and + // then uses CTFontCopyName to get more fine-grained names. + pub static kCTFontURLAttribute: CFStringRef; // value: CFURLRef + pub static kCTFontNameAttribute: CFStringRef; // value: CFStringRef + pub static kCTFontDisplayNameAttribute: CFStringRef; // value: CFStringRef + pub static kCTFontFamilyNameAttribute: CFStringRef; // value: CFStringRef + pub static kCTFontStyleNameAttribute: CFStringRef; // value: CFStringRef + pub static kCTFontTraitsAttribute: CFStringRef; + pub static kCTFontVariationAttribute: CFStringRef; + pub static kCTFontSizeAttribute: CFStringRef; + pub static kCTFontMatrixAttribute: CFStringRef; + pub static kCTFontCascadeListAttribute: CFStringRef; + pub static kCTFontCharacterSetAttribute: CFStringRef; + pub static kCTFontLanguagesAttribute: CFStringRef; + pub static kCTFontBaselineAdjustAttribute: CFStringRef; + pub static kCTFontMacintoshEncodingsAttribute: CFStringRef; + pub static kCTFontFeaturesAttribute: CFStringRef; + pub static kCTFontFeatureSettingsAttribute: CFStringRef; + pub static kCTFontFixedAdvanceAttribute: CFStringRef; + pub static kCTFontOrientationAttribute: CFStringRef; + pub static kCTFontFormatAttribute: CFStringRef; + pub static kCTFontRegistrationScopeAttribute: CFStringRef; + pub static kCTFontPriorityAttribute: CFStringRef; + pub static kCTFontEnabledAttribute: CFStringRef; + + pub fn CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef, + attribute: CFStringRef) -> CFTypeRef; + pub fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef; + pub fn CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef, + attribute: CFStringRef, + language: *mut CFStringRef) -> CFTypeRef; + pub fn CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef, + attributes: CFDictionaryRef) -> CTFontDescriptorRef; + pub fn CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef, + featureTypeIdentifier: CFNumberRef, + featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef; + pub fn CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef, + variationIdentifier: CFNumberRef, + variationValue: CGFloat) -> CTFontDescriptorRef; + pub fn CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef, + mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef; + pub fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef; + pub fn CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef; + pub fn CTFontDescriptorGetTypeID() -> CFTypeID; +} + +extern { + pub fn CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef, + mandatoryAttributes: CFSetRef) -> CFArrayRef; +} diff --git a/third_party/rust/core-text/src/font_manager.rs b/third_party/rust/core-text/src/font_manager.rs new file mode 100644 index 0000000000..cdf65ee3bf --- /dev/null +++ b/third_party/rust/core-text/src/font_manager.rs @@ -0,0 +1,72 @@ +// 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 core_foundation::array::{CFArray, CFArrayRef}; +use core_foundation::base::TCFType; +use core_foundation::string::CFString; +use core_foundation::url::CFURLRef; +use core_foundation::data::{CFDataRef, CFData}; +use crate::font_descriptor::{CTFontDescriptorRef, CTFontDescriptor}; + +pub fn copy_available_font_family_names() -> CFArray<CFString> { + unsafe { + TCFType::wrap_under_create_rule(CTFontManagerCopyAvailableFontFamilyNames()) + } +} + +pub fn create_font_descriptor(buffer: &[u8]) -> Result<CTFontDescriptor, ()> { + let cf_data = CFData::from_buffer(buffer); + unsafe { + let ct_font_descriptor_ref = CTFontManagerCreateFontDescriptorFromData(cf_data.as_concrete_TypeRef()); + if ct_font_descriptor_ref.is_null() { + return Err(()); + } + Ok(CTFontDescriptor::wrap_under_create_rule(ct_font_descriptor_ref)) + } +} + +pub fn create_font_descriptor_with_data(data: CFData) -> Result<CTFontDescriptor, ()> { + unsafe { + let ct_font_descriptor_ref = CTFontManagerCreateFontDescriptorFromData(data.as_concrete_TypeRef()); + if ct_font_descriptor_ref.is_null() { + return Err(()); + } + Ok(CTFontDescriptor::wrap_under_create_rule(ct_font_descriptor_ref)) + } +} + +extern { + /* + * CTFontManager.h + */ + + // Incomplete function bindings are mostly related to CoreText font matching, which + // we implement in a platform-independent manner using FontMatcher. + + //pub fn CTFontManagerCompareFontFamilyNames + pub fn CTFontManagerCopyAvailableFontURLs() -> CFArrayRef; + pub fn CTFontManagerCopyAvailableFontFamilyNames() -> CFArrayRef; + pub fn CTFontManagerCopyAvailablePostScriptNames() -> CFArrayRef; + pub fn CTFontManagerCreateFontDescriptorsFromURL(fileURL: CFURLRef) -> CFArrayRef; + pub fn CTFontManagerCreateFontDescriptorFromData(data: CFDataRef) -> CTFontDescriptorRef; + //pub fn CTFontManagerCreateFontRequestRunLoopSource + //pub fn CTFontManagerEnableFontDescriptors + //pub fn CTFontManagerGetAutoActivationSetting + //pub fn CTFontManagerGetScopeForURL + //pub fn CTFontManagerGetAutoActivationSetting + //pub fn CTFontManagerGetScopeForURL + pub fn CTFontManagerIsSupportedFont(fontURL: CFURLRef) -> bool; + //pub fn CTFontManagerRegisterFontsForURL + //pub fn CTFontManagerRegisterFontsForURLs + //pub fn CTFontManagerRegisterGraphicsFont + //pub fn CTFontManagerSetAutoActivationSetting + //pub fn CTFontManagerUnregisterFontsForURL + //pub fn CTFontManagerUnregisterFontsForURLs + //pub fn CTFontManagerUnregisterGraphicsFont +} diff --git a/third_party/rust/core-text/src/frame.rs b/third_party/rust/core-text/src/frame.rs new file mode 100644 index 0000000000..95b97c802b --- /dev/null +++ b/third_party/rust/core-text/src/frame.rs @@ -0,0 +1,93 @@ +// 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::base::{CFRange, CFTypeID, TCFType}; +use core_foundation::array::{CFArrayRef, CFArray}; +use core_graphics::context::{CGContext, CGContextRef}; +use core_graphics::geometry::CGPoint; +use core_graphics::path::{CGPath, SysCGPathRef}; +use foreign_types::{ForeignType, ForeignTypeRef}; +use crate::line::CTLine; + +#[repr(C)] +pub struct __CTFrame(c_void); + +pub type CTFrameRef = *const __CTFrame; + +declare_TCFType! { + CTFrame, CTFrameRef +} +impl_TCFType!(CTFrame, CTFrameRef, CTFrameGetTypeID); +impl_CFTypeDescription!(CTFrame); + +impl CTFrame { + /// The `CGPath` used to create this `CTFrame`. + pub fn get_path(&self) -> CGPath { + unsafe { + CGPath::from_ptr(CTFrameGetPath(self.as_concrete_TypeRef())).clone() + } + } + + /// Returns an owned copy of the underlying lines. + /// + /// Each line is retained, and will remain valid past the life of this `CTFrame`. + pub fn get_lines(&self) -> Vec<CTLine> { + unsafe { + let array_ref = CTFrameGetLines(self.as_concrete_TypeRef()); + let array: CFArray<CTLine> = CFArray::wrap_under_get_rule(array_ref); + array.iter().map(|l| CTLine::wrap_under_get_rule(l.as_concrete_TypeRef())).collect() + } + } + + /// Return the origin of each line in a given range. + /// + /// If no range is provided, returns the origin of each line in the frame. + /// + /// If the length of the range is 0, returns the origin of all lines from + /// the range's start to the end. + /// + /// The origin is the position relative to the path used to create this `CTFFrame`; + /// to get the path use [`get_path`]. + /// + /// [`get_path`]: #method.get_path + pub fn get_line_origins(&self, range: impl Into<Option<CFRange>>) -> Vec<CGPoint> { + let range = range.into().unwrap_or_else(|| CFRange::init(0, 0)); + let len = match range.length { + // range length of 0 means 'all remaining lines' + 0 => unsafe { + let array_ref = CTFrameGetLines(self.as_concrete_TypeRef()); + let array: CFArray<CTLine> = CFArray::wrap_under_get_rule(array_ref); + array.len() - range.location + } + n => n, + }; + let len = len.max(0) as usize; + let mut out = vec![CGPoint::new(0., 0.); len]; + unsafe { + CTFrameGetLineOrigins(self.as_concrete_TypeRef(), range, out.as_mut_ptr()); + } + out + } + + pub fn draw(&self, context: &CGContextRef) { + unsafe { + CTFrameDraw(self.as_concrete_TypeRef(), context.as_ptr()); + } + } +} + +#[link(name = "CoreText", kind = "framework")] +extern { + fn CTFrameGetTypeID() -> CFTypeID; + fn CTFrameGetLines(frame: CTFrameRef) -> CFArrayRef; + fn CTFrameDraw(frame: CTFrameRef, context: *mut <CGContext as ForeignType>::CType); + fn CTFrameGetLineOrigins(frame: CTFrameRef, range: CFRange, origins: *mut CGPoint); + fn CTFrameGetPath(frame: CTFrameRef) -> SysCGPathRef; +} diff --git a/third_party/rust/core-text/src/framesetter.rs b/third_party/rust/core-text/src/framesetter.rs new file mode 100644 index 0000000000..dacb540b85 --- /dev/null +++ b/third_party/rust/core-text/src/framesetter.rs @@ -0,0 +1,94 @@ +// 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 super::frame::{CTFrame, CTFrameRef}; +use core_foundation::attributed_string::CFAttributedStringRef; +use core_foundation::base::{CFRange, CFTypeID, TCFType}; +use core_foundation::dictionary::CFDictionaryRef; +use core_graphics::geometry::CGSize; +use core_graphics::path::{CGPath, CGPathRef}; +use foreign_types::{ForeignType, ForeignTypeRef}; +use std::os::raw::c_void; +use std::ptr::null; + +#[repr(C)] +pub struct __CTFramesetter(c_void); + +pub type CTFramesetterRef = *const __CTFramesetter; + +declare_TCFType! { + CTFramesetter, CTFramesetterRef +} +impl_TCFType!(CTFramesetter, CTFramesetterRef, CTFramesetterGetTypeID); +impl_CFTypeDescription!(CTFramesetter); + +impl CTFramesetter { + pub fn new_with_attributed_string(string: CFAttributedStringRef) -> Self { + unsafe { + let ptr = CTFramesetterCreateWithAttributedString(string); + CTFramesetter::wrap_under_create_rule(ptr) + } + } + + pub fn create_frame(&self, string_range: CFRange, path: &CGPathRef) -> CTFrame { + unsafe { + let ptr = CTFramesetterCreateFrame( + self.as_concrete_TypeRef(), + string_range, + path.as_ptr(), + null(), + ); + + CTFrame::wrap_under_create_rule(ptr) + } + } + + /// Suggest an appropriate frame size for displaying a text range. + /// + /// Returns a tuple containing an appropriate size (that should be smaller + /// than the provided constraints) as well as the range of text that fits in + /// this frame. + pub fn suggest_frame_size_with_constraints( + &self, + string_range: CFRange, + frame_attributes: CFDictionaryRef, + constraints: CGSize, + ) -> (CGSize, CFRange) { + unsafe { + let mut fit_range = CFRange::init(0, 0); + let size = CTFramesetterSuggestFrameSizeWithConstraints( + self.as_concrete_TypeRef(), + string_range, + frame_attributes, + constraints, + &mut fit_range, + ); + (size, fit_range) + } + } +} + +#[link(name = "CoreText", kind = "framework")] +extern "C" { + fn CTFramesetterGetTypeID() -> CFTypeID; + fn CTFramesetterCreateWithAttributedString(string: CFAttributedStringRef) -> CTFramesetterRef; + fn CTFramesetterCreateFrame( + framesetter: CTFramesetterRef, + string_range: CFRange, + path: *mut <CGPath as ForeignType>::CType, + attributes: *const c_void, + ) -> CTFrameRef; + fn CTFramesetterSuggestFrameSizeWithConstraints( + framesetter: CTFramesetterRef, + string_range: CFRange, + frame_attributes: CFDictionaryRef, + constraints: CGSize, + fitRange: *mut CFRange, + ) -> CGSize; +} diff --git a/third_party/rust/core-text/src/lib.rs b/third_party/rust/core-text/src/lib.rs new file mode 100644 index 0000000000..1e6288bcd1 --- /dev/null +++ b/third_party/rust/core-text/src/lib.rs @@ -0,0 +1,35 @@ +// 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. + +#![crate_name = "core_text"] +#![crate_type = "rlib"] + +#![allow(non_snake_case)] + +/*! +Many of these functions will add objects to the autorelease pool. +If you don't have one this will cause leaks. +*/ + +extern crate foreign_types; +extern crate libc; + +#[macro_use] +extern crate core_foundation; +extern crate core_graphics; + +pub mod font; +pub mod font_collection; +pub mod font_descriptor; +pub mod font_manager; +pub mod frame; +pub mod framesetter; +pub mod line; +pub mod run; +pub mod string_attributes; diff --git a/third_party/rust/core-text/src/line.rs b/third_party/rust/core-text/src/line.rs new file mode 100644 index 0000000000..50c1b4785d --- /dev/null +++ b/third_party/rust/core-text/src/line.rs @@ -0,0 +1,113 @@ +// 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::{CFIndex, CFRange, CFTypeID, TCFType}; +use core_graphics::base::{CGFloat}; +use core_graphics::context::{CGContext}; +use core_graphics::geometry::{CGPoint,CGRect}; +use foreign_types::{ForeignType}; +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); + +/// Metrics for a given line. +pub struct TypographicBounds { + pub width: CGFloat, + pub ascent: CGFloat, + pub descent: CGFloat, + pub leading: CGFloat, +} + +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)) + } + } + + pub fn get_string_range(&self) -> CFRange { + unsafe { + CTLineGetStringRange(self.as_concrete_TypeRef()) + } + } + + pub fn draw(&self, context: &CGContext) { + unsafe { + CTLineDraw(self.as_concrete_TypeRef(), context.as_ptr()) + } + } + + pub fn get_image_bounds(&self, context: &CGContext) -> CGRect { + unsafe { + CTLineGetImageBounds(self.as_concrete_TypeRef(), context.as_ptr()) + } + } + + pub fn get_typographic_bounds(&self) -> TypographicBounds { + let mut ascent = 0.0; + let mut descent = 0.0; + let mut leading = 0.0; + unsafe { + let width = CTLineGetTypographicBounds(self.as_concrete_TypeRef(), &mut ascent, &mut descent, &mut leading); + TypographicBounds { width, ascent, descent, leading } + } + } + + pub fn get_string_index_for_position(&self, position: CGPoint) -> CFIndex { + unsafe { + CTLineGetStringIndexForPosition(self.as_concrete_TypeRef(), position) + } + } + + pub fn get_string_offset_for_string_index(&self, charIndex: CFIndex) -> CGFloat { + unsafe { + CTLineGetOffsetForStringIndex(self.as_concrete_TypeRef(), charIndex, std::ptr::null()) + } + } +} + +#[link(name = "CoreText", kind = "framework")] +extern { + fn CTLineGetTypeID() -> CFTypeID; + fn CTLineGetGlyphRuns(line: CTLineRef) -> CFArrayRef; + fn CTLineGetStringRange(line: CTLineRef) -> CFRange; + + // Creating Lines + fn CTLineCreateWithAttributedString(string: CFAttributedStringRef) -> CTLineRef; + + // Drawing the Line + fn CTLineDraw(line: CTLineRef, context: * const core_graphics::sys::CGContext); + + // Measuring Lines + fn CTLineGetImageBounds(line: CTLineRef, context: * const core_graphics::sys::CGContext) -> CGRect; + fn CTLineGetTypographicBounds(line: CTLineRef, ascent: *mut CGFloat, descent: *mut CGFloat, leading: *mut CGFloat) -> CGFloat; + + // Getting Line Positioning + fn CTLineGetStringIndexForPosition(line: CTLineRef, position: CGPoint) -> CFIndex; + fn CTLineGetOffsetForStringIndex(line: CTLineRef, charIndex: CFIndex, secondaryOffset: *const CGFloat) -> CGFloat; +} diff --git a/third_party/rust/core-text/src/run.rs b/third_party/rust/core-text/src/run.rs new file mode 100644 index 0000000000..b7cb37616e --- /dev/null +++ b/third_party/rust/core-text/src/run.rs @@ -0,0 +1,152 @@ +// 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 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.is_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.is_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) + } + } + } + + pub fn string_indices(&self) -> Cow<[CFIndex]> { + unsafe { + // CTRunGetStringIndicesPtr can return null under some not understood circumstances. + // If it does the Apple documentation tells us to allocate our own buffer and call + // CTRunGetStringIndices + let count = CTRunGetGlyphCount(self.0); + let indices_ptr = CTRunGetStringIndicesPtr(self.0); + if !indices_ptr.is_null() { + Cow::from(slice::from_raw_parts(indices_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" + CTRunGetStringIndices(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]); + + let indices = run.string_indices(); + assert_eq!(indices.as_ref(), &[0, 1, 2, 3]); + } +} + +#[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 CTRunGetStringIndicesPtr(run: CTRunRef) -> *const CFIndex; + fn CTRunGetStringIndices(run: CTRunRef, range: CFRange, buffer: *const CFIndex); + fn CTRunGetGlyphsPtr(run: CTRunRef) -> *const CGGlyph; + fn CTRunGetGlyphs(run: CTRunRef, range: CFRange, buffer: *const CGGlyph); +} diff --git a/third_party/rust/core-text/src/string_attributes.rs b/third_party/rust/core-text/src/string_attributes.rs new file mode 100644 index 0000000000..dde1936c48 --- /dev/null +++ b/third_party/rust/core-text/src/string_attributes.rs @@ -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; +} |