diff --git a/third_party/rust/dwrote/.cargo-checksum.json b/third_party/rust/dwrote/.cargo-checksum.json index c984f282265f0..e9ccf84fc6c04 100644 --- a/third_party/rust/dwrote/.cargo-checksum.json +++ b/third_party/rust/dwrote/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"97226421832e89c8a4c1b25a5e86493fc13b0d085ceb913a04f501f5c3859b0b","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","appveyor.yml":"6a91cdfbcc8c363ead82321b3be509bb7bf9cf8b90c63518d6484371abcfed48","src/bitmap_render_target.rs":"fc13525d7459515e4bf9769c8a8961b046b4d1ba4042591aaf0925dd5edebf64","src/com_helpers.rs":"02535b27bfb0cee6e4d8db3abd22f2d2e8137a4ce3ab3504beaf4fa3ca9370df","src/comptr.rs":"84794cf04b772398e75fdb5d55fd8fa015abf26c61b1f9c761a597133682b2e1","src/font.rs":"a79b944f2f5125bbef9e24921355dc6996f073e3742ddd410b8efaa0df3a3ee2","src/font_collection.rs":"67cd566714f4c0a20cba24dd064ba471e75016fa2672b2153a19878e6b71f24d","src/font_collection_impl.rs":"a585a6ce62083b3346d67619ea47fec46423a7fb04cc11372828389ab26c5a05","src/font_face.rs":"7f78c4132df39857d8118ac3eacbb57e11bca1d69f9d7f8e1c1c24b7a2b69749","src/font_family.rs":"4e948542dba0c158187d0cb2d72343c443380480cacd12894070d0ef1351dd0a","src/font_file.rs":"4bfcaa94c97174e7ab98130011c76ba56c4d25673c02cd46463bb258eecc823b","src/font_file_loader_impl.rs":"71c4153971dbfc21d42ba2e33f159fcb145f7dcfbd17e856e9fd75f0571d41e0","src/gdi_interop.rs":"04dbef7c34bb0fe62c4f2c2ceca62ca94c75a964d744b29b3322a6c3bbb4eabd","src/geometry_sink_impl.rs":"d615de212e55b8b8d95c8d605fc5d78044b4ae4dfd846f706911a16cc3afc049","src/glyph_run_analysis.rs":"23c674e892287884ad92faf02813397e4347d61d3b363f6acb8d578c14e65051","src/helpers.rs":"2f3c57642b24b80c45bbd012e7d6ca1fc524b1b42a8be004cb9b52ea13f4166d","src/lib.rs":"16cc8c236226047bc5ca65f921d2aebec4a3a6101a2c8f2853f39a5db4639e16","src/outline_builder.rs":"0f5c842b2ffe75e21d68f93be6a3834c120bd43303d4e490fdfee9f4f964cdc4","src/rendering_params.rs":"850a51143790f5d29422dc49cbceddc232d814ecd0e6933434ad644e6eec539b","src/test.rs":"158aa4d03655f4efef00327fe72a03dfb504659176aa0eef976ca2485b2c1d74","src/types.rs":"9374d8c5bac80e5e0b66188c5ff4f5f49264e15db837049932d4fd703c33746e"},"package":"c31c624339dab99c223a4b26c2e803b7c248adaca91549ce654c76f39a03f5c8"} \ No newline at end of file +{"files":{"Cargo.toml":"f9e7e5a23ac28b65778fce2d14b4378ce59a2f7cfb954663992c862cc95a7626","README.md":"2583afe9b90e5f23ce4e9926efea35ebbe1bd0fc6d7f8a3097cb1fe589524d50","appveyor.yml":"cc2f2d621f6357214fc14aeccfb387dccec74876e2e977691f532e98e8648088","src/bitmap_render_target.rs":"966d19609319c57af0b41bc3e3a6e78d8ad320e18c2f2927a775c8d461de1f97","src/com_helpers.rs":"1278c5eeffdde4270eac69c407b9bd32ea2ea871a3d7b8cc0455ae9533b02616","src/comptr.rs":"2355265138f0fb358eeb663806d121de2c5289783aeb8ce5fa405109ee4cac5b","src/font.rs":"5443f57dbfde84fe6d40e77b65a835595fa5c8d3cab7069aa5def1113b8f2956","src/font_collection.rs":"de26b878c0b915d3a5b8bdaa381279cee26efa2aa1e4392ad124702d09d082db","src/font_collection_impl.rs":"7007724f027168870674e9b7d42b78c634458cebed6b04563bd37be4c152da4a","src/font_face.rs":"0ebaca13ec525dd9f1963757dd9d6f9229792ee8b4ce42ab9840bc91801d885f","src/font_fallback.rs":"b79ba0a389ef8b2a1cdbb9204a2ed32e0da2945dd5e32a3f9741b1c3e8e18707","src/font_family.rs":"4dc374fbd43fdc160031b2055d79cb8d6aa7fcc020a791bcd8be6bf16ce7cc9b","src/font_file.rs":"c82b8c3ec4d5d2d791b357223c601deff3097df940edf3b2bb3d553422ea23e1","src/font_file_loader_impl.rs":"05c5d332b66a0029d04e27dfc59ba0bd28e0cac82a717d2203a7aa399db6d599","src/gdi_interop.rs":"2c463961e96dde4754ed430e57866e5e16e985f50c95d6a73c40a1a846ba48a6","src/geometry_sink_impl.rs":"0327f47fa709ecf2b663274f04d1c4cbf2277c05db088cb631aa3688aef68f95","src/glyph_run_analysis.rs":"82a553204a3dcb9719d45366e86230054edc2ad4204faea77aa498a46e303b1b","src/helpers.rs":"5386acfa2e5016e07ebe2486e880d86c836ab2c6f31071e545f0136ca640bc2e","src/lib.rs":"571e008d202e67ab8c6b79795f3a74d12210876d34221df4ca661ee5adbe5243","src/outline_builder.rs":"dc548624af669f086bf3f009e9f049fa4606470ba065b1b2bef48da7023140ef","src/rendering_params.rs":"18ffff6e8f4c1b020837cdfaf9acdf0fcda818dbf863c1fbafe66ed23a810167","src/test.rs":"dca44ed337f5b2b9409076428881ed4f57dbc10f09bc5cad7d6bbd8ab4fe2415","src/text_analysis_source.rs":"328fdc42cf8a962363f6da08af6a1936da89158be30ae05dac2e8f653ff432e0","src/text_analysis_source_impl.rs":"70747bb3e6cd7d4ae4acfe181fee0d8fe1f6966c48064597de88ad69120f34da","src/types.rs":"628ba0d2fa199b26e6d47be0a9fd924b9c67401f3ee0d67b41d7b93f96007232"},"package":"0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"} \ No newline at end of file diff --git a/third_party/rust/dwrote/Cargo.toml b/third_party/rust/dwrote/Cargo.toml index a2bf71e223d18..663f32168a3de 100644 --- a/third_party/rust/dwrote/Cargo.toml +++ b/third_party/rust/dwrote/Cargo.toml @@ -12,8 +12,8 @@ [package] name = "dwrote" -version = "0.8.0" -authors = ["Vladimir Vukicevic "] +version = "0.9.0" +authors = ["The Servo Project Developers", "Vladimir Vukicevic "] description = "Lightweight binding to DirectWrite." license = "MPL-2.0" repository = "https://github.com/servo/dwrote-rs" diff --git a/third_party/rust/dwrote/README.md b/third_party/rust/dwrote/README.md index d436740898ebc..e9791fc8412b7 100644 --- a/third_party/rust/dwrote/README.md +++ b/third_party/rust/dwrote/README.md @@ -1,12 +1,12 @@ -# dwrote -A thin wrapper around Windows DirectWrite for Rust - -Dwrote provides access to pieces of DirectWrite needed by WebRender -and Servo. It can be easily extended to other parts of DirectWrite, -but full mapping of the DirectWrite API is not a goal (pull requests -accepted, of course). - -There are a few additional helper functions on individual types that -don't exist in DirectWrite, and a few have had their signatures changed, -but for the most part this library attempts to replicate the DirectWrite -API. +# dwrote +A thin wrapper around Windows DirectWrite for Rust + +Dwrote provides access to pieces of DirectWrite needed by WebRender +and Servo. It can be easily extended to other parts of DirectWrite, +but full mapping of the DirectWrite API is not a goal (pull requests +accepted, of course). + +There are a few additional helper functions on individual types that +don't exist in DirectWrite, and a few have had their signatures changed, +but for the most part this library attempts to replicate the DirectWrite +API. diff --git a/third_party/rust/dwrote/appveyor.yml b/third_party/rust/dwrote/appveyor.yml index 21508dc49c7be..fa8c27896760f 100644 --- a/third_party/rust/dwrote/appveyor.yml +++ b/third_party/rust/dwrote/appveyor.yml @@ -1,122 +1,122 @@ -# Appveyor configuration template for Rust using rustup for Rust installation -# https://github.com/starkat99/appveyor-rust - -## Operating System (VM environment) ## - -# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. -os: Visual Studio 2015 - -## Build Matrix ## - -# This configuration will setup a build for each channel & target combination (12 windows -# combinations in all). -# -# There are 3 channels: stable, beta, and nightly. -# -# Alternatively, the full version may be specified for the channel to build using that specific -# version (e.g. channel: 1.5.0) -# -# The values for target are the set of windows Rust build targets. Each value is of the form -# -# ARCH-pc-windows-TOOLCHAIN -# -# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker -# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for -# a description of the toolchain differences. -# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of -# toolchains and host triples. -# -# Comment out channel/target combos you do not wish to build in CI. -# -# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands -# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly -# channels to enable unstable features when building for nightly. Or you could add additional -# matrix entries to test different combinations of features. -environment: - matrix: - -### MSVC Toolchains ### - - # Stable 64-bit MSVC - - channel: stable - target: x86_64-pc-windows-msvc - # Stable 32-bit MSVC - # - channel: stable - # target: i686-pc-windows-msvc - # Beta 64-bit MSVC - # - channel: beta - # target: x86_64-pc-windows-msvc - # Beta 32-bit MSVC - # - channel: beta - # target: i686-pc-windows-msvc - # Nightly 64-bit MSVC - # - channel: nightly - # target: x86_64-pc-windows-msvc - #cargoflags: --features "unstable" - # Nightly 32-bit MSVC - # - channel: nightly - # target: i686-pc-windows-msvc - #cargoflags: --features "unstable" - -### GNU Toolchains ### - - # Stable 64-bit GNU - # - channel: stable - # target: x86_64-pc-windows-gnu - # Stable 32-bit GNU - # - channel: stable - # target: i686-pc-windows-gnu - # Beta 64-bit GNU - # - channel: beta - # target: x86_64-pc-windows-gnu - # Beta 32-bit GNU - # - channel: beta - # target: i686-pc-windows-gnu - # Nightly 64-bit GNU - # - channel: nightly - # target: x86_64-pc-windows-gnu - # #cargoflags: --features "unstable" - # Nightly 32-bit GNU - # - channel: nightly - # target: i686-pc-windows-gnu - #cargoflags: --features "unstable" - -### Allowed failures ### - -# See Appveyor documentation for specific details. In short, place any channel or targets you wish -# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build -# or test failure in the matching channels/targets from failing the entire build. -matrix: - allow_failures: - - channel: nightly - -# If you only care about stable channel build failures, uncomment the following line: - #- channel: beta - -## Install Script ## - -# This is the most important part of the Appveyor configuration. This installs the version of Rust -# specified by the 'channel' and 'target' environment variables from the build matrix. This uses -# rustup to install Rust. -# -# For simple configurations, instead of using the build matrix, you can simply set the -# default-toolchain and default-host manually here. -install: - - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - rustup-init -yv --default-toolchain %channel% --default-host %target% - - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - - rustc -vV - - cargo -vV - -## Build Script ## - -# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents -# the "directory does not contain a project or solution file" error. -build: false - -# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs -#directly or perform other testing commands. Rust will automatically be placed in the PATH -# environment variable. -test_script: - - cargo check --no-default-features - - cargo test --verbose %cargoflags% +# Appveyor configuration template for Rust using rustup for Rust installation +# https://github.com/starkat99/appveyor-rust + +## Operating System (VM environment) ## + +# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. +os: Visual Studio 2015 + +## Build Matrix ## + +# This configuration will setup a build for each channel & target combination (12 windows +# combinations in all). +# +# There are 3 channels: stable, beta, and nightly. +# +# Alternatively, the full version may be specified for the channel to build using that specific +# version (e.g. channel: 1.5.0) +# +# The values for target are the set of windows Rust build targets. Each value is of the form +# +# ARCH-pc-windows-TOOLCHAIN +# +# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker +# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for +# a description of the toolchain differences. +# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of +# toolchains and host triples. +# +# Comment out channel/target combos you do not wish to build in CI. +# +# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands +# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly +# channels to enable unstable features when building for nightly. Or you could add additional +# matrix entries to test different combinations of features. +environment: + matrix: + +### MSVC Toolchains ### + + # Stable 64-bit MSVC + - channel: stable + target: x86_64-pc-windows-msvc + # Stable 32-bit MSVC + # - channel: stable + # target: i686-pc-windows-msvc + # Beta 64-bit MSVC + # - channel: beta + # target: x86_64-pc-windows-msvc + # Beta 32-bit MSVC + # - channel: beta + # target: i686-pc-windows-msvc + # Nightly 64-bit MSVC + # - channel: nightly + # target: x86_64-pc-windows-msvc + #cargoflags: --features "unstable" + # Nightly 32-bit MSVC + # - channel: nightly + # target: i686-pc-windows-msvc + #cargoflags: --features "unstable" + +### GNU Toolchains ### + + # Stable 64-bit GNU + # - channel: stable + # target: x86_64-pc-windows-gnu + # Stable 32-bit GNU + # - channel: stable + # target: i686-pc-windows-gnu + # Beta 64-bit GNU + # - channel: beta + # target: x86_64-pc-windows-gnu + # Beta 32-bit GNU + # - channel: beta + # target: i686-pc-windows-gnu + # Nightly 64-bit GNU + # - channel: nightly + # target: x86_64-pc-windows-gnu + # #cargoflags: --features "unstable" + # Nightly 32-bit GNU + # - channel: nightly + # target: i686-pc-windows-gnu + #cargoflags: --features "unstable" + +### Allowed failures ### + +# See Appveyor documentation for specific details. In short, place any channel or targets you wish +# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build +# or test failure in the matching channels/targets from failing the entire build. +matrix: + allow_failures: + - channel: nightly + +# If you only care about stable channel build failures, uncomment the following line: + #- channel: beta + +## Install Script ## + +# This is the most important part of the Appveyor configuration. This installs the version of Rust +# specified by the 'channel' and 'target' environment variables from the build matrix. This uses +# rustup to install Rust. +# +# For simple configurations, instead of using the build matrix, you can simply set the +# default-toolchain and default-host manually here. +install: + - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init -yv --default-toolchain %channel% --default-host %target% + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - rustc -vV + - cargo -vV + +## Build Script ## + +# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents +# the "directory does not contain a project or solution file" error. +build: false + +# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs +#directly or perform other testing commands. Rust will automatically be placed in the PATH +# environment variable. +test_script: + - cargo check --no-default-features + - cargo test --verbose %cargoflags% diff --git a/third_party/rust/dwrote/src/bitmap_render_target.rs b/third_party/rust/dwrote/src/bitmap_render_target.rs index 8bb397d6ce672..f6622c8aed498 100644 --- a/third_party/rust/dwrote/src/bitmap_render_target.rs +++ b/third_party/rust/dwrote/src/bitmap_render_target.rs @@ -1,127 +1,127 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::slice; -use std::cell::UnsafeCell; -use std::mem::{zeroed, size_of}; - -use comptr::ComPtr; -use winapi::um::dwrite::{DWRITE_GLYPH_RUN, DWRITE_GLYPH_OFFSET}; -use winapi::um::dwrite::IDWriteBitmapRenderTarget; -use winapi::um::dcommon::{DWRITE_MEASURING_MODE}; -use winapi::um::wingdi::{BITMAP, OBJ_BITMAP, RGB, GetObjectW, GetCurrentObject}; -use winapi::shared::windef::{RECT, HDC}; -use winapi::ctypes::c_void; -use super::{FontFace, RenderingParams}; - -pub struct BitmapRenderTarget { - native: UnsafeCell>, -} - -impl BitmapRenderTarget { - pub fn take(native: ComPtr) -> BitmapRenderTarget { - BitmapRenderTarget { - native: UnsafeCell::new(native), - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteBitmapRenderTarget { - (*self.native.get()).as_ptr() - } - - // A dip is 1/96th of an inch, so this value is the number of pixels per inch divided by 96. - pub fn set_pixels_per_dip(&self, ppd: f32) { - unsafe { - (*self.native.get()).SetPixelsPerDip(ppd); - } - } - - pub fn get_memory_dc(&self) -> HDC { - unsafe { - (*self.native.get()).GetMemoryDC() - } - } - - pub fn draw_glyph_run(&self, - baseline_origin_x: f32, - baseline_origin_y: f32, - measuring_mode: DWRITE_MEASURING_MODE, - font_face: &FontFace, - em_size: f32, - glyph_indices: &[u16], - glyph_advances: &[f32], - glyph_offsets: &[DWRITE_GLYPH_OFFSET], - rendering_params: &RenderingParams, - color: &(f32, f32, f32)) - -> RECT - { - unsafe { - assert!(glyph_indices.len() == glyph_advances.len()); - assert!(glyph_indices.len() == glyph_offsets.len()); - - let r = (color.0 * 255.0) as u8; - let g = (color.1 * 255.0) as u8; - let b = (color.2 * 255.0) as u8; - - let mut glyph_run: DWRITE_GLYPH_RUN = zeroed(); - glyph_run.fontFace = font_face.as_ptr(); - glyph_run.fontEmSize = em_size; - glyph_run.glyphCount = glyph_indices.len() as u32; - glyph_run.glyphIndices = glyph_indices.as_ptr(); - glyph_run.glyphAdvances = glyph_advances.as_ptr(); - glyph_run.glyphOffsets = glyph_offsets.as_ptr(); - glyph_run.isSideways = 0; - glyph_run.bidiLevel = 0; - - let mut rect: RECT = zeroed(); - let hr = (*self.native.get()).DrawGlyphRun(baseline_origin_x, - baseline_origin_y, - measuring_mode, - &glyph_run, - rendering_params.as_ptr(), - RGB(r,g,b), - &mut rect); - assert!(hr == 0); - rect - } - } - - // This function expects to have glyphs rendered in WHITE, - // and pulls out a u8 vector of width*height*4 size with - // the coverage value (we pull out R) broadcast to the alpha - // channel, with the color white. That is, it performs: - // RGBX -> xxxR, where xxx = 0xff - pub fn get_opaque_values_as_mask(&self) -> Vec { - // Now grossness to pull out the pixels - unsafe { - let memory_dc = self.get_memory_dc(); - let mut bitmap: BITMAP = zeroed(); - let ret = GetObjectW(GetCurrentObject(memory_dc, OBJ_BITMAP), - size_of::() as i32, - &mut bitmap as *mut _ as *mut c_void); - assert!(ret == size_of::() as i32); - assert!(bitmap.bmBitsPixel == 32); - - let width = bitmap.bmWidth as usize; - let stride = bitmap.bmWidthBytes as usize; - let height = bitmap.bmHeight as usize; - - let mut out_bytes: Vec = vec![0; width * height * 4]; - let mut out_u32 = slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32, - width * height); - - for row in 0..height { - let in_offset = (row * stride) as isize; - let in_u32 = slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32, - width); - for col in 0..width { - let r = in_u32[col] & 0xff; - out_u32[width*row + col] = (r << 24) | (0x00ffffffu32); - } - } - - out_bytes - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::slice; +use std::cell::UnsafeCell; +use std::mem::{zeroed, size_of}; + +use comptr::ComPtr; +use winapi::um::dwrite::{DWRITE_GLYPH_RUN, DWRITE_GLYPH_OFFSET}; +use winapi::um::dwrite::IDWriteBitmapRenderTarget; +use winapi::um::dcommon::{DWRITE_MEASURING_MODE}; +use winapi::um::wingdi::{BITMAP, OBJ_BITMAP, RGB, GetObjectW, GetCurrentObject}; +use winapi::shared::windef::{RECT, HDC}; +use winapi::ctypes::c_void; +use super::{FontFace, RenderingParams}; + +pub struct BitmapRenderTarget { + native: UnsafeCell>, +} + +impl BitmapRenderTarget { + pub fn take(native: ComPtr) -> BitmapRenderTarget { + BitmapRenderTarget { + native: UnsafeCell::new(native), + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteBitmapRenderTarget { + (*self.native.get()).as_ptr() + } + + // A dip is 1/96th of an inch, so this value is the number of pixels per inch divided by 96. + pub fn set_pixels_per_dip(&self, ppd: f32) { + unsafe { + (*self.native.get()).SetPixelsPerDip(ppd); + } + } + + pub fn get_memory_dc(&self) -> HDC { + unsafe { + (*self.native.get()).GetMemoryDC() + } + } + + pub fn draw_glyph_run(&self, + baseline_origin_x: f32, + baseline_origin_y: f32, + measuring_mode: DWRITE_MEASURING_MODE, + font_face: &FontFace, + em_size: f32, + glyph_indices: &[u16], + glyph_advances: &[f32], + glyph_offsets: &[DWRITE_GLYPH_OFFSET], + rendering_params: &RenderingParams, + color: &(f32, f32, f32)) + -> RECT + { + unsafe { + assert!(glyph_indices.len() == glyph_advances.len()); + assert!(glyph_indices.len() == glyph_offsets.len()); + + let r = (color.0 * 255.0) as u8; + let g = (color.1 * 255.0) as u8; + let b = (color.2 * 255.0) as u8; + + let mut glyph_run: DWRITE_GLYPH_RUN = zeroed(); + glyph_run.fontFace = font_face.as_ptr(); + glyph_run.fontEmSize = em_size; + glyph_run.glyphCount = glyph_indices.len() as u32; + glyph_run.glyphIndices = glyph_indices.as_ptr(); + glyph_run.glyphAdvances = glyph_advances.as_ptr(); + glyph_run.glyphOffsets = glyph_offsets.as_ptr(); + glyph_run.isSideways = 0; + glyph_run.bidiLevel = 0; + + let mut rect: RECT = zeroed(); + let hr = (*self.native.get()).DrawGlyphRun(baseline_origin_x, + baseline_origin_y, + measuring_mode, + &glyph_run, + rendering_params.as_ptr(), + RGB(r,g,b), + &mut rect); + assert!(hr == 0); + rect + } + } + + // This function expects to have glyphs rendered in WHITE, + // and pulls out a u8 vector of width*height*4 size with + // the coverage value (we pull out R) broadcast to the alpha + // channel, with the color white. That is, it performs: + // RGBX -> xxxR, where xxx = 0xff + pub fn get_opaque_values_as_mask(&self) -> Vec { + // Now grossness to pull out the pixels + unsafe { + let memory_dc = self.get_memory_dc(); + let mut bitmap: BITMAP = zeroed(); + let ret = GetObjectW(GetCurrentObject(memory_dc, OBJ_BITMAP), + size_of::() as i32, + &mut bitmap as *mut _ as *mut c_void); + assert!(ret == size_of::() as i32); + assert!(bitmap.bmBitsPixel == 32); + + let width = bitmap.bmWidth as usize; + let stride = bitmap.bmWidthBytes as usize; + let height = bitmap.bmHeight as usize; + + let mut out_bytes: Vec = vec![0; width * height * 4]; + let mut out_u32 = slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32, + width * height); + + for row in 0..height { + let in_offset = (row * stride) as isize; + let in_u32 = slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32, + width); + for col in 0..width { + let r = in_u32[col] & 0xff; + out_u32[width*row + col] = (r << 24) | (0x00ffffffu32); + } + } + + out_bytes + } + } +} diff --git a/third_party/rust/dwrote/src/com_helpers.rs b/third_party/rust/dwrote/src/com_helpers.rs index a948f2df34b93..4e792c3c872ef 100644 --- a/third_party/rust/dwrote/src/com_helpers.rs +++ b/third_party/rust/dwrote/src/com_helpers.rs @@ -1,116 +1,116 @@ - -// This is only handy for implementing a single-interface-implementing IUnknown. -// -// it assumes that there's a UuidOf$interface GUID globally defined - -DEFINE_GUID!{UuidOfIUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} - -macro_rules! guid_equals { - ($left:expr, $right:expr) => { - $left.Data1 == $right.Data1 && - $left.Data2 == $right.Data2 && - $left.Data3 == $right.Data3 && - $left.Data4 == $right.Data4 - } -} - -macro_rules! implement_iunknown { - ($interface:ident, $iuud:ident, $typ:ident) => { - IUnknownVtbl { - QueryInterface: { - unsafe extern "system" fn QueryInterface(This: *mut IUnknown, - riid: REFIID, - ppvObject: *mut *mut c_void) -> HRESULT { - let this = if guid_equals!(*riid, $iuud) { - mem::transmute(This) - } else if guid_equals!(*riid, UuidOfIUnknown) { - mem::transmute(This) - } else { - return $crate::winapi::shared::winerror::E_NOINTERFACE; - }; - - (*This).AddRef(); - *ppvObject = this; - return S_OK; - } - QueryInterface - }, - AddRef: { - unsafe extern "system" fn AddRef(This: *mut IUnknown) -> ULONG { - let this = $typ::from_interface(This); - let count = this.refcount.fetch_add(1, atomic::Ordering::Relaxed) + 1; - count as ULONG - } - AddRef - }, - Release: { - unsafe extern "system" fn Release(This: *mut IUnknown) -> ULONG { - let this = $typ::from_interface(This); - let count = this.refcount.fetch_sub(1, atomic::Ordering::Release) - 1; - if count == 0 { - <$typ as Com<$interface>>::destroy(This as *mut $interface); - } - count as ULONG - } - Release - }, - } - }; - (static $interface:ident, $iuud:ident, $typ:ident) => { - IUnknownVtbl { - QueryInterface: { - unsafe extern "system" fn QueryInterface(This: *mut IUnknown, - riid: REFIID, - ppvObject: *mut *mut $crate::winapi::ctypes::c_void) -> HRESULT { - let this = if guid_equals!(*riid, $iuud) { - mem::transmute(This) - } else if guid_equals!(*riid, UuidOfIUnknown) { - mem::transmute(This) - } else { - return $crate::winapi::shared::winerror::E_NOINTERFACE; - }; - - (*This).AddRef(); - *ppvObject = this; - return S_OK; - } - QueryInterface - }, - AddRef: { - unsafe extern "system" fn AddRef(_This: *mut IUnknown) -> ULONG { - 1 - } - AddRef - }, - Release: { - unsafe extern "system" fn Release(_This: *mut IUnknown) -> ULONG { - 1 - } - Release - }, - } - } -} - -#[repr(C)] -pub struct ComRepr(*const Vtbl, Type); - -pub trait Com where Self: Sized { - type Vtbl: 'static; - - fn vtbl() -> &'static Self::Vtbl; - - fn into_interface(self) -> *mut Interface { - let com = Box::new(ComRepr(Self::vtbl(), self)); - Box::into_raw(com) as *mut Interface - } - - unsafe fn from_interface<'a>(thing: *mut Interface) -> &'a mut Self { - &mut (*(thing as *mut ComRepr)).1 - } - - unsafe fn destroy(thing: *mut Interface) { - Box::from_raw(thing as *mut ComRepr); - } -} - + +// This is only handy for implementing a single-interface-implementing IUnknown. +// +// it assumes that there's a UuidOf$interface GUID globally defined + +DEFINE_GUID!{UuidOfIUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} + +macro_rules! guid_equals { + ($left:expr, $right:expr) => { + $left.Data1 == $right.Data1 && + $left.Data2 == $right.Data2 && + $left.Data3 == $right.Data3 && + $left.Data4 == $right.Data4 + } +} + +macro_rules! implement_iunknown { + ($interface:ident, $iuud:ident, $typ:ident) => { + IUnknownVtbl { + QueryInterface: { + unsafe extern "system" fn QueryInterface(This: *mut IUnknown, + riid: REFIID, + ppvObject: *mut *mut c_void) -> HRESULT { + let this = if guid_equals!(*riid, $iuud) { + mem::transmute(This) + } else if guid_equals!(*riid, UuidOfIUnknown) { + mem::transmute(This) + } else { + return $crate::winapi::shared::winerror::E_NOINTERFACE; + }; + + (*This).AddRef(); + *ppvObject = this; + return S_OK; + } + QueryInterface + }, + AddRef: { + unsafe extern "system" fn AddRef(This: *mut IUnknown) -> ULONG { + let this = $typ::from_interface(This); + let count = this.refcount.fetch_add(1, atomic::Ordering::Relaxed) + 1; + count as ULONG + } + AddRef + }, + Release: { + unsafe extern "system" fn Release(This: *mut IUnknown) -> ULONG { + let this = $typ::from_interface(This); + let count = this.refcount.fetch_sub(1, atomic::Ordering::Release) - 1; + if count == 0 { + <$typ as Com<$interface>>::destroy(This as *mut $interface); + } + count as ULONG + } + Release + }, + } + }; + (static $interface:ident, $iuud:ident, $typ:ident) => { + IUnknownVtbl { + QueryInterface: { + unsafe extern "system" fn QueryInterface(This: *mut IUnknown, + riid: REFIID, + ppvObject: *mut *mut $crate::winapi::ctypes::c_void) -> HRESULT { + let this = if guid_equals!(*riid, $iuud) { + mem::transmute(This) + } else if guid_equals!(*riid, UuidOfIUnknown) { + mem::transmute(This) + } else { + return $crate::winapi::shared::winerror::E_NOINTERFACE; + }; + + (*This).AddRef(); + *ppvObject = this; + return S_OK; + } + QueryInterface + }, + AddRef: { + unsafe extern "system" fn AddRef(_This: *mut IUnknown) -> ULONG { + 1 + } + AddRef + }, + Release: { + unsafe extern "system" fn Release(_This: *mut IUnknown) -> ULONG { + 1 + } + Release + }, + } + } +} + +#[repr(C)] +pub struct ComRepr(*const Vtbl, Type); + +pub trait Com where Self: Sized { + type Vtbl: 'static; + + fn vtbl() -> &'static Self::Vtbl; + + fn into_interface(self) -> *mut Interface { + let com = Box::new(ComRepr(Self::vtbl(), self)); + Box::into_raw(com) as *mut Interface + } + + unsafe fn from_interface<'a>(thing: *mut Interface) -> &'a mut Self { + &mut (*(thing as *mut ComRepr)).1 + } + + unsafe fn destroy(thing: *mut Interface) { + Box::from_raw(thing as *mut ComRepr); + } +} + diff --git a/third_party/rust/dwrote/src/comptr.rs b/third_party/rust/dwrote/src/comptr.rs index 4eddfb5f50f8e..0d5f96d9c0a97 100644 --- a/third_party/rust/dwrote/src/comptr.rs +++ b/third_party/rust/dwrote/src/comptr.rs @@ -1,121 +1,121 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::ops::{Deref, DerefMut}; -use std::ptr; -use winapi::um::unknwnbase::IUnknown; -use winapi::shared::guiddef::REFIID; -use winapi::shared::winerror::{S_OK, E_NOINTERFACE}; - -#[derive(Debug)] -pub struct ComPtr { - ptr: *mut T, -} - -impl ComPtr { - pub fn new() -> Self { - ComPtr { ptr: ptr::null_mut() } - } - - pub fn from_ptr(ptr: *mut T) -> Self { - unsafe { - if !ptr.is_null() { - (*(ptr as *mut IUnknown)).AddRef(); - } - } - ComPtr { ptr: ptr } - } - - pub unsafe fn already_addrefed(ptr: *mut T) -> Self { - ComPtr { ptr: ptr } - } - - pub unsafe fn getter_addrefs(&mut self) -> *mut *mut Q { - self.release(); - return &mut self.ptr as *mut *mut _ as *mut *mut Q; - } - - pub fn as_ptr(&self) -> *mut T { - self.ptr - } - - pub fn query_interface(&self, iid: REFIID) -> Option> { - if self.ptr.is_null() { - return None; - } - - unsafe { - let mut p = ComPtr::::new(); - let hr = (*(self.ptr as *mut IUnknown)).QueryInterface(iid, p.getter_addrefs()); - if hr == S_OK { - return Some(p); - } - assert!(hr == E_NOINTERFACE); - return None; - } - } - - pub fn addref(&self) { - unsafe { - assert!(!self.ptr.is_null()); - (*(self.ptr as *mut IUnknown)).AddRef(); - } - } - - pub unsafe fn release(&self) { - if !self.ptr.is_null() { - (*(self.ptr as *mut IUnknown)).Release(); - } - } - - pub fn forget(&mut self) -> *mut T { - let ptr = self.ptr; - self.ptr = ptr::null_mut(); - ptr - } - - pub fn is_null(&self) -> bool { - self.ptr.is_null() - } -} - -impl Clone for ComPtr { - fn clone(&self) -> Self { - if !self.ptr.is_null() { - self.addref(); - } - ComPtr { ptr: self.ptr } - } -} - -impl Deref for ComPtr { - type Target = T; - fn deref(&self) -> &T { - assert!(!self.ptr.is_null()); - unsafe { &mut *self.ptr } - } -} - -impl DerefMut for ComPtr { - fn deref_mut(&mut self) -> &mut T { - assert!(!self.ptr.is_null()); - unsafe { &mut *self.ptr } - } -} - -impl PartialEq for ComPtr { - fn eq(&self, other: &ComPtr) -> bool { - self.ptr == other.ptr - } -} - -impl Drop for ComPtr { - fn drop(&mut self) { - unsafe { - self.release(); - } - } -} - -unsafe impl Send for ComPtr {} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::ops::{Deref, DerefMut}; +use std::ptr; +use winapi::um::unknwnbase::IUnknown; +use winapi::shared::guiddef::REFIID; +use winapi::shared::winerror::{S_OK, E_NOINTERFACE}; + +#[derive(Debug)] +pub struct ComPtr { + ptr: *mut T, +} + +impl ComPtr { + pub fn new() -> Self { + ComPtr { ptr: ptr::null_mut() } + } + + pub fn from_ptr(ptr: *mut T) -> Self { + unsafe { + if !ptr.is_null() { + (*(ptr as *mut IUnknown)).AddRef(); + } + } + ComPtr { ptr: ptr } + } + + pub unsafe fn already_addrefed(ptr: *mut T) -> Self { + ComPtr { ptr: ptr } + } + + pub unsafe fn getter_addrefs(&mut self) -> *mut *mut Q { + self.release(); + return &mut self.ptr as *mut *mut _ as *mut *mut Q; + } + + pub fn as_ptr(&self) -> *mut T { + self.ptr + } + + pub fn query_interface(&self, iid: REFIID) -> Option> { + if self.ptr.is_null() { + return None; + } + + unsafe { + let mut p = ComPtr::::new(); + let hr = (*(self.ptr as *mut IUnknown)).QueryInterface(iid, p.getter_addrefs()); + if hr == S_OK { + return Some(p); + } + assert!(hr == E_NOINTERFACE); + return None; + } + } + + pub fn addref(&self) { + unsafe { + assert!(!self.ptr.is_null()); + (*(self.ptr as *mut IUnknown)).AddRef(); + } + } + + pub unsafe fn release(&self) { + if !self.ptr.is_null() { + (*(self.ptr as *mut IUnknown)).Release(); + } + } + + pub fn forget(&mut self) -> *mut T { + let ptr = self.ptr; + self.ptr = ptr::null_mut(); + ptr + } + + pub fn is_null(&self) -> bool { + self.ptr.is_null() + } +} + +impl Clone for ComPtr { + fn clone(&self) -> Self { + if !self.ptr.is_null() { + self.addref(); + } + ComPtr { ptr: self.ptr } + } +} + +impl Deref for ComPtr { + type Target = T; + fn deref(&self) -> &T { + assert!(!self.ptr.is_null()); + unsafe { &mut *self.ptr } + } +} + +impl DerefMut for ComPtr { + fn deref_mut(&mut self) -> &mut T { + assert!(!self.ptr.is_null()); + unsafe { &mut *self.ptr } + } +} + +impl PartialEq for ComPtr { + fn eq(&self, other: &ComPtr) -> bool { + self.ptr == other.ptr + } +} + +impl Drop for ComPtr { + fn drop(&mut self) { + unsafe { + self.release(); + } + } +} + +unsafe impl Send for ComPtr {} diff --git a/third_party/rust/dwrote/src/font.rs b/third_party/rust/dwrote/src/font.rs index 1205c882ef718..40fe59d0c0e7e 100644 --- a/third_party/rust/dwrote/src/font.rs +++ b/third_party/rust/dwrote/src/font.rs @@ -1,148 +1,148 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::cell::UnsafeCell; - -use comptr::ComPtr; -use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; -use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::{DWRITE_FONT_METRICS, DWRITE_INFORMATIONAL_STRING_FULL_NAME, DWRITE_INFORMATIONAL_STRING_ID}; -use winapi::um::dwrite::{DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME}; -use winapi::um::dwrite::{DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, IDWriteFontFace}; -use winapi::um::dwrite::{IDWriteLocalizedStrings, IDWriteFont, IDWriteFontFamily}; -use winapi::um::dwrite_1::IDWriteFont1; -use std::mem; - -use super::*; -use helpers::*; - -pub struct Font { - native: UnsafeCell>, -} - -impl Font { - pub fn take(native: ComPtr) -> Font { - Font { - native: UnsafeCell::new(native), - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteFont { - (*self.native.get()).as_ptr() - } - - pub fn to_descriptor(&self) -> FontDescriptor { - FontDescriptor { - family_name: self.family_name(), - stretch: self.stretch(), - style: self.style(), - weight: self.weight(), - } - } - - pub fn stretch(&self) -> FontStretch { - unsafe { - mem::transmute::((*self.native.get()).GetStretch()) - } - } - - pub fn style(&self) -> FontStyle { - unsafe { - mem::transmute::((*self.native.get()).GetStyle()) - } - } - - pub fn weight(&self) -> FontWeight { - unsafe { - FontWeight::from_u32((*self.native.get()).GetWeight()) - } - } - - pub fn is_monospace(&self) -> Option { - unsafe { - let font1: Option> = (*self.native.get()).query_interface(&IDWriteFont1::uuidof()); - font1.map(|font| font.IsMonospacedFont() == TRUE) - } - } - - pub fn simulations(&self) -> FontSimulations { - unsafe { - mem::transmute::((*self.native.get()).GetSimulations()) - } - } - - pub fn family_name(&self) -> String { - unsafe { - let mut family: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFontFamily(family.getter_addrefs()); - assert!(hr == 0); - - FontFamily::take(family).name() - } - } - - pub fn face_name(&self) -> String { - unsafe { - let mut names: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFaceNames(names.getter_addrefs()); - assert!(hr == 0); - - get_locale_string(&mut names) - } - } - - pub fn informational_string(&self, id: InformationalStringId) -> Option { - unsafe { - let mut names: ComPtr = ComPtr::new(); - let mut exists = FALSE; - let id = id as DWRITE_INFORMATIONAL_STRING_ID; - let hr = (*self.native.get()).GetInformationalStrings(id, - names.getter_addrefs(), - &mut exists); - assert!(hr == S_OK); - if exists == TRUE { - Some(get_locale_string(&mut names)) - } else { - None - } - } - } - - pub fn create_font_face(&self) -> FontFace { - // FIXME create_font_face should cache the FontFace and return it, - // there's a 1:1 relationship - unsafe { - let mut face: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).CreateFontFace(face.getter_addrefs()); - assert!(hr == 0); - FontFace::take(face) - } - } - - pub fn metrics(&self) -> DWRITE_FONT_METRICS { - unsafe { - let mut metrics = mem::zeroed(); - (*self.native.get()).GetMetrics(&mut metrics); - metrics - } - } -} - -impl Clone for Font { - fn clone(&self) -> Font { - unsafe { - Font { - native: UnsafeCell::new((*self.native.get()).clone()), - } - } - } -} - -#[repr(u32)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum InformationalStringId { - FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, - PostscriptName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, - PostscriptCidName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; + +use comptr::ComPtr; +use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; +use winapi::shared::winerror::S_OK; +use winapi::um::dwrite::{DWRITE_FONT_METRICS, DWRITE_INFORMATIONAL_STRING_FULL_NAME, DWRITE_INFORMATIONAL_STRING_ID}; +use winapi::um::dwrite::{DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME}; +use winapi::um::dwrite::{DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, IDWriteFontFace}; +use winapi::um::dwrite::{IDWriteLocalizedStrings, IDWriteFont, IDWriteFontFamily}; +use winapi::um::dwrite_1::IDWriteFont1; +use std::mem; + +use super::*; +use helpers::*; + +pub struct Font { + native: UnsafeCell>, +} + +impl Font { + pub fn take(native: ComPtr) -> Font { + Font { + native: UnsafeCell::new(native), + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteFont { + (*self.native.get()).as_ptr() + } + + pub fn to_descriptor(&self) -> FontDescriptor { + FontDescriptor { + family_name: self.family_name(), + stretch: self.stretch(), + style: self.style(), + weight: self.weight(), + } + } + + pub fn stretch(&self) -> FontStretch { + unsafe { + mem::transmute::((*self.native.get()).GetStretch()) + } + } + + pub fn style(&self) -> FontStyle { + unsafe { + mem::transmute::((*self.native.get()).GetStyle()) + } + } + + pub fn weight(&self) -> FontWeight { + unsafe { + FontWeight::from_u32((*self.native.get()).GetWeight()) + } + } + + pub fn is_monospace(&self) -> Option { + unsafe { + let font1: Option> = (*self.native.get()).query_interface(&IDWriteFont1::uuidof()); + font1.map(|font| font.IsMonospacedFont() == TRUE) + } + } + + pub fn simulations(&self) -> FontSimulations { + unsafe { + mem::transmute::((*self.native.get()).GetSimulations()) + } + } + + pub fn family_name(&self) -> String { + unsafe { + let mut family: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFontFamily(family.getter_addrefs()); + assert!(hr == 0); + + FontFamily::take(family).name() + } + } + + pub fn face_name(&self) -> String { + unsafe { + let mut names: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFaceNames(names.getter_addrefs()); + assert!(hr == 0); + + get_locale_string(&mut names) + } + } + + pub fn informational_string(&self, id: InformationalStringId) -> Option { + unsafe { + let mut names: ComPtr = ComPtr::new(); + let mut exists = FALSE; + let id = id as DWRITE_INFORMATIONAL_STRING_ID; + let hr = (*self.native.get()).GetInformationalStrings(id, + names.getter_addrefs(), + &mut exists); + assert!(hr == S_OK); + if exists == TRUE { + Some(get_locale_string(&mut names)) + } else { + None + } + } + } + + pub fn create_font_face(&self) -> FontFace { + // FIXME create_font_face should cache the FontFace and return it, + // there's a 1:1 relationship + unsafe { + let mut face: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).CreateFontFace(face.getter_addrefs()); + assert!(hr == 0); + FontFace::take(face) + } + } + + pub fn metrics(&self) -> DWRITE_FONT_METRICS { + unsafe { + let mut metrics = mem::zeroed(); + (*self.native.get()).GetMetrics(&mut metrics); + metrics + } + } +} + +impl Clone for Font { + fn clone(&self) -> Font { + unsafe { + Font { + native: UnsafeCell::new((*self.native.get()).clone()), + } + } + } +} + +#[repr(u32)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum InformationalStringId { + FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, + PostscriptName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, + PostscriptCidName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, +} diff --git a/third_party/rust/dwrote/src/font_collection.rs b/third_party/rust/dwrote/src/font_collection.rs index ef51ff5d58dd8..2d26e1f2c50db 100644 --- a/third_party/rust/dwrote/src/font_collection.rs +++ b/third_party/rust/dwrote/src/font_collection.rs @@ -1,166 +1,166 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use comptr::ComPtr; -use winapi::um::dwrite::{IDWriteFontFamily, IDWriteFont, IDWriteFontCollection}; -use winapi::um::dwrite::{IDWriteFontCollectionLoader}; -use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; -use winapi::shared::winerror::S_OK; -use std::cell::UnsafeCell; -use std::mem; -use std::ptr; -use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; - -use super::{CustomFontCollectionLoaderImpl, DWriteFactory, FontFamily, Font}; -use super::{FontFace, FontDescriptor}; -use helpers::*; -use com_helpers::Com; - -static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; - -pub struct FontCollectionFamilyIterator { - collection: ComPtr, - curr: u32, - count: u32, -} - -impl Iterator for FontCollectionFamilyIterator { - type Item = FontFamily; - fn next(&mut self) -> Option { - if self.curr == self.count { - return None; - } - - unsafe { - let mut family: ComPtr = ComPtr::new(); - let hr = self.collection.GetFontFamily(self.curr, family.getter_addrefs()); - assert!(hr == 0); - self.curr += 1; - Some(FontFamily::take(family)) - } - } -} - -pub struct FontCollection { - native: UnsafeCell>, -} - -impl FontCollection { - pub fn get_system(update: bool) -> FontCollection { - unsafe { - let mut native: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).GetSystemFontCollection( - native.getter_addrefs(), - if update { TRUE } else { FALSE }, - ); - assert!(hr == 0); - - FontCollection { - native: UnsafeCell::new(native) - } - } - } - - pub fn system() -> FontCollection { - FontCollection::get_system(false) - } - - pub fn take(native: ComPtr) -> FontCollection { - FontCollection { - native: UnsafeCell::new(native) - } - } - - pub fn from_loader(collection_loader: ComPtr) -> FontCollection { - unsafe { - let factory = DWriteFactory(); - assert_eq!((*factory).RegisterFontCollectionLoader(collection_loader.clone().forget()), - S_OK); - let mut collection: ComPtr = ComPtr::new(); - let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); - assert_eq!((*factory).CreateCustomFontCollection( - collection_loader.clone().forget(), - &id as *const usize as *const _, - mem::size_of::() as u32, - collection.getter_addrefs()), - S_OK); - FontCollection::take(collection) - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteFontCollection { - (*self.native.get()).as_ptr() - } - - pub fn families_iter(&self) -> FontCollectionFamilyIterator { - unsafe { - FontCollectionFamilyIterator { - collection: (*self.native.get()).clone(), - curr: 0, - count: (*self.native.get()).GetFontFamilyCount(), - } - } - } - - pub fn get_font_family_count(&self) -> u32 { - unsafe { - (*self.native.get()).GetFontFamilyCount() - } - } - - pub fn get_font_family(&self, index: u32) -> FontFamily { - unsafe { - let mut family: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFontFamily(index, family.getter_addrefs()); - assert!(hr == 0); - FontFamily::take(family) - } - } - - // Find a font matching the given font descriptor in this - // font collection. - pub fn get_font_from_descriptor(&self, desc: &FontDescriptor) -> Option { - if let Some(family) = self.get_font_family_by_name(&desc.family_name) { - let font = family.get_first_matching_font(desc.weight, desc.stretch, desc.style); - // Exact matches only here - if font.weight() == desc.weight && - font.stretch() == desc.stretch && - font.style() == desc.style - { - return Some(font); - } - } - - None - } - - pub fn get_font_from_face(&self, face: &FontFace) -> Option { - unsafe { - let mut font: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFontFromFontFace(face.as_ptr(), font.getter_addrefs()); - if hr != 0 { - return None; - } - Some(Font::take(font)) - } - } - - pub fn get_font_family_by_name(&self, family_name: &str) -> Option { - unsafe { - let mut index: u32 = 0; - let mut exists: BOOL = FALSE; - let hr = (*self.native.get()).FindFamilyName(family_name.to_wide_null().as_ptr(), &mut index, &mut exists); - assert!(hr == 0); - if exists == FALSE { - return None; - } - - let mut family: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFontFamily(index, family.getter_addrefs()); - assert!(hr == 0); - - Some(FontFamily::take(family)) - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use comptr::ComPtr; +use winapi::um::dwrite::{IDWriteFontFamily, IDWriteFont, IDWriteFontCollection}; +use winapi::um::dwrite::{IDWriteFontCollectionLoader}; +use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; +use winapi::shared::winerror::S_OK; +use std::cell::UnsafeCell; +use std::mem; +use std::ptr; +use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; + +use super::{CustomFontCollectionLoaderImpl, DWriteFactory, FontFamily, Font}; +use super::{FontFace, FontDescriptor}; +use helpers::*; +use com_helpers::Com; + +static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; + +pub struct FontCollectionFamilyIterator { + collection: ComPtr, + curr: u32, + count: u32, +} + +impl Iterator for FontCollectionFamilyIterator { + type Item = FontFamily; + fn next(&mut self) -> Option { + if self.curr == self.count { + return None; + } + + unsafe { + let mut family: ComPtr = ComPtr::new(); + let hr = self.collection.GetFontFamily(self.curr, family.getter_addrefs()); + assert!(hr == 0); + self.curr += 1; + Some(FontFamily::take(family)) + } + } +} + +pub struct FontCollection { + native: UnsafeCell>, +} + +impl FontCollection { + pub fn get_system(update: bool) -> FontCollection { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).GetSystemFontCollection( + native.getter_addrefs(), + if update { TRUE } else { FALSE }, + ); + assert!(hr == 0); + + FontCollection { + native: UnsafeCell::new(native) + } + } + } + + pub fn system() -> FontCollection { + FontCollection::get_system(false) + } + + pub fn take(native: ComPtr) -> FontCollection { + FontCollection { + native: UnsafeCell::new(native) + } + } + + pub fn from_loader(collection_loader: ComPtr) -> FontCollection { + unsafe { + let factory = DWriteFactory(); + assert_eq!((*factory).RegisterFontCollectionLoader(collection_loader.clone().forget()), + S_OK); + let mut collection: ComPtr = ComPtr::new(); + let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); + assert_eq!((*factory).CreateCustomFontCollection( + collection_loader.clone().forget(), + &id as *const usize as *const _, + mem::size_of::() as u32, + collection.getter_addrefs()), + S_OK); + FontCollection::take(collection) + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteFontCollection { + (*self.native.get()).as_ptr() + } + + pub fn families_iter(&self) -> FontCollectionFamilyIterator { + unsafe { + FontCollectionFamilyIterator { + collection: (*self.native.get()).clone(), + curr: 0, + count: (*self.native.get()).GetFontFamilyCount(), + } + } + } + + pub fn get_font_family_count(&self) -> u32 { + unsafe { + (*self.native.get()).GetFontFamilyCount() + } + } + + pub fn get_font_family(&self, index: u32) -> FontFamily { + unsafe { + let mut family: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFontFamily(index, family.getter_addrefs()); + assert!(hr == 0); + FontFamily::take(family) + } + } + + // Find a font matching the given font descriptor in this + // font collection. + pub fn get_font_from_descriptor(&self, desc: &FontDescriptor) -> Option { + if let Some(family) = self.get_font_family_by_name(&desc.family_name) { + let font = family.get_first_matching_font(desc.weight, desc.stretch, desc.style); + // Exact matches only here + if font.weight() == desc.weight && + font.stretch() == desc.stretch && + font.style() == desc.style + { + return Some(font); + } + } + + None + } + + pub fn get_font_from_face(&self, face: &FontFace) -> Option { + unsafe { + let mut font: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFontFromFontFace(face.as_ptr(), font.getter_addrefs()); + if hr != 0 { + return None; + } + Some(Font::take(font)) + } + } + + pub fn get_font_family_by_name(&self, family_name: &str) -> Option { + unsafe { + let mut index: u32 = 0; + let mut exists: BOOL = FALSE; + let hr = (*self.native.get()).FindFamilyName(family_name.to_wide_null().as_ptr(), &mut index, &mut exists); + assert!(hr == 0); + if exists == FALSE { + return None; + } + + let mut family: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFontFamily(index, family.getter_addrefs()); + assert!(hr == 0); + + Some(FontFamily::take(family)) + } + } +} diff --git a/third_party/rust/dwrote/src/font_collection_impl.rs b/third_party/rust/dwrote/src/font_collection_impl.rs index 08efe2a88683f..58772129d2b02 100644 --- a/third_party/rust/dwrote/src/font_collection_impl.rs +++ b/third_party/rust/dwrote/src/font_collection_impl.rs @@ -1,156 +1,156 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// A temporary custom font collection that exists solely for the face-to-font mapping to work. - -use std::mem; -use std::sync::atomic::AtomicUsize; -use winapi::ctypes::c_void; -use winapi::shared::guiddef::REFIID; -use winapi::shared::minwindef::{BOOL, FALSE, TRUE, ULONG}; -use winapi::shared::winerror::{E_INVALIDARG, S_OK}; -use winapi::um::dwrite::{IDWriteFactory, IDWriteFontCollectionLoader}; -use winapi::um::dwrite::{IDWriteFontCollectionLoaderVtbl, IDWriteFontFile, IDWriteFontFileEnumerator}; -use winapi::um::dwrite::{IDWriteFontFileEnumeratorVtbl}; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winnt::HRESULT; - -use com_helpers::{Com, UuidOfIUnknown}; -use comptr::ComPtr; -use FontFile; - -DEFINE_GUID! { - DWRITE_FONT_COLLECTION_LOADER_UUID, - 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 -} -DEFINE_GUID! { - DWRITE_FONT_FILE_ENUMERATOR_UUID, - 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 -} - -static FONT_COLLECTION_LOADER_VTBL: IDWriteFontCollectionLoaderVtbl = - IDWriteFontCollectionLoaderVtbl { - parent: implement_iunknown!(static IDWriteFontCollectionLoader, - DWRITE_FONT_COLLECTION_LOADER_UUID, - CustomFontCollectionLoaderImpl), - CreateEnumeratorFromKey: CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey, -}; - -pub struct CustomFontCollectionLoaderImpl { - refcount: AtomicUsize, - font_files: Vec>, -} - -impl Com for CustomFontCollectionLoaderImpl { - type Vtbl = IDWriteFontCollectionLoaderVtbl; - #[inline] - fn vtbl() -> &'static IDWriteFontCollectionLoaderVtbl { - &FONT_COLLECTION_LOADER_VTBL - } -} - -impl Com for CustomFontCollectionLoaderImpl { - type Vtbl = IUnknownVtbl; - #[inline] - fn vtbl() -> &'static IUnknownVtbl { - &FONT_COLLECTION_LOADER_VTBL.parent - } -} - -impl CustomFontCollectionLoaderImpl { - pub fn new(font_files: &[FontFile]) -> ComPtr { - unsafe { - ComPtr::already_addrefed(CustomFontCollectionLoaderImpl { - refcount: AtomicUsize::new(1), - font_files: font_files.iter().map(|file| file.as_com_ptr()).collect(), - }.into_interface()) - } - } -} - -unsafe extern "system" fn CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey( - this: *mut IDWriteFontCollectionLoader, - _: *mut IDWriteFactory, - _: *const c_void, - _: u32, - out_enumerator: *mut *mut IDWriteFontFileEnumerator) - -> HRESULT { - let this = CustomFontCollectionLoaderImpl::from_interface(this); - let enumerator = CustomFontFileEnumeratorImpl::new((*this).font_files.clone()); - let enumerator = ComPtr::::from_ptr(enumerator.into_interface()); - *out_enumerator = enumerator.as_ptr(); - mem::forget(enumerator); - S_OK -} - -struct CustomFontFileEnumeratorImpl { - refcount: AtomicUsize, - font_files: Vec>, - index: isize, -} - -impl Com for CustomFontFileEnumeratorImpl { - type Vtbl = IDWriteFontFileEnumeratorVtbl; - #[inline] - fn vtbl() -> &'static IDWriteFontFileEnumeratorVtbl { - &FONT_FILE_ENUMERATOR_VTBL - } -} - -impl Com for CustomFontFileEnumeratorImpl { - type Vtbl = IUnknownVtbl; - #[inline] - fn vtbl() -> &'static IUnknownVtbl { - &FONT_FILE_ENUMERATOR_VTBL.parent - } -} - -static FONT_FILE_ENUMERATOR_VTBL: IDWriteFontFileEnumeratorVtbl = IDWriteFontFileEnumeratorVtbl { - parent: implement_iunknown!(static IDWriteFontFileEnumerator, - DWRITE_FONT_FILE_ENUMERATOR_UUID, - CustomFontFileEnumeratorImpl), - GetCurrentFontFile: CustomFontFileEnumeratorImpl_GetCurrentFontFile, - MoveNext: CustomFontFileEnumeratorImpl_MoveNext, -}; - -impl CustomFontFileEnumeratorImpl { - pub fn new(font_files: Vec>) -> CustomFontFileEnumeratorImpl { - CustomFontFileEnumeratorImpl { - refcount: AtomicUsize::new(1), - font_files, - index: -1, - } - } -} - -unsafe extern "system" fn CustomFontFileEnumeratorImpl_GetCurrentFontFile( - this: *mut IDWriteFontFileEnumerator, - out_font_file: *mut *mut IDWriteFontFile) - -> HRESULT { - let this = CustomFontFileEnumeratorImpl::from_interface(this); - if (*this).index < 0 || (*this).index >= (*this).font_files.len() as isize { - return E_INVALIDARG - } - let new_font_file = (*this).font_files[(*this).index as usize].clone(); - *out_font_file = new_font_file.as_ptr(); - mem::forget(new_font_file); - S_OK -} - -unsafe extern "system" fn CustomFontFileEnumeratorImpl_MoveNext( - this: *mut IDWriteFontFileEnumerator, - has_current_file: *mut BOOL) - -> HRESULT { - let this = CustomFontFileEnumeratorImpl::from_interface(this); - let font_file_count = (*this).font_files.len() as isize; - if (*this).index < font_file_count { - (*this).index += 1 - } - *has_current_file = if (*this).index >= 0 && (*this).index < font_file_count { - TRUE - } else { - FALSE - }; - S_OK -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// A temporary custom font collection that exists solely for the face-to-font mapping to work. + +use std::mem; +use std::sync::atomic::AtomicUsize; +use winapi::ctypes::c_void; +use winapi::shared::guiddef::REFIID; +use winapi::shared::minwindef::{BOOL, FALSE, TRUE, ULONG}; +use winapi::shared::winerror::{E_INVALIDARG, S_OK}; +use winapi::um::dwrite::{IDWriteFactory, IDWriteFontCollectionLoader}; +use winapi::um::dwrite::{IDWriteFontCollectionLoaderVtbl, IDWriteFontFile, IDWriteFontFileEnumerator}; +use winapi::um::dwrite::{IDWriteFontFileEnumeratorVtbl}; +use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; +use winapi::um::winnt::HRESULT; + +use com_helpers::{Com, UuidOfIUnknown}; +use comptr::ComPtr; +use FontFile; + +DEFINE_GUID! { + DWRITE_FONT_COLLECTION_LOADER_UUID, + 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 +} +DEFINE_GUID! { + DWRITE_FONT_FILE_ENUMERATOR_UUID, + 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 +} + +static FONT_COLLECTION_LOADER_VTBL: IDWriteFontCollectionLoaderVtbl = + IDWriteFontCollectionLoaderVtbl { + parent: implement_iunknown!(static IDWriteFontCollectionLoader, + DWRITE_FONT_COLLECTION_LOADER_UUID, + CustomFontCollectionLoaderImpl), + CreateEnumeratorFromKey: CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey, +}; + +pub struct CustomFontCollectionLoaderImpl { + refcount: AtomicUsize, + font_files: Vec>, +} + +impl Com for CustomFontCollectionLoaderImpl { + type Vtbl = IDWriteFontCollectionLoaderVtbl; + #[inline] + fn vtbl() -> &'static IDWriteFontCollectionLoaderVtbl { + &FONT_COLLECTION_LOADER_VTBL + } +} + +impl Com for CustomFontCollectionLoaderImpl { + type Vtbl = IUnknownVtbl; + #[inline] + fn vtbl() -> &'static IUnknownVtbl { + &FONT_COLLECTION_LOADER_VTBL.parent + } +} + +impl CustomFontCollectionLoaderImpl { + pub fn new(font_files: &[FontFile]) -> ComPtr { + unsafe { + ComPtr::already_addrefed(CustomFontCollectionLoaderImpl { + refcount: AtomicUsize::new(1), + font_files: font_files.iter().map(|file| file.as_com_ptr()).collect(), + }.into_interface()) + } + } +} + +unsafe extern "system" fn CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey( + this: *mut IDWriteFontCollectionLoader, + _: *mut IDWriteFactory, + _: *const c_void, + _: u32, + out_enumerator: *mut *mut IDWriteFontFileEnumerator) + -> HRESULT { + let this = CustomFontCollectionLoaderImpl::from_interface(this); + let enumerator = CustomFontFileEnumeratorImpl::new((*this).font_files.clone()); + let enumerator = ComPtr::::from_ptr(enumerator.into_interface()); + *out_enumerator = enumerator.as_ptr(); + mem::forget(enumerator); + S_OK +} + +struct CustomFontFileEnumeratorImpl { + refcount: AtomicUsize, + font_files: Vec>, + index: isize, +} + +impl Com for CustomFontFileEnumeratorImpl { + type Vtbl = IDWriteFontFileEnumeratorVtbl; + #[inline] + fn vtbl() -> &'static IDWriteFontFileEnumeratorVtbl { + &FONT_FILE_ENUMERATOR_VTBL + } +} + +impl Com for CustomFontFileEnumeratorImpl { + type Vtbl = IUnknownVtbl; + #[inline] + fn vtbl() -> &'static IUnknownVtbl { + &FONT_FILE_ENUMERATOR_VTBL.parent + } +} + +static FONT_FILE_ENUMERATOR_VTBL: IDWriteFontFileEnumeratorVtbl = IDWriteFontFileEnumeratorVtbl { + parent: implement_iunknown!(static IDWriteFontFileEnumerator, + DWRITE_FONT_FILE_ENUMERATOR_UUID, + CustomFontFileEnumeratorImpl), + GetCurrentFontFile: CustomFontFileEnumeratorImpl_GetCurrentFontFile, + MoveNext: CustomFontFileEnumeratorImpl_MoveNext, +}; + +impl CustomFontFileEnumeratorImpl { + pub fn new(font_files: Vec>) -> CustomFontFileEnumeratorImpl { + CustomFontFileEnumeratorImpl { + refcount: AtomicUsize::new(1), + font_files, + index: -1, + } + } +} + +unsafe extern "system" fn CustomFontFileEnumeratorImpl_GetCurrentFontFile( + this: *mut IDWriteFontFileEnumerator, + out_font_file: *mut *mut IDWriteFontFile) + -> HRESULT { + let this = CustomFontFileEnumeratorImpl::from_interface(this); + if (*this).index < 0 || (*this).index >= (*this).font_files.len() as isize { + return E_INVALIDARG + } + let new_font_file = (*this).font_files[(*this).index as usize].clone(); + *out_font_file = new_font_file.as_ptr(); + mem::forget(new_font_file); + S_OK +} + +unsafe extern "system" fn CustomFontFileEnumeratorImpl_MoveNext( + this: *mut IDWriteFontFileEnumerator, + has_current_file: *mut BOOL) + -> HRESULT { + let this = CustomFontFileEnumeratorImpl::from_interface(this); + let font_file_count = (*this).font_files.len() as isize; + if (*this).index < font_file_count { + (*this).index += 1 + } + *has_current_file = if (*this).index >= 0 && (*this).index < font_file_count { + TRUE + } else { + FALSE + }; + S_OK +} diff --git a/third_party/rust/dwrote/src/font_face.rs b/third_party/rust/dwrote/src/font_face.rs index 0ec3f87a7da0f..9bb9cee27b70f 100644 --- a/third_party/rust/dwrote/src/font_face.rs +++ b/third_party/rust/dwrote/src/font_face.rs @@ -1,348 +1,348 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::slice; -use std::ptr; -use std::cell::UnsafeCell; -use std::mem::{self, zeroed}; - -use com_helpers::Com; -use comptr::ComPtr; -use font::Font; -use geometry_sink_impl::GeometrySinkImpl; -use outline_builder::OutlineBuilder; -use super::{FontMetrics, FontFile, DefaultDWriteRenderParams, DWriteFactory}; - -use winapi::Interface; -use winapi::ctypes::c_void; -use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; -use winapi::shared::winerror::S_OK; -use winapi::um::dcommon::DWRITE_MEASURING_MODE; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_BITMAP, DWRITE_FONT_FACE_TYPE_CFF}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_RAW_CFF, DWRITE_FONT_FACE_TYPE_TYPE1}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, DWRITE_FONT_FACE_TYPE_VECTOR}; -use winapi::um::dwrite::{DWRITE_FONT_METRICS, DWRITE_FONT_SIMULATIONS, DWRITE_GLYPH_METRICS}; -use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MODE}; -use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC}; -use winapi::um::dwrite::{IDWriteFontCollection, IDWriteFont, IDWriteFontFace, IDWriteFontFile}; -use winapi::um::dwrite::{IDWriteRenderingParams}; -use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE}; - -pub struct FontFace { - native: UnsafeCell>, - face5: UnsafeCell>>, - metrics: FontMetrics, -} - -impl FontFace { - pub fn take(native: ComPtr) -> FontFace { - unsafe { - let mut metrics: FontMetrics = zeroed(); - let cell = UnsafeCell::new(native); - (*cell.get()).GetMetrics(&mut metrics); - FontFace { - native: cell, - face5: UnsafeCell::new(None), - metrics: metrics, - } - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFace { - (*self.native.get()).as_ptr() - } - - unsafe fn get_raw_files(&self) -> Vec<*mut IDWriteFontFile> { - let mut number_of_files: u32 = 0; - let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut()); - assert!(hr == 0); - - let mut file_ptrs: Vec<*mut IDWriteFontFile> = - vec![ptr::null_mut(); number_of_files as usize]; - let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr()); - assert!(hr == 0); - file_ptrs - } - - pub fn get_files(&self) -> Vec { - unsafe { - let file_ptrs = self.get_raw_files(); - file_ptrs.iter().map(|p| FontFile::take(ComPtr::from_ptr(*p))).collect() - } - } - - pub fn create_font_face_with_simulations(&self, simulations: DWRITE_FONT_SIMULATIONS) -> FontFace { - unsafe { - let file_ptrs = self.get_raw_files(); - let face_type = (*self.native.get()).GetType(); - let face_index = (*self.native.get()).GetIndex(); - let mut face: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).CreateFontFace( - face_type, - file_ptrs.len() as u32, - file_ptrs.as_ptr(), - face_index, - simulations, - face.getter_addrefs() - ); - for p in file_ptrs { - let _ = ComPtr::::already_addrefed(p); - } - assert!(hr == 0); - FontFace::take(face) - } - } - - pub fn get_glyph_count(&self) -> u16 { - unsafe { - (*self.native.get()).GetGlyphCount() - } - } - - pub fn metrics(&self) -> &FontMetrics { - &self.metrics - } - - pub fn get_metrics(&self) -> FontMetrics { - unsafe { - let mut metrics: DWRITE_FONT_METRICS = zeroed(); - (*self.native.get()).GetMetrics(&mut metrics); - metrics - } - } - - pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec { - unsafe { - let mut glyph_indices: Vec = vec![0; code_points.len()]; - let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(), - code_points.len() as u32, - glyph_indices.as_mut_ptr()); - assert!(hr == 0); - glyph_indices - } - } - - pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec { - unsafe { - let mut metrics: Vec = vec![zeroed(); glyph_indices.len()]; - let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(), - glyph_indices.len() as u32, - metrics.as_mut_ptr(), - is_sideways as BOOL); - assert!(hr == 0); - metrics - } - } - - pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const DWRITE_MATRIX, - use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool) - -> Vec - { - unsafe { - let mut metrics: Vec = vec![zeroed(); glyph_indices.len()]; - let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip, - transform, - use_gdi_natural as BOOL, - glyph_indices.as_ptr(), - glyph_indices.len() as u32, - metrics.as_mut_ptr(), - is_sideways as BOOL); - assert!(hr == 0); - metrics - } - } - - pub fn get_font_table(&self, opentype_table_tag: u32) -> Option> { - unsafe { - let mut table_data_ptr: *const u8 = ptr::null_mut(); - let mut table_size: u32 = 0; - let mut table_context: *mut c_void = ptr::null_mut(); - let mut exists: BOOL = FALSE; - - let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag, - &mut table_data_ptr as *mut *const _ as *mut *const c_void, - &mut table_size, - &mut table_context, - &mut exists); - assert!(hr == 0); - - if exists == FALSE { - return None; - } - - let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec(); - - (*self.native.get()).ReleaseFontTable(table_context); - - Some(table_bytes) - } - } - - pub fn get_recommended_rendering_mode(&self, - em_size: f32, - pixels_per_dip: f32, - measure_mode: DWRITE_MEASURING_MODE, - rendering_params: *mut IDWriteRenderingParams) -> - DWRITE_RENDERING_MODE { - unsafe { - let mut render_mode : DWRITE_RENDERING_MODE = DWRITE_RENDERING_MODE_DEFAULT; - let hr = (*self.native.get()).GetRecommendedRenderingMode(em_size, - pixels_per_dip, - measure_mode, - rendering_params, - &mut render_mode); - - if hr != 0 { - return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; - } - - render_mode - } - } - - pub fn get_recommended_rendering_mode_default_params(&self, - em_size: f32, - pixels_per_dip: f32, - measure_mode: DWRITE_MEASURING_MODE) -> - DWRITE_RENDERING_MODE { - self.get_recommended_rendering_mode(em_size, - pixels_per_dip, - measure_mode, - DefaultDWriteRenderParams()) - } - - pub fn get_glyph_run_outline(&self, - em_size: f32, - glyph_indices: &[u16], - glyph_advances: Option<&[f32]>, - glyph_offsets: Option<&[DWRITE_GLYPH_OFFSET]>, - is_sideways: bool, - is_right_to_left: bool, - outline_builder: Box) { - unsafe { - let glyph_advances = match glyph_advances { - None => ptr::null(), - Some(glyph_advances) => { - assert_eq!(glyph_advances.len(), glyph_indices.len()); - glyph_advances.as_ptr() - } - }; - let glyph_offsets = match glyph_offsets { - None => ptr::null(), - Some(glyph_offsets) => { - assert_eq!(glyph_offsets.len(), glyph_indices.len()); - glyph_offsets.as_ptr() - } - }; - let is_sideways = if is_sideways { TRUE } else { FALSE }; - let is_right_to_left = if is_right_to_left { TRUE } else { FALSE }; - let geometry_sink = GeometrySinkImpl::new(outline_builder); - let geometry_sink = geometry_sink.into_interface(); - let hr = (*self.native.get()).GetGlyphRunOutline(em_size, - glyph_indices.as_ptr(), - glyph_advances, - glyph_offsets, - glyph_indices.len() as u32, - is_sideways, - is_right_to_left, - geometry_sink); - assert_eq!(hr, S_OK); - } - } - - #[inline] - pub fn get_type(&self) -> FontFaceType { - unsafe { - match (*self.native.get()).GetType() { - DWRITE_FONT_FACE_TYPE_CFF => FontFaceType::Cff, - DWRITE_FONT_FACE_TYPE_RAW_CFF => FontFaceType::RawCff, - DWRITE_FONT_FACE_TYPE_TRUETYPE => FontFaceType::TrueType, - DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION => FontFaceType::TrueTypeCollection, - DWRITE_FONT_FACE_TYPE_TYPE1 => FontFaceType::Type1, - DWRITE_FONT_FACE_TYPE_VECTOR => FontFaceType::Vector, - DWRITE_FONT_FACE_TYPE_BITMAP => FontFaceType::Bitmap, - _ => FontFaceType::Unknown, - } - } - } - - #[inline] - pub fn get_index(&self) -> u32 { - unsafe { - (*self.native.get()).GetIndex() - } - } - - #[inline] - unsafe fn get_face5(&self) -> &mut ComPtr { - (*self.face5.get()).get_or_insert_with(|| { - (*self.native.get()) - .query_interface(&IDWriteFontFace5::uuidof()) - .unwrap_or(ComPtr::new()) - }) - } - - pub fn has_variations(&self) -> bool { - unsafe { - let face5 = self.get_face5(); - if !face5.is_null() { - face5.HasVariations() == TRUE - } else { - false - } - } - } - - pub fn create_font_face_with_variations( - &self, - simulations: DWRITE_FONT_SIMULATIONS, - axis_values: &[DWRITE_FONT_AXIS_VALUE], - ) -> Option { - unsafe { - let face5 = self.get_face5(); - if !face5.is_null() { - let mut resource: ComPtr = ComPtr::new(); - let hr = face5.GetFontResource(resource.getter_addrefs()); - if hr == S_OK && !resource.is_null() { - let mut var_face: ComPtr = ComPtr::new(); - let hr = resource.CreateFontFace( - simulations, - axis_values.as_ptr(), - axis_values.len() as u32, - var_face.getter_addrefs(), - ); - if hr == S_OK && !var_face.is_null() { - return Some(FontFace::take(var_face)); - } - } - } - None - } - } -} - -impl Clone for FontFace { - fn clone(&self) -> FontFace { - unsafe { - FontFace { - native: UnsafeCell::new((*self.native.get()).clone()), - face5: UnsafeCell::new(None), - metrics: self.metrics, - } - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum FontFaceType { - Unknown, - Cff, - RawCff, - TrueType, - TrueTypeCollection, - Type1, - Vector, - Bitmap, -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::slice; +use std::ptr; +use std::cell::UnsafeCell; +use std::mem::{self, zeroed}; + +use com_helpers::Com; +use comptr::ComPtr; +use font::Font; +use geometry_sink_impl::GeometrySinkImpl; +use outline_builder::OutlineBuilder; +use super::{FontMetrics, FontFile, DefaultDWriteRenderParams, DWriteFactory}; + +use winapi::Interface; +use winapi::ctypes::c_void; +use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; +use winapi::shared::winerror::S_OK; +use winapi::um::dcommon::DWRITE_MEASURING_MODE; +use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_BITMAP, DWRITE_FONT_FACE_TYPE_CFF}; +use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_RAW_CFF, DWRITE_FONT_FACE_TYPE_TYPE1}; +use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE}; +use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, DWRITE_FONT_FACE_TYPE_VECTOR}; +use winapi::um::dwrite::{DWRITE_FONT_METRICS, DWRITE_FONT_SIMULATIONS, DWRITE_GLYPH_METRICS}; +use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MODE}; +use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC}; +use winapi::um::dwrite::{IDWriteFontCollection, IDWriteFont, IDWriteFontFace, IDWriteFontFile}; +use winapi::um::dwrite::{IDWriteRenderingParams}; +use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE}; + +pub struct FontFace { + native: UnsafeCell>, + face5: UnsafeCell>>, + metrics: FontMetrics, +} + +impl FontFace { + pub fn take(native: ComPtr) -> FontFace { + unsafe { + let mut metrics: FontMetrics = zeroed(); + let cell = UnsafeCell::new(native); + (*cell.get()).GetMetrics(&mut metrics); + FontFace { + native: cell, + face5: UnsafeCell::new(None), + metrics: metrics, + } + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFace { + (*self.native.get()).as_ptr() + } + + unsafe fn get_raw_files(&self) -> Vec<*mut IDWriteFontFile> { + let mut number_of_files: u32 = 0; + let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut()); + assert!(hr == 0); + + let mut file_ptrs: Vec<*mut IDWriteFontFile> = + vec![ptr::null_mut(); number_of_files as usize]; + let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr()); + assert!(hr == 0); + file_ptrs + } + + pub fn get_files(&self) -> Vec { + unsafe { + let file_ptrs = self.get_raw_files(); + file_ptrs.iter().map(|p| FontFile::take(ComPtr::from_ptr(*p))).collect() + } + } + + pub fn create_font_face_with_simulations(&self, simulations: DWRITE_FONT_SIMULATIONS) -> FontFace { + unsafe { + let file_ptrs = self.get_raw_files(); + let face_type = (*self.native.get()).GetType(); + let face_index = (*self.native.get()).GetIndex(); + let mut face: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateFontFace( + face_type, + file_ptrs.len() as u32, + file_ptrs.as_ptr(), + face_index, + simulations, + face.getter_addrefs() + ); + for p in file_ptrs { + let _ = ComPtr::::already_addrefed(p); + } + assert!(hr == 0); + FontFace::take(face) + } + } + + pub fn get_glyph_count(&self) -> u16 { + unsafe { + (*self.native.get()).GetGlyphCount() + } + } + + pub fn metrics(&self) -> &FontMetrics { + &self.metrics + } + + pub fn get_metrics(&self) -> FontMetrics { + unsafe { + let mut metrics: DWRITE_FONT_METRICS = zeroed(); + (*self.native.get()).GetMetrics(&mut metrics); + metrics + } + } + + pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec { + unsafe { + let mut glyph_indices: Vec = vec![0; code_points.len()]; + let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(), + code_points.len() as u32, + glyph_indices.as_mut_ptr()); + assert!(hr == 0); + glyph_indices + } + } + + pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec { + unsafe { + let mut metrics: Vec = vec![zeroed(); glyph_indices.len()]; + let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(), + glyph_indices.len() as u32, + metrics.as_mut_ptr(), + is_sideways as BOOL); + assert!(hr == 0); + metrics + } + } + + pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const DWRITE_MATRIX, + use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool) + -> Vec + { + unsafe { + let mut metrics: Vec = vec![zeroed(); glyph_indices.len()]; + let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip, + transform, + use_gdi_natural as BOOL, + glyph_indices.as_ptr(), + glyph_indices.len() as u32, + metrics.as_mut_ptr(), + is_sideways as BOOL); + assert!(hr == 0); + metrics + } + } + + pub fn get_font_table(&self, opentype_table_tag: u32) -> Option> { + unsafe { + let mut table_data_ptr: *const u8 = ptr::null_mut(); + let mut table_size: u32 = 0; + let mut table_context: *mut c_void = ptr::null_mut(); + let mut exists: BOOL = FALSE; + + let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag, + &mut table_data_ptr as *mut *const _ as *mut *const c_void, + &mut table_size, + &mut table_context, + &mut exists); + assert!(hr == 0); + + if exists == FALSE { + return None; + } + + let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec(); + + (*self.native.get()).ReleaseFontTable(table_context); + + Some(table_bytes) + } + } + + pub fn get_recommended_rendering_mode(&self, + em_size: f32, + pixels_per_dip: f32, + measure_mode: DWRITE_MEASURING_MODE, + rendering_params: *mut IDWriteRenderingParams) -> + DWRITE_RENDERING_MODE { + unsafe { + let mut render_mode : DWRITE_RENDERING_MODE = DWRITE_RENDERING_MODE_DEFAULT; + let hr = (*self.native.get()).GetRecommendedRenderingMode(em_size, + pixels_per_dip, + measure_mode, + rendering_params, + &mut render_mode); + + if hr != 0 { + return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; + } + + render_mode + } + } + + pub fn get_recommended_rendering_mode_default_params(&self, + em_size: f32, + pixels_per_dip: f32, + measure_mode: DWRITE_MEASURING_MODE) -> + DWRITE_RENDERING_MODE { + self.get_recommended_rendering_mode(em_size, + pixels_per_dip, + measure_mode, + DefaultDWriteRenderParams()) + } + + pub fn get_glyph_run_outline(&self, + em_size: f32, + glyph_indices: &[u16], + glyph_advances: Option<&[f32]>, + glyph_offsets: Option<&[DWRITE_GLYPH_OFFSET]>, + is_sideways: bool, + is_right_to_left: bool, + outline_builder: Box) { + unsafe { + let glyph_advances = match glyph_advances { + None => ptr::null(), + Some(glyph_advances) => { + assert_eq!(glyph_advances.len(), glyph_indices.len()); + glyph_advances.as_ptr() + } + }; + let glyph_offsets = match glyph_offsets { + None => ptr::null(), + Some(glyph_offsets) => { + assert_eq!(glyph_offsets.len(), glyph_indices.len()); + glyph_offsets.as_ptr() + } + }; + let is_sideways = if is_sideways { TRUE } else { FALSE }; + let is_right_to_left = if is_right_to_left { TRUE } else { FALSE }; + let geometry_sink = GeometrySinkImpl::new(outline_builder); + let geometry_sink = geometry_sink.into_interface(); + let hr = (*self.native.get()).GetGlyphRunOutline(em_size, + glyph_indices.as_ptr(), + glyph_advances, + glyph_offsets, + glyph_indices.len() as u32, + is_sideways, + is_right_to_left, + geometry_sink); + assert_eq!(hr, S_OK); + } + } + + #[inline] + pub fn get_type(&self) -> FontFaceType { + unsafe { + match (*self.native.get()).GetType() { + DWRITE_FONT_FACE_TYPE_CFF => FontFaceType::Cff, + DWRITE_FONT_FACE_TYPE_RAW_CFF => FontFaceType::RawCff, + DWRITE_FONT_FACE_TYPE_TRUETYPE => FontFaceType::TrueType, + DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION => FontFaceType::TrueTypeCollection, + DWRITE_FONT_FACE_TYPE_TYPE1 => FontFaceType::Type1, + DWRITE_FONT_FACE_TYPE_VECTOR => FontFaceType::Vector, + DWRITE_FONT_FACE_TYPE_BITMAP => FontFaceType::Bitmap, + _ => FontFaceType::Unknown, + } + } + } + + #[inline] + pub fn get_index(&self) -> u32 { + unsafe { + (*self.native.get()).GetIndex() + } + } + + #[inline] + unsafe fn get_face5(&self) -> &mut ComPtr { + (*self.face5.get()).get_or_insert_with(|| { + (*self.native.get()) + .query_interface(&IDWriteFontFace5::uuidof()) + .unwrap_or(ComPtr::new()) + }) + } + + pub fn has_variations(&self) -> bool { + unsafe { + let face5 = self.get_face5(); + if !face5.is_null() { + face5.HasVariations() == TRUE + } else { + false + } + } + } + + pub fn create_font_face_with_variations( + &self, + simulations: DWRITE_FONT_SIMULATIONS, + axis_values: &[DWRITE_FONT_AXIS_VALUE], + ) -> Option { + unsafe { + let face5 = self.get_face5(); + if !face5.is_null() { + let mut resource: ComPtr = ComPtr::new(); + let hr = face5.GetFontResource(resource.getter_addrefs()); + if hr == S_OK && !resource.is_null() { + let mut var_face: ComPtr = ComPtr::new(); + let hr = resource.CreateFontFace( + simulations, + axis_values.as_ptr(), + axis_values.len() as u32, + var_face.getter_addrefs(), + ); + if hr == S_OK && !var_face.is_null() { + return Some(FontFace::take(var_face)); + } + } + } + None + } + } +} + +impl Clone for FontFace { + fn clone(&self) -> FontFace { + unsafe { + FontFace { + native: UnsafeCell::new((*self.native.get()).clone()), + face5: UnsafeCell::new(None), + metrics: self.metrics, + } + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum FontFaceType { + Unknown, + Cff, + RawCff, + TrueType, + TrueTypeCollection, + Type1, + Vector, + Bitmap, +} diff --git a/third_party/rust/dwrote/src/font_fallback.rs b/third_party/rust/dwrote/src/font_fallback.rs new file mode 100644 index 0000000000000..6f1aff8ac67bb --- /dev/null +++ b/third_party/rust/dwrote/src/font_fallback.rs @@ -0,0 +1,93 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; +use std::ptr::null_mut; + +use winapi::um::dwrite_2::{IDWriteFactory2, IDWriteFontFallback}; + +use super::*; +use helpers::*; + +pub struct FontFallback { + native: UnsafeCell>, +} + +pub struct FallbackResult { + /// Length of mapped substring, in utf-16 code units. + pub mapped_length: usize, + /// The font that should be used to render the substring. + pub mapped_font: Option, + /// The scale factor to apply. + pub scale: f32, +} + +impl FontFallback { + pub fn get_system_fallback() -> Option { + unsafe { + let factory = ComPtr::already_addrefed(DWriteFactory()); + let factory2 = factory.query_interface::(&IDWriteFactory2::uuidof()); + std::mem::forget(factory); + let factory2 = factory2?; + let mut native = null_mut(); + let hr = factory2.GetSystemFontFallback(&mut native); + assert_eq!(hr, 0); + Some(Self::take(ComPtr::from_ptr(native))) + } + } + + pub fn take(native: ComPtr) -> FontFallback { + FontFallback { + native: UnsafeCell::new(native), + } + } + + // TODO: I'm following crate conventions for unsafe, but it's bullshit + pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFallback { + (*self.native.get()).as_ptr() + } + + // TODO: map_characters (main function) + pub fn map_characters( + &self, + text_analysis_source: &TextAnalysisSource, + text_position: u32, + text_length: u32, + base_font: &FontCollection, + base_family: Option<&str>, + base_weight: FontWeight, + base_style: FontStyle, + base_stretch: FontStretch) + -> FallbackResult { + unsafe { + let mut font = null_mut(); + let mut mapped_length = 0; + let mut scale = 0.0; + let hr = (*self.as_ptr()).MapCharacters( + text_analysis_source.as_ptr(), + text_position, + text_length, + base_font.as_ptr(), + base_family.map(|s| s.to_wide_null().as_mut_ptr()).unwrap_or(null_mut()), + base_weight.t(), + base_style.t(), + base_stretch.t(), + &mut mapped_length, + &mut font, + &mut scale, + ); + assert_eq!(hr, 0); + let mapped_font = if font.is_null() { + None + } else { + Some(Font::take(ComPtr::already_addrefed(font))) + }; + FallbackResult { + mapped_length: mapped_length as usize, + mapped_font, + scale + } + } + } +} diff --git a/third_party/rust/dwrote/src/font_family.rs b/third_party/rust/dwrote/src/font_family.rs index 1166f9933b2df..e0dcc27a731d9 100644 --- a/third_party/rust/dwrote/src/font_family.rs +++ b/third_party/rust/dwrote/src/font_family.rs @@ -1,77 +1,77 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::cell::UnsafeCell; - -use comptr::ComPtr; -use winapi::um::dwrite::{IDWriteFont, IDWriteFontFamily, IDWriteFontCollection}; -use winapi::um::dwrite::{IDWriteLocalizedStrings}; - -use super::*; -use helpers::*; - -pub struct FontFamily { - native: UnsafeCell>, -} - -impl FontFamily { - pub fn take(native: ComPtr) -> FontFamily { - FontFamily { - native: UnsafeCell::new(native) - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFamily { - (*self.native.get()).as_ptr() - } - - pub fn name(&self) -> String { - unsafe { - let mut family_names: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFamilyNames(family_names.getter_addrefs()); - assert!(hr == 0); - - get_locale_string(&mut family_names) - } - } - - pub fn get_first_matching_font(&self, - weight: FontWeight, - stretch: FontStretch, - style: FontStyle) - -> Font - { - unsafe { - let mut font: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFirstMatchingFont(weight.t(), stretch.t(), style.t(), font.getter_addrefs()); - assert!(hr == 0); - Font::take(font) - } - } - - pub fn get_font_collection(&self) -> FontCollection { - unsafe { - let mut collection: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFontCollection(collection.getter_addrefs()); - assert!(hr == 0); - FontCollection::take(collection) - } - } - - pub fn get_font_count(&self) -> u32 { - unsafe { - (*self.native.get()).GetFontCount() - } - } - - pub fn get_font(&self, index: u32) -> Font { - unsafe { - let mut font: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetFont(index, font.getter_addrefs()); - assert!(hr == 0); - assert!(!font.as_ptr().is_null()); - Font::take(font) - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; + +use comptr::ComPtr; +use winapi::um::dwrite::{IDWriteFont, IDWriteFontFamily, IDWriteFontCollection}; +use winapi::um::dwrite::{IDWriteLocalizedStrings}; + +use super::*; +use helpers::*; + +pub struct FontFamily { + native: UnsafeCell>, +} + +impl FontFamily { + pub fn take(native: ComPtr) -> FontFamily { + FontFamily { + native: UnsafeCell::new(native) + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFamily { + (*self.native.get()).as_ptr() + } + + pub fn name(&self) -> String { + unsafe { + let mut family_names: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFamilyNames(family_names.getter_addrefs()); + assert!(hr == 0); + + get_locale_string(&mut family_names) + } + } + + pub fn get_first_matching_font(&self, + weight: FontWeight, + stretch: FontStretch, + style: FontStyle) + -> Font + { + unsafe { + let mut font: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFirstMatchingFont(weight.t(), stretch.t(), style.t(), font.getter_addrefs()); + assert!(hr == 0); + Font::take(font) + } + } + + pub fn get_font_collection(&self) -> FontCollection { + unsafe { + let mut collection: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFontCollection(collection.getter_addrefs()); + assert!(hr == 0); + FontCollection::take(collection) + } + } + + pub fn get_font_count(&self) -> u32 { + unsafe { + (*self.native.get()).GetFontCount() + } + } + + pub fn get_font(&self, index: u32) -> Font { + unsafe { + let mut font: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetFont(index, font.getter_addrefs()); + assert!(hr == 0); + assert!(!font.as_ptr().is_null()); + Font::take(font) + } + } +} diff --git a/third_party/rust/dwrote/src/font_file.rs b/third_party/rust/dwrote/src/font_file.rs index 8c70cedb3b21a..9f5607294744d 100644 --- a/third_party/rust/dwrote/src/font_file.rs +++ b/third_party/rust/dwrote/src/font_file.rs @@ -1,243 +1,243 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::slice; -use std::ptr; -use std::cell::UnsafeCell; -use std::path::PathBuf; -use std::ffi::OsString; -use std::fs::File; -use std::os::windows::ffi::{OsStrExt, OsStringExt}; -use std::os::windows::io::IntoRawHandle; -use std::path::Path; -use std::sync::Arc; - -use comptr::ComPtr; - -use winapi::Interface; -use winapi::ctypes::c_void; -use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile, IDWriteFontFileStream}; -use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteLocalFontFileLoader}; -use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS, DWRITE_FONT_FACE_TYPE_UNKNOWN}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE, DWRITE_FONT_FILE_TYPE_UNKNOWN}; -use winapi::um::winnt::HRESULT; - -use font_file_loader_impl::DataFontHelper; -use font_face::FontFace; -use super::DWriteFactory; - -pub struct FontFile { - native: UnsafeCell>, - stream: UnsafeCell>>, - data_key: usize, - face_type: DWRITE_FONT_FACE_TYPE, -} - -impl FontFile { - pub fn new_from_path

(path: P) -> Option where P: AsRef { - unsafe { - let mut path: Vec = path.as_ref().as_os_str().encode_wide().collect(); - path.push(0); - - let mut font_file: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).CreateFontFileReference(path.as_ptr(), - ptr::null(), - font_file.getter_addrefs()); - if hr != 0 || font_file.is_null() { - return None - } - - let mut ff = FontFile { - native: UnsafeCell::new(font_file), - stream: UnsafeCell::new(None), - data_key: 0, - face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, - }; - - if ff.analyze() == 0 { - None - } else { - Some(ff) - } - } - } - - pub fn new_from_data(data: Arc>) -> Option { - let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); - - let mut ff = FontFile { - native: UnsafeCell::new(font_file), - stream: UnsafeCell::new(Some(font_file_stream)), - data_key: key, - face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, - }; - - if ff.analyze() == 0 { - None - } else { - Some(ff) - } - } - - pub fn analyze_data(data: Arc>) -> u32 { - let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); - - let mut ff = FontFile { - native: UnsafeCell::new(font_file), - stream: UnsafeCell::new(Some(font_file_stream)), - data_key: key, - face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, - }; - - ff.analyze() - } - - fn analyze(&mut self) -> u32 { - let mut face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN; - let mut num_faces = 0; - unsafe { - let mut supported = 0; - let mut _file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN; - - let hr = (*self.native.get()).Analyze(&mut supported, - &mut _file_type, - &mut face_type, - &mut num_faces); - if hr != 0 || supported == 0 { - return 0 - } - } - self.face_type = face_type; - num_faces as u32 - } - - pub fn take(native: ComPtr) -> FontFile { - let mut ff = FontFile { - native: UnsafeCell::new(native), - stream: UnsafeCell::new(None), - data_key: 0, - face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, - }; - ff.analyze(); - ff - } - - pub fn data_key(&self) -> Option { - if self.data_key != 0 { - Some(self.data_key) - } else { - None - } - } - - pub(crate) unsafe fn as_com_ptr(&self) -> ComPtr { - (*self.native.get()).clone() - } - - // This is a helper to read the contents of this FontFile, - // without requiring callers to deal with loaders, keys, - // or streams. - pub fn get_font_file_bytes(&self) -> Vec { - unsafe { - let mut ref_key: *const c_void = ptr::null(); - let mut ref_key_size: u32 = 0; - let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); - - let mut loader: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetLoader(loader.getter_addrefs()); - assert!(hr == 0); - - let mut stream: ComPtr = ComPtr::new(); - let hr = loader.CreateStreamFromKey(ref_key, ref_key_size, stream.getter_addrefs()); - assert!(hr == 0); - - let mut file_size: u64 = 0; - let hr = stream.GetFileSize(&mut file_size); - assert!(hr == 0); - - let mut fragment_start: *const c_void = ptr::null(); - let mut fragment_context: *mut c_void = ptr::null_mut(); - let hr = stream.ReadFileFragment(&mut fragment_start, 0, file_size, &mut fragment_context); - assert!(hr == 0); - - let in_ptr = slice::from_raw_parts(fragment_start as *const u8, file_size as usize); - let bytes = in_ptr.to_vec(); - - stream.ReleaseFileFragment(fragment_context); - - bytes - } - } - - // This is a helper to get the path of a font file, - // without requiring callers to deal with loaders. - pub fn get_font_file_path(&self) -> Option { - unsafe { - let mut ref_key: *const c_void = ptr::null(); - let mut ref_key_size: u32 = 0; - let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); - - let mut loader: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).GetLoader(loader.getter_addrefs()); - assert!(hr == 0); - - let mut local_loader: ComPtr = - match loader.query_interface(&IDWriteLocalFontFileLoader::uuidof()) { - Some(local_loader) => local_loader, - None => return None, - }; - - let mut file_path_len = 0; - let hr = local_loader.GetFilePathLengthFromKey(ref_key, - ref_key_size, - &mut file_path_len); - assert_eq!(hr, 0); - - let mut file_path_buf = vec![0; file_path_len as usize + 1]; - let hr = local_loader.GetFilePathFromKey(ref_key, - ref_key_size, - file_path_buf.as_mut_ptr(), - file_path_len + 1); - assert_eq!(hr, 0); - - if let Some(&0) = file_path_buf.last() { - file_path_buf.pop(); - } - - Some(PathBuf::from(OsString::from_wide(&file_path_buf))) - } - } - - pub fn create_face(&self, - face_index: u32, - simulations: DWRITE_FONT_SIMULATIONS, - ) -> Result { - unsafe { - let mut face: ComPtr = ComPtr::new(); - let ptr = self.as_com_ptr(); - let hr = (*DWriteFactory()).CreateFontFace(self.face_type, 1, &ptr.as_ptr(), - face_index, simulations, face.getter_addrefs()); - if hr != 0 { - Err(hr) - } else { - Ok(FontFace::take(face)) - } - } - } -} - -impl Clone for FontFile { - fn clone(&self) -> FontFile { - unsafe { - FontFile { - native: UnsafeCell::new((*self.native.get()).clone()), - stream: UnsafeCell::new((*self.stream.get()).clone()), - data_key: self.data_key, - face_type: self.face_type, - } - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::slice; +use std::ptr; +use std::cell::UnsafeCell; +use std::path::PathBuf; +use std::ffi::OsString; +use std::fs::File; +use std::os::windows::ffi::{OsStrExt, OsStringExt}; +use std::os::windows::io::IntoRawHandle; +use std::path::Path; +use std::sync::Arc; + +use comptr::ComPtr; + +use winapi::Interface; +use winapi::ctypes::c_void; +use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile, IDWriteFontFileStream}; +use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteLocalFontFileLoader}; +use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS, DWRITE_FONT_FACE_TYPE_UNKNOWN}; +use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE, DWRITE_FONT_FILE_TYPE_UNKNOWN}; +use winapi::um::winnt::HRESULT; + +use font_file_loader_impl::DataFontHelper; +use font_face::FontFace; +use super::DWriteFactory; + +pub struct FontFile { + native: UnsafeCell>, + stream: UnsafeCell>>, + data_key: usize, + face_type: DWRITE_FONT_FACE_TYPE, +} + +impl FontFile { + pub fn new_from_path

(path: P) -> Option where P: AsRef { + unsafe { + let mut path: Vec = path.as_ref().as_os_str().encode_wide().collect(); + path.push(0); + + let mut font_file: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateFontFileReference(path.as_ptr(), + ptr::null(), + font_file.getter_addrefs()); + if hr != 0 || font_file.is_null() { + return None + } + + let mut ff = FontFile { + native: UnsafeCell::new(font_file), + stream: UnsafeCell::new(None), + data_key: 0, + face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, + }; + + if ff.analyze() == 0 { + None + } else { + Some(ff) + } + } + } + + pub fn new_from_data(data: Arc>) -> Option { + let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); + + let mut ff = FontFile { + native: UnsafeCell::new(font_file), + stream: UnsafeCell::new(Some(font_file_stream)), + data_key: key, + face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, + }; + + if ff.analyze() == 0 { + None + } else { + Some(ff) + } + } + + pub fn analyze_data(data: Arc>) -> u32 { + let (font_file, font_file_stream, key) = DataFontHelper::register_font_data(data); + + let mut ff = FontFile { + native: UnsafeCell::new(font_file), + stream: UnsafeCell::new(Some(font_file_stream)), + data_key: key, + face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, + }; + + ff.analyze() + } + + fn analyze(&mut self) -> u32 { + let mut face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN; + let mut num_faces = 0; + unsafe { + let mut supported = 0; + let mut _file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN; + + let hr = (*self.native.get()).Analyze(&mut supported, + &mut _file_type, + &mut face_type, + &mut num_faces); + if hr != 0 || supported == 0 { + return 0 + } + } + self.face_type = face_type; + num_faces as u32 + } + + pub fn take(native: ComPtr) -> FontFile { + let mut ff = FontFile { + native: UnsafeCell::new(native), + stream: UnsafeCell::new(None), + data_key: 0, + face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, + }; + ff.analyze(); + ff + } + + pub fn data_key(&self) -> Option { + if self.data_key != 0 { + Some(self.data_key) + } else { + None + } + } + + pub(crate) unsafe fn as_com_ptr(&self) -> ComPtr { + (*self.native.get()).clone() + } + + // This is a helper to read the contents of this FontFile, + // without requiring callers to deal with loaders, keys, + // or streams. + pub fn get_font_file_bytes(&self) -> Vec { + unsafe { + let mut ref_key: *const c_void = ptr::null(); + let mut ref_key_size: u32 = 0; + let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); + assert!(hr == 0); + + let mut loader: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetLoader(loader.getter_addrefs()); + assert!(hr == 0); + + let mut stream: ComPtr = ComPtr::new(); + let hr = loader.CreateStreamFromKey(ref_key, ref_key_size, stream.getter_addrefs()); + assert!(hr == 0); + + let mut file_size: u64 = 0; + let hr = stream.GetFileSize(&mut file_size); + assert!(hr == 0); + + let mut fragment_start: *const c_void = ptr::null(); + let mut fragment_context: *mut c_void = ptr::null_mut(); + let hr = stream.ReadFileFragment(&mut fragment_start, 0, file_size, &mut fragment_context); + assert!(hr == 0); + + let in_ptr = slice::from_raw_parts(fragment_start as *const u8, file_size as usize); + let bytes = in_ptr.to_vec(); + + stream.ReleaseFileFragment(fragment_context); + + bytes + } + } + + // This is a helper to get the path of a font file, + // without requiring callers to deal with loaders. + pub fn get_font_file_path(&self) -> Option { + unsafe { + let mut ref_key: *const c_void = ptr::null(); + let mut ref_key_size: u32 = 0; + let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); + assert!(hr == 0); + + let mut loader: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).GetLoader(loader.getter_addrefs()); + assert!(hr == 0); + + let mut local_loader: ComPtr = + match loader.query_interface(&IDWriteLocalFontFileLoader::uuidof()) { + Some(local_loader) => local_loader, + None => return None, + }; + + let mut file_path_len = 0; + let hr = local_loader.GetFilePathLengthFromKey(ref_key, + ref_key_size, + &mut file_path_len); + assert_eq!(hr, 0); + + let mut file_path_buf = vec![0; file_path_len as usize + 1]; + let hr = local_loader.GetFilePathFromKey(ref_key, + ref_key_size, + file_path_buf.as_mut_ptr(), + file_path_len + 1); + assert_eq!(hr, 0); + + if let Some(&0) = file_path_buf.last() { + file_path_buf.pop(); + } + + Some(PathBuf::from(OsString::from_wide(&file_path_buf))) + } + } + + pub fn create_face(&self, + face_index: u32, + simulations: DWRITE_FONT_SIMULATIONS, + ) -> Result { + unsafe { + let mut face: ComPtr = ComPtr::new(); + let ptr = self.as_com_ptr(); + let hr = (*DWriteFactory()).CreateFontFace(self.face_type, 1, &ptr.as_ptr(), + face_index, simulations, face.getter_addrefs()); + if hr != 0 { + Err(hr) + } else { + Ok(FontFace::take(face)) + } + } + } +} + +impl Clone for FontFile { + fn clone(&self) -> FontFile { + unsafe { + FontFile { + native: UnsafeCell::new((*self.native.get()).clone()), + stream: UnsafeCell::new((*self.stream.get()).clone()), + data_key: self.data_key, + face_type: self.face_type, + } + } + } +} diff --git a/third_party/rust/dwrote/src/font_file_loader_impl.rs b/third_party/rust/dwrote/src/font_file_loader_impl.rs index 496666bdb014a..7a48ab668fa68 100644 --- a/third_party/rust/dwrote/src/font_file_loader_impl.rs +++ b/third_party/rust/dwrote/src/font_file_loader_impl.rs @@ -1,223 +1,223 @@ -#![allow(non_snake_case, non_upper_case_globals)] - -use std::{mem, ptr}; -use std::collections::HashMap; -use std::sync::atomic::AtomicUsize; -use std::sync::{Arc, Mutex, atomic}; -use std::marker::Send; -use winapi::ctypes::c_void; -use winapi::shared::basetsd::{UINT32, UINT64}; -use winapi::shared::guiddef::REFIID; -use winapi::shared::minwindef::ULONG; -use winapi::shared::winerror::{E_FAIL, E_INVALIDARG, E_NOTIMPL, S_OK}; -use winapi::um::dwrite::IDWriteFontFile; -use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteFontFileLoaderVtbl}; -use winapi::um::dwrite::{IDWriteFontFileStream, IDWriteFontFileStreamVtbl}; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winnt::HRESULT; - -use super::DWriteFactory; -use comptr::ComPtr; -use com_helpers::*; - -struct FontFileLoader; - -DEFINE_GUID!{UuidOfIDWriteFontFileLoader, 0x727cad4e, 0xd6af, 0x4c9e, 0x8a, 0x08, 0xd6, 0x95, 0xb1, 0x1c, 0xaa, 0x49} -DEFINE_GUID!{UuidOfIDWriteFontFileStream, 0x6d4865fe, 0x0ab8, 0x4d91, 0x8f, 0x62, 0x5d, 0xd6, 0xbe, 0x34, 0xa3, 0xe0} - -const FontFileLoaderVtbl: &'static IDWriteFontFileLoaderVtbl = &IDWriteFontFileLoaderVtbl { - parent: implement_iunknown!(static IDWriteFontFileLoader, UuidOfIDWriteFontFileLoader, FontFileLoader), - CreateStreamFromKey: { - unsafe extern "system" fn CreateStreamFromKey( - _This: *mut IDWriteFontFileLoader, - fontFileReferenceKey: *const c_void, - fontFileReferenceKeySize: UINT32, - fontFileStream: *mut *mut IDWriteFontFileStream) -> HRESULT - { - if fontFileReferenceKey.is_null() || fontFileStream.is_null() { - return E_INVALIDARG - } - assert!(fontFileReferenceKeySize == mem::size_of::() as UINT32); - let key = *(fontFileReferenceKey as *const usize); - let stream = match FONT_FILE_STREAM_MAP.lock().unwrap().get(&key) { - None => { - *fontFileStream = ptr::null_mut(); - return E_FAIL - } - Some(&FontFileStreamPtr(file_stream)) => { - file_stream - } - }; - - // This is an addref getter, so make sure to do that! - (*stream).AddRef(); - - *fontFileStream = stream; - S_OK - } - CreateStreamFromKey - } -}; - -impl Com for FontFileLoader { - type Vtbl = IDWriteFontFileLoaderVtbl; - fn vtbl() -> &'static IDWriteFontFileLoaderVtbl { FontFileLoaderVtbl } -} - -impl Com for FontFileLoader { - type Vtbl = IUnknownVtbl; - fn vtbl() -> &'static IUnknownVtbl { &FontFileLoaderVtbl.parent } -} - -impl FontFileLoader { - pub fn new() -> FontFileLoader { - FontFileLoader - } -} - -unsafe impl Send for FontFileLoader {} -unsafe impl Sync for FontFileLoader {} - -struct FontFileStream { - refcount: atomic::AtomicUsize, - key: usize, - data: Arc>, -} - -const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileStreamVtbl { - parent: implement_iunknown!(IDWriteFontFileStream, UuidOfIDWriteFontFileStream, FontFileStream), - ReadFileFragment: { - unsafe extern "system" fn ReadFileFragment( - This: *mut IDWriteFontFileStream, - fragmentStart: *mut *const c_void, - fileOffset: UINT64, - fragmentSize: UINT64, - fragmentContext: *mut *mut c_void) -> HRESULT - { - let this = FontFileStream::from_interface(This); - *fragmentContext = ptr::null_mut(); - if (fileOffset + fragmentSize) as usize > this.data.len() { - return E_INVALIDARG - } - let index = fileOffset as usize; - *fragmentStart = this.data[index..].as_ptr() as *const c_void; - S_OK - } - ReadFileFragment - }, - ReleaseFileFragment: { - unsafe extern "system" fn ReleaseFileFragment( - _This: *mut IDWriteFontFileStream, - _fragmentContext: *mut c_void) - { - } - ReleaseFileFragment - }, - GetFileSize: { - unsafe extern "system" fn GetFileSize( - This: *mut IDWriteFontFileStream, - fileSize: *mut UINT64) -> HRESULT - { - let this = FontFileStream::from_interface(This); - *fileSize = this.data.len() as UINT64; - S_OK - } - GetFileSize - }, - GetLastWriteTime: { - unsafe extern "system" fn GetLastWriteTime( - _This: *mut IDWriteFontFileStream, - _lastWriteTime: *mut UINT64) -> HRESULT - { - E_NOTIMPL - } - GetLastWriteTime - }, -}; - -impl FontFileStream { - pub fn new(key: usize, data: Arc>) -> FontFileStream { - FontFileStream { - refcount: AtomicUsize::new(1), - key, - data, - } - } -} - -impl Drop for FontFileStream { - fn drop(&mut self) { - DataFontHelper::unregister_font_data(self.key); - } -} - -impl Com for FontFileStream { - type Vtbl = IDWriteFontFileStreamVtbl; - fn vtbl() -> &'static IDWriteFontFileStreamVtbl { FontFileStreamVtbl } -} - -impl Com for FontFileStream { - type Vtbl = IUnknownVtbl; - fn vtbl() -> &'static IUnknownVtbl { &FontFileStreamVtbl.parent } -} - -struct FontFileStreamPtr(*mut IDWriteFontFileStream); - -unsafe impl Send for FontFileStreamPtr {} - -static mut FONT_FILE_KEY: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; - -lazy_static! { - static ref FONT_FILE_STREAM_MAP: Mutex> = { - Mutex::new(HashMap::new()) - }; - - static ref FONT_FILE_LOADER: Mutex> = { - let ffl_native = FontFileLoader::new(); - let ffl = ComPtr::::from_ptr(ffl_native.into_interface()); - unsafe { - let hr = (*DWriteFactory()).RegisterFontFileLoader(ffl.as_ptr()); - assert!(hr == 0); - } - Mutex::new(ffl) - }; -} - -pub struct DataFontHelper; - -impl DataFontHelper { - pub fn register_font_data(font_data: Arc>) - -> (ComPtr, ComPtr, usize) { - unsafe { - let key = FONT_FILE_KEY.fetch_add(1, atomic::Ordering::Relaxed); - let font_file_stream_native = FontFileStream::new(key, font_data); - let font_file_stream: ComPtr = - ComPtr::already_addrefed(font_file_stream_native.into_interface()); - - { - let mut map = FONT_FILE_STREAM_MAP.lock().unwrap(); - map.insert(key, FontFileStreamPtr(font_file_stream.as_ptr())); - } - - let mut font_file: ComPtr = ComPtr::new(); - { - let loader = FONT_FILE_LOADER.lock().unwrap(); - let hr = (*DWriteFactory()).CreateCustomFontFileReference( - mem::transmute(&key), - mem::size_of::() as UINT32, - loader.as_ptr(), - font_file.getter_addrefs()); - assert!(hr == S_OK); - } - - (font_file, font_file_stream, key) - } - } - - fn unregister_font_data(key: usize) { - let mut map = FONT_FILE_STREAM_MAP.lock().unwrap(); - if map.remove(&key).is_none() { - panic!("unregister_font_data: trying to unregister key that is no longer registered"); - } - } -} +#![allow(non_snake_case, non_upper_case_globals)] + +use std::{mem, ptr}; +use std::collections::HashMap; +use std::sync::atomic::AtomicUsize; +use std::sync::{Arc, Mutex, atomic}; +use std::marker::Send; +use winapi::ctypes::c_void; +use winapi::shared::basetsd::{UINT32, UINT64}; +use winapi::shared::guiddef::REFIID; +use winapi::shared::minwindef::ULONG; +use winapi::shared::winerror::{E_FAIL, E_INVALIDARG, E_NOTIMPL, S_OK}; +use winapi::um::dwrite::IDWriteFontFile; +use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteFontFileLoaderVtbl}; +use winapi::um::dwrite::{IDWriteFontFileStream, IDWriteFontFileStreamVtbl}; +use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; +use winapi::um::winnt::HRESULT; + +use super::DWriteFactory; +use comptr::ComPtr; +use com_helpers::*; + +struct FontFileLoader; + +DEFINE_GUID!{UuidOfIDWriteFontFileLoader, 0x727cad4e, 0xd6af, 0x4c9e, 0x8a, 0x08, 0xd6, 0x95, 0xb1, 0x1c, 0xaa, 0x49} +DEFINE_GUID!{UuidOfIDWriteFontFileStream, 0x6d4865fe, 0x0ab8, 0x4d91, 0x8f, 0x62, 0x5d, 0xd6, 0xbe, 0x34, 0xa3, 0xe0} + +const FontFileLoaderVtbl: &'static IDWriteFontFileLoaderVtbl = &IDWriteFontFileLoaderVtbl { + parent: implement_iunknown!(static IDWriteFontFileLoader, UuidOfIDWriteFontFileLoader, FontFileLoader), + CreateStreamFromKey: { + unsafe extern "system" fn CreateStreamFromKey( + _This: *mut IDWriteFontFileLoader, + fontFileReferenceKey: *const c_void, + fontFileReferenceKeySize: UINT32, + fontFileStream: *mut *mut IDWriteFontFileStream) -> HRESULT + { + if fontFileReferenceKey.is_null() || fontFileStream.is_null() { + return E_INVALIDARG + } + assert!(fontFileReferenceKeySize == mem::size_of::() as UINT32); + let key = *(fontFileReferenceKey as *const usize); + let stream = match FONT_FILE_STREAM_MAP.lock().unwrap().get(&key) { + None => { + *fontFileStream = ptr::null_mut(); + return E_FAIL + } + Some(&FontFileStreamPtr(file_stream)) => { + file_stream + } + }; + + // This is an addref getter, so make sure to do that! + (*stream).AddRef(); + + *fontFileStream = stream; + S_OK + } + CreateStreamFromKey + } +}; + +impl Com for FontFileLoader { + type Vtbl = IDWriteFontFileLoaderVtbl; + fn vtbl() -> &'static IDWriteFontFileLoaderVtbl { FontFileLoaderVtbl } +} + +impl Com for FontFileLoader { + type Vtbl = IUnknownVtbl; + fn vtbl() -> &'static IUnknownVtbl { &FontFileLoaderVtbl.parent } +} + +impl FontFileLoader { + pub fn new() -> FontFileLoader { + FontFileLoader + } +} + +unsafe impl Send for FontFileLoader {} +unsafe impl Sync for FontFileLoader {} + +struct FontFileStream { + refcount: atomic::AtomicUsize, + key: usize, + data: Arc>, +} + +const FontFileStreamVtbl: &'static IDWriteFontFileStreamVtbl = &IDWriteFontFileStreamVtbl { + parent: implement_iunknown!(IDWriteFontFileStream, UuidOfIDWriteFontFileStream, FontFileStream), + ReadFileFragment: { + unsafe extern "system" fn ReadFileFragment( + This: *mut IDWriteFontFileStream, + fragmentStart: *mut *const c_void, + fileOffset: UINT64, + fragmentSize: UINT64, + fragmentContext: *mut *mut c_void) -> HRESULT + { + let this = FontFileStream::from_interface(This); + *fragmentContext = ptr::null_mut(); + if (fileOffset + fragmentSize) as usize > this.data.len() { + return E_INVALIDARG + } + let index = fileOffset as usize; + *fragmentStart = this.data[index..].as_ptr() as *const c_void; + S_OK + } + ReadFileFragment + }, + ReleaseFileFragment: { + unsafe extern "system" fn ReleaseFileFragment( + _This: *mut IDWriteFontFileStream, + _fragmentContext: *mut c_void) + { + } + ReleaseFileFragment + }, + GetFileSize: { + unsafe extern "system" fn GetFileSize( + This: *mut IDWriteFontFileStream, + fileSize: *mut UINT64) -> HRESULT + { + let this = FontFileStream::from_interface(This); + *fileSize = this.data.len() as UINT64; + S_OK + } + GetFileSize + }, + GetLastWriteTime: { + unsafe extern "system" fn GetLastWriteTime( + _This: *mut IDWriteFontFileStream, + _lastWriteTime: *mut UINT64) -> HRESULT + { + E_NOTIMPL + } + GetLastWriteTime + }, +}; + +impl FontFileStream { + pub fn new(key: usize, data: Arc>) -> FontFileStream { + FontFileStream { + refcount: AtomicUsize::new(1), + key, + data, + } + } +} + +impl Drop for FontFileStream { + fn drop(&mut self) { + DataFontHelper::unregister_font_data(self.key); + } +} + +impl Com for FontFileStream { + type Vtbl = IDWriteFontFileStreamVtbl; + fn vtbl() -> &'static IDWriteFontFileStreamVtbl { FontFileStreamVtbl } +} + +impl Com for FontFileStream { + type Vtbl = IUnknownVtbl; + fn vtbl() -> &'static IUnknownVtbl { &FontFileStreamVtbl.parent } +} + +struct FontFileStreamPtr(*mut IDWriteFontFileStream); + +unsafe impl Send for FontFileStreamPtr {} + +static mut FONT_FILE_KEY: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; + +lazy_static! { + static ref FONT_FILE_STREAM_MAP: Mutex> = { + Mutex::new(HashMap::new()) + }; + + static ref FONT_FILE_LOADER: Mutex> = { + let ffl_native = FontFileLoader::new(); + let ffl = ComPtr::::from_ptr(ffl_native.into_interface()); + unsafe { + let hr = (*DWriteFactory()).RegisterFontFileLoader(ffl.as_ptr()); + assert!(hr == 0); + } + Mutex::new(ffl) + }; +} + +pub struct DataFontHelper; + +impl DataFontHelper { + pub fn register_font_data(font_data: Arc>) + -> (ComPtr, ComPtr, usize) { + unsafe { + let key = FONT_FILE_KEY.fetch_add(1, atomic::Ordering::Relaxed); + let font_file_stream_native = FontFileStream::new(key, font_data); + let font_file_stream: ComPtr = + ComPtr::already_addrefed(font_file_stream_native.into_interface()); + + { + let mut map = FONT_FILE_STREAM_MAP.lock().unwrap(); + map.insert(key, FontFileStreamPtr(font_file_stream.as_ptr())); + } + + let mut font_file: ComPtr = ComPtr::new(); + { + let loader = FONT_FILE_LOADER.lock().unwrap(); + let hr = (*DWriteFactory()).CreateCustomFontFileReference( + mem::transmute(&key), + mem::size_of::() as UINT32, + loader.as_ptr(), + font_file.getter_addrefs()); + assert!(hr == S_OK); + } + + (font_file, font_file_stream, key) + } + } + + fn unregister_font_data(key: usize) { + let mut map = FONT_FILE_STREAM_MAP.lock().unwrap(); + if map.remove(&key).is_none() { + panic!("unregister_font_data: trying to unregister key that is no longer registered"); + } + } +} diff --git a/third_party/rust/dwrote/src/gdi_interop.rs b/third_party/rust/dwrote/src/gdi_interop.rs index fe8830cb94641..0a51b1574cc12 100644 --- a/third_party/rust/dwrote/src/gdi_interop.rs +++ b/third_party/rust/dwrote/src/gdi_interop.rs @@ -1,43 +1,43 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::ptr; -use std::cell::UnsafeCell; - -use comptr::ComPtr; -use winapi::um::dwrite::IDWriteBitmapRenderTarget; -use winapi::um::dwrite::IDWriteGdiInterop; -use super::{DWriteFactory, BitmapRenderTarget}; - -pub struct GdiInterop { - native: UnsafeCell>, -} - -impl GdiInterop { - pub fn create() -> GdiInterop { - unsafe { - let mut native: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).GetGdiInterop(native.getter_addrefs()); - assert!(hr == 0); - GdiInterop::take(native) - } - } - - pub fn take(native: ComPtr) -> GdiInterop { - GdiInterop { - native: UnsafeCell::new(native), - } - } - - pub fn create_bitmap_render_target(&self, width: u32, height: u32) -> BitmapRenderTarget { - unsafe { - let mut native: ComPtr = ComPtr::new(); - let hr = (*self.native.get()).CreateBitmapRenderTarget(ptr::null_mut(), - width, height, - native.getter_addrefs()); - assert!(hr == 0); - BitmapRenderTarget::take(native) - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::ptr; +use std::cell::UnsafeCell; + +use comptr::ComPtr; +use winapi::um::dwrite::IDWriteBitmapRenderTarget; +use winapi::um::dwrite::IDWriteGdiInterop; +use super::{DWriteFactory, BitmapRenderTarget}; + +pub struct GdiInterop { + native: UnsafeCell>, +} + +impl GdiInterop { + pub fn create() -> GdiInterop { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).GetGdiInterop(native.getter_addrefs()); + assert!(hr == 0); + GdiInterop::take(native) + } + } + + pub fn take(native: ComPtr) -> GdiInterop { + GdiInterop { + native: UnsafeCell::new(native), + } + } + + pub fn create_bitmap_render_target(&self, width: u32, height: u32) -> BitmapRenderTarget { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*self.native.get()).CreateBitmapRenderTarget(ptr::null_mut(), + width, height, + native.getter_addrefs()); + assert!(hr == 0); + BitmapRenderTarget::take(native) + } + } +} diff --git a/third_party/rust/dwrote/src/geometry_sink_impl.rs b/third_party/rust/dwrote/src/geometry_sink_impl.rs index 6ae917b287475..588d8d4cb248d 100644 --- a/third_party/rust/dwrote/src/geometry_sink_impl.rs +++ b/third_party/rust/dwrote/src/geometry_sink_impl.rs @@ -1,113 +1,113 @@ -#![allow(non_snake_case, non_upper_case_globals)] - -use std::mem; -use std::os::raw::c_void; -use std::slice; -use std::sync::atomic::AtomicUsize; -use winapi::shared::guiddef::REFIID; -use winapi::shared::minwindef::{UINT, ULONG}; -use winapi::shared::winerror::S_OK; -use winapi::um::d2d1::{D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END, D2D1_FIGURE_END_CLOSED}; -use winapi::um::d2d1::{D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D1_POINT_2F}; -use winapi::um::d2d1::{ID2D1SimplifiedGeometrySink, ID2D1SimplifiedGeometrySinkVtbl}; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winnt::HRESULT; - -use com_helpers::{Com, UuidOfIUnknown}; -use comptr::ComPtr; -use outline_builder::OutlineBuilder; - -DEFINE_GUID!{ - D2D1_SIMPLIFIED_GEOMETRY_SINK_UUID, - 0x2cd9069e, 0x12e2, 0x11dc, 0x9f, 0xed, 0x00, 0x11, 0x43, 0xa0, 0x55, 0xf9 -} - -static GEOMETRY_SINK_VTBL: ID2D1SimplifiedGeometrySinkVtbl = ID2D1SimplifiedGeometrySinkVtbl { - parent: implement_iunknown!(static ID2D1SimplifiedGeometrySink, - D2D1_SIMPLIFIED_GEOMETRY_SINK_UUID, - GeometrySinkImpl), - BeginFigure: GeometrySinkImpl_BeginFigure, - EndFigure: GeometrySinkImpl_EndFigure, - AddLines: GeometrySinkImpl_AddLines, - AddBeziers: GeometrySinkImpl_AddBeziers, - Close: GeometrySinkImpl_Close, - SetFillMode: GeometrySinkImpl_SetFillMode, - SetSegmentFlags: GeometrySinkImpl_SetSegmentFlags, -}; - -pub struct GeometrySinkImpl { - refcount: AtomicUsize, - outline_builder: Box, -} - -impl Com for GeometrySinkImpl { - type Vtbl = ID2D1SimplifiedGeometrySinkVtbl; - #[inline] - fn vtbl() -> &'static ID2D1SimplifiedGeometrySinkVtbl { - &GEOMETRY_SINK_VTBL - } -} - -impl Com for GeometrySinkImpl { - type Vtbl = IUnknownVtbl; - #[inline] - fn vtbl() -> &'static IUnknownVtbl { - &GEOMETRY_SINK_VTBL.parent - } -} - -impl GeometrySinkImpl { - pub fn new(outline_builder: Box) -> GeometrySinkImpl { - GeometrySinkImpl { - refcount: AtomicUsize::new(1), - outline_builder, - } - } -} - -unsafe extern "system" fn GeometrySinkImpl_BeginFigure(this: *mut ID2D1SimplifiedGeometrySink, - start_point: D2D1_POINT_2F, - _: D2D1_FIGURE_BEGIN) { - let this = GeometrySinkImpl::from_interface(this); - (*this).outline_builder.move_to(start_point.x, start_point.y) -} - -unsafe extern "system" fn GeometrySinkImpl_EndFigure(this: *mut ID2D1SimplifiedGeometrySink, - figure_end: D2D1_FIGURE_END) { - let this = GeometrySinkImpl::from_interface(this); - if figure_end == D2D1_FIGURE_END_CLOSED { - (*this).outline_builder.close() - } -} - -unsafe extern "system" fn GeometrySinkImpl_AddLines(this: *mut ID2D1SimplifiedGeometrySink, - points: *const D2D1_POINT_2F, - points_count: UINT) { - let this = GeometrySinkImpl::from_interface(this); - let points = slice::from_raw_parts(points, points_count as usize); - for point in points { - (*this).outline_builder.line_to(point.x, point.y) - } -} - -unsafe extern "system" fn GeometrySinkImpl_AddBeziers(this: *mut ID2D1SimplifiedGeometrySink, - beziers: *const D2D1_BEZIER_SEGMENT, - beziers_count: UINT) { - let this = GeometrySinkImpl::from_interface(this); - let beziers = slice::from_raw_parts(beziers, beziers_count as usize); - for bezier in beziers { - (*this).outline_builder.curve_to(bezier.point1.x, bezier.point1.y, - bezier.point2.x, bezier.point2.y, - bezier.point3.x, bezier.point3.y) - } -} - -unsafe extern "system" fn GeometrySinkImpl_Close(_: *mut ID2D1SimplifiedGeometrySink) -> HRESULT { - S_OK -} - -unsafe extern "system" fn GeometrySinkImpl_SetFillMode(_: *mut ID2D1SimplifiedGeometrySink, - _: D2D1_FILL_MODE) {} - -unsafe extern "system" fn GeometrySinkImpl_SetSegmentFlags(_: *mut ID2D1SimplifiedGeometrySink, - _: D2D1_PATH_SEGMENT) {} +#![allow(non_snake_case, non_upper_case_globals)] + +use std::mem; +use std::os::raw::c_void; +use std::slice; +use std::sync::atomic::AtomicUsize; +use winapi::shared::guiddef::REFIID; +use winapi::shared::minwindef::{UINT, ULONG}; +use winapi::shared::winerror::S_OK; +use winapi::um::d2d1::{D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END, D2D1_FIGURE_END_CLOSED}; +use winapi::um::d2d1::{D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D1_POINT_2F}; +use winapi::um::d2d1::{ID2D1SimplifiedGeometrySink, ID2D1SimplifiedGeometrySinkVtbl}; +use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; +use winapi::um::winnt::HRESULT; + +use com_helpers::{Com, UuidOfIUnknown}; +use comptr::ComPtr; +use outline_builder::OutlineBuilder; + +DEFINE_GUID!{ + D2D1_SIMPLIFIED_GEOMETRY_SINK_UUID, + 0x2cd9069e, 0x12e2, 0x11dc, 0x9f, 0xed, 0x00, 0x11, 0x43, 0xa0, 0x55, 0xf9 +} + +static GEOMETRY_SINK_VTBL: ID2D1SimplifiedGeometrySinkVtbl = ID2D1SimplifiedGeometrySinkVtbl { + parent: implement_iunknown!(static ID2D1SimplifiedGeometrySink, + D2D1_SIMPLIFIED_GEOMETRY_SINK_UUID, + GeometrySinkImpl), + BeginFigure: GeometrySinkImpl_BeginFigure, + EndFigure: GeometrySinkImpl_EndFigure, + AddLines: GeometrySinkImpl_AddLines, + AddBeziers: GeometrySinkImpl_AddBeziers, + Close: GeometrySinkImpl_Close, + SetFillMode: GeometrySinkImpl_SetFillMode, + SetSegmentFlags: GeometrySinkImpl_SetSegmentFlags, +}; + +pub struct GeometrySinkImpl { + refcount: AtomicUsize, + outline_builder: Box, +} + +impl Com for GeometrySinkImpl { + type Vtbl = ID2D1SimplifiedGeometrySinkVtbl; + #[inline] + fn vtbl() -> &'static ID2D1SimplifiedGeometrySinkVtbl { + &GEOMETRY_SINK_VTBL + } +} + +impl Com for GeometrySinkImpl { + type Vtbl = IUnknownVtbl; + #[inline] + fn vtbl() -> &'static IUnknownVtbl { + &GEOMETRY_SINK_VTBL.parent + } +} + +impl GeometrySinkImpl { + pub fn new(outline_builder: Box) -> GeometrySinkImpl { + GeometrySinkImpl { + refcount: AtomicUsize::new(1), + outline_builder, + } + } +} + +unsafe extern "system" fn GeometrySinkImpl_BeginFigure(this: *mut ID2D1SimplifiedGeometrySink, + start_point: D2D1_POINT_2F, + _: D2D1_FIGURE_BEGIN) { + let this = GeometrySinkImpl::from_interface(this); + (*this).outline_builder.move_to(start_point.x, start_point.y) +} + +unsafe extern "system" fn GeometrySinkImpl_EndFigure(this: *mut ID2D1SimplifiedGeometrySink, + figure_end: D2D1_FIGURE_END) { + let this = GeometrySinkImpl::from_interface(this); + if figure_end == D2D1_FIGURE_END_CLOSED { + (*this).outline_builder.close() + } +} + +unsafe extern "system" fn GeometrySinkImpl_AddLines(this: *mut ID2D1SimplifiedGeometrySink, + points: *const D2D1_POINT_2F, + points_count: UINT) { + let this = GeometrySinkImpl::from_interface(this); + let points = slice::from_raw_parts(points, points_count as usize); + for point in points { + (*this).outline_builder.line_to(point.x, point.y) + } +} + +unsafe extern "system" fn GeometrySinkImpl_AddBeziers(this: *mut ID2D1SimplifiedGeometrySink, + beziers: *const D2D1_BEZIER_SEGMENT, + beziers_count: UINT) { + let this = GeometrySinkImpl::from_interface(this); + let beziers = slice::from_raw_parts(beziers, beziers_count as usize); + for bezier in beziers { + (*this).outline_builder.curve_to(bezier.point1.x, bezier.point1.y, + bezier.point2.x, bezier.point2.y, + bezier.point3.x, bezier.point3.y) + } +} + +unsafe extern "system" fn GeometrySinkImpl_Close(_: *mut ID2D1SimplifiedGeometrySink) -> HRESULT { + S_OK +} + +unsafe extern "system" fn GeometrySinkImpl_SetFillMode(_: *mut ID2D1SimplifiedGeometrySink, + _: D2D1_FILL_MODE) {} + +unsafe extern "system" fn GeometrySinkImpl_SetSegmentFlags(_: *mut ID2D1SimplifiedGeometrySink, + _: D2D1_PATH_SEGMENT) {} diff --git a/third_party/rust/dwrote/src/glyph_run_analysis.rs b/third_party/rust/dwrote/src/glyph_run_analysis.rs index a673f0101a414..2f9adaa9eb999 100644 --- a/third_party/rust/dwrote/src/glyph_run_analysis.rs +++ b/third_party/rust/dwrote/src/glyph_run_analysis.rs @@ -1,86 +1,86 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::ptr; -use std::cell::UnsafeCell; - -use comptr::ComPtr; -use winapi::um::dcommon::DWRITE_MEASURING_MODE; -use winapi::um::dwrite::{DWRITE_RENDERING_MODE, DWRITE_MATRIX}; -use winapi::um::dwrite::{DWRITE_GLYPH_RUN, DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_TYPE}; -use winapi::um::dwrite::DWRITE_TEXTURE_CLEARTYPE_3x1; -use winapi::shared::windef::RECT; -use winapi::um::dwrite::IDWriteGlyphRunAnalysis; -use winapi::um::winnt::HRESULT; -use std::mem; -use super::DWriteFactory; - -pub struct GlyphRunAnalysis { - native: UnsafeCell>, -} - -impl GlyphRunAnalysis { - pub fn create(glyph_run: &DWRITE_GLYPH_RUN, - pixels_per_dip: f32, - transform: Option, - rendering_mode: DWRITE_RENDERING_MODE, - measuring_mode: DWRITE_MEASURING_MODE, - baseline_x: f32, - baseline_y: f32) -> Result - { - unsafe { - let mut native: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).CreateGlyphRunAnalysis(glyph_run as *const DWRITE_GLYPH_RUN, - pixels_per_dip, - transform.as_ref().map(|x| x as *const _).unwrap_or(ptr::null()), - rendering_mode, measuring_mode, - baseline_x, baseline_y, - native.getter_addrefs()); - if hr != 0 { - Err(hr) - } else { - Ok(GlyphRunAnalysis::take(native)) - } - } - } - - pub fn take(native: ComPtr) -> GlyphRunAnalysis { - GlyphRunAnalysis { - native: UnsafeCell::new(native), - } - } - - pub fn get_alpha_texture_bounds(&self, texture_type: DWRITE_TEXTURE_TYPE) -> Result { - unsafe { - let mut rect: RECT = mem::zeroed(); - rect.left = 1234; - rect.top = 1234; - let hr = (*self.native.get()).GetAlphaTextureBounds(texture_type, &mut rect); - if hr != 0 { - Err(hr) - } else { - Ok(rect) - } - } - } - - pub fn create_alpha_texture(&self, texture_type: DWRITE_TEXTURE_TYPE, rect: RECT) -> Result, HRESULT> { - unsafe { - let rect_pixels = (rect.right - rect.left) * (rect.bottom - rect.top); - let rect_bytes = rect_pixels * match texture_type { - DWRITE_TEXTURE_ALIASED_1x1 => 1, - DWRITE_TEXTURE_CLEARTYPE_3x1 => 3, - _ => panic!("bad texture type specified"), - }; - - let mut out_bytes: Vec = vec![0; rect_bytes as usize]; - let hr = (*self.native.get()).CreateAlphaTexture(texture_type, &rect, out_bytes.as_mut_ptr(), out_bytes.len() as u32); - if hr != 0 { - Err(hr) - } else { - Ok(out_bytes) - } - } - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::ptr; +use std::cell::UnsafeCell; + +use comptr::ComPtr; +use winapi::um::dcommon::DWRITE_MEASURING_MODE; +use winapi::um::dwrite::{DWRITE_RENDERING_MODE, DWRITE_MATRIX}; +use winapi::um::dwrite::{DWRITE_GLYPH_RUN, DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_TYPE}; +use winapi::um::dwrite::DWRITE_TEXTURE_CLEARTYPE_3x1; +use winapi::shared::windef::RECT; +use winapi::um::dwrite::IDWriteGlyphRunAnalysis; +use winapi::um::winnt::HRESULT; +use std::mem; +use super::DWriteFactory; + +pub struct GlyphRunAnalysis { + native: UnsafeCell>, +} + +impl GlyphRunAnalysis { + pub fn create(glyph_run: &DWRITE_GLYPH_RUN, + pixels_per_dip: f32, + transform: Option, + rendering_mode: DWRITE_RENDERING_MODE, + measuring_mode: DWRITE_MEASURING_MODE, + baseline_x: f32, + baseline_y: f32) -> Result + { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateGlyphRunAnalysis(glyph_run as *const DWRITE_GLYPH_RUN, + pixels_per_dip, + transform.as_ref().map(|x| x as *const _).unwrap_or(ptr::null()), + rendering_mode, measuring_mode, + baseline_x, baseline_y, + native.getter_addrefs()); + if hr != 0 { + Err(hr) + } else { + Ok(GlyphRunAnalysis::take(native)) + } + } + } + + pub fn take(native: ComPtr) -> GlyphRunAnalysis { + GlyphRunAnalysis { + native: UnsafeCell::new(native), + } + } + + pub fn get_alpha_texture_bounds(&self, texture_type: DWRITE_TEXTURE_TYPE) -> Result { + unsafe { + let mut rect: RECT = mem::zeroed(); + rect.left = 1234; + rect.top = 1234; + let hr = (*self.native.get()).GetAlphaTextureBounds(texture_type, &mut rect); + if hr != 0 { + Err(hr) + } else { + Ok(rect) + } + } + } + + pub fn create_alpha_texture(&self, texture_type: DWRITE_TEXTURE_TYPE, rect: RECT) -> Result, HRESULT> { + unsafe { + let rect_pixels = (rect.right - rect.left) * (rect.bottom - rect.top); + let rect_bytes = rect_pixels * match texture_type { + DWRITE_TEXTURE_ALIASED_1x1 => 1, + DWRITE_TEXTURE_CLEARTYPE_3x1 => 3, + _ => panic!("bad texture type specified"), + }; + + let mut out_bytes: Vec = vec![0; rect_bytes as usize]; + let hr = (*self.native.get()).CreateAlphaTexture(texture_type, &rect, out_bytes.as_mut_ptr(), out_bytes.len() as u32); + if hr != 0 { + Err(hr) + } else { + Ok(out_bytes) + } + } + } +} diff --git a/third_party/rust/dwrote/src/helpers.rs b/third_party/rust/dwrote/src/helpers.rs index 1d6f71d302ac3..33a94c56115d4 100644 --- a/third_party/rust/dwrote/src/helpers.rs +++ b/third_party/rust/dwrote/src/helpers.rs @@ -1,68 +1,68 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use winapi::um::dwrite::IDWriteLocalizedStrings; -use winapi::ctypes::wchar_t; -use comptr::ComPtr; -use winapi::shared::winerror::S_OK; -use winapi::shared::minwindef::{BOOL, FALSE}; -use winapi::um::winnls::GetUserDefaultLocaleName; -use std::ffi::{OsStr}; -use std::os::windows::ffi::{OsStrExt}; - - -lazy_static! { - static ref SYSTEM_LOCALE: Vec = { - unsafe { - let mut locale: Vec = vec![0; 85]; - GetUserDefaultLocaleName(locale.as_mut_ptr(), locale.len() as i32 - 1); - locale - } - }; - static ref EN_US_LOCALE: Vec = { - OsStr::new("en-us").encode_wide().collect() - }; -} - -pub fn get_locale_string(strings: &mut ComPtr) -> String { - unsafe { - let mut index: u32 = 0; - let mut exists: BOOL = FALSE; - let hr = strings.FindLocaleName((*SYSTEM_LOCALE).as_ptr(), &mut index, &mut exists); - if hr != S_OK || exists == FALSE { - let hr = strings.FindLocaleName((*EN_US_LOCALE).as_ptr(), &mut index, &mut exists); - if hr != S_OK || exists == FALSE { - // Ultimately fall back to first locale on list - index = 0; - } - } - - let mut length: u32 = 0; - let hr = strings.GetStringLength(index, &mut length); - assert!(hr == 0); - - let mut name: Vec = Vec::with_capacity(length as usize + 1); - let hr = strings.GetString(index, name.as_mut_ptr(), length + 1); - assert!(hr == 0); - name.set_len(length as usize); - - String::from_utf16(&name).ok().unwrap() - } -} - -// ToWide from https://github.com/retep998/wio-rs/blob/master/src/wide.rs - -pub trait ToWide { - fn to_wide(&self) -> Vec; - fn to_wide_null(&self) -> Vec; -} - -impl ToWide for T where T: AsRef { - fn to_wide(&self) -> Vec { - self.as_ref().encode_wide().collect() - } - fn to_wide_null(&self) -> Vec { - self.as_ref().encode_wide().chain(Some(0)).collect() - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use winapi::um::dwrite::IDWriteLocalizedStrings; +use winapi::ctypes::wchar_t; +use comptr::ComPtr; +use winapi::shared::winerror::S_OK; +use winapi::shared::minwindef::{BOOL, FALSE}; +use winapi::um::winnls::GetUserDefaultLocaleName; +use std::ffi::{OsStr}; +use std::os::windows::ffi::{OsStrExt}; + + +lazy_static! { + static ref SYSTEM_LOCALE: Vec = { + unsafe { + let mut locale: Vec = vec![0; 85]; + GetUserDefaultLocaleName(locale.as_mut_ptr(), locale.len() as i32 - 1); + locale + } + }; + static ref EN_US_LOCALE: Vec = { + OsStr::new("en-us").encode_wide().collect() + }; +} + +pub fn get_locale_string(strings: &mut ComPtr) -> String { + unsafe { + let mut index: u32 = 0; + let mut exists: BOOL = FALSE; + let hr = strings.FindLocaleName((*SYSTEM_LOCALE).as_ptr(), &mut index, &mut exists); + if hr != S_OK || exists == FALSE { + let hr = strings.FindLocaleName((*EN_US_LOCALE).as_ptr(), &mut index, &mut exists); + if hr != S_OK || exists == FALSE { + // Ultimately fall back to first locale on list + index = 0; + } + } + + let mut length: u32 = 0; + let hr = strings.GetStringLength(index, &mut length); + assert!(hr == 0); + + let mut name: Vec = Vec::with_capacity(length as usize + 1); + let hr = strings.GetString(index, name.as_mut_ptr(), length + 1); + assert!(hr == 0); + name.set_len(length as usize); + + String::from_utf16(&name).ok().unwrap() + } +} + +// ToWide from https://github.com/retep998/wio-rs/blob/master/src/wide.rs + +pub trait ToWide { + fn to_wide(&self) -> Vec; + fn to_wide_null(&self) -> Vec; +} + +impl ToWide for T where T: AsRef { + fn to_wide(&self) -> Vec { + self.as_ref().encode_wide().collect() + } + fn to_wide_null(&self) -> Vec { + self.as_ref().encode_wide().chain(Some(0)).collect() + } +} diff --git a/third_party/rust/dwrote/src/lib.rs b/third_party/rust/dwrote/src/lib.rs index 0de78729bc0e6..ca32146d8e48c 100644 --- a/third_party/rust/dwrote/src/lib.rs +++ b/third_party/rust/dwrote/src/lib.rs @@ -1,151 +1,159 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#![allow(non_upper_case_globals)] - -#[cfg_attr(feature = "serde_serialization", macro_use)] -#[cfg(feature = "serde_serialization")] -extern crate serde_derive; -#[cfg(feature = "serde_serialization")] -extern crate serde; - -#[macro_use] -extern crate lazy_static; -#[macro_use(DEFINE_GUID)] -extern crate winapi; -extern crate libc; - -include!("types.rs"); - -use winapi::Interface; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE_SHARED; -use winapi::um::dwrite::IDWriteFactory; -use winapi::um::dwrite::IDWriteRenderingParams; -pub use winapi::um::winnt::HRESULT; -use winapi::um::winnt::LPCSTR; -use winapi::shared::guiddef::REFIID; -use winapi::um::unknwnbase::IUnknown; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE; -use std::ffi::CString; - -use comptr::ComPtr; -use winapi::shared::winerror::S_OK; - -mod comptr; -mod helpers; -use helpers::ToWide; -use std::os::raw::c_void; - -#[cfg(test)] -mod test; - -// We still use the DWrite structs for things like metrics; re-export them -// here -pub use winapi::um::dwrite::DWRITE_FONT_METRICS as FontMetrics; -pub use winapi::um::dwrite::DWRITE_GLYPH_OFFSET as GlyphOffset; -pub use winapi::um::dwrite::{DWRITE_MATRIX, DWRITE_GLYPH_RUN}; -pub use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, - DWRITE_RENDERING_MODE_ALIASED, - DWRITE_RENDERING_MODE_GDI_CLASSIC, - DWRITE_RENDERING_MODE_GDI_NATURAL, - DWRITE_RENDERING_MODE_NATURAL, - DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, - DWRITE_RENDERING_MODE_OUTLINE, - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, - DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, - DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC}; -pub use winapi::um::dcommon::{DWRITE_MEASURING_MODE_NATURAL, - DWRITE_MEASURING_MODE_GDI_CLASSIC, - DWRITE_MEASURING_MODE_GDI_NATURAL}; -pub use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS_NONE, - DWRITE_FONT_SIMULATIONS_BOLD, - DWRITE_FONT_SIMULATIONS_OBLIQUE}; -pub use winapi::um::dwrite::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1}; -pub use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS}; -pub use winapi::um::dwrite::{DWRITE_RENDERING_MODE}; -pub use winapi::um::dwrite::{DWRITE_TEXTURE_TYPE}; -pub use winapi::um::dwrite_3::{DWRITE_FONT_AXIS_VALUE}; -pub use winapi::um::dcommon::{DWRITE_MEASURING_MODE}; -pub use winapi::shared::windef::RECT; -use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryW}; - -#[macro_use] mod com_helpers; - -mod bitmap_render_target; pub use bitmap_render_target::BitmapRenderTarget; -mod font; pub use font::{Font, InformationalStringId}; -mod font_collection; pub use font_collection::FontCollection; -mod font_face; pub use font_face::{FontFace, FontFaceType}; -mod font_family; pub use font_family::FontFamily; -mod font_file; pub use font_file::FontFile; -mod gdi_interop; pub use gdi_interop::GdiInterop; -mod outline_builder; pub use outline_builder::OutlineBuilder; -mod rendering_params; pub use rendering_params::RenderingParams; -mod glyph_run_analysis; pub use glyph_run_analysis::GlyphRunAnalysis; - -// This is an internal implementation of FontFileLoader, for our utility -// functions. We don't wrap the DWriteFontFileLoader interface and -// related things. -mod font_file_loader_impl; - -// This is an implementation of `FontCollectionLoader` for client code. -mod font_collection_impl; pub use font_collection_impl::CustomFontCollectionLoaderImpl; - -// This is an internal implementation of `GeometrySink` so that we can -// expose `IDWriteGeometrySink` in an idiomatic way. -mod geometry_sink_impl; - -unsafe impl Sync for ComPtr { } -unsafe impl Sync for ComPtr {} - -lazy_static! { - static ref DWRITE_FACTORY_RAW_PTR: usize = { - unsafe { - type DWriteCreateFactoryType = extern "system" fn(DWRITE_FACTORY_TYPE, REFIID, *mut *mut IUnknown) -> HRESULT; - - let dwrite_dll = LoadLibraryW("dwrite.dll".to_wide_null().as_ptr()); - assert!(!dwrite_dll.is_null()); - let create_factory_name = CString::new("DWriteCreateFactory").unwrap(); - let dwrite_create_factory_ptr = - GetProcAddress(dwrite_dll, create_factory_name.as_ptr() as LPCSTR); - assert!(!dwrite_create_factory_ptr.is_null()); - - let dwrite_create_factory = - mem::transmute::<*const c_void, DWriteCreateFactoryType>(dwrite_create_factory_ptr as *const _); - - let mut factory: ComPtr = ComPtr::new(); - let hr = dwrite_create_factory( - DWRITE_FACTORY_TYPE_SHARED, - &IDWriteFactory::uuidof(), - factory.getter_addrefs()); - assert!(hr == S_OK); - factory.forget() as usize - } - }; - - static ref DEFAULT_DWRITE_RENDERING_PARAMS_RAW_PTR: usize = { - unsafe { - let mut default_rendering_params: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).CreateRenderingParams(default_rendering_params.getter_addrefs()); - assert!(hr == S_OK); - - default_rendering_params.forget() as usize - } - }; - -} // end lazy static - -// FIXME vlad would be nice to return, say, FactoryPtr -// that has a DerefMut impl, so that we can write -// DWriteFactory().SomeOperation() as opposed to -// (*DWriteFactory()).SomeOperation() -#[allow(non_snake_case)] -fn DWriteFactory() -> *mut IDWriteFactory { - (*DWRITE_FACTORY_RAW_PTR) as *mut IDWriteFactory -} - -#[allow(non_snake_case)] -fn DefaultDWriteRenderParams() -> *mut IDWriteRenderingParams { - (*DEFAULT_DWRITE_RENDERING_PARAMS_RAW_PTR) as *mut IDWriteRenderingParams -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![allow(non_upper_case_globals)] + +#[cfg_attr(feature = "serde_serialization", macro_use)] +#[cfg(feature = "serde_serialization")] +extern crate serde_derive; +#[cfg(feature = "serde_serialization")] +extern crate serde; + +#[macro_use] +extern crate lazy_static; +#[macro_use(DEFINE_GUID)] +extern crate winapi; +extern crate libc; + +include!("types.rs"); + +use winapi::Interface; +use winapi::um::dwrite::DWRITE_FACTORY_TYPE_SHARED; +use winapi::um::dwrite::IDWriteFactory; +use winapi::um::dwrite::IDWriteRenderingParams; +pub use winapi::um::winnt::HRESULT; +use winapi::um::winnt::LPCSTR; +use winapi::shared::guiddef::REFIID; +use winapi::um::unknwnbase::IUnknown; +use winapi::um::dwrite::DWRITE_FACTORY_TYPE; +use std::ffi::CString; + +use comptr::ComPtr; +use winapi::shared::winerror::S_OK; + +mod comptr; +mod helpers; +use helpers::ToWide; +use std::os::raw::c_void; + +#[cfg(test)] +mod test; + +// We still use the DWrite structs for things like metrics; re-export them +// here +pub use winapi::um::dwrite::DWRITE_FONT_METRICS as FontMetrics; +pub use winapi::um::dwrite::DWRITE_GLYPH_OFFSET as GlyphOffset; +pub use winapi::um::dwrite::{DWRITE_MATRIX, DWRITE_GLYPH_RUN}; +pub use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, + DWRITE_RENDERING_MODE_ALIASED, + DWRITE_RENDERING_MODE_GDI_CLASSIC, + DWRITE_RENDERING_MODE_GDI_NATURAL, + DWRITE_RENDERING_MODE_NATURAL, + DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, + DWRITE_RENDERING_MODE_OUTLINE, + DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, + DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC}; +pub use winapi::um::dcommon::{DWRITE_MEASURING_MODE_NATURAL, + DWRITE_MEASURING_MODE_GDI_CLASSIC, + DWRITE_MEASURING_MODE_GDI_NATURAL}; +pub use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS_NONE, + DWRITE_FONT_SIMULATIONS_BOLD, + DWRITE_FONT_SIMULATIONS_OBLIQUE}; +pub use winapi::um::dwrite::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1}; +pub use winapi::um::dwrite::{DWRITE_FONT_SIMULATIONS}; +pub use winapi::um::dwrite::{DWRITE_RENDERING_MODE}; +pub use winapi::um::dwrite::{DWRITE_TEXTURE_TYPE}; +pub use winapi::um::dwrite_3::{DWRITE_FONT_AXIS_VALUE}; +pub use winapi::um::dcommon::{DWRITE_MEASURING_MODE}; +pub use winapi::shared::windef::RECT; +use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryW}; + +#[macro_use] mod com_helpers; + +mod bitmap_render_target; pub use bitmap_render_target::BitmapRenderTarget; +mod font; pub use font::{Font, InformationalStringId}; +mod font_collection; pub use font_collection::FontCollection; +mod font_face; pub use font_face::{FontFace, FontFaceType}; +mod font_fallback; pub use font_fallback::{FallbackResult, FontFallback}; +mod font_family; pub use font_family::FontFamily; +mod font_file; pub use font_file::FontFile; +mod gdi_interop; pub use gdi_interop::GdiInterop; +mod outline_builder; pub use outline_builder::OutlineBuilder; +mod rendering_params; pub use rendering_params::RenderingParams; +mod text_analysis_source; pub use text_analysis_source::TextAnalysisSource; +mod glyph_run_analysis; pub use glyph_run_analysis::GlyphRunAnalysis; + +// This is an internal implementation of FontFileLoader, for our utility +// functions. We don't wrap the DWriteFontFileLoader interface and +// related things. +mod font_file_loader_impl; + +// This is an implementation of `FontCollectionLoader` for client code. +mod font_collection_impl; pub use font_collection_impl::CustomFontCollectionLoaderImpl; + +// This is an implementation of `TextAnalysisSource` for client code. +mod text_analysis_source_impl; +pub use text_analysis_source_impl::{CustomTextAnalysisSourceImpl, NumberSubstitution, + TextAnalysisSourceMethods +}; + +// This is an internal implementation of `GeometrySink` so that we can +// expose `IDWriteGeometrySink` in an idiomatic way. +mod geometry_sink_impl; + +unsafe impl Sync for ComPtr { } +unsafe impl Sync for ComPtr {} + +lazy_static! { + static ref DWRITE_FACTORY_RAW_PTR: usize = { + unsafe { + type DWriteCreateFactoryType = extern "system" fn(DWRITE_FACTORY_TYPE, REFIID, *mut *mut IUnknown) -> HRESULT; + + let dwrite_dll = LoadLibraryW("dwrite.dll".to_wide_null().as_ptr()); + assert!(!dwrite_dll.is_null()); + let create_factory_name = CString::new("DWriteCreateFactory").unwrap(); + let dwrite_create_factory_ptr = + GetProcAddress(dwrite_dll, create_factory_name.as_ptr() as LPCSTR); + assert!(!dwrite_create_factory_ptr.is_null()); + + let dwrite_create_factory = + mem::transmute::<*const c_void, DWriteCreateFactoryType>(dwrite_create_factory_ptr as *const _); + + let mut factory: ComPtr = ComPtr::new(); + let hr = dwrite_create_factory( + DWRITE_FACTORY_TYPE_SHARED, + &IDWriteFactory::uuidof(), + factory.getter_addrefs()); + assert!(hr == S_OK); + factory.forget() as usize + } + }; + + static ref DEFAULT_DWRITE_RENDERING_PARAMS_RAW_PTR: usize = { + unsafe { + let mut default_rendering_params: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateRenderingParams(default_rendering_params.getter_addrefs()); + assert!(hr == S_OK); + + default_rendering_params.forget() as usize + } + }; + +} // end lazy static + +// FIXME vlad would be nice to return, say, FactoryPtr +// that has a DerefMut impl, so that we can write +// DWriteFactory().SomeOperation() as opposed to +// (*DWriteFactory()).SomeOperation() +#[allow(non_snake_case)] +fn DWriteFactory() -> *mut IDWriteFactory { + (*DWRITE_FACTORY_RAW_PTR) as *mut IDWriteFactory +} + +#[allow(non_snake_case)] +fn DefaultDWriteRenderParams() -> *mut IDWriteRenderingParams { + (*DEFAULT_DWRITE_RENDERING_PARAMS_RAW_PTR) as *mut IDWriteRenderingParams +} diff --git a/third_party/rust/dwrote/src/outline_builder.rs b/third_party/rust/dwrote/src/outline_builder.rs index 7e7716b4f08db..8a5feac0cf9a5 100644 --- a/third_party/rust/dwrote/src/outline_builder.rs +++ b/third_party/rust/dwrote/src/outline_builder.rs @@ -1,6 +1,6 @@ -pub trait OutlineBuilder { - fn move_to(&mut self, x: f32, y: f32); - fn line_to(&mut self, x: f32, y: f32); - fn curve_to(&mut self, cp0x: f32, cp0y: f32, cp1x: f32, cp1y: f32, x: f32, y: f32); - fn close(&mut self); -} +pub trait OutlineBuilder { + fn move_to(&mut self, x: f32, y: f32); + fn line_to(&mut self, x: f32, y: f32); + fn curve_to(&mut self, cp0x: f32, cp0y: f32, cp1x: f32, cp1y: f32, x: f32, y: f32); + fn close(&mut self); +} diff --git a/third_party/rust/dwrote/src/rendering_params.rs b/third_party/rust/dwrote/src/rendering_params.rs index 3a38c6846b3ff..b190cc2328f1c 100644 --- a/third_party/rust/dwrote/src/rendering_params.rs +++ b/third_party/rust/dwrote/src/rendering_params.rs @@ -1,34 +1,34 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::cell::UnsafeCell; - -use comptr::ComPtr; -use winapi::um::dwrite::IDWriteRenderingParams; -use super::DWriteFactory; - -pub struct RenderingParams { - native: UnsafeCell>, -} - -impl RenderingParams { - pub fn create_for_primary_monitor() -> RenderingParams { - unsafe { - let mut native: ComPtr = ComPtr::new(); - let hr = (*DWriteFactory()).CreateRenderingParams(native.getter_addrefs()); - assert!(hr == 0); - RenderingParams::take(native) - } - } - - pub fn take(native: ComPtr) -> RenderingParams { - RenderingParams { - native: UnsafeCell::new(native), - } - } - - pub unsafe fn as_ptr(&self) -> *mut IDWriteRenderingParams { - (*self.native.get()).as_ptr() - } -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; + +use comptr::ComPtr; +use winapi::um::dwrite::IDWriteRenderingParams; +use super::DWriteFactory; + +pub struct RenderingParams { + native: UnsafeCell>, +} + +impl RenderingParams { + pub fn create_for_primary_monitor() -> RenderingParams { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateRenderingParams(native.getter_addrefs()); + assert!(hr == 0); + RenderingParams::take(native) + } + } + + pub fn take(native: ComPtr) -> RenderingParams { + RenderingParams { + native: UnsafeCell::new(native), + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteRenderingParams { + (*self.native.get()).as_ptr() + } +} diff --git a/third_party/rust/dwrote/src/test.rs b/third_party/rust/dwrote/src/test.rs index d5e183c01462f..eab815d46be84 100644 --- a/third_party/rust/dwrote/src/test.rs +++ b/third_party/rust/dwrote/src/test.rs @@ -1,139 +1,139 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use super::*; -use std::sync::Arc; - -#[test] -fn test_system_family_iter() { - let system_fc = FontCollection::system(); - let count = system_fc.families_iter().count(); - assert!(count > 0); - assert!(system_fc.families_iter().find(|f| f.name() == "Arial").is_some()); -} - -#[test] -fn test_descriptor_round_trip() { - let system_fc = FontCollection::system(); - - let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); - let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - - let descriptor = arial_font.to_descriptor(); - assert!(descriptor.family_name == "Arial"); - - let arial_font_2 = system_fc.get_font_from_descriptor(&descriptor).unwrap(); - let descriptor2 = arial_font_2.to_descriptor(); - assert_eq!(descriptor, descriptor2); -} - -#[test] -fn test_get_font_file_bytes() { - let system_fc = FontCollection::system(); - - let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); - let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - let face = arial_font.create_font_face(); - let files = face.get_files(); - assert!(files.len() > 0); - - let bytes = files[0].get_font_file_bytes(); - assert!(bytes.len() > 0); -} - -#[test] -fn test_font_file_is_monospace() { - let system_fc = FontCollection::system(); - - let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); - let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - assert!(arial_font.is_monospace() == Some(false)); - - let courier_new_family = system_fc.get_font_family_by_name("Courier New").unwrap(); - let courier_new_font = courier_new_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - assert!(courier_new_font.is_monospace() == Some(true)); -} - - -#[test] -fn test_create_font_file_from_bytes() { - let system_fc = FontCollection::system(); - - let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); - let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - let face = arial_font.create_font_face(); - let files = face.get_files(); - assert!(files.len() > 0); - - let bytes = files[0].get_font_file_bytes(); - assert!(bytes.len() > 0); - - // now go back - let new_font = FontFile::new_from_data(Arc::new(bytes)); - assert!(new_font.is_some()); - - let new_font = new_font.unwrap(); -} - -#[test] -fn test_glyph_image() { - let system_fc = FontCollection::system(); - let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); - let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, - FontStretch::Normal, - FontStyle::Normal); - - let face = arial_font.create_font_face(); - let a_index = face.get_glyph_indices(&['A' as u32])[0]; - - let metrics = face.get_metrics(); - - let gm = face.get_design_glyph_metrics(&[a_index], false)[0]; - - let device_pixel_ratio = 1.0f32; - let em_size = 10.0f32; - - let design_units_per_pixel = face.metrics().designUnitsPerEm as f32 / 16. as f32; - let scaled_design_units_to_pixels = (em_size * device_pixel_ratio) / design_units_per_pixel; - - let width = (gm.advanceWidth as i32 - (gm.leftSideBearing + gm.rightSideBearing)) as f32 * scaled_design_units_to_pixels; - let height = (gm.advanceHeight as i32 - (gm.topSideBearing + gm.bottomSideBearing)) as f32 * scaled_design_units_to_pixels; - let x = (-gm.leftSideBearing) as f32 * scaled_design_units_to_pixels; - let y = (gm.verticalOriginY - gm.topSideBearing) as f32 * scaled_design_units_to_pixels; - - // FIXME I'm pretty sure we need to do a proper RoundOut type - // operation on this rect to properly handle any aliasing - let left_i = x.floor() as i32; - let top_i = (height - y).floor() as i32; - let width_u = width.ceil() as u32; - let height_u = height.ceil() as u32; - - println!("GlyphDimensions: {} {} {} {}", left_i, top_i, width_u, height_u); - - let gdi_interop = GdiInterop::create(); - let rt = gdi_interop.create_bitmap_render_target(width_u, height_u); - let rp = RenderingParams::create_for_primary_monitor(); - rt.set_pixels_per_dip(device_pixel_ratio); - rt.draw_glyph_run(x as f32, y as f32, - DWRITE_MEASURING_MODE_NATURAL, - &face, - em_size, - &[a_index], - &[0f32], - &[GlyphOffset { advanceOffset: 0., ascenderOffset: 0. }], - &rp, - &(255.0f32, 255.0f32, 255.0f32)); - let bytes = rt.get_opaque_values_as_mask(); - println!("bytes length: {}", bytes.len()); -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use super::*; +use std::sync::Arc; + +#[test] +fn test_system_family_iter() { + let system_fc = FontCollection::system(); + let count = system_fc.families_iter().count(); + assert!(count > 0); + assert!(system_fc.families_iter().find(|f| f.name() == "Arial").is_some()); +} + +#[test] +fn test_descriptor_round_trip() { + let system_fc = FontCollection::system(); + + let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); + let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + + let descriptor = arial_font.to_descriptor(); + assert!(descriptor.family_name == "Arial"); + + let arial_font_2 = system_fc.get_font_from_descriptor(&descriptor).unwrap(); + let descriptor2 = arial_font_2.to_descriptor(); + assert_eq!(descriptor, descriptor2); +} + +#[test] +fn test_get_font_file_bytes() { + let system_fc = FontCollection::system(); + + let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); + let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + let face = arial_font.create_font_face(); + let files = face.get_files(); + assert!(files.len() > 0); + + let bytes = files[0].get_font_file_bytes(); + assert!(bytes.len() > 0); +} + +#[test] +fn test_font_file_is_monospace() { + let system_fc = FontCollection::system(); + + let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); + let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + assert!(arial_font.is_monospace() == Some(false)); + + let courier_new_family = system_fc.get_font_family_by_name("Courier New").unwrap(); + let courier_new_font = courier_new_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + assert!(courier_new_font.is_monospace() == Some(true)); +} + + +#[test] +fn test_create_font_file_from_bytes() { + let system_fc = FontCollection::system(); + + let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); + let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + let face = arial_font.create_font_face(); + let files = face.get_files(); + assert!(files.len() > 0); + + let bytes = files[0].get_font_file_bytes(); + assert!(bytes.len() > 0); + + // now go back + let new_font = FontFile::new_from_data(Arc::new(bytes)); + assert!(new_font.is_some()); + + let new_font = new_font.unwrap(); +} + +#[test] +fn test_glyph_image() { + let system_fc = FontCollection::system(); + let arial_family = system_fc.get_font_family_by_name("Arial").unwrap(); + let arial_font = arial_family.get_first_matching_font(FontWeight::Regular, + FontStretch::Normal, + FontStyle::Normal); + + let face = arial_font.create_font_face(); + let a_index = face.get_glyph_indices(&['A' as u32])[0]; + + let metrics = face.get_metrics(); + + let gm = face.get_design_glyph_metrics(&[a_index], false)[0]; + + let device_pixel_ratio = 1.0f32; + let em_size = 10.0f32; + + let design_units_per_pixel = face.metrics().designUnitsPerEm as f32 / 16. as f32; + let scaled_design_units_to_pixels = (em_size * device_pixel_ratio) / design_units_per_pixel; + + let width = (gm.advanceWidth as i32 - (gm.leftSideBearing + gm.rightSideBearing)) as f32 * scaled_design_units_to_pixels; + let height = (gm.advanceHeight as i32 - (gm.topSideBearing + gm.bottomSideBearing)) as f32 * scaled_design_units_to_pixels; + let x = (-gm.leftSideBearing) as f32 * scaled_design_units_to_pixels; + let y = (gm.verticalOriginY - gm.topSideBearing) as f32 * scaled_design_units_to_pixels; + + // FIXME I'm pretty sure we need to do a proper RoundOut type + // operation on this rect to properly handle any aliasing + let left_i = x.floor() as i32; + let top_i = (height - y).floor() as i32; + let width_u = width.ceil() as u32; + let height_u = height.ceil() as u32; + + println!("GlyphDimensions: {} {} {} {}", left_i, top_i, width_u, height_u); + + let gdi_interop = GdiInterop::create(); + let rt = gdi_interop.create_bitmap_render_target(width_u, height_u); + let rp = RenderingParams::create_for_primary_monitor(); + rt.set_pixels_per_dip(device_pixel_ratio); + rt.draw_glyph_run(x as f32, y as f32, + DWRITE_MEASURING_MODE_NATURAL, + &face, + em_size, + &[a_index], + &[0f32], + &[GlyphOffset { advanceOffset: 0., ascenderOffset: 0. }], + &rp, + &(255.0f32, 255.0f32, 255.0f32)); + let bytes = rt.get_opaque_values_as_mask(); + println!("bytes length: {}", bytes.len()); +} diff --git a/third_party/rust/dwrote/src/text_analysis_source.rs b/third_party/rust/dwrote/src/text_analysis_source.rs new file mode 100644 index 0000000000000..0bf571c5fcb45 --- /dev/null +++ b/third_party/rust/dwrote/src/text_analysis_source.rs @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; + +use winapi::ctypes::wchar_t; +use winapi::um::dwrite::IDWriteTextAnalysisSource; + +use com_helpers::Com; + +use super::*; + +pub struct TextAnalysisSource { + native: UnsafeCell>, +} + +impl TextAnalysisSource { + /// Create a new custom TextAnalysisSource for the given text and a trait + /// implementation. + /// + /// Note: this method only supports a single `NumberSubstitution` for the + /// entire string. + pub fn from_text_and_number_subst(inner: Box, + text: Vec, number_subst: NumberSubstitution) -> TextAnalysisSource + { + let native = CustomTextAnalysisSourceImpl::from_text_and_number_subst_native( + inner, text, number_subst + ); + TextAnalysisSource::take(native) + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteTextAnalysisSource { + (*self.native.get()).as_ptr() + } + + // TODO: following crate conventions, but there's a safety problem + pub fn take(native: ComPtr) -> TextAnalysisSource { + TextAnalysisSource { + native: UnsafeCell::new(native), + } + } + +} diff --git a/third_party/rust/dwrote/src/text_analysis_source_impl.rs b/third_party/rust/dwrote/src/text_analysis_source_impl.rs new file mode 100644 index 0000000000000..91a5226e49e86 --- /dev/null +++ b/third_party/rust/dwrote/src/text_analysis_source_impl.rs @@ -0,0 +1,203 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! A custom implementation of the "text analysis source" interface so that +//! we can convey data to the `FontFallback::map_characters` method. + +#![allow(non_snake_case)] + +use std::borrow::Cow; +use std::cell::UnsafeCell; +use std::mem; +use std::ptr::null; +use std::sync::atomic::AtomicUsize; +use winapi::ctypes::wchar_t; +use winapi::shared::basetsd::UINT32; +use winapi::shared::guiddef::REFIID; +use winapi::shared::minwindef::{BOOL, FALSE, TRUE, ULONG}; +use winapi::shared::winerror::{E_INVALIDARG, S_OK}; +use winapi::um::dwrite::{DWRITE_NUMBER_SUBSTITUTION_METHOD, DWRITE_READING_DIRECTION, + IDWriteNumberSubstitution, IDWriteTextAnalysisSource, IDWriteTextAnalysisSourceVtbl, +}; +use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; +use winapi::um::winnt::HRESULT; + +use helpers::ToWide; +use super::DWriteFactory; +use com_helpers::{Com, UuidOfIUnknown}; +use comptr::ComPtr; + +/// The Rust side of a custom text analysis source implementation. +pub trait TextAnalysisSourceMethods { + /// Determine the locale for a range of text. + /// + /// Return locale and length of text (in utf-16 code units) for which the + /// locale is valid. + fn get_locale_name<'a>(&'a self, text_position: u32) -> (Cow<'a, str>, u32); + + /// Get the text direction for the paragraph. + fn get_paragraph_reading_direction(&self) -> DWRITE_READING_DIRECTION; +} + +pub struct CustomTextAnalysisSourceImpl { + refcount: AtomicUsize, + inner: Box, + text: Vec, + number_subst: NumberSubstitution, + locale_buf: Vec, +} + +/// A wrapped version of an `IDWriteNumberSubstitution` object. +pub struct NumberSubstitution { + native: UnsafeCell>, +} + +// TODO: implement Clone, for convenience and efficiency? + +DEFINE_GUID! { + DWRITE_TEXT_ANALYSIS_SOURCE_UUID, + 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 +} + +static TEXT_ANALYSIS_SOURCE_VTBL: IDWriteTextAnalysisSourceVtbl = + IDWriteTextAnalysisSourceVtbl { + parent: implement_iunknown!(static IDWriteTextAnalysisSource, + DWRITE_TEXT_ANALYSIS_SOURCE_UUID, + CustomTextAnalysisSourceImpl), + GetLocaleName: CustomTextAnalysisSourceImpl_GetLocaleName, + GetNumberSubstitution: CustomTextAnalysisSourceImpl_GetNumberSubstitution, + GetParagraphReadingDirection: CustomTextAnalysisSourceImpl_GetParagraphReadingDirection, + GetTextAtPosition: CustomTextAnalysisSourceImpl_GetTextAtPosition, + GetTextBeforePosition: CustomTextAnalysisSourceImpl_GetTextBeforePosition, +}; + +impl CustomTextAnalysisSourceImpl { + /// Create a new custom TextAnalysisSource for the given text and a trait + /// implementation. + /// + /// Note: this method only supports a single `NumberSubstitution` for the + /// entire string. + pub fn from_text_and_number_subst_native(inner: Box, + text: Vec, number_subst: NumberSubstitution) -> ComPtr + { + assert!(text.len() <= (std::u32::MAX as usize)); + unsafe { + ComPtr::already_addrefed(CustomTextAnalysisSourceImpl { + refcount: AtomicUsize::new(1), + inner, + text, + number_subst, + locale_buf: Vec::new(), + }.into_interface()) + } + } +} + +impl Com for CustomTextAnalysisSourceImpl { + type Vtbl = IDWriteTextAnalysisSourceVtbl; + #[inline] + fn vtbl() -> &'static IDWriteTextAnalysisSourceVtbl { + &TEXT_ANALYSIS_SOURCE_VTBL + } +} + +impl Com for CustomTextAnalysisSourceImpl { + type Vtbl = IUnknownVtbl; + #[inline] + fn vtbl() -> &'static IUnknownVtbl { + &TEXT_ANALYSIS_SOURCE_VTBL.parent + } +} + +unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetLocaleName( + this: *mut IDWriteTextAnalysisSource, + text_position: UINT32, + text_length: *mut UINT32, + locale_name: *mut *const wchar_t) + -> HRESULT { + let this = CustomTextAnalysisSourceImpl::from_interface(this); + let (locale, text_len) = this.inner.get_locale_name(text_position); + // TODO(performance): reuse buffer (and maybe use smallvec) + this.locale_buf = locale.as_ref().to_wide_null(); + *text_length = text_len; + *locale_name = this.locale_buf.as_ptr(); + S_OK +} + +unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetNumberSubstitution( + this: *mut IDWriteTextAnalysisSource, + text_position: UINT32, + text_length: *mut UINT32, + number_substitution: *mut *mut IDWriteNumberSubstitution) + -> HRESULT { + let this = CustomTextAnalysisSourceImpl::from_interface(this); + if text_position >= (this.text.len() as u32) { + return E_INVALIDARG; + } + (*this.number_subst.native.get()).addref(); + *text_length = (this.text.len() as UINT32) - text_position; + *number_substitution = (*this.number_subst.native.get()).as_ptr(); + S_OK +} + +unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetParagraphReadingDirection( + this: *mut IDWriteTextAnalysisSource) + -> DWRITE_READING_DIRECTION { + let this = CustomTextAnalysisSourceImpl::from_interface(this); + this.inner.get_paragraph_reading_direction() +} + +unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetTextAtPosition( + this: *mut IDWriteTextAnalysisSource, + text_position: UINT32, + text_string: *mut *const wchar_t, + text_length: *mut UINT32) + -> HRESULT { + let this = CustomTextAnalysisSourceImpl::from_interface(this); + if text_position >= (this.text.len() as u32) { + *text_string = null(); + *text_length = 0; + return S_OK; + } + *text_string = this.text.as_ptr().add(text_position as usize); + *text_length = (this.text.len() as UINT32) - text_position; + S_OK +} + +unsafe extern "system" fn CustomTextAnalysisSourceImpl_GetTextBeforePosition( + this: *mut IDWriteTextAnalysisSource, + text_position: UINT32, + text_string: *mut *const wchar_t, + text_length: *mut UINT32) + -> HRESULT { + let this = CustomTextAnalysisSourceImpl::from_interface(this); + if text_position == 0 || text_position > (this.text.len() as u32) { + *text_string = null(); + *text_length = 0; + return S_OK; + } + *text_string = this.text.as_ptr(); + *text_length = text_position; + S_OK +} + +impl NumberSubstitution { + pub fn new(subst_method: DWRITE_NUMBER_SUBSTITUTION_METHOD, locale: &str, + ignore_user_overrides: bool) -> NumberSubstitution + { + unsafe { + let mut native: ComPtr = ComPtr::new(); + let hr = (*DWriteFactory()).CreateNumberSubstitution( + subst_method, + locale.to_wide_null().as_ptr(), + if ignore_user_overrides { TRUE } else { FALSE }, + native.getter_addrefs(), + ); + assert_eq!(hr, 0, "error creating number substitution"); + NumberSubstitution { + native: UnsafeCell::new(native) + } + } + } +} diff --git a/third_party/rust/dwrote/src/types.rs b/third_party/rust/dwrote/src/types.rs index d488a0805e3f0..d9b9e68cea17e 100644 --- a/third_party/rust/dwrote/src/types.rs +++ b/third_party/rust/dwrote/src/types.rs @@ -1,126 +1,126 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* this is include!()'d in lib.rs */ -use std::mem; -use winapi::um::dwrite::{DWRITE_FONT_STYLE, DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH}; - -// mirrors DWRITE_FONT_WEIGHT -#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum FontWeight { - Thin, - ExtraLight, - Light, - SemiLight, - Regular, - Medium, - SemiBold, - Bold, - ExtraBold, - Black, - ExtraBlack, - Unknown(u32) -} - -impl FontWeight { - fn t(&self) -> DWRITE_FONT_WEIGHT { - unsafe { mem::transmute::(self.to_u32()) } - } - pub fn to_u32(&self) -> u32 { - match self { - FontWeight::Thin=> 100, - FontWeight::ExtraLight=> 200, - FontWeight::Light=> 300, - FontWeight::SemiLight=> 350, - FontWeight::Regular=> 400, - FontWeight::Medium=> 500, - FontWeight::SemiBold=> 600, - FontWeight::Bold=> 700, - FontWeight::ExtraBold=> 800, - FontWeight::Black=> 900, - FontWeight::ExtraBlack=> 950, - FontWeight::Unknown(v) => *v as u32 - } - } - pub fn from_u32(v: u32) -> FontWeight { - match v { - 100 => FontWeight::Thin, - 200 => FontWeight::ExtraLight, - 300 => FontWeight::Light, - 350 => FontWeight::SemiLight, - 400 => FontWeight::Regular, - 500 => FontWeight::Medium, - 600 => FontWeight::SemiBold, - 700 => FontWeight::Bold, - 800 => FontWeight::ExtraBold, - 900 => FontWeight::Black, - 950 => FontWeight::ExtraBlack, - _ => FontWeight::Unknown(v) - } - } -} - -// mirrors DWRITE_FONT_STRETCH -#[repr(u32)] -#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum FontStretch { - Undefined = 0, - UltraCondensed = 1, - ExtraCondensed = 2, - Condensed = 3, - SemiCondensed = 4, - Normal = 5, - SemiExpanded = 6, - Expanded = 7, - ExtraExpanded = 8, - UltraExpanded = 9, -} - -impl FontStretch { - fn t(&self) -> DWRITE_FONT_STRETCH { - unsafe { mem::transmute::(*self) } - } - pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::(*self) } } - pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute::(v) } } -} - -// mirrors DWRITE_FONT_STYLE -#[repr(u32)] -#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum FontStyle { - Normal = 0, - Oblique = 1, - Italic = 2, -} - -impl FontStyle { - fn t(&self) -> DWRITE_FONT_STYLE { - unsafe { mem::transmute::(*self) } - } - pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::(*self) } } - pub fn from_u32(v: u32) -> FontStyle { unsafe { mem::transmute::(v) } } -} - -// mirrors DWRITE_FONT_SIMULATIONS -#[repr(u32)] -#[derive(PartialEq, Debug, Clone, Copy)] -pub enum FontSimulations { - None = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_NONE, - Bold = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_BOLD, - Oblique = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_OBLIQUE, - BoldOblique = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_BOLD | - winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_OBLIQUE, -} - -#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] -#[derive(PartialEq, Debug, Clone)] -pub struct FontDescriptor { - pub family_name: String, - pub weight: FontWeight, - pub stretch: FontStretch, - pub style: FontStyle, -} +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* this is include!()'d in lib.rs */ +use std::mem; +use winapi::um::dwrite::{DWRITE_FONT_STYLE, DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH}; + +// mirrors DWRITE_FONT_WEIGHT +#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum FontWeight { + Thin, + ExtraLight, + Light, + SemiLight, + Regular, + Medium, + SemiBold, + Bold, + ExtraBold, + Black, + ExtraBlack, + Unknown(u32) +} + +impl FontWeight { + fn t(&self) -> DWRITE_FONT_WEIGHT { + unsafe { mem::transmute::(self.to_u32()) } + } + pub fn to_u32(&self) -> u32 { + match self { + FontWeight::Thin=> 100, + FontWeight::ExtraLight=> 200, + FontWeight::Light=> 300, + FontWeight::SemiLight=> 350, + FontWeight::Regular=> 400, + FontWeight::Medium=> 500, + FontWeight::SemiBold=> 600, + FontWeight::Bold=> 700, + FontWeight::ExtraBold=> 800, + FontWeight::Black=> 900, + FontWeight::ExtraBlack=> 950, + FontWeight::Unknown(v) => *v as u32 + } + } + pub fn from_u32(v: u32) -> FontWeight { + match v { + 100 => FontWeight::Thin, + 200 => FontWeight::ExtraLight, + 300 => FontWeight::Light, + 350 => FontWeight::SemiLight, + 400 => FontWeight::Regular, + 500 => FontWeight::Medium, + 600 => FontWeight::SemiBold, + 700 => FontWeight::Bold, + 800 => FontWeight::ExtraBold, + 900 => FontWeight::Black, + 950 => FontWeight::ExtraBlack, + _ => FontWeight::Unknown(v) + } + } +} + +// mirrors DWRITE_FONT_STRETCH +#[repr(u32)] +#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum FontStretch { + Undefined = 0, + UltraCondensed = 1, + ExtraCondensed = 2, + Condensed = 3, + SemiCondensed = 4, + Normal = 5, + SemiExpanded = 6, + Expanded = 7, + ExtraExpanded = 8, + UltraExpanded = 9, +} + +impl FontStretch { + fn t(&self) -> DWRITE_FONT_STRETCH { + unsafe { mem::transmute::(*self) } + } + pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::(*self) } } + pub fn from_u32(v: u32) -> FontStretch { unsafe { mem::transmute::(v) } } +} + +// mirrors DWRITE_FONT_STYLE +#[repr(u32)] +#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum FontStyle { + Normal = 0, + Oblique = 1, + Italic = 2, +} + +impl FontStyle { + fn t(&self) -> DWRITE_FONT_STYLE { + unsafe { mem::transmute::(*self) } + } + pub fn to_u32(&self) -> u32 { unsafe { mem::transmute::(*self) } } + pub fn from_u32(v: u32) -> FontStyle { unsafe { mem::transmute::(v) } } +} + +// mirrors DWRITE_FONT_SIMULATIONS +#[repr(u32)] +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum FontSimulations { + None = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_NONE, + Bold = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_BOLD, + Oblique = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_OBLIQUE, + BoldOblique = winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_BOLD | + winapi::um::dwrite::DWRITE_FONT_SIMULATIONS_OBLIQUE, +} + +#[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] +#[derive(PartialEq, Debug, Clone)] +pub struct FontDescriptor { + pub family_name: String, + pub weight: FontWeight, + pub stretch: FontStretch, + pub style: FontStyle, +}