Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/ab_glyph/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/ab_glyph/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"4991589f97c0b45b6a65669ac834c1e36b63b6fc27aa3cdd8efad8ab018c94c7","Cargo.toml":"ec6f15394241acb2d0118504e9797130c0324d4ceff46218ce31f1a2ed856850","LICENSE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","README.md":"da6bee2fc99fc8f96283e3382d85330569b59b97960558aed28a665c2bac7ba1","src/codepoint_ids.rs":"dad69e55584e9b3a9c28d13c6b9fe50e0190e3bd9966662a6532e361d2efb7a4","src/err.rs":"cf565d2c68afc5261b46d707d760636d9ac9c8a55b2653024544ccbb2c035572","src/font.rs":"a586cb6d71e99b8ffd0f6a80be2278841cfc12f65b30cfaa6c342a2131e46d74","src/font_arc.rs":"791d0fd55cf13624577a77d63fc398f890f143b97df34763e8daed900d4d6344","src/glyph.rs":"02017141b7f5a6982494f6a708e6f843d4be8da784b9322ba585e4416fcc0b9e","src/lib.rs":"b5f6926f64887d85b74ef5e9f4a797d67777df19688d7ccd582fc0d848d76efd","src/nostd_float.rs":"2bcf37dbc84b917a118cf3675161090f022bba7662e07dbfe7f0db4bfa2a1452","src/outlined.rs":"5c9ca46a8af0cef450d209b3a0d56ca3128ece7280b4c93599ef9ee421c64872","src/scale.rs":"c712fb8388b9f86ea20f50f86a5d9b83448905816fdf908f3d4586d78f206c94","src/ttfp.rs":"3a9fe6ba373db0a0b93b41986f4a45d0eb5a92bf59c61d6cd20b009562beda63","src/ttfp/outliner.rs":"e4ef3695155e5da8ab7260eeac5ac3e9e5f2d64d588a5ee625571e0eed63154c","src/ttfp/variable.rs":"ee1293438364f60fbc40829dbec33d2d0a884e3e8173cb68aa282c9f0a9e822e","src/variable.rs":"48d3b514f22b279e4b5ca82776167b954856f4419759446c98a3d32d17ce3b20"},"package":"80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225"}
|
||||
95
third-party/vendor/ab_glyph/CHANGELOG.md
vendored
Normal file
95
third-party/vendor/ab_glyph/CHANGELOG.md
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# v0.2.23
|
||||
* Update _ttf-parser_ to `0.20`.
|
||||
|
||||
# 0.2.22
|
||||
* Add `v2::GlyphImage` and `Font::glyph_raster_image2` to expose width and height info.
|
||||
* Deprecate `Font::glyph_raster_image` & `GlyphImage`.
|
||||
* Improve `OutlinedGlyph::draw` documentation.
|
||||
|
||||
# 0.2.21
|
||||
* Update _ttf-parser_ to `0.19`.
|
||||
* Add `GlyphImageFormat` variants `BitmapMono`, `BitmapMonoPacked`, `BitmapGray2`, `BitmapGray2Packed`,
|
||||
`BitmapGray4`, `BitmapGray4Packed`, `BitmapGray8`, `BitmapPremulBgra32`.
|
||||
* `Font::h_advance_unscaled`, `h_side_bearing_unscaled`, `v_advance_unscaled`, `v_side_bearing_unscaled`
|
||||
and related `ScaleFont` methods now return `0.0` if the font does not define that value.
|
||||
Previously calls would panic when fonts lacked support.
|
||||
* Use edition 2021.
|
||||
|
||||
# 0.2.20
|
||||
* Add `FontVec::as_slice`, `FontVec::into_vec`.
|
||||
|
||||
# 0.2.19
|
||||
* Update _ttf-parser_ to `0.18`.
|
||||
|
||||
# 0.2.18
|
||||
* Update _ttf-parser_ to `0.17`.
|
||||
|
||||
# 0.2.17
|
||||
* Add `VariableFont` trait implemented by `FontRef` & `FontVec`.
|
||||
Provides `variations` & `set_variation` functions.
|
||||
* Add default enabled feature `variable-fonts`.
|
||||
|
||||
# 0.2.16
|
||||
* Add `Font::pt_to_px_scale` to ease converting point size to `PxScale`.
|
||||
* Add `PxScale::round`.
|
||||
|
||||
# 0.2.15
|
||||
* Fix some font outlines by always trying to "close" them at the end. Fixes _Cantarell-VF.otf_ outlining.
|
||||
|
||||
# 0.2.14
|
||||
* Update _ttf-parser_ to `0.15`.
|
||||
|
||||
# 0.2.13
|
||||
* Update _ttf-parser_ to `0.14`.
|
||||
|
||||
# 0.2.12
|
||||
* Update _owned-ttf-parser_ to `0.13.2`.
|
||||
* Pre-parse cmap & kern subtables on all `Font` variants at initialization. This provides
|
||||
much faster `glyph_id` & `kern` method performance, results in 25-30% faster layout
|
||||
benchmark performance.
|
||||
|
||||
# 0.2.11
|
||||
* `Font::outline` will return `None` for rare invalid/empty glyph bounds instead of panicking.
|
||||
* Add `Font::glyph_raster_image` for color emoji fonts.
|
||||
|
||||
# 0.2.10
|
||||
* Update _ttf-parser_ to `0.12`.
|
||||
|
||||
# 0.2.9
|
||||
* Update _ttf-parser_ to `0.11`.
|
||||
|
||||
# 0.2.8
|
||||
* Add fallback bounding box calculation for malformed font glyphs with zero sized boxes.
|
||||
* Update _ttf-parser_ to `0.10`.
|
||||
|
||||
# 0.2.7
|
||||
* Update _ttf-parser_ to `0.9`.
|
||||
|
||||
# 0.2.6
|
||||
* Add `Font::codepoint_ids` method for iterating over `(GlyphId, char)` pairs.
|
||||
* Clarify documentation.
|
||||
|
||||
# 0.2.5
|
||||
* Add `Font::units_per_em` + documentation on unscaled font units.
|
||||
* Update _ttf-parser_ to `0.8`.
|
||||
|
||||
# 0.2.4
|
||||
* Update _ttf-parser_ to `0.7` adding CID font support.
|
||||
|
||||
# 0.2.3
|
||||
* Add `v_advance` & `v_side_bearing` methods to `ScaleFont` + `_unscaled` variants to `Font`.
|
||||
|
||||
# 0.2.2
|
||||
* Add `Font::glyph_bounds` method, similar to glyph_brush's `glyph_bounds` but for a single glyph.
|
||||
* Rename `OutlinedGlyph::bounds` to `OutlinedGlyph::px_bounds` for clarity.
|
||||
|
||||
# 0.2.1
|
||||
* Update _ttf-parser_ to `0.6`.
|
||||
|
||||
# 0.2
|
||||
* Add `_unscaled` suffix to `Font` trait methods that deal with unscaled metrics.
|
||||
This helps distinguish `ScaleFont`'s scaled metrics and can avoid unintended behaviour.
|
||||
* Rename "libm-math" -> "libm" for consistency with _ab_glyph_rasterizer_.
|
||||
|
||||
# 0.1
|
||||
* Implement fast glyph layout, outline & drawing primitives.
|
||||
56
third-party/vendor/ab_glyph/Cargo.toml
vendored
Normal file
56
third-party/vendor/ab_glyph/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# 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 are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "ab_glyph"
|
||||
version = "0.2.23"
|
||||
authors = ["Alex Butler <alexheretic@gmail.com>"]
|
||||
description = "API for loading, scaling, positioning and rasterizing OpenType font glyphs."
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"text",
|
||||
"ttf",
|
||||
"truetype",
|
||||
"otf",
|
||||
"opentype",
|
||||
]
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/alexheretic/ab-glyph"
|
||||
|
||||
[dependencies.ab_glyph_rasterizer]
|
||||
version = "0.1.2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.libm]
|
||||
version = "0.2.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.owned_ttf_parser]
|
||||
version = "0.20"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
[features]
|
||||
default = [
|
||||
"std",
|
||||
"variable-fonts",
|
||||
]
|
||||
libm = [
|
||||
"dep:libm",
|
||||
"ab_glyph_rasterizer/libm",
|
||||
]
|
||||
std = [
|
||||
"owned_ttf_parser/default",
|
||||
"ab_glyph_rasterizer/default",
|
||||
]
|
||||
variable-fonts = ["owned_ttf_parser/variable-fonts"]
|
||||
176
third-party/vendor/ab_glyph/LICENSE
vendored
Normal file
176
third-party/vendor/ab_glyph/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
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
|
||||
42
third-party/vendor/ab_glyph/README.md
vendored
Normal file
42
third-party/vendor/ab_glyph/README.md
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
ab_glyph
|
||||
[](https://crates.io/crates/ab_glyph)
|
||||
[](https://docs.rs/ab_glyph)
|
||||
========
|
||||
Fast API for loading, scaling, positioning and rasterizing OpenType font glyphs.
|
||||
|
||||
```rust
|
||||
use ab_glyph::{FontRef, Font, Glyph, point};
|
||||
|
||||
let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
|
||||
// Get a glyph for 'q' with a scale & position.
|
||||
let q_glyph: Glyph = font.glyph_id('q').with_scale_and_position(24.0, point(100.0, 0.0));
|
||||
|
||||
// Draw it.
|
||||
if let Some(q) = font.outline_glyph(q_glyph) {
|
||||
q.draw(|x, y, c| { /* draw pixel `(x, y)` with coverage: `c` */ });
|
||||
}
|
||||
```
|
||||
|
||||
## no_std
|
||||
no_std environments are supported using `alloc` & [`libm`](https://github.com/rust-lang/libm).
|
||||
```toml
|
||||
ab_glyph = { default-features = false, features = ["libm"] }
|
||||
```
|
||||
|
||||
## Comparison with [`rusttype`](https://gitlab.redox-os.org/redox-os/rusttype)
|
||||
ab_glyph is a rewrite of rusttype made after I added .otf support for the latter and saw some performance issue's
|
||||
with the rusttype API.
|
||||
|
||||
ab_glyph is a more focussed API concentrating on high performance for both .ttf & .otf fonts.
|
||||
|
||||
When laying out glyphs into paragraph, ab_glyph is faster than rusttype using .ttf fonts &
|
||||
**much** faster for .otf fonts.
|
||||
|
||||
```
|
||||
group ab-glyph rusttype 0.9
|
||||
----- -------- ------------
|
||||
layout_a_sentence (exo2-ttf) 1.00 11.1±0.08µs 1.56 17.3±0.14µs
|
||||
layout_a_sentence (exo2-otf) 1.00 11.1±0.12µs 8.85 98.1±1.17µs
|
||||
```
|
||||
_Note: Numbers from May-2020 benchmarks, ab-glyph performance is also expected to have improved since then_.
|
||||
24
third-party/vendor/ab_glyph/src/codepoint_ids.rs
vendored
Normal file
24
third-party/vendor/ab_glyph/src/codepoint_ids.rs
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use crate::GlyphId;
|
||||
use alloc::boxed::Box;
|
||||
use core::{fmt, iter};
|
||||
|
||||
pub struct CodepointIdIter<'a> {
|
||||
pub(crate) inner: Box<dyn Iterator<Item = (GlyphId, char)> + 'a>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CodepointIdIter<'a> {
|
||||
type Item = (GlyphId, char);
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl iter::FusedIterator for CodepointIdIter<'_> {}
|
||||
|
||||
impl fmt::Debug for CodepointIdIter<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "CodepointIdIter")
|
||||
}
|
||||
}
|
||||
14
third-party/vendor/ab_glyph/src/err.rs
vendored
Normal file
14
third-party/vendor/ab_glyph/src/err.rs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use core::fmt;
|
||||
|
||||
/// Invalid font data error.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct InvalidFont;
|
||||
|
||||
impl fmt::Display for InvalidFont {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "InvalidFont")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for InvalidFont {}
|
||||
318
third-party/vendor/ab_glyph/src/font.rs
vendored
Normal file
318
third-party/vendor/ab_glyph/src/font.rs
vendored
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
use crate::{
|
||||
point, v2, Glyph, GlyphId, Outline, OutlinedGlyph, PxScale, PxScaleFont, Rect, ScaleFont,
|
||||
};
|
||||
|
||||
/// Functionality required from font data.
|
||||
///
|
||||
/// See also [`FontArc`](struct.FontArc.html), [`FontRef`](struct.FontRef.html)
|
||||
/// and [`FontVec`](struct.FontVec.html).
|
||||
///
|
||||
/// ## Units
|
||||
///
|
||||
/// Units of unscaled accessors are "font units", which is an arbitrary unit
|
||||
/// defined by the font. See [`Font::units_per_em`].
|
||||
///
|
||||
/// ab_glyph uses a non-standard scale [`PxScale`] which is the pixel height
|
||||
/// of the text. See [`Font::pt_to_px_scale`] to convert standard point sizes.
|
||||
pub trait Font {
|
||||
/// Get the size of the font unit
|
||||
///
|
||||
/// This returns "font units per em", where 1em is a base unit of font scale
|
||||
/// (typically the width of a capital 'M').
|
||||
///
|
||||
/// Returns `None` in case the font unit size exceeds the expected range.
|
||||
/// See [`Face::units_per_em`](https://docs.rs/ttf-parser/latest/ttf_parser/struct.Face.html#method.units_per_em).
|
||||
///
|
||||
/// May be used to calculate [`PxScale`] from pt size, see [`Font::pt_to_px_scale`].
|
||||
fn units_per_em(&self) -> Option<f32>;
|
||||
|
||||
/// Converts pt units into [`PxScale`].
|
||||
///
|
||||
/// Note: To handle a screen scale factor multiply it to the `pt_size` argument.
|
||||
///
|
||||
/// Returns `None` in case the [`Font::units_per_em`] unit size exceeds the expected range.
|
||||
///
|
||||
/// ## Point size (pt)
|
||||
///
|
||||
/// Font sizes are typically specified in "points". According to the modern
|
||||
/// standard, 1pt = 1/72in. The "point size" of a font is the number of points
|
||||
/// per em.
|
||||
///
|
||||
/// The DPI (dots-per-inch) of a screen depends on the screen in question;
|
||||
/// 96 DPI is often considered the "standard". For high-DPI displays the
|
||||
/// DPI may be specified directly or one may multiply 96 by a scale-factor.
|
||||
///
|
||||
/// Thus, for example, a 10pt font on a 96 pixels-per-inch display has
|
||||
/// 10 / 72 * 96 = 13.333... pixels-per-em. If we divide this number by
|
||||
/// `units_per_em` we then get a scaling factor: pixels-per-font-unit.
|
||||
///
|
||||
/// Note however that since [`PxScale`] values are relative to the text height,
|
||||
/// one further step is needed: multiply by [`Font::height_unscaled`].
|
||||
fn pt_to_px_scale(&self, pt_size: f32) -> Option<PxScale> {
|
||||
let px_per_em = pt_size * (96.0 / 72.0);
|
||||
let units_per_em = self.units_per_em()?;
|
||||
let height = self.height_unscaled();
|
||||
Some(PxScale::from(px_per_em * height / units_per_em))
|
||||
}
|
||||
|
||||
/// Unscaled glyph ascent.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn ascent_unscaled(&self) -> f32;
|
||||
|
||||
/// Unscaled glyph descent.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn descent_unscaled(&self) -> f32;
|
||||
|
||||
/// Unscaled height `ascent - descent`.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
#[inline]
|
||||
fn height_unscaled(&self) -> f32 {
|
||||
self.ascent_unscaled() - self.descent_unscaled()
|
||||
}
|
||||
|
||||
/// Unscaled line gap.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn line_gap_unscaled(&self) -> f32;
|
||||
|
||||
/// Lookup a `GlyphId` matching a given `char`.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn glyph_id(&self, c: char) -> GlyphId;
|
||||
|
||||
/// Unscaled horizontal advance for a given glyph id.
|
||||
///
|
||||
/// Returns `0.0` if the font does not define this value.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn h_advance_unscaled(&self, id: GlyphId) -> f32;
|
||||
|
||||
/// Unscaled horizontal side bearing for a given glyph id.
|
||||
///
|
||||
/// Returns `0.0` if the font does not define this value.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn h_side_bearing_unscaled(&self, id: GlyphId) -> f32;
|
||||
|
||||
/// Unscaled vertical advance for a given glyph id.
|
||||
///
|
||||
/// Returns `0.0` if the font does not define this value.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn v_advance_unscaled(&self, id: GlyphId) -> f32;
|
||||
|
||||
/// Unscaled vertical side bearing for a given glyph id.
|
||||
///
|
||||
/// Returns `0.0` if the font does not define this value.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn v_side_bearing_unscaled(&self, id: GlyphId) -> f32;
|
||||
|
||||
/// Returns additional unscaled kerning to apply for a particular pair of glyph ids.
|
||||
///
|
||||
/// Scaling can be done with [as_scaled](trait.Font.html#method.as_scaled).
|
||||
fn kern_unscaled(&self, first: GlyphId, second: GlyphId) -> f32;
|
||||
|
||||
/// Compute unscaled glyph outline curves & bounding box.
|
||||
fn outline(&self, id: GlyphId) -> Option<Outline>;
|
||||
|
||||
/// The number of glyphs present in this font. Glyph identifiers for this
|
||||
/// font will always be in the range `0..self.glyph_count()`
|
||||
fn glyph_count(&self) -> usize;
|
||||
|
||||
/// Returns an iterator of all distinct `(GlyphId, char)` pairs. Not ordered.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::{Font, FontRef, GlyphId};
|
||||
/// # use std::collections::HashMap;
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// // Iterate over pairs, each id will appear at most once.
|
||||
/// let mut codepoint_ids = font.codepoint_ids();
|
||||
/// assert_eq!(codepoint_ids.next(), Some((GlyphId(408), '\r')));
|
||||
/// assert_eq!(codepoint_ids.next(), Some((GlyphId(1), ' ')));
|
||||
/// assert_eq!(codepoint_ids.next(), Some((GlyphId(75), '!')));
|
||||
///
|
||||
/// // Build a lookup map for all ids
|
||||
/// let map: HashMap<_, _> = font.codepoint_ids().collect();
|
||||
/// assert_eq!(map.get(&GlyphId(75)), Some(&'!'));
|
||||
/// # assert_eq!(map.len(), 908);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_>;
|
||||
|
||||
/// Returns a pre-rendered image of the glyph.
|
||||
///
|
||||
/// This is normally only present when an outline is not sufficient to describe the glyph, such
|
||||
/// as emojis (particularly color ones). The `pixel_size` parameter is in pixels per em, and will be
|
||||
/// used to select between multiple possible images (if present); the returned image will
|
||||
/// likely not match this value, requiring you to scale it to match the target resolution.
|
||||
/// To get the largest image use `u16::MAX`.
|
||||
#[allow(deprecated)]
|
||||
#[deprecated(
|
||||
since = "0.2.22",
|
||||
note = "Deprecated in favor of `glyph_raster_image2`"
|
||||
)]
|
||||
fn glyph_raster_image(&self, id: GlyphId, pixel_size: u16) -> Option<crate::GlyphImage> {
|
||||
self.glyph_raster_image2(id, pixel_size)
|
||||
.map(|i| crate::GlyphImage {
|
||||
origin: i.origin,
|
||||
scale: i.pixels_per_em.into(),
|
||||
data: i.data,
|
||||
format: i.format,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a pre-rendered image of the glyph.
|
||||
///
|
||||
/// This is normally only present when an outline is not sufficient to describe the glyph, such
|
||||
/// as emojis (particularly color ones). The `pixel_size` parameter is in pixels per em, and will be
|
||||
/// used to select between multiple possible images (if present); the returned image will
|
||||
/// likely not match this value, requiring you to scale it to match the target resolution.
|
||||
/// To get the largest image use `u16::MAX`.
|
||||
fn glyph_raster_image2(&self, id: GlyphId, pixel_size: u16) -> Option<v2::GlyphImage>;
|
||||
|
||||
/// Returns the layout bounds of this glyph. These are different to the outline `px_bounds()`.
|
||||
///
|
||||
/// Horizontally: Glyph position +/- h_advance/h_side_bearing.
|
||||
/// Vertically: Glyph position +/- ascent/descent.
|
||||
#[inline]
|
||||
fn glyph_bounds(&self, glyph: &Glyph) -> Rect
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let sf = self.as_scaled(glyph.scale);
|
||||
let pos = glyph.position;
|
||||
Rect {
|
||||
min: point(pos.x - sf.h_side_bearing(glyph.id), pos.y - sf.ascent()),
|
||||
max: point(pos.x + sf.h_advance(glyph.id), pos.y - sf.descent()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute glyph outline ready for drawing.
|
||||
#[inline]
|
||||
fn outline_glyph(&self, glyph: Glyph) -> Option<OutlinedGlyph>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let outline = self.outline(glyph.id)?;
|
||||
let scale_factor = self.as_scaled(glyph.scale).scale_factor();
|
||||
Some(OutlinedGlyph::new(glyph, outline, scale_factor))
|
||||
}
|
||||
|
||||
/// Construct a [`PxScaleFontRef`](struct.PxScaleFontRef.html) by associating with the
|
||||
/// given pixel `scale`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::{Font, FontRef, PxScale, ScaleFont};
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// assert_eq!(font.descent_unscaled(), -201.0);
|
||||
///
|
||||
/// assert_eq!(font.as_scaled(24.0).descent(), -4.02);
|
||||
/// assert_eq!(font.as_scaled(50.0).descent(), -8.375);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
fn as_scaled<S: Into<PxScale>>(&self, scale: S) -> PxScaleFont<&'_ Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
PxScaleFont {
|
||||
font: self,
|
||||
scale: scale.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Move into a [`PxScaleFont`](struct.PxScaleFont.html) associated with the
|
||||
/// given pixel `scale`.
|
||||
#[inline]
|
||||
fn into_scaled<S: Into<PxScale>>(self, scale: S) -> PxScaleFont<Self>
|
||||
where
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
PxScaleFont {
|
||||
font: self,
|
||||
scale: scale.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Font> Font for &F {
|
||||
#[inline]
|
||||
fn units_per_em(&self) -> Option<f32> {
|
||||
(*self).units_per_em()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ascent_unscaled(&self) -> f32 {
|
||||
(*self).ascent_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descent_unscaled(&self) -> f32 {
|
||||
(*self).descent_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_gap_unscaled(&self) -> f32 {
|
||||
(*self).line_gap_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_id(&self, c: char) -> GlyphId {
|
||||
(*self).glyph_id(c)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
(*self).h_advance_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
(*self).h_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
(*self).v_advance_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
(*self).v_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn kern_unscaled(&self, first: GlyphId, second: GlyphId) -> f32 {
|
||||
(*self).kern_unscaled(first, second)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn outline(&self, glyph: GlyphId) -> Option<Outline> {
|
||||
(*self).outline(glyph)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_count(&self) -> usize {
|
||||
(*self).glyph_count()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_> {
|
||||
(*self).codepoint_ids()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_raster_image2(&self, id: GlyphId, size: u16) -> Option<v2::GlyphImage> {
|
||||
(*self).glyph_raster_image2(id, size)
|
||||
}
|
||||
}
|
||||
162
third-party/vendor/ab_glyph/src/font_arc.rs
vendored
Normal file
162
third-party/vendor/ab_glyph/src/font_arc.rs
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
use crate::{v2, Font, FontRef, FontVec, GlyphId, InvalidFont, Outline};
|
||||
use alloc::sync::Arc;
|
||||
use core::fmt;
|
||||
|
||||
/// `Font` implementor that wraps another concrete `Font + 'static` type storing in an `Arc`.
|
||||
///
|
||||
/// Provides convenient type erasure & cheap clones (particularly for `FontVec`).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{Font, FontArc};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontArc::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// assert_eq!(font.glyph_id('s'), ab_glyph::GlyphId(56));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct FontArc(Arc<dyn Font + Send + Sync + 'static>);
|
||||
|
||||
impl FontArc {
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// # let font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// # let font_vec = FontVec::try_from_vec(font_data)?;
|
||||
/// let font_arc = FontArc::new(font_vec);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new<F: Font + Send + Sync + 'static>(font: F) -> Self {
|
||||
Self(Arc::new(font))
|
||||
}
|
||||
|
||||
/// Creates an `FontArc` from owned data.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font = FontArc::try_from_vec(owned_font_data)?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_vec(data: Vec<u8>) -> Result<Self, InvalidFont> {
|
||||
Ok(FontVec::try_from_vec(data)?.into())
|
||||
}
|
||||
|
||||
/// Creates an `FontArc` from a byte-slice.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// let font = FontArc::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_slice(data: &'static [u8]) -> Result<Self, InvalidFont> {
|
||||
Ok(FontRef::try_from_slice(data)?.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FontArc {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FontArc")
|
||||
}
|
||||
}
|
||||
|
||||
impl Font for FontArc {
|
||||
#[inline]
|
||||
fn units_per_em(&self) -> Option<f32> {
|
||||
self.0.units_per_em()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ascent_unscaled(&self) -> f32 {
|
||||
self.0.ascent_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descent_unscaled(&self) -> f32 {
|
||||
self.0.descent_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_gap_unscaled(&self) -> f32 {
|
||||
self.0.line_gap_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_id(&self, c: char) -> GlyphId {
|
||||
self.0.glyph_id(c)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0.h_advance_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0.h_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0.v_advance_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0.v_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn kern_unscaled(&self, first: GlyphId, second: GlyphId) -> f32 {
|
||||
self.0.kern_unscaled(first, second)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn outline(&self, glyph: GlyphId) -> Option<Outline> {
|
||||
self.0.outline(glyph)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_count(&self) -> usize {
|
||||
self.0.glyph_count()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_> {
|
||||
self.0.codepoint_ids()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_raster_image2(&self, id: GlyphId, size: u16) -> Option<v2::GlyphImage> {
|
||||
self.0.glyph_raster_image2(id, size)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FontVec> for FontArc {
|
||||
#[inline]
|
||||
fn from(font: FontVec) -> Self {
|
||||
Self::new(font)
|
||||
}
|
||||
}
|
||||
impl From<FontRef<'static>> for FontArc {
|
||||
#[inline]
|
||||
fn from(font: FontRef<'static>) -> Self {
|
||||
Self::new(font)
|
||||
}
|
||||
}
|
||||
impl From<Arc<dyn Font + Send + Sync + 'static>> for FontArc {
|
||||
#[inline]
|
||||
fn from(font: Arc<dyn Font + Send + Sync + 'static>) -> Self {
|
||||
Self(font)
|
||||
}
|
||||
}
|
||||
171
third-party/vendor/ab_glyph/src/glyph.rs
vendored
Normal file
171
third-party/vendor/ab_glyph/src/glyph.rs
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
use crate::{Point, PxScale};
|
||||
|
||||
/// Glyph id.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{Font, FontRef, GlyphId};
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// let q_id: GlyphId = font.glyph_id('q');
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct GlyphId(pub u16);
|
||||
|
||||
impl GlyphId {
|
||||
/// Construct a `Glyph` with given scale & position.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf")).unwrap();
|
||||
/// let glyph = font.glyph_id('z').with_scale_and_position(24.0, point(100.0, 0.0));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn with_scale_and_position<S: Into<PxScale>, P: Into<Point>>(
|
||||
self,
|
||||
scale: S,
|
||||
position: P,
|
||||
) -> Glyph {
|
||||
Glyph {
|
||||
id: self,
|
||||
scale: scale.into(),
|
||||
position: position.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a `Glyph` with given scale and position `point(0.0, 0.0)`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf")).unwrap();
|
||||
/// let glyph = font.glyph_id('w').with_scale(48.0);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn with_scale<S: Into<PxScale>>(self, scale: S) -> Glyph {
|
||||
self.with_scale_and_position(scale, Point::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// A glyph with pixel scale & position.
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub struct Glyph {
|
||||
/// Glyph id.
|
||||
pub id: GlyphId,
|
||||
/// Pixel scale of this glyph.
|
||||
pub scale: PxScale,
|
||||
/// Position of this glyph.
|
||||
pub position: Point,
|
||||
}
|
||||
|
||||
/// Old version of [`v2::GlyphImage`].
|
||||
#[deprecated(since = "0.2.22", note = "Deprecated in favor of `v2::GlyphImage`")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GlyphImage<'a> {
|
||||
/// Offset of the image from the normal origin (top at the baseline plus
|
||||
/// ascent), measured in pixels at the image's current scale.
|
||||
pub origin: Point,
|
||||
/// Current scale of the image in pixels per em.
|
||||
pub scale: f32,
|
||||
/// Raw image data, not a bitmap in the case of [`GlyphImageFormat::Png`] format.
|
||||
pub data: &'a [u8],
|
||||
/// Format of the raw data.
|
||||
pub format: GlyphImageFormat,
|
||||
}
|
||||
|
||||
pub mod v2 {
|
||||
use crate::{GlyphImageFormat, Point};
|
||||
|
||||
/// A pre-rendered image of a glyph, usually used for emojis or other glyphs
|
||||
/// that can't be represented only using an outline.
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GlyphImage<'a> {
|
||||
/// Offset of the image from the normal origin (top at the baseline plus
|
||||
/// ascent), measured in pixels at the image's current scale.
|
||||
pub origin: Point,
|
||||
/// Image width.
|
||||
///
|
||||
/// It doesn't guarantee that this value is the same as set in the `data` in the case of
|
||||
/// [`GlyphImageFormat::Png`] format.
|
||||
pub width: u16,
|
||||
/// Image height.
|
||||
///
|
||||
/// It doesn't guarantee that this value is the same as set in the `data` in the case of
|
||||
/// [`GlyphImageFormat::Png`] format.
|
||||
pub height: u16,
|
||||
/// Pixels per em of the selected strike.
|
||||
pub pixels_per_em: u16,
|
||||
/// Raw image data, see [`format`](GlyphImageFormat).
|
||||
pub data: &'a [u8],
|
||||
/// Format of the raw [`data`](Self::data).
|
||||
pub format: GlyphImageFormat,
|
||||
}
|
||||
}
|
||||
|
||||
/// Valid formats for a [`GlyphImage`].
|
||||
// Possible future formats: SVG, JPEG, TIFF
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum GlyphImageFormat {
|
||||
Png,
|
||||
|
||||
/// A monochrome bitmap.
|
||||
///
|
||||
/// The most significant bit of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. The data for each row is padded to a byte
|
||||
/// boundary, so the next row begins with the most significant bit of a new byte. 1 corresponds
|
||||
/// to black, and 0 to white.
|
||||
BitmapMono,
|
||||
|
||||
/// A packed monochrome bitmap.
|
||||
///
|
||||
/// The most significant bit of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. Data is tightly packed with no padding. 1
|
||||
/// corresponds to black, and 0 to white.
|
||||
BitmapMonoPacked,
|
||||
|
||||
/// A grayscale bitmap with 2 bits per pixel.
|
||||
///
|
||||
/// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. The data for each row is padded to a byte
|
||||
/// boundary, so the next row begins with the most significant bit of a new byte.
|
||||
BitmapGray2,
|
||||
|
||||
/// A packed grayscale bitmap with 2 bits per pixel.
|
||||
///
|
||||
/// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. Data is tightly packed with no padding.
|
||||
BitmapGray2Packed,
|
||||
|
||||
/// A grayscale bitmap with 4 bits per pixel.
|
||||
///
|
||||
/// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. The data for each row is padded to a byte
|
||||
/// boundary, so the next row begins with the most significant bit of a new byte.
|
||||
BitmapGray4,
|
||||
|
||||
/// A packed grayscale bitmap with 4 bits per pixel.
|
||||
///
|
||||
/// The most significant bits of the first byte corresponds to the top-left pixel, proceeding
|
||||
/// through succeeding bits moving left to right. Data is tightly packed with no padding.
|
||||
BitmapGray4Packed,
|
||||
|
||||
/// A grayscale bitmap with 8 bits per pixel.
|
||||
///
|
||||
/// The first byte corresponds to the top-left pixel, proceeding through succeeding bytes
|
||||
/// moving left to right.
|
||||
BitmapGray8,
|
||||
|
||||
/// A color bitmap with 32 bits per pixel.
|
||||
///
|
||||
/// The first group of four bytes corresponds to the top-left pixel, proceeding through
|
||||
/// succeeding pixels moving left to right. Each byte corresponds to a color channel and the
|
||||
/// channels within a pixel are in blue, green, red, alpha order. Color values are
|
||||
/// pre-multiplied by the alpha. For example, the color "full-green with half translucency"
|
||||
/// is encoded as `\x00\x80\x00\x80`, and not `\x00\xFF\x00\x80`.
|
||||
BitmapPremulBgra32,
|
||||
}
|
||||
54
third-party/vendor/ab_glyph/src/lib.rs
vendored
Normal file
54
third-party/vendor/ab_glyph/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//! API for loading, scaling, positioning and rasterizing OpenType font glyphs.
|
||||
//!
|
||||
//! # Example
|
||||
//! ```
|
||||
//! use ab_glyph::{point, Font, FontRef, Glyph};
|
||||
//!
|
||||
//! # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
//! let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
//!
|
||||
//! // Get a glyph for 'q' with a scale & position.
|
||||
//! let q_glyph: Glyph = font
|
||||
//! .glyph_id('q')
|
||||
//! .with_scale_and_position(24.0, point(100.0, 0.0));
|
||||
//!
|
||||
//! // Draw it.
|
||||
//! if let Some(q) = font.outline_glyph(q_glyph) {
|
||||
//! q.draw(|x, y, c| { /* draw pixel `(x, y)` with coverage: `c` */ });
|
||||
//! }
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod codepoint_ids;
|
||||
mod err;
|
||||
mod font;
|
||||
#[cfg(feature = "std")]
|
||||
mod font_arc;
|
||||
mod glyph;
|
||||
#[cfg(all(feature = "libm", not(feature = "std")))]
|
||||
mod nostd_float;
|
||||
mod outlined;
|
||||
mod scale;
|
||||
mod ttfp;
|
||||
#[cfg(feature = "variable-fonts")]
|
||||
mod variable;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use crate::font_arc::*;
|
||||
#[allow(deprecated)]
|
||||
pub use crate::{
|
||||
codepoint_ids::*,
|
||||
err::*,
|
||||
font::*,
|
||||
glyph::*,
|
||||
outlined::*,
|
||||
scale::*,
|
||||
ttfp::{FontRef, FontVec},
|
||||
};
|
||||
pub use ab_glyph_rasterizer::{point, Point};
|
||||
#[cfg(feature = "variable-fonts")]
|
||||
pub use variable::*;
|
||||
41
third-party/vendor/ab_glyph/src/nostd_float.rs
vendored
Normal file
41
third-party/vendor/ab_glyph/src/nostd_float.rs
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/// Basic required float operations.
|
||||
pub(crate) trait FloatExt {
|
||||
fn floor(self) -> Self;
|
||||
fn ceil(self) -> Self;
|
||||
fn sqrt(self) -> Self;
|
||||
fn round(self) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
fn trunc(self) -> Self;
|
||||
fn fract(self) -> Self;
|
||||
}
|
||||
|
||||
impl FloatExt for f32 {
|
||||
#[inline]
|
||||
fn floor(self) -> Self {
|
||||
libm::floorf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn ceil(self) -> Self {
|
||||
libm::ceilf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn sqrt(self) -> Self {
|
||||
libm::sqrtf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn round(self) -> Self {
|
||||
libm::roundf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn abs(self) -> Self {
|
||||
libm::fabsf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn trunc(self) -> Self {
|
||||
libm::truncf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn fract(self) -> Self {
|
||||
self - self.trunc()
|
||||
}
|
||||
}
|
||||
176
third-party/vendor/ab_glyph/src/outlined.rs
vendored
Normal file
176
third-party/vendor/ab_glyph/src/outlined.rs
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#[cfg(all(feature = "libm", not(feature = "std")))]
|
||||
use crate::nostd_float::FloatExt;
|
||||
use crate::{point, Glyph, Point, PxScaleFactor};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// A "raw" collection of outline curves for a glyph, unscaled & unpositioned.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Outline {
|
||||
/// Unscaled bounding box.
|
||||
pub bounds: Rect,
|
||||
/// Unscaled & unpositioned outline curves.
|
||||
pub curves: Vec<OutlineCurve>,
|
||||
}
|
||||
|
||||
impl Outline {
|
||||
/// Convert unscaled bounds into pixel bounds at a given scale & position.
|
||||
pub fn px_bounds(&self, scale_factor: PxScaleFactor, position: Point) -> Rect {
|
||||
let Rect { min, max } = self.bounds;
|
||||
|
||||
// Use subpixel fraction in floor/ceil rounding to elimate rounding error
|
||||
// from identical subpixel positions
|
||||
let (x_trunc, x_fract) = (position.x.trunc(), position.x.fract());
|
||||
let (y_trunc, y_fract) = (position.y.trunc(), position.y.fract());
|
||||
|
||||
Rect {
|
||||
min: point(
|
||||
(min.x * scale_factor.horizontal + x_fract).floor() + x_trunc,
|
||||
(min.y * -scale_factor.vertical + y_fract).floor() + y_trunc,
|
||||
),
|
||||
max: point(
|
||||
(max.x * scale_factor.horizontal + x_fract).ceil() + x_trunc,
|
||||
(max.y * -scale_factor.vertical + y_fract).ceil() + y_trunc,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A glyph that has been outlined at a scale & position.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OutlinedGlyph {
|
||||
glyph: Glyph,
|
||||
// Pixel scale bounds.
|
||||
px_bounds: Rect,
|
||||
// Scale factor
|
||||
scale_factor: PxScaleFactor,
|
||||
// Raw outline
|
||||
outline: Outline,
|
||||
}
|
||||
|
||||
impl OutlinedGlyph {
|
||||
/// Constructs an `OutlinedGlyph` from the source `Glyph`, pixel bounds
|
||||
/// & relatively positioned outline curves.
|
||||
#[inline]
|
||||
pub fn new(glyph: Glyph, outline: Outline, scale_factor: PxScaleFactor) -> Self {
|
||||
// work this out now as it'll usually be used more than once
|
||||
let px_bounds = outline.px_bounds(scale_factor, glyph.position);
|
||||
|
||||
Self {
|
||||
glyph,
|
||||
px_bounds,
|
||||
scale_factor,
|
||||
outline,
|
||||
}
|
||||
}
|
||||
|
||||
/// Glyph info.
|
||||
#[inline]
|
||||
pub fn glyph(&self) -> &Glyph {
|
||||
&self.glyph
|
||||
}
|
||||
|
||||
#[deprecated = "Renamed to `px_bounds`"]
|
||||
#[doc(hidden)]
|
||||
pub fn bounds(&self) -> Rect {
|
||||
self.px_bounds()
|
||||
}
|
||||
|
||||
/// Conservative whole number pixel bounding box for this glyph.
|
||||
#[inline]
|
||||
pub fn px_bounds(&self) -> Rect {
|
||||
self.px_bounds
|
||||
}
|
||||
|
||||
/// Draw this glyph outline using a pixel & coverage handling function.
|
||||
///
|
||||
/// The callback will be called for each `(x, y)` pixel coordinate inside the bounds
|
||||
/// with a coverage value indicating how much the glyph covered that pixel.
|
||||
///
|
||||
/// A coverage value of `0.0` means the pixel is totally uncoverred by the glyph.
|
||||
/// A value of `1.0` or greater means fully coverred.
|
||||
pub fn draw<O: FnMut(u32, u32, f32)>(&self, o: O) {
|
||||
use ab_glyph_rasterizer::Rasterizer;
|
||||
let h_factor = self.scale_factor.horizontal;
|
||||
let v_factor = -self.scale_factor.vertical;
|
||||
let offset = self.glyph.position - self.px_bounds.min;
|
||||
let (w, h) = (
|
||||
self.px_bounds.width() as usize,
|
||||
self.px_bounds.height() as usize,
|
||||
);
|
||||
|
||||
let scale_up = |&Point { x, y }| point(x * h_factor, y * v_factor);
|
||||
|
||||
self.outline
|
||||
.curves
|
||||
.iter()
|
||||
.fold(Rasterizer::new(w, h), |mut rasterizer, curve| match curve {
|
||||
OutlineCurve::Line(p0, p1) => {
|
||||
// eprintln!("r.draw_line({:?}, {:?});",
|
||||
// scale_up(p0) + offset, scale_up(p1) + offset);
|
||||
rasterizer.draw_line(scale_up(p0) + offset, scale_up(p1) + offset);
|
||||
rasterizer
|
||||
}
|
||||
OutlineCurve::Quad(p0, p1, p2) => {
|
||||
// eprintln!("r.draw_quad({:?}, {:?}, {:?});",
|
||||
// scale_up(p0) + offset, scale_up(p1) + offset, scale_up(p2) + offset);
|
||||
rasterizer.draw_quad(
|
||||
scale_up(p0) + offset,
|
||||
scale_up(p1) + offset,
|
||||
scale_up(p2) + offset,
|
||||
);
|
||||
rasterizer
|
||||
}
|
||||
OutlineCurve::Cubic(p0, p1, p2, p3) => {
|
||||
// eprintln!("r.draw_cubic({:?}, {:?}, {:?}, {:?});",
|
||||
// scale_up(p0) + offset, scale_up(p1) + offset, scale_up(p2) + offset, scale_up(p3) + offset);
|
||||
rasterizer.draw_cubic(
|
||||
scale_up(p0) + offset,
|
||||
scale_up(p1) + offset,
|
||||
scale_up(p2) + offset,
|
||||
scale_up(p3) + offset,
|
||||
);
|
||||
rasterizer
|
||||
}
|
||||
})
|
||||
.for_each_pixel_2d(o);
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Glyph> for OutlinedGlyph {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &Glyph {
|
||||
self.glyph()
|
||||
}
|
||||
}
|
||||
|
||||
/// Glyph outline primitives.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OutlineCurve {
|
||||
/// Straight line from `.0` to `.1`.
|
||||
Line(Point, Point),
|
||||
/// Quadratic Bézier curve from `.0` to `.2` using `.1` as the control.
|
||||
Quad(Point, Point, Point),
|
||||
/// Cubic Bézier curve from `.0` to `.3` using `.1` as the control at the beginning of the
|
||||
/// curve and `.2` at the end of the curve.
|
||||
Cubic(Point, Point, Point, Point),
|
||||
}
|
||||
|
||||
/// A rectangle, with top-left corner at `min`, and bottom-right corner at `max`.
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||
pub struct Rect {
|
||||
pub min: Point,
|
||||
pub max: Point,
|
||||
}
|
||||
|
||||
impl Rect {
|
||||
#[inline]
|
||||
pub fn width(&self) -> f32 {
|
||||
self.max.x - self.min.x
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> f32 {
|
||||
self.max.y - self.min.y
|
||||
}
|
||||
}
|
||||
270
third-party/vendor/ab_glyph/src/scale.rs
vendored
Normal file
270
third-party/vendor/ab_glyph/src/scale.rs
vendored
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
#[cfg(all(feature = "libm", not(feature = "std")))]
|
||||
use crate::nostd_float::FloatExt;
|
||||
use crate::{Font, Glyph, GlyphId, OutlinedGlyph, Rect};
|
||||
|
||||
/// Pixel scale.
|
||||
///
|
||||
/// This is the pixel-height of text.
|
||||
///
|
||||
/// Usually one uses `x == y`, but one may use a different ratio to stretch a
|
||||
/// font horizontally or vertically.
|
||||
///
|
||||
/// To convert pt size into pixel-scale see [`Font::pt_to_px_scale`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::PxScale;
|
||||
///
|
||||
/// let uniform_scale_24px = PxScale::from(24.0);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub struct PxScale {
|
||||
/// Horizontal scale in pixels.
|
||||
pub x: f32,
|
||||
/// Vertical scale in pixels.
|
||||
///
|
||||
/// By definition, this is the pixel-height of a font.
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl PxScale {
|
||||
/// Returns a `PxScale` with both x & y scale values set to the nearest integer.
|
||||
#[inline]
|
||||
pub fn round(self) -> Self {
|
||||
Self {
|
||||
x: self.x.round(),
|
||||
y: self.y.round(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for PxScale {
|
||||
/// Uniform scaling where x & y are the same.
|
||||
#[inline]
|
||||
fn from(s: f32) -> Self {
|
||||
PxScale { x: s, y: s }
|
||||
}
|
||||
}
|
||||
|
||||
/// 2D scale factors for use with unscaled metrics.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub struct PxScaleFactor {
|
||||
pub horizontal: f32,
|
||||
pub vertical: f32,
|
||||
}
|
||||
|
||||
/// A [`Font`](trait.Font.html) with an associated pixel scale. This can be used to provide
|
||||
/// pixel scale values for glyph advances, heights etc.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{Font, FontRef, PxScale, ScaleFont};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// // Associate the font with a scale of 45px
|
||||
/// let scaled_font = font.as_scaled(PxScale::from(45.0));
|
||||
///
|
||||
/// assert_eq!(scaled_font.height(), 45.0);
|
||||
/// assert_eq!(scaled_font.h_advance(scaled_font.glyph_id('b')), 21.225);
|
||||
///
|
||||
/// // Replace associated scale with another
|
||||
/// let scaled_font = scaled_font.with_scale(180.0);
|
||||
///
|
||||
/// assert_eq!(scaled_font.height(), 180.0);
|
||||
/// assert_eq!(scaled_font.h_advance(scaled_font.glyph_id('b')), 84.9);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub trait ScaleFont<F: Font> {
|
||||
/// Returns the pixel scale associated with this font.
|
||||
fn scale(&self) -> PxScale;
|
||||
|
||||
/// Returns a font reference.
|
||||
fn font(&self) -> &F;
|
||||
|
||||
/// Scale factor for unscaled font horizontal values.
|
||||
#[inline]
|
||||
fn h_scale_factor(&self) -> f32 {
|
||||
self.scale().x / self.font().height_unscaled()
|
||||
}
|
||||
|
||||
/// Scale factor for unscaled font vertical values.
|
||||
#[inline]
|
||||
fn v_scale_factor(&self) -> f32 {
|
||||
self.scale().y / self.font().height_unscaled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn scale_factor(&self) -> PxScaleFactor {
|
||||
PxScaleFactor {
|
||||
horizontal: self.h_scale_factor(),
|
||||
vertical: self.v_scale_factor(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Pixel scaled glyph ascent.
|
||||
#[inline]
|
||||
fn ascent(&self) -> f32 {
|
||||
self.v_scale_factor() * self.font().ascent_unscaled()
|
||||
}
|
||||
|
||||
/// Pixel scaled glyph descent.
|
||||
#[inline]
|
||||
fn descent(&self) -> f32 {
|
||||
self.v_scale_factor() * self.font().descent_unscaled()
|
||||
}
|
||||
|
||||
/// Pixel scaled height `ascent - descent`.
|
||||
///
|
||||
/// By definition of [`PxScale`], this is `self.scale().y`.
|
||||
#[inline]
|
||||
fn height(&self) -> f32 {
|
||||
self.scale().y
|
||||
}
|
||||
|
||||
/// Pixel scaled line gap.
|
||||
#[inline]
|
||||
fn line_gap(&self) -> f32 {
|
||||
self.v_scale_factor() * self.font().line_gap_unscaled()
|
||||
}
|
||||
|
||||
/// Lookup a `GlyphId` matching a given `char`.
|
||||
#[inline]
|
||||
fn glyph_id(&self, c: char) -> GlyphId {
|
||||
self.font().glyph_id(c)
|
||||
}
|
||||
|
||||
/// Construct a [`Glyph`](struct.Glyph.html) with the font's pixel scale at
|
||||
/// position `point(0.0, 0.0)`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf")).unwrap();
|
||||
/// let scaled_font = font.as_scaled(50.0);
|
||||
///
|
||||
/// let a1 = scaled_font.scaled_glyph('a');
|
||||
/// let a2 = font.glyph_id('a').with_scale(50.0); // equivalent
|
||||
///
|
||||
/// # assert_eq!(a1.id, a2.id);
|
||||
/// assert_eq!(a1.scale, PxScale::from(50.0));
|
||||
/// assert_eq!(a1.position, point(0.0, 0.0));
|
||||
/// ```
|
||||
#[inline]
|
||||
fn scaled_glyph(&self, c: char) -> Glyph {
|
||||
self.font().glyph_id(c).with_scale(self.scale())
|
||||
}
|
||||
|
||||
/// Pixel scaled horizontal advance for a given glyph.
|
||||
#[inline]
|
||||
fn h_advance(&self, id: GlyphId) -> f32 {
|
||||
self.h_scale_factor() * self.font().h_advance_unscaled(id)
|
||||
}
|
||||
|
||||
/// Pixel scaled horizontal side bearing for a given glyph.
|
||||
#[inline]
|
||||
fn h_side_bearing(&self, id: GlyphId) -> f32 {
|
||||
self.h_scale_factor() * self.font().h_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
/// Pixel scaled vertical advance for a given glyph.
|
||||
#[inline]
|
||||
fn v_advance(&self, id: GlyphId) -> f32 {
|
||||
self.v_scale_factor() * self.font().v_advance_unscaled(id)
|
||||
}
|
||||
|
||||
/// Pixel scaled vertical side bearing for a given glyph.
|
||||
#[inline]
|
||||
fn v_side_bearing(&self, id: GlyphId) -> f32 {
|
||||
self.v_scale_factor() * self.font().v_side_bearing_unscaled(id)
|
||||
}
|
||||
|
||||
/// Returns additional pixel scaled kerning to apply for a particular pair of glyphs.
|
||||
#[inline]
|
||||
fn kern(&self, first: GlyphId, second: GlyphId) -> f32 {
|
||||
self.h_scale_factor() * self.font().kern_unscaled(first, second)
|
||||
}
|
||||
|
||||
/// Returns the layout bounds of this glyph. These are different to the outline `px_bounds()`.
|
||||
///
|
||||
/// Horizontally: Glyph position +/- h_advance/h_side_bearing.
|
||||
/// Vertically: Glyph position +/- ascent/descent.
|
||||
///
|
||||
/// Note this method does not make use of the associated scale, as `Glyph`
|
||||
/// already includes one of it's own.
|
||||
#[inline]
|
||||
fn glyph_bounds(&self, glyph: &Glyph) -> Rect {
|
||||
self.font().glyph_bounds(glyph)
|
||||
}
|
||||
|
||||
/// The number of glyphs present in this font. Glyph identifiers for this
|
||||
/// font will always be in the range `0..self.glyph_count()`
|
||||
#[inline]
|
||||
fn glyph_count(&self) -> usize {
|
||||
self.font().glyph_count()
|
||||
}
|
||||
|
||||
/// Returns an iterator of all distinct `(GlyphId, char)` pairs. Not ordered.
|
||||
///
|
||||
/// Same as [`Font::codepoint_ids`](trait.Font.html#tymethod.codepoint_ids).
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_>;
|
||||
|
||||
/// Compute glyph outline ready for drawing.
|
||||
///
|
||||
/// Note this method does not make use of the associated scale, as `Glyph`
|
||||
/// already includes one of it's own.
|
||||
#[inline]
|
||||
fn outline_glyph(&self, glyph: Glyph) -> Option<OutlinedGlyph> {
|
||||
self.font().outline_glyph(glyph)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Font, SF: ScaleFont<F>> ScaleFont<F> for &SF {
|
||||
#[inline]
|
||||
fn scale(&self) -> PxScale {
|
||||
(*self).scale()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn font(&self) -> &F {
|
||||
(*self).font()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_> {
|
||||
(*self).codepoint_ids()
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`Font`](trait.Font.html) and an associated pixel scale.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PxScaleFont<F> {
|
||||
pub font: F,
|
||||
pub scale: PxScale,
|
||||
}
|
||||
|
||||
impl<F> PxScaleFont<F> {
|
||||
#[inline]
|
||||
pub fn with_scale<S: Into<PxScale>>(mut self, scale: S) -> Self {
|
||||
self.scale = scale.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Font> ScaleFont<F> for PxScaleFont<F> {
|
||||
#[inline]
|
||||
fn scale(&self) -> PxScale {
|
||||
self.scale
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn font(&self) -> &F {
|
||||
&self.font
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_> {
|
||||
self.font.codepoint_ids()
|
||||
}
|
||||
}
|
||||
349
third-party/vendor/ab_glyph/src/ttfp.rs
vendored
Normal file
349
third-party/vendor/ab_glyph/src/ttfp.rs
vendored
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
//! ttf-parser crate specific code. ttf-parser types should not be leaked publicly.
|
||||
mod outliner;
|
||||
#[cfg(feature = "variable-fonts")]
|
||||
mod variable;
|
||||
|
||||
use crate::{point, v2, Font, GlyphId, GlyphImageFormat, InvalidFont, Outline, Rect};
|
||||
use alloc::boxed::Box;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use owned_ttf_parser::{self as ttfp, AsFaceRef};
|
||||
|
||||
impl From<GlyphId> for ttfp::GlyphId {
|
||||
#[inline]
|
||||
fn from(id: GlyphId) -> Self {
|
||||
Self(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Font data handle stored as a `&[u8]` + parsed data.
|
||||
/// See [`Font`](trait.Font.html) for more methods.
|
||||
///
|
||||
/// Also see the owned version [`FontVec`](struct.FontVec.html).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{Font, FontRef};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
///
|
||||
/// assert_eq!(font.glyph_id('s'), ab_glyph::GlyphId(56));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct FontRef<'font>(ttfp::PreParsedSubtables<'font, ttfp::Face<'font>>);
|
||||
|
||||
impl fmt::Debug for FontRef<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FontRef")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'font> FontRef<'font> {
|
||||
/// Creates an `FontRef` from a byte-slice.
|
||||
///
|
||||
/// For font collections see
|
||||
/// [`FontRef::try_from_slice_and_index`](#method.try_from_slice_and_index).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_slice(data: &'font [u8]) -> Result<Self, InvalidFont> {
|
||||
Self::try_from_slice_and_index(data, 0)
|
||||
}
|
||||
|
||||
/// Creates an `FontRef` from byte-slice.
|
||||
///
|
||||
/// You can set index for font collections. For simple fonts use `0` or
|
||||
/// [`FontRef::try_from_slice`](#method.try_from_slice).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// let font =
|
||||
/// FontRef::try_from_slice_and_index(include_bytes!("../../dev/fonts/Exo2-Light.otf"), 0)?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_slice_and_index(data: &'font [u8], index: u32) -> Result<Self, InvalidFont> {
|
||||
Ok(Self(ttfp::PreParsedSubtables::from(
|
||||
ttfp::Face::parse(data, index).map_err(|_| InvalidFont)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Font data handle stored in a `Vec<u8>` + parsed data.
|
||||
/// See [`Font`](trait.Font.html) for more methods.
|
||||
///
|
||||
/// Also see [`FontRef`](struct.FontRef.html).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{Font, FontVec};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font = FontVec::try_from_vec_and_index(owned_font_data, 0)?;
|
||||
///
|
||||
/// assert_eq!(font.glyph_id('s'), ab_glyph::GlyphId(56));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub struct FontVec(ttfp::PreParsedSubtables<'static, ttfp::OwnedFace>);
|
||||
|
||||
impl fmt::Debug for FontVec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FontVec")
|
||||
}
|
||||
}
|
||||
|
||||
impl FontVec {
|
||||
/// Creates an `FontVec` from owned data.
|
||||
///
|
||||
/// For font collections see
|
||||
/// [`FontVec::try_from_vec_and_index`](#method.try_from_vec_and_index).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font = FontVec::try_from_vec(owned_font_data)?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_vec(data: Vec<u8>) -> Result<Self, InvalidFont> {
|
||||
Self::try_from_vec_and_index(data, 0)
|
||||
}
|
||||
|
||||
/// Creates an `FontVec` from owned data.
|
||||
///
|
||||
/// You can set index for font collections. For simple fonts use `0` or
|
||||
/// [`FontVec::try_from_vec`](#method.try_from_vec).
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font = FontVec::try_from_vec_and_index(owned_font_data, 0)?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn try_from_vec_and_index(data: Vec<u8>, index: u32) -> Result<Self, InvalidFont> {
|
||||
Ok(Self(ttfp::PreParsedSubtables::from(
|
||||
ttfp::OwnedFace::from_vec(data, index).map_err(|_| InvalidFont)?,
|
||||
)))
|
||||
}
|
||||
|
||||
/// Extracts a slice containing the data passed into e.g. [`FontVec::try_from_vec`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font_data_clone = owned_font_data.clone();
|
||||
/// let font = FontVec::try_from_vec(owned_font_data)?;
|
||||
/// assert_eq!(font.as_slice(), font_data_clone);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0.face.as_slice()
|
||||
}
|
||||
|
||||
/// Unwraps the data passed into e.g. [`FontVec::try_from_vec`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use ab_glyph::*;
|
||||
/// # fn main() -> Result<(), InvalidFont> {
|
||||
/// # let owned_font_data = include_bytes!("../../dev/fonts/Exo2-Light.otf").to_vec();
|
||||
/// let font_data_clone = owned_font_data.clone();
|
||||
/// let font = FontVec::try_from_vec(owned_font_data)?;
|
||||
/// assert_eq!(font.into_vec(), font_data_clone);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn into_vec(self) -> Vec<u8> {
|
||||
self.0.face.into_vec()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement `Font` for `Self(AsFontRef)` types.
|
||||
macro_rules! impl_font {
|
||||
($font:ty) => {
|
||||
impl Font for $font {
|
||||
#[inline]
|
||||
fn units_per_em(&self) -> Option<f32> {
|
||||
// TODO unwrap signature when making next breaking change
|
||||
Some(self.0.as_face_ref().units_per_em().into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ascent_unscaled(&self) -> f32 {
|
||||
self.0.as_face_ref().ascender().into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descent_unscaled(&self) -> f32 {
|
||||
self.0.as_face_ref().descender().into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_gap_unscaled(&self) -> f32 {
|
||||
self.0.as_face_ref().line_gap().into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_id(&self, c: char) -> GlyphId {
|
||||
// Note: Using `PreParsedSubtables` method for better performance.
|
||||
let index = self.0.glyph_index(c).map(|id| id.0).unwrap_or(0);
|
||||
GlyphId(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0
|
||||
.as_face_ref()
|
||||
.glyph_hor_advance(id.into())
|
||||
.unwrap_or_default()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn h_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0
|
||||
.as_face_ref()
|
||||
.glyph_hor_side_bearing(id.into())
|
||||
.unwrap_or_default()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_advance_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0
|
||||
.as_face_ref()
|
||||
.glyph_ver_advance(id.into())
|
||||
.unwrap_or_default()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn v_side_bearing_unscaled(&self, id: GlyphId) -> f32 {
|
||||
self.0
|
||||
.as_face_ref()
|
||||
.glyph_ver_side_bearing(id.into())
|
||||
.unwrap_or_default()
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn kern_unscaled(&self, first: GlyphId, second: GlyphId) -> f32 {
|
||||
// Note: Using `PreParsedSubtables` method for better performance.
|
||||
self.0
|
||||
.glyphs_hor_kerning(first.into(), second.into())
|
||||
.map(f32::from)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn outline(&self, id: GlyphId) -> Option<Outline> {
|
||||
let mut outliner = outliner::OutlineCurveBuilder::default();
|
||||
|
||||
let ttfp::Rect {
|
||||
x_min,
|
||||
x_max,
|
||||
y_min,
|
||||
y_max,
|
||||
} = self
|
||||
.0
|
||||
.as_face_ref()
|
||||
.outline_glyph(id.into(), &mut outliner)
|
||||
// invalid bounds are treated as having no outline
|
||||
.filter(|b| b.x_min < b.x_max && b.y_min < b.y_max)?;
|
||||
|
||||
let curves = outliner.take_outline();
|
||||
|
||||
let bounds = Rect {
|
||||
min: point(x_min.into(), y_max.into()),
|
||||
max: point(x_max.into(), y_min.into()),
|
||||
};
|
||||
|
||||
Some(Outline { bounds, curves })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn glyph_count(&self) -> usize {
|
||||
self.0.as_face_ref().number_of_glyphs() as _
|
||||
}
|
||||
|
||||
fn codepoint_ids(&self) -> crate::CodepointIdIter<'_> {
|
||||
let face_ref = self.0.as_face_ref();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
let mut used_indices =
|
||||
std::collections::HashSet::with_capacity(face_ref.number_of_glyphs() as _);
|
||||
#[cfg(not(feature = "std"))]
|
||||
let mut used_indices = alloc::collections::BTreeSet::new();
|
||||
|
||||
let inner = Box::new(
|
||||
face_ref
|
||||
.tables()
|
||||
.cmap
|
||||
.iter()
|
||||
.flat_map(|c| c.subtables)
|
||||
.filter(|s| s.is_unicode())
|
||||
.flat_map(move |subtable| {
|
||||
let mut pairs = Vec::new();
|
||||
subtable.codepoints(|c| {
|
||||
if let Ok(ch) = char::try_from(c) {
|
||||
if let Some(idx) = subtable.glyph_index(c).filter(|i| i.0 > 0) {
|
||||
if used_indices.insert(idx.0) {
|
||||
pairs.push((GlyphId(idx.0), ch));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
pairs
|
||||
}),
|
||||
);
|
||||
|
||||
crate::CodepointIdIter { inner }
|
||||
}
|
||||
|
||||
fn glyph_raster_image2(&self, id: GlyphId, size: u16) -> Option<v2::GlyphImage> {
|
||||
use GlyphImageFormat::*;
|
||||
|
||||
let img = self.0.as_face_ref().glyph_raster_image(id.into(), size)?;
|
||||
Some(v2::GlyphImage {
|
||||
origin: point(img.x.into(), img.y.into()),
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
pixels_per_em: img.pixels_per_em,
|
||||
data: img.data,
|
||||
format: match img.format {
|
||||
ttfp::RasterImageFormat::PNG => Png,
|
||||
ttfp::RasterImageFormat::BitmapMono => BitmapMono,
|
||||
ttfp::RasterImageFormat::BitmapMonoPacked => BitmapMonoPacked,
|
||||
ttfp::RasterImageFormat::BitmapGray2 => BitmapGray2,
|
||||
ttfp::RasterImageFormat::BitmapGray2Packed => BitmapGray2Packed,
|
||||
ttfp::RasterImageFormat::BitmapGray4 => BitmapGray4,
|
||||
ttfp::RasterImageFormat::BitmapGray4Packed => BitmapGray4Packed,
|
||||
ttfp::RasterImageFormat::BitmapGray8 => BitmapGray8,
|
||||
ttfp::RasterImageFormat::BitmapPremulBgra32 => BitmapPremulBgra32,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_font!(FontRef<'_>);
|
||||
impl_font!(FontVec);
|
||||
65
third-party/vendor/ab_glyph/src/ttfp/outliner.rs
vendored
Normal file
65
third-party/vendor/ab_glyph/src/ttfp/outliner.rs
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
use crate::{point, OutlineCurve, Point};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct OutlineCurveBuilder {
|
||||
last: Point,
|
||||
last_move: Option<Point>,
|
||||
outline: Vec<OutlineCurve>,
|
||||
}
|
||||
|
||||
impl OutlineCurveBuilder {
|
||||
#[inline]
|
||||
pub(crate) fn take_outline(mut self) -> Vec<OutlineCurve> {
|
||||
// some font glyphs implicitly close, e.g. Cantarell-VF.otf
|
||||
owned_ttf_parser::OutlineBuilder::close(&mut self);
|
||||
self.outline
|
||||
}
|
||||
}
|
||||
|
||||
impl owned_ttf_parser::OutlineBuilder for OutlineCurveBuilder {
|
||||
#[inline]
|
||||
fn move_to(&mut self, x: f32, y: f32) {
|
||||
// eprintln!("M {x} {y}");
|
||||
self.last = point(x, y);
|
||||
self.last_move = Some(self.last);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_to(&mut self, x1: f32, y1: f32) {
|
||||
// eprintln!("L {x1} {y1}");
|
||||
let p1 = point(x1, y1);
|
||||
self.outline.push(OutlineCurve::Line(self.last, p1));
|
||||
self.last = p1;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn quad_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
|
||||
// eprintln!("Q {x1} {y1}");
|
||||
let p1 = point(x1, y1);
|
||||
let p2 = point(x2, y2);
|
||||
self.outline.push(OutlineCurve::Quad(self.last, p1, p2));
|
||||
self.last = p2;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) {
|
||||
// eprintln!("C {x1} {y1} {x3} {y3}");
|
||||
let p1 = point(x1, y1);
|
||||
let p2 = point(x2, y2);
|
||||
let p3 = point(x3, y3);
|
||||
|
||||
self.outline
|
||||
.push(OutlineCurve::Cubic(self.last, p1, p2, p3));
|
||||
self.last = p3;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn close(&mut self) {
|
||||
// eprintln!("Z");
|
||||
if let Some(m) = self.last_move.take() {
|
||||
self.outline.push(OutlineCurve::Line(self.last, m));
|
||||
}
|
||||
}
|
||||
}
|
||||
63
third-party/vendor/ab_glyph/src/ttfp/variable.rs
vendored
Normal file
63
third-party/vendor/ab_glyph/src/ttfp/variable.rs
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use crate::{FontRef, FontVec, VariableFont, VariationAxis};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use owned_ttf_parser::{self as ttfp, AsFaceRef, FaceMut};
|
||||
|
||||
impl VariableFont for FontRef<'_> {
|
||||
fn set_variation(&mut self, axis: &[u8; 4], value: f32) -> bool {
|
||||
let tag = ttfp::Tag::from_bytes(axis);
|
||||
// TODO remove existence check in next breaking version
|
||||
let exists = self
|
||||
.0
|
||||
.as_face_ref()
|
||||
.variation_axes()
|
||||
.into_iter()
|
||||
.any(|axis| axis.tag == tag);
|
||||
if exists {
|
||||
self.0.set_variation(tag, value);
|
||||
}
|
||||
exists
|
||||
}
|
||||
|
||||
fn variations(&self) -> Vec<VariationAxis> {
|
||||
variations(self.0.as_face_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl VariableFont for FontVec {
|
||||
fn set_variation(&mut self, axis: &[u8; 4], value: f32) -> bool {
|
||||
self.0
|
||||
.set_variation(ttfp::Tag::from_bytes(axis), value)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn variations(&self) -> Vec<VariationAxis> {
|
||||
variations(self.0.as_face_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn variations(face: &ttfp::Face<'_>) -> Vec<VariationAxis> {
|
||||
face.variation_axes()
|
||||
.into_iter()
|
||||
.map(|axis| {
|
||||
#[cfg(feature = "std")]
|
||||
let name = face.names().into_iter().find_map(|n| {
|
||||
if n.name_id == axis.name_id {
|
||||
n.to_string()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
#[cfg(not(feature = "std"))]
|
||||
let name = None;
|
||||
VariationAxis {
|
||||
tag: axis.tag.to_bytes(),
|
||||
name,
|
||||
min_value: axis.min_value,
|
||||
default_value: axis.def_value,
|
||||
max_value: axis.max_value,
|
||||
hidden: axis.hidden,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
67
third-party/vendor/ab_glyph/src/variable.rs
vendored
Normal file
67
third-party/vendor/ab_glyph/src/variable.rs
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#[cfg(not(feature = "std"))]
|
||||
use alloc::string::String;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// Logic for variable fonts.
|
||||
///
|
||||
/// Requires feature `variable-fonts` (enabled by default).
|
||||
pub trait VariableFont {
|
||||
/// Sets a variation axis coordinate value by it's tag.
|
||||
///
|
||||
/// Returns false if there is no such axis tag.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{FontRef, VariableFont};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let mut font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Cantarell-VF.otf"))?;
|
||||
///
|
||||
/// // set weight to 600
|
||||
/// assert!(font.set_variation(b"wght", 600.0));
|
||||
///
|
||||
/// // no such variation tag "foob" so return false
|
||||
/// assert!(!font.set_variation(b"foob", 200.0));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
fn set_variation(&mut self, tag: &[u8; 4], value: f32) -> bool;
|
||||
|
||||
/// Returns variation axes.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use ab_glyph::{FontRef, VariableFont};
|
||||
///
|
||||
/// # fn main() -> Result<(), ab_glyph::InvalidFont> {
|
||||
/// let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Cantarell-VF.otf"))?;
|
||||
/// let var = &font.variations()[0];
|
||||
/// # eprintln!("{var:#?}");
|
||||
///
|
||||
/// assert_eq!(var.tag, *b"wght");
|
||||
/// assert_eq!(var.name.as_deref(), Some("Weight"));
|
||||
/// assert!((var.min_value - 100.0).abs() < f32::EPSILON);
|
||||
/// assert!((var.default_value - 400.0).abs() < f32::EPSILON);
|
||||
/// assert!((var.max_value - 800.0).abs() < f32::EPSILON);
|
||||
/// assert!(!var.hidden);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
fn variations(&self) -> Vec<VariationAxis>;
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VariationAxis {
|
||||
/// Tag identifying the design variation for the axis.
|
||||
pub tag: [u8; 4],
|
||||
/// Unicode name.
|
||||
pub name: Option<String>,
|
||||
/// The minimum coordinate value for the axis.
|
||||
pub min_value: f32,
|
||||
/// The default coordinate value for the axis.
|
||||
pub default_value: f32,
|
||||
/// The maximum coordinate value for the axis.
|
||||
pub max_value: f32,
|
||||
/// Whether the axis should be exposed directly in user interfaces.
|
||||
pub hidden: bool,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue