diff --git a/Cargo.toml b/Cargo.toml index 3a607a0..660b527 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,18 @@ lazy_static = "1" winapi = { version = "0.3.6", features = ["dwrite", "dwrite_1", "dwrite_3", "winnt", "unknwnbase", "libloaderapi", "winnls"] } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } -wio = "0.2" +windows-core = "0.58" +windows = { version = "0.58", features = [ + "implement", + "Win32_Graphics_DirectWrite", + "Win32_Graphics_Gdi", + "Win32_Graphics_Direct2D", + "Win32_Graphics_Direct2D_Common", + "Win32_System_Com", + "Win32_System_LibraryLoader", + "Win32_System_SystemServices", + "Win32_Globalization" +] } [package.metadata.docs.rs] targets = ["x86_64-pc-windows-msvc"] diff --git a/src/bitmap_render_target.rs b/src/bitmap_render_target.rs index d4753b8..b11066f 100644 --- a/src/bitmap_render_target.rs +++ b/src/bitmap_render_target.rs @@ -2,43 +2,34 @@ * 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::mem::{size_of, zeroed}; +use std::mem::{size_of, zeroed, ManuallyDrop}; use std::slice; -use winapi::ctypes::c_void; -use winapi::shared::windef::{HDC, RECT}; -use winapi::um::dcommon::DWRITE_MEASURING_MODE; -use winapi::um::dwrite::IDWriteBitmapRenderTarget; -use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_GLYPH_RUN}; -use winapi::um::wingdi::{GetCurrentObject, GetObjectW, BITMAP, OBJ_BITMAP, RGB}; -use wio::com::ComPtr; +use windows::Win32::Foundation::{COLORREF, FALSE, RECT}; +use windows::Win32::Graphics::DirectWrite::{ + IDWriteBitmapRenderTarget, DWRITE_GLYPH_OFFSET, DWRITE_GLYPH_RUN, DWRITE_MEASURING_MODE, +}; +use windows::Win32::Graphics::Gdi::{GetCurrentObject, GetObjectW, BITMAP, HDC, OBJ_BITMAP}; use super::{FontFace, RenderingParams}; pub struct BitmapRenderTarget { - native: UnsafeCell>, + native: IDWriteBitmapRenderTarget, } 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_raw() + pub fn take(native: IDWriteBitmapRenderTarget) -> BitmapRenderTarget { + BitmapRenderTarget { native } } // 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); + let _ = self.native.SetPixelsPerDip(ppd); } } pub fn get_memory_dc(&self) -> HDC { - unsafe { (*self.native.get()).GetMemoryDC() } + unsafe { self.native.GetMemoryDC() } } pub fn draw_glyph_run( @@ -61,28 +52,31 @@ impl BitmapRenderTarget { 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 color = COLORREF((r as u32) | ((g as u32) << 8) | ((b as u32) << 16)); + + let glyph_run = DWRITE_GLYPH_RUN { + fontFace: ManuallyDrop::new(Some(font_face.native.clone())), + fontEmSize: em_size, + glyphCount: glyph_indices.len() as u32, + glyphIndices: glyph_indices.as_ptr(), + glyphAdvances: glyph_advances.as_ptr(), + glyphOffsets: glyph_offsets.as_ptr(), + isSideways: FALSE, + 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); + self.native + .DrawGlyphRun( + baseline_origin_x, + baseline_origin_y, + measuring_mode, + &glyph_run, + &rendering_params.native, + color, + Some(&mut rect), + ) + .unwrap(); rect } } @@ -98,9 +92,9 @@ impl BitmapRenderTarget { let memory_dc = self.get_memory_dc(); let mut bitmap: BITMAP = zeroed(); let ret = GetObjectW( - GetCurrentObject(memory_dc, OBJ_BITMAP), + GetCurrentObject(HDC(memory_dc.0), OBJ_BITMAP), size_of::() as i32, - &mut bitmap as *mut _ as *mut c_void, + Some(&mut bitmap as *mut _ as *mut _), ); assert!(ret == size_of::() as i32); assert!(bitmap.bmBitsPixel == 32); diff --git a/src/font.rs b/src/font.rs index 37b915d..83c616c 100644 --- a/src/font.rs +++ b/src/font.rs @@ -2,57 +2,22 @@ * 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::mem; -use std::ptr; -use winapi::shared::minwindef::{FALSE, TRUE}; -use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::IDWriteFont; -use winapi::um::dwrite::IDWriteFontFace; -use winapi::um::dwrite::IDWriteFontFamily; -use winapi::um::dwrite::IDWriteLocalizedStrings; -use winapi::um::dwrite::DWRITE_FONT_METRICS; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESCRIPTION; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGNER; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGNER_URL; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FULL_NAME; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_ID; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_MANUFACTURER; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_TRADEMARK; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES; -use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME; -use winapi::um::dwrite_1::{IDWriteFont1, DWRITE_FONT_METRICS1}; -use wio::com::ComPtr; +use windows::core::Interface; +use windows::Win32::Foundation::{FALSE, TRUE}; +use windows::Win32::Graphics::DirectWrite::{ + IDWriteFont, IDWriteFont1, DWRITE_INFORMATIONAL_STRING_ID, +}; use super::*; use helpers::*; pub struct Font { - native: UnsafeCell>, + native: IDWriteFont, } 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_raw() + pub fn take(native: IDWriteFont) -> Font { + Font { native } } pub fn to_descriptor(&self) -> FontDescriptor { @@ -65,57 +30,53 @@ impl Font { } pub fn stretch(&self) -> FontStretch { - unsafe { mem::transmute::((*self.native.get()).GetStretch()) } + unsafe { mem::transmute::(self.native.GetStretch()) } } pub fn style(&self) -> FontStyle { - unsafe { mem::transmute::((*self.native.get()).GetStyle()) } + unsafe { mem::transmute::(self.native.GetStyle()) } } pub fn weight(&self) -> FontWeight { - unsafe { FontWeight::from_u32((*self.native.get()).GetWeight()) } + FontWeight::from(unsafe { self.native.GetWeight() }) } pub fn is_monospace(&self) -> Option { unsafe { - let font1: Option> = (*self.native.get()).cast().ok(); - font1.map(|font| font.IsMonospacedFont() == TRUE) + self.native + .cast::() + .ok() + .map(|font_1| font_1.IsMonospacedFont() == TRUE) } } pub fn simulations(&self) -> FontSimulations { - unsafe { mem::transmute::((*self.native.get()).GetSimulations()) } + FontSimulations::from(unsafe { self.native.GetSimulations() }) } pub fn family_name(&self) -> String { unsafe { - let mut family: *mut IDWriteFontFamily = ptr::null_mut(); - let hr = (*self.native.get()).GetFontFamily(&mut family); - assert!(hr == 0); - - FontFamily::take(ComPtr::from_raw(family)).name() + let family = self.native.GetFontFamily().unwrap(); + FontFamily::take(family).name() } } pub fn face_name(&self) -> String { unsafe { - let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); - let hr = (*self.native.get()).GetFaceNames(&mut names); - assert!(hr == 0); - - get_locale_string(&mut ComPtr::from_raw(names)) + let names = self.native.GetFaceNames().unwrap(); + get_locale_string(&names) } } pub fn informational_string(&self, id: InformationalStringId) -> Option { unsafe { - let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); + let mut names = None; let mut exists = FALSE; - let id = id as DWRITE_INFORMATIONAL_STRING_ID; - let hr = (*self.native.get()).GetInformationalStrings(id, &mut names, &mut exists); - assert!(hr == S_OK); + self.native + .GetInformationalStrings(id.into(), &mut names, &mut exists) + .ok()?; if exists == TRUE { - Some(get_locale_string(&mut ComPtr::from_raw(names))) + Some(names.map(|names| get_locale_string(&names))?) } else { None } @@ -126,24 +87,22 @@ impl Font { // FIXME create_font_face should cache the FontFace and return it, // there's a 1:1 relationship unsafe { - let mut face: *mut IDWriteFontFace = ptr::null_mut(); - let hr = (*self.native.get()).CreateFontFace(&mut face); - assert!(hr == 0); - FontFace::take(ComPtr::from_raw(face)) + let face = self.native.CreateFontFace().unwrap(); + FontFace::take(face) } } pub fn metrics(&self) -> FontMetrics { unsafe { - let font_1: Option> = (*self.native.get()).cast().ok(); + let font_1: Option = self.native.cast().ok(); match font_1 { None => { - let mut metrics = mem::zeroed(); - (*self.native.get()).GetMetrics(&mut metrics); + let mut metrics = std::mem::zeroed(); + self.native.GetMetrics(&mut metrics); FontMetrics::Metrics0(metrics) } Some(font_1) => { - let mut metrics_1 = mem::zeroed(); + let mut metrics_1 = std::mem::zeroed(); font_1.GetMetrics(&mut metrics_1); FontMetrics::Metrics1(metrics_1) } @@ -154,15 +113,44 @@ impl Font { impl Clone for Font { fn clone(&self) -> Font { - unsafe { - Font { - native: UnsafeCell::new((*self.native.get()).clone()), - } + Font { + native: self.native.clone(), } } } -#[repr(u32)] +macro_rules! make_const_informational_string { + ($($name:ident),*) => { + $( + const $name: i32 = windows::Win32::Graphics::DirectWrite::$name.0; + )* + }; +} +make_const_informational_string!( + DWRITE_INFORMATIONAL_STRING_FULL_NAME, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, + DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, + DWRITE_INFORMATIONAL_STRING_DESCRIPTION, + DWRITE_INFORMATIONAL_STRING_DESIGNER, + DWRITE_INFORMATIONAL_STRING_DESIGNER_URL, + DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG, + DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL, + DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION, + DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL, + DWRITE_INFORMATIONAL_STRING_MANUFACTURER, + DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT, + DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG, + DWRITE_INFORMATIONAL_STRING_TRADEMARK, + DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS, + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME +); + +#[repr(i32)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum InformationalStringId { FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, @@ -187,32 +175,69 @@ pub enum InformationalStringId { Win32SubfamilyNames = DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, WwsFamilyName = DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME, } +impl From for InformationalStringId { + fn from(v: DWRITE_INFORMATIONAL_STRING_ID) -> Self { + match v.0 { + DWRITE_INFORMATIONAL_STRING_FULL_NAME => Self::FullName, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME => Self::PostscriptName, + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME => Self::PostscriptCidName, + DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE => Self::CopyrightNotice, + DWRITE_INFORMATIONAL_STRING_DESCRIPTION => Self::Description, + DWRITE_INFORMATIONAL_STRING_DESIGNER => Self::Designer, + DWRITE_INFORMATIONAL_STRING_DESIGNER_URL => Self::DesignerUrl, + DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG => Self::DesignScriptLanguageTag, + DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL => Self::VendorUrl, + DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION => Self::LicenseDescription, + DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL => Self::LicenseInfoUrl, + DWRITE_INFORMATIONAL_STRING_MANUFACTURER => Self::Manufacturer, + DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES => Self::PreferredFamilyNames, + DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES => Self::PreferredSubfamilyNames, + DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT => Self::SampleText, + DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG => { + Self::SupportedScriptLanguageTag + } + DWRITE_INFORMATIONAL_STRING_TRADEMARK => Self::Trademark, + DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS => Self::Version, + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES => Self::Win32FamilyNames, + DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES => Self::Win32SubfamilyNames, + DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME => Self::WwsFamilyName, + _ => panic!("Unknown DWRITE_INFORMATIONAL_STRING_ID"), + } + } +} +impl Into for InformationalStringId { + fn into(self) -> i32 { + unsafe { mem::transmute::(self) } + } +} +impl Into for InformationalStringId { + #[inline] + fn into(self) -> DWRITE_INFORMATIONAL_STRING_ID { + DWRITE_INFORMATIONAL_STRING_ID(self.into()) + } +} +impl Into for InformationalStringId { + #[inline] + fn into(self) -> u32 { + Into::::into(self) as u32 + } +} /// A wrapper around the `DWRITE_FONT_METRICS` and `DWRITE_FONT_METRICS1` types. pub enum FontMetrics { /// Windows 7. - Metrics0(DWRITE_FONT_METRICS), + Metrics0(FontMetrics0), /// Windows 8 and up. - Metrics1(DWRITE_FONT_METRICS1), + Metrics1(FontMetrics1), } impl FontMetrics { /// Convert self to the Metrics0 arm (throwing away additional information) - pub fn metrics0(self) -> DWRITE_FONT_METRICS { + #[inline] + pub fn metrics0(self) -> FontMetrics0 { match self { FontMetrics::Metrics0(metrics) => metrics, - FontMetrics::Metrics1(metrics) => DWRITE_FONT_METRICS { - designUnitsPerEm: metrics.designUnitsPerEm, - ascent: metrics.ascent, - descent: metrics.descent, - lineGap: metrics.lineGap, - capHeight: metrics.capHeight, - xHeight: metrics.xHeight, - underlinePosition: metrics.underlinePosition, - underlineThickness: metrics.underlineThickness, - strikethroughPosition: metrics.strikethroughPosition, - strikethroughThickness: metrics.strikethroughThickness, - }, + FontMetrics::Metrics1(metrics) => metrics.Base, } } } diff --git a/src/font_collection.rs b/src/font_collection.rs index 90b9121..db2086f 100644 --- a/src/font_collection.rs +++ b/src/font_collection.rs @@ -2,23 +2,21 @@ * 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::mem; -use std::ptr; -use std::sync::atomic::{AtomicUsize, Ordering}; -use winapi::shared::minwindef::{BOOL, FALSE, TRUE}; -use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::IDWriteFontCollectionLoader; -use winapi::um::dwrite::{IDWriteFont, IDWriteFontCollection, IDWriteFontFamily}; -use wio::com::ComPtr; +use std::sync::atomic::{AtomicU32, Ordering}; +use windows::core::HSTRING; +use windows::Win32::Foundation::{BOOL, FALSE}; +use windows::Win32::Graphics::DirectWrite::DWriteCreateFactory; +use windows::Win32::Graphics::DirectWrite::IDWriteFactory; +use windows::Win32::Graphics::DirectWrite::IDWriteFontCollection; +use windows::Win32::Graphics::DirectWrite::IDWriteFontCollectionLoader; +use windows::Win32::Graphics::DirectWrite::DWRITE_FACTORY_TYPE_SHARED; -use super::{DWriteFactory, Font, FontDescriptor, FontFace, FontFamily}; -use crate::helpers::*; +use super::{Font, FontDescriptor, FontFace, FontFamily}; -static NEXT_ID: AtomicUsize = AtomicUsize::new(0); +static NEXT_ID: AtomicU32 = AtomicU32::new(0); pub struct FontCollectionFamilyIterator { - collection: ComPtr, + collection: IDWriteFontCollection, curr: u32, count: u32, } @@ -31,29 +29,28 @@ impl Iterator for FontCollectionFamilyIterator { } unsafe { - let mut family: *mut IDWriteFontFamily = ptr::null_mut(); - let hr = self.collection.GetFontFamily(self.curr, &mut family); - assert!(hr == 0); + let family = self.collection.GetFontFamily(self.curr).ok()?; self.curr += 1; - Some(FontFamily::take(ComPtr::from_raw(family))) + Some(FontFamily::take(family)) } } } pub struct FontCollection { - native: UnsafeCell>, + pub(crate) native: IDWriteFontCollection, } impl FontCollection { pub fn get_system(update: bool) -> FontCollection { unsafe { - let mut native: *mut IDWriteFontCollection = ptr::null_mut(); - let hr = (*DWriteFactory()) - .GetSystemFontCollection(&mut native, if update { TRUE } else { FALSE }); - assert!(hr == 0); + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let mut collection = None; + factory + .GetSystemFontCollection(&mut collection, update) + .unwrap(); FontCollection { - native: UnsafeCell::new(ComPtr::from_raw(native)), + native: collection.unwrap(), } } } @@ -62,58 +59,46 @@ impl FontCollection { FontCollection::get_system(false) } - pub fn take(native: ComPtr) -> FontCollection { - FontCollection { - native: UnsafeCell::new(native), - } + pub fn take(native: IDWriteFontCollection) -> FontCollection { + FontCollection { native } } - pub fn from_loader(collection_loader: ComPtr) -> FontCollection { + pub fn from_loader(collection_loader: &IDWriteFontCollectionLoader) -> FontCollection { unsafe { - let factory = DWriteFactory(); - assert_eq!( - (*factory).RegisterFontCollectionLoader(collection_loader.clone().into_raw()), - S_OK - ); - let mut collection: *mut IDWriteFontCollection = ptr::null_mut(); - let id = NEXT_ID.fetch_add(1, Ordering::SeqCst); - assert_eq!( - (*factory).CreateCustomFontCollection( - collection_loader.clone().into_raw(), - &id as *const usize as *const _, - mem::size_of::() as u32, - &mut collection - ), - S_OK - ); - FontCollection::take(ComPtr::from_raw(collection)) + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + factory + .RegisterFontCollectionLoader(collection_loader) + .unwrap(); + let id: *const _ = &NEXT_ID.fetch_add(1, Ordering::SeqCst); + let collection = factory + .CreateCustomFontCollection( + collection_loader, + id as *const _, + std::mem::size_of::() as u32, + ) + .unwrap(); + FontCollection::take(collection) } } - pub unsafe fn as_ptr(&self) -> *mut IDWriteFontCollection { - (*self.native.get()).as_raw() - } - pub fn families_iter(&self) -> FontCollectionFamilyIterator { unsafe { FontCollectionFamilyIterator { - collection: (*self.native.get()).clone(), + collection: self.native.clone(), curr: 0, - count: (*self.native.get()).GetFontFamilyCount(), + count: self.native.GetFontFamilyCount(), } } } pub fn get_font_family_count(&self) -> u32 { - unsafe { (*self.native.get()).GetFontFamilyCount() } + unsafe { self.native.GetFontFamilyCount() } } pub fn get_font_family(&self, index: u32) -> FontFamily { unsafe { - let mut family: *mut IDWriteFontFamily = ptr::null_mut(); - let hr = (*self.native.get()).GetFontFamily(index, &mut family); - assert!(hr == 0); - FontFamily::take(ComPtr::from_raw(family)) + let family = self.native.GetFontFamily(index).unwrap(); + FontFamily::take(family) } } @@ -136,12 +121,8 @@ impl FontCollection { pub fn get_font_from_face(&self, face: &FontFace) -> Option { unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); - let hr = (*self.native.get()).GetFontFromFontFace(face.as_ptr(), &mut font); - if hr != 0 { - return None; - } - Some(Font::take(ComPtr::from_raw(font))) + let font = self.native.GetFontFromFontFace(&face.native).ok()?; + Some(Font::take(font)) } } @@ -149,21 +130,16 @@ impl FontCollection { 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); + self.native + .FindFamilyName(&HSTRING::from(family_name), &mut index, &mut exists) + .ok()?; if exists == FALSE { return None; } - let mut family: *mut IDWriteFontFamily = ptr::null_mut(); - let hr = (*self.native.get()).GetFontFamily(index, &mut family); - assert!(hr == 0); + let mut family = self.native.GetFontFamily(index).ok()?; - Some(FontFamily::take(ComPtr::from_raw(family))) + Some(FontFamily::take(family)) } } } diff --git a/src/font_collection_impl.rs b/src/font_collection_impl.rs index 56c85d3..cdb7a46 100644 --- a/src/font_collection_impl.rs +++ b/src/font_collection_impl.rs @@ -4,117 +4,107 @@ // 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; -use winapi::um::dwrite::IDWriteFontCollectionLoader; -use winapi::um::dwrite::IDWriteFontCollectionLoaderVtbl; -use winapi::um::dwrite::IDWriteFontFile; -use winapi::um::dwrite::IDWriteFontFileEnumerator; -use winapi::um::dwrite::IDWriteFontFileEnumeratorVtbl; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winnt::HRESULT; -use wio::com::ComPtr; - -use crate::com_helpers::Com; +use std::{ffi::c_void, mem, sync::atomic::AtomicUsize}; +use windows::{ + core::HRESULT, + Win32::{ + Foundation::S_OK, + Graphics::DirectWrite::{ + IDWriteFactory, IDWriteFontCollectionLoader, IDWriteFontCollectionLoader_Vtbl, + IDWriteFontFile, IDWriteFontFileEnumerator, + }, + }, +}; + use crate::FontFile; -static FONT_COLLECTION_LOADER_VTBL: IDWriteFontCollectionLoaderVtbl = - IDWriteFontCollectionLoaderVtbl { - parent: implement_iunknown!(static IDWriteFontCollectionLoader, - CustomFontCollectionLoaderImpl), - CreateEnumeratorFromKey: CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey, - }; +// static FONT_COLLECTION_LOADER_VTBL: IDWriteFontCollectionLoader_Vtbl = +// IDWriteFontCollectionLoader_Vtbl { +// parent: implement_iunknown!(static IDWriteFontCollectionLoader, +// CustomFontCollectionLoaderImpl), +// CreateEnumeratorFromKey: CustomFontCollectionLoaderImpl_CreateEnumeratorFromKey, +// }; #[repr(C)] pub struct CustomFontCollectionLoaderImpl { // NB: This must be the first field. _refcount: AtomicUsize, - font_files: Vec>, + 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 Com for CustomFontCollectionLoaderImpl { +// type Vtbl = IDWriteFontCollectionLoader_Vtbl; +// #[inline] +// fn vtbl() -> &'static IDWriteFontCollectionLoader_Vtbl { +// &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::from_raw( - CustomFontCollectionLoaderImpl { - _refcount: AtomicUsize::new(1), - font_files: font_files.iter().map(|file| file.as_com_ptr()).collect(), - } - .into_interface(), - ) + pub fn new(font_files: &[FontFile]) -> CustomFontCollectionLoaderImpl { + CustomFontCollectionLoaderImpl { + _refcount: AtomicUsize::new(1), + font_files: font_files.iter().map(|file| file.native.clone()).collect(), } } } -#[allow(non_snake_case)] -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_raw(enumerator.into_interface()); - *out_enumerator = enumerator.as_raw(); - mem::forget(enumerator); - S_OK -} +// #[allow(non_snake_case)] +// 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 = enumerator.into_interface(); +// *out_enumerator = enumerator.as_raw(); +// mem::forget(enumerator); +// S_OK +// } #[repr(C)] struct CustomFontFileEnumeratorImpl { // NB(pcwalton): This must be the first field. _refcount: AtomicUsize, - font_files: Vec>, + 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, CustomFontFileEnumeratorImpl), - GetCurrentFontFile: CustomFontFileEnumeratorImpl_GetCurrentFontFile, - MoveNext: CustomFontFileEnumeratorImpl_MoveNext, -}; +// impl Com for CustomFontFileEnumeratorImpl { +// type Vtbl = IDWriteFontFileEnumerator_Vtbl; +// #[inline] +// fn vtbl() -> &'static IDWriteFontFileEnumerator_Vtbl { +// &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: IDWriteFontFileEnumerator_Vtbl = IDWriteFontFileEnumerator_Vtbl { +// parent: implement_iunknown!(static IDWriteFontFileEnumerator, CustomFontFileEnumeratorImpl), +// GetCurrentFontFile: CustomFontFileEnumeratorImpl_GetCurrentFontFile, +// MoveNext: CustomFontFileEnumeratorImpl_MoveNext, +// }; impl CustomFontFileEnumeratorImpl { - pub fn new(font_files: Vec>) -> CustomFontFileEnumeratorImpl { + pub fn new(font_files: Vec) -> CustomFontFileEnumeratorImpl { CustomFontFileEnumeratorImpl { _refcount: AtomicUsize::new(1), font_files, @@ -123,35 +113,35 @@ impl CustomFontFileEnumeratorImpl { } } -#[allow(non_snake_case)] -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_raw(); - mem::forget(new_font_file); - S_OK -} - -#[allow(non_snake_case)] -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 -} +// #[allow(non_snake_case)] +// 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_raw(); +// mem::forget(new_font_file); +// S_OK +// } + +// #[allow(non_snake_case)] +// 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/src/font_face.rs b/src/font_face.rs index 2e3d149..e728f1d 100644 --- a/src/font_face.rs +++ b/src/font_face.rs @@ -2,73 +2,79 @@ * 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::ffi::c_void; use std::mem::{self, zeroed}; use std::ptr; use std::slice; -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::IDWriteRenderingParams; -use winapi::um::dwrite::DWRITE_FONT_FACE_TYPE_TRUETYPE; -use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile}; -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_COLLECTION, DWRITE_FONT_FACE_TYPE_VECTOR}; -use winapi::um::dwrite::{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_1::IDWriteFontFace1; -use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE}; -use winapi::Interface; -use wio::com::ComPtr; - -use super::{DWriteFactory, DefaultDWriteRenderParams, FontFile, FontMetrics}; -use crate::com_helpers::Com; -use crate::geometry_sink_impl::GeometrySinkImpl; +use windows::core::Interface; +use windows::Win32::Foundation::{BOOL, FALSE, TRUE}; +use windows::Win32::Graphics::DirectWrite::IDWriteRenderingParams; +use windows::Win32::Graphics::DirectWrite::DWRITE_FONT_FACE_TYPE_TRUETYPE; +use windows::Win32::Graphics::DirectWrite::DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, DWRITE_FACTORY_TYPE_SHARED, DWRITE_FONT_SIMULATIONS_NONE, + DWRITE_MEASURING_MODE, +}; +use windows::Win32::Graphics::DirectWrite::{IDWriteFontFace, IDWriteFontFile}; +use windows::Win32::Graphics::DirectWrite::{ + IDWriteFontFace1, IDWriteFontFace5, DWRITE_FONT_AXIS_VALUE, +}; +use windows::Win32::Graphics::DirectWrite::{ + DWRITE_FONT_FACE_TYPE_BITMAP, DWRITE_FONT_FACE_TYPE_CFF, +}; +use windows::Win32::Graphics::DirectWrite::{ + DWRITE_FONT_FACE_TYPE_RAW_CFF, DWRITE_FONT_FACE_TYPE_TYPE1, +}; +use windows::Win32::Graphics::DirectWrite::{ + DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, DWRITE_FONT_FACE_TYPE_VECTOR, +}; +use windows::Win32::Graphics::DirectWrite::{DWRITE_FONT_SIMULATIONS, DWRITE_GLYPH_METRICS}; +use windows::Win32::Graphics::DirectWrite::{ + DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MODE, +}; + +use super::{FontFile, FontMetrics}; +// use crate::geometry_sink_impl::GeometrySinkImpl; use crate::outline_builder::OutlineBuilder; pub struct FontFace { - native: UnsafeCell>, - face1: UnsafeCell>>, - face5: UnsafeCell>>, + pub(crate) native: IDWriteFontFace, + face1: Option, + face5: Option, } impl FontFace { - pub fn take(native: ComPtr) -> FontFace { - let cell = UnsafeCell::new(native); + pub fn take(native: IDWriteFontFace) -> FontFace { + let cell = native; FontFace { native: cell, - face1: UnsafeCell::new(None), - face5: UnsafeCell::new(None), + face1: None, + face5: None, } } - pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFace { - (*self.native.get()).as_raw() - } - - 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); + fn get_raw_files(&self) -> Vec> { + unsafe { + let mut number_of_files: u32 = 0; + self.native.GetFiles(&mut number_of_files, None).unwrap(); + if number_of_files == 0 { + return vec![]; + } - 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 + let mut files = vec![None; number_of_files as usize]; + self.native + .GetFiles(&mut number_of_files, Some(files.as_mut_ptr())) + .unwrap(); + files + } } pub fn get_files(&self) -> Vec { - unsafe { - let file_ptrs = self.get_raw_files(); - file_ptrs - .iter() - .map(|p| FontFile::take(ComPtr::from_raw(*p))) - .collect() - } + let files = self.get_raw_files(); + files + .into_iter() + .filter_map(|f| f.map(FontFile::take)) + .collect() } pub fn create_font_face_with_simulations( @@ -76,37 +82,33 @@ impl FontFace { simulations: DWRITE_FONT_SIMULATIONS, ) -> FontFace { unsafe { + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); let file_ptrs = self.get_raw_files(); - let face_type = (*self.native.get()).GetType(); - let face_index = (*self.native.get()).GetIndex(); - let mut face: *mut IDWriteFontFace = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateFontFace( - face_type, - file_ptrs.len() as u32, - file_ptrs.as_ptr(), - face_index, - simulations, - &mut face, - ); - for p in file_ptrs { - let _ = ComPtr::::from_raw(p); - } - assert!(hr == 0); - FontFace::take(ComPtr::from_raw(face)) + let face_type = self.native.GetType(); + let face_index = self.native.GetIndex(); + let face = factory + .CreateFontFace( + face_type, + &file_ptrs, + face_index, + DWRITE_FONT_SIMULATIONS_NONE, + ) + .unwrap(); + FontFace::take(face) } } pub fn get_glyph_count(&self) -> u16 { - unsafe { (*self.native.get()).GetGlyphCount() } + unsafe { self.native.GetGlyphCount() } } pub fn metrics(&self) -> FontMetrics { unsafe { - let font_1 = self.get_face1(); + let font_1 = &self.face1; match font_1 { None => { let mut metrics = mem::zeroed(); - (*self.native.get()).GetMetrics(&mut metrics); + self.native.GetMetrics(&mut metrics); FontMetrics::Metrics0(metrics) } Some(font_1) => { @@ -121,12 +123,13 @@ impl FontFace { 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); + self.native + .GetGlyphIndices( + code_points.as_ptr(), + code_points.len() as u32, + glyph_indices.as_mut_ptr(), + ) + .unwrap(); glyph_indices } } @@ -138,13 +141,14 @@ impl FontFace { ) -> 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); + self.native + .GetDesignGlyphMetrics( + glyph_indices.as_ptr(), + glyph_indices.len() as u32, + metrics.as_mut_ptr(), + is_sideways, + ) + .unwrap(); metrics } } @@ -160,17 +164,18 @@ impl FontFace { ) -> 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); + self.native + .GetGdiCompatibleGlyphMetrics( + em_size, + pixels_per_dip, + Some(transform), + use_gdi_natural, + glyph_indices.as_ptr(), + glyph_indices.len() as u32, + metrics.as_mut_ptr(), + is_sideways, + ) + .unwrap(); metrics } } @@ -186,14 +191,15 @@ impl FontFace { 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); + self.native + .TryGetFontTable( + opentype_table_tag, + &mut table_data_ptr as *mut *const _ as *mut *mut c_void, + &mut table_size, + &mut table_context, + &mut exists, + ) + .unwrap(); if exists == FALSE { return None; @@ -201,7 +207,7 @@ impl FontFace { let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec(); - (*self.native.get()).ReleaseFontTable(table_context); + self.native.ReleaseFontTable(table_context); Some(table_bytes) } @@ -212,23 +218,17 @@ impl FontFace { em_size: f32, pixels_per_dip: f32, measure_mode: DWRITE_MEASURING_MODE, - rendering_params: *mut IDWriteRenderingParams, + rendering_params: &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 + self.native + .GetRecommendedRenderingMode( + em_size, + pixels_per_dip, + measure_mode, + rendering_params, + ) + .unwrap_or(DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC) } } @@ -238,12 +238,15 @@ impl FontFace { 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(), - ) + unsafe { + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + self.get_recommended_rendering_mode( + em_size, + pixels_per_dip, + measure_mode, + &factory.CreateRenderingParams().unwrap(), + ) + } } pub fn get_glyph_run_outline( @@ -256,42 +259,43 @@ impl FontFace { 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); - } + todo!(); + // 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 = BOOL::from(is_sideways); + // let is_right_to_left = BOOL::from(is_right_to_left); + // let geometry_sink = GeometrySinkImpl::new(outline_builder); + // self.native + // .GetGlyphRunOutline( + // em_size, + // glyph_indices.as_ptr(), + // Some(glyph_advances), + // Some(glyph_offsets), + // glyph_indices.len() as u32, + // is_sideways, + // is_right_to_left, + // geometry_sink, + // ) + // .unwrap(); + // } } pub fn has_kerning_pairs(&self) -> bool { unsafe { - match self.get_face1() { + match &self.face1 { Some(face1) => face1.HasKerningPairs() == TRUE, None => false, } @@ -300,15 +304,16 @@ impl FontFace { pub fn get_glyph_pair_kerning_adjustment(&self, first_glyph: u16, second_glyph: u16) -> i32 { unsafe { - match self.get_face1() { + match &self.face1 { Some(face1) => { let mut adjustments = [0; 2]; - let hr = face1.GetKerningPairAdjustments( - 2, - [first_glyph, second_glyph].as_ptr(), - adjustments.as_mut_ptr(), - ); - assert_eq!(hr, S_OK); + face1 + .GetKerningPairAdjustments( + 2, + [first_glyph, second_glyph].as_ptr(), + adjustments.as_mut_ptr(), + ) + .unwrap(); adjustments[0] } @@ -320,7 +325,7 @@ impl FontFace { #[inline] pub fn get_type(&self) -> FontFaceType { unsafe { - match (*self.native.get()).GetType() { + match self.native.GetType() { DWRITE_FONT_FACE_TYPE_CFF => FontFaceType::Cff, DWRITE_FONT_FACE_TYPE_RAW_CFF => FontFaceType::RawCff, DWRITE_FONT_FACE_TYPE_TRUETYPE => FontFaceType::TrueType, @@ -335,35 +340,15 @@ impl FontFace { #[inline] pub fn get_index(&self) -> u32 { - unsafe { (*self.native.get()).GetIndex() } - } - - #[inline] - unsafe fn get_face1(&self) -> Option> { - self.get_interface(&self.face1) - } - - #[inline] - unsafe fn get_face5(&self) -> Option> { - self.get_interface(&self.face5) - } - - #[inline] - unsafe fn get_interface( - &self, - interface: &UnsafeCell>>, - ) -> Option> { - if (*interface.get()).is_none() { - *interface.get() = (*self.native.get()).cast().ok() - } - (*interface.get()).clone() + unsafe { self.native.GetIndex() } } pub fn has_variations(&self) -> bool { unsafe { - match self.get_face5() { - Some(face5) => face5.HasVariations() == TRUE, - None => false, + if let Some(face5) = &self.face5 { + face5.HasVariations() == TRUE + } else { + false } } } @@ -374,25 +359,15 @@ impl FontFace { axis_values: &[DWRITE_FONT_AXIS_VALUE], ) -> Option { unsafe { - if let Some(face5) = self.get_face5() { - let mut resource: *mut IDWriteFontResource = ptr::null_mut(); - let hr = face5.GetFontResource(&mut resource); - if hr == S_OK && !resource.is_null() { - let resource = ComPtr::from_raw(resource); - let mut var_face: *mut IDWriteFontFace5 = ptr::null_mut(); - let hr = resource.CreateFontFace( - simulations, - axis_values.as_ptr(), - axis_values.len() as u32, - &mut var_face, - ); - if hr == S_OK && !var_face.is_null() { - let var_face = ComPtr::from_raw(var_face).cast().unwrap(); - return Some(FontFace::take(var_face)); - } - } - } - None + let face5 = &self.face5; + let face5 = match face5 { + None => return None, + Some(face5) => face5, + }; + let resource = face5.GetFontResource().ok()?; + let var_face = resource.CreateFontFace(simulations, &axis_values).ok()?; + let var_face = (var_face).cast().ok()?; + Some(FontFace::take(var_face)) } } } @@ -401,9 +376,9 @@ impl Clone for FontFace { fn clone(&self) -> FontFace { unsafe { FontFace { - native: UnsafeCell::new((*self.native.get()).clone()), - face1: UnsafeCell::new(None), - face5: UnsafeCell::new(None), + native: self.native.clone(), + face1: self.face1.clone(), + face5: self.face5.clone(), } } } diff --git a/src/font_fallback.rs b/src/font_fallback.rs index 1fa1338..c626e2f 100644 --- a/src/font_fallback.rs +++ b/src/font_fallback.rs @@ -2,15 +2,15 @@ * 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 wio::com::ComPtr; +use windows::core::HSTRING; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory2, IDWriteFontFallback, DWRITE_FACTORY_TYPE_SHARED, +}; use super::*; pub struct FontFallback { - native: UnsafeCell>, + native: IDWriteFontFallback, } pub struct FallbackResult { @@ -25,26 +25,14 @@ pub struct FallbackResult { impl FontFallback { pub fn get_system_fallback() -> Option { unsafe { - let factory = ComPtr::from_raw(DWriteFactory()); - let factory2: Option> = factory.cast().ok(); - 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_raw(native))) + let factory: IDWriteFactory2 = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).ok()?; + let native = factory.GetSystemFontFallback().ok()?; + Some(Self::take(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_raw() + pub fn take(native: IDWriteFontFallback) -> FontFallback { + FontFallback { native } } // TODO: map_characters (main function) @@ -54,36 +42,31 @@ impl FontFallback { text_position: u32, text_length: u32, base_font: &FontCollection, - base_family: Option<&str>, + base_family: &str, base_weight: FontWeight, base_style: FontStyle, base_stretch: FontStretch, ) -> FallbackResult { unsafe { - let mut font = null_mut(); + let mut font = None; 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::from_raw(font))) - }; + self.native + .MapCharacters( + &text_analysis_source.native, + text_position, + text_length, + &base_font.native, + &HSTRING::from(base_family), + base_weight.into(), + base_style.into(), + base_stretch.into(), + &mut mapped_length, + &mut font, + &mut scale, + ) + .unwrap(); + let mapped_font = font.map(|f| Font::take(f)); FallbackResult { mapped_length: mapped_length as usize, mapped_font, diff --git a/src/font_family.rs b/src/font_family.rs index 72f13b6..56850a1 100644 --- a/src/font_family.rs +++ b/src/font_family.rs @@ -2,37 +2,24 @@ * 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; -use winapi::um::dwrite::IDWriteLocalizedStrings; -use winapi::um::dwrite::{IDWriteFont, IDWriteFontCollection, IDWriteFontFamily}; -use wio::com::ComPtr; +use windows::Win32::Graphics::DirectWrite::IDWriteFontFamily; use super::*; use helpers::*; pub struct FontFamily { - native: UnsafeCell>, + native: IDWriteFontFamily, } 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_raw() + pub fn take(native: IDWriteFontFamily) -> FontFamily { + FontFamily { native } } pub fn name(&self) -> String { unsafe { - let mut family_names: *mut IDWriteLocalizedStrings = ptr::null_mut(); - let hr = (*self.native.get()).GetFamilyNames(&mut family_names); - assert!(hr == 0); - - get_locale_string(&mut ComPtr::from_raw(family_names)) + let family_names = self.native.GetFamilyNames().unwrap(); + get_locale_string(&family_names) } } @@ -43,37 +30,29 @@ impl FontFamily { style: FontStyle, ) -> Font { unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); - let hr = (*self.native.get()).GetFirstMatchingFont( - weight.t(), - stretch.t(), - style.t(), - &mut font, - ); - assert!(hr == 0); - Font::take(ComPtr::from_raw(font)) + let font = self + .native + .GetFirstMatchingFont(weight.into(), stretch.into(), style.into()) + .unwrap(); + Font::take(font) } } pub fn get_font_collection(&self) -> FontCollection { unsafe { - let mut collection: *mut IDWriteFontCollection = ptr::null_mut(); - let hr = (*self.native.get()).GetFontCollection(&mut collection); - assert!(hr == 0); - FontCollection::take(ComPtr::from_raw(collection)) + let collection = self.native.GetFontCollection().unwrap(); + FontCollection::take(collection) } } pub fn get_font_count(&self) -> u32 { - unsafe { (*self.native.get()).GetFontCount() } + unsafe { self.native.GetFontCount() } } pub fn get_font(&self, index: u32) -> Font { unsafe { - let mut font: *mut IDWriteFont = ptr::null_mut(); - let hr = (*self.native.get()).GetFont(index, &mut font); - assert!(hr == 0); - Font::take(ComPtr::from_raw(font)) + let font = self.native.GetFont(index).unwrap(); + Font::take(font) } } } diff --git a/src/font_file.rs b/src/font_file.rs index b0bbd76..9972cbf 100644 --- a/src/font_file.rs +++ b/src/font_file.rs @@ -2,29 +2,26 @@ * 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::ffi::OsString; -use std::os::windows::ffi::{OsStrExt, OsStringExt}; -use std::path::Path; -use std::path::PathBuf; +use std::ffi::{c_void, OsString}; +use std::os::windows::ffi::OsStringExt; +use std::path::{Path, PathBuf}; use std::ptr; use std::slice; use std::sync::Arc; -use winapi::ctypes::c_void; -use winapi::um::dwrite::{IDWriteFontFace, IDWriteFontFile, IDWriteFontFileStream}; -use winapi::um::dwrite::{IDWriteFontFileLoader, IDWriteLocalFontFileLoader}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE, DWRITE_FONT_FILE_TYPE_UNKNOWN}; -use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_UNKNOWN, DWRITE_FONT_SIMULATIONS}; -use winapi::um::winnt::HRESULT; -use wio::com::ComPtr; - -use super::DWriteFactory; +use windows::core::{Interface, HSTRING}; +use windows::Win32::Foundation::FALSE; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteFontFile, IDWriteFontFileStream, + IDWriteLocalFontFileLoader, DWRITE_FACTORY_TYPE_SHARED, DWRITE_FONT_FACE_TYPE, + DWRITE_FONT_FACE_TYPE_UNKNOWN, DWRITE_FONT_FILE_TYPE_UNKNOWN, DWRITE_FONT_SIMULATIONS, +}; + use crate::font_face::FontFace; use crate::font_file_loader_impl::DataFontHelper; pub struct FontFile { - native: UnsafeCell>, - stream: UnsafeCell>>, + pub(crate) native: IDWriteFontFile, + stream: Option, data_key: usize, face_type: DWRITE_FONT_FACE_TYPE, } @@ -35,22 +32,14 @@ impl FontFile { P: AsRef, { unsafe { - let mut path: Vec = path.as_ref().as_os_str().encode_wide().collect(); - path.push(0); - - let mut font_file: *mut IDWriteFontFile = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateFontFileReference( - path.as_ptr(), - ptr::null(), - &mut font_file, - ); - if hr != 0 || font_file.is_null() { - return None; - } + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).ok()?; + let font_file = factory + .CreateFontFileReference(&HSTRING::from(path.as_ref()), None) + .ok()?; let mut ff = FontFile { - native: UnsafeCell::new(ComPtr::from_raw(font_file)), - stream: UnsafeCell::new(None), + native: font_file, + stream: None, data_key: 0, face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, }; @@ -63,17 +52,12 @@ impl FontFile { } } - #[deprecated(since = "0.11.2", note = "please use `new_from_buffer` instead")] - pub fn new_from_data(data: Arc>) -> Option { - Self::new_from_buffer(data) - } - pub fn new_from_buffer(data: Arc + Sync + Send>) -> Option { let (font_file, font_file_stream, key) = DataFontHelper::register_font_buffer(data); let mut ff = FontFile { - native: UnsafeCell::new(font_file), - stream: UnsafeCell::new(Some(font_file_stream)), + native: font_file, + stream: Some(font_file_stream), data_key: key, face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, }; @@ -85,17 +69,12 @@ impl FontFile { } } - #[deprecated(since = "0.11.2", note = "please use `analyze_buffer` instead")] - pub fn analyze_data(data: Arc>) -> u32 { - Self::analyze_buffer(data) - } - pub fn analyze_buffer(buffer: Arc + Sync + Send>) -> u32 { let (font_file, font_file_stream, key) = DataFontHelper::register_font_buffer(buffer); let mut ff = FontFile { - native: UnsafeCell::new(font_file), - stream: UnsafeCell::new(Some(font_file_stream)), + native: font_file, + stream: Some(font_file_stream), data_key: key, face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, }; @@ -107,16 +86,19 @@ impl FontFile { let mut face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN; let mut num_faces = 0; unsafe { - let mut supported = 0; + let mut supported = FALSE; let mut _file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN; - let hr = (*self.native.get()).Analyze( + if let Ok(_) = self.native.Analyze( &mut supported, &mut _file_type, - &mut face_type, + Some(&mut face_type), &mut num_faces, - ); - if hr != 0 || supported == 0 { + ) { + if supported == FALSE { + return 0; + } + } else { return 0; } } @@ -124,10 +106,10 @@ impl FontFile { num_faces } - pub fn take(native: ComPtr) -> FontFile { + pub fn take(native: IDWriteFontFile) -> FontFile { let mut ff = FontFile { - native: UnsafeCell::new(native), - stream: UnsafeCell::new(None), + native, + stream: None, data_key: 0, face_type: DWRITE_FONT_FACE_TYPE_UNKNOWN, }; @@ -143,39 +125,28 @@ impl FontFile { } } - 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: *mut c_void = ptr::null_mut(); let mut ref_key_size: u32 = 0; - let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); + self.native + .GetReferenceKey(&mut ref_key, &mut ref_key_size) + .unwrap(); - let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut(); - let hr = (*self.native.get()).GetLoader(&mut loader); - assert!(hr == 0); - let loader = ComPtr::from_raw(loader); + let loader = self.native.GetLoader().unwrap(); - let mut stream: *mut IDWriteFontFileStream = ptr::null_mut(); - let hr = loader.CreateStreamFromKey(ref_key, ref_key_size, &mut stream); - assert!(hr == 0); - let stream = ComPtr::from_raw(stream); + let stream = loader.CreateStreamFromKey(ref_key, ref_key_size).unwrap(); - let mut file_size: u64 = 0; - let hr = stream.GetFileSize(&mut file_size); - assert!(hr == 0); + let file_size = stream.GetFileSize().unwrap(); - let mut fragment_start: *const c_void = ptr::null(); + let mut fragment_start: *mut c_void = ptr::null_mut(); 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); + stream + .ReadFileFragment(&mut fragment_start, 0, file_size, &mut fragment_context) + .unwrap(); let in_ptr = slice::from_raw_parts(fragment_start as *const u8, file_size as usize); let bytes = in_ptr.to_vec(); @@ -190,34 +161,27 @@ impl FontFile { // 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: *mut c_void = ptr::null_mut(); let mut ref_key_size: u32 = 0; - let hr = (*self.native.get()).GetReferenceKey(&mut ref_key, &mut ref_key_size); - assert!(hr == 0); + self.native + .GetReferenceKey(&mut ref_key, &mut ref_key_size) + .ok()?; - let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut(); - let hr = (*self.native.get()).GetLoader(&mut loader); - assert!(hr == 0); - let loader = ComPtr::from_raw(loader); + let loader = self.native.GetLoader().ok()?; - let local_loader: ComPtr = match loader.cast() { + let local_loader = match loader.cast::() { Ok(local_loader) => local_loader, Err(_) => 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 file_path_len = local_loader + .GetFilePathLengthFromKey(ref_key, ref_key_size) + .ok()?; 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); + local_loader + .GetFilePathFromKey(ref_key, ref_key_size, &mut file_path_buf) + .ok()?; if let Some(&0) = file_path_buf.last() { file_path_buf.pop(); @@ -231,36 +195,27 @@ impl FontFile { &self, face_index: u32, simulations: DWRITE_FONT_SIMULATIONS, - ) -> Result { + ) -> windows::core::Result { unsafe { - let mut face: *mut IDWriteFontFace = ptr::null_mut(); - let ptr = self.as_com_ptr(); - let hr = (*DWriteFactory()).CreateFontFace( + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)?; + let face = factory.CreateFontFace( self.face_type, - 1, - &ptr.as_raw(), + &[Some(self.native.clone())], face_index, simulations, - &mut face, - ); - if hr != 0 { - Err(hr) - } else { - Ok(FontFace::take(ComPtr::from_raw(face))) - } + )?; + 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, - } + FontFile { + native: self.native.clone(), + stream: self.stream.clone(), + data_key: self.data_key, + face_type: self.face_type, } } } diff --git a/src/font_file_loader_impl.rs b/src/font_file_loader_impl.rs index 8887830..e85cdd3 100644 --- a/src/font_file_loader_impl.rs +++ b/src/font_file_loader_impl.rs @@ -2,139 +2,45 @@ use std::collections::HashMap; use std::marker::Send; +use std::mem; use std::sync::atomic::AtomicUsize; use std::sync::{atomic, Arc, Mutex}; -use std::{mem, ptr}; -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 wio::com::ComPtr; - -use super::DWriteFactory; -use crate::com_helpers::*; +use windows::core::Interface; +use windows::Win32::Foundation::E_INVALIDARG; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteFontFile, IDWriteFontFileLoader, IDWriteFontFileLoader_Impl, + IDWriteFontFileStream, IDWriteFontFileStream_Impl, DWRITE_FACTORY_TYPE_SHARED, +}; +#[windows::core::implement(IDWriteFontFileLoader)] struct FontFileLoader; -const FontFileLoaderVtbl: &IDWriteFontFileLoaderVtbl = &IDWriteFontFileLoaderVtbl { - parent: implement_iunknown!(static IDWriteFontFileLoader, 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 +impl IDWriteFontFileLoader_Impl for FontFileLoader_Impl { + fn CreateStreamFromKey( + &self, + fontfilereferencekey: *const core::ffi::c_void, + fontfilereferencekeysize: u32, + ) -> windows_core::Result { + if fontfilereferencekey.is_null() { + return Err(E_INVALIDARG.into()); } - CreateStreamFromKey - }, -}; + assert!(fontfilereferencekeysize == mem::size_of::() as u32); -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 + let key = unsafe { *(fontfilereferencekey as *const usize) }; + match FONT_FILE_STREAM_MAP.lock().unwrap().get(&key) { + None => Err(E_INVALIDARG.into()), + Some(&FontFileStreamPtr(ref file_stream)) => Ok(file_stream.clone()), + } } } -unsafe impl Send for FontFileLoader {} -unsafe impl Sync for FontFileLoader {} - +#[windows::core::implement(IDWriteFontFileStream)] struct FontFileStream { refcount: atomic::AtomicUsize, key: usize, data: Arc + Sync + Send>, } -const FontFileStreamVtbl: &IDWriteFontFileStreamVtbl = &IDWriteFontFileStreamVtbl { - parent: implement_iunknown!(IDWriteFontFileStream, 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(); - let data = (*this.data).as_ref(); - if (fileOffset + fragmentSize) as usize > data.len() { - return E_INVALIDARG; - } - let index = fileOffset as usize; - *fragmentStart = 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).as_ref().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 + Sync + Send>) -> FontFileStream { FontFileStream { @@ -151,28 +57,32 @@ impl Drop for FontFileStream { } } -impl Com for FontFileStream { - type Vtbl = IDWriteFontFileStreamVtbl; - fn vtbl() -> &'static IDWriteFontFileStreamVtbl { - FontFileStreamVtbl +impl IDWriteFontFileStream_Impl for FontFileStream_Impl { + fn ReadFileFragment(&self,fragmentstart: *mut *mut core::ffi::c_void,fileoffset:u64,fragmentsize:u64,fragmentcontext: *mut *mut core::ffi::c_void) -> windows_core::Result<()> { + todo!() } -} -impl Com for FontFileStream { - type Vtbl = IUnknownVtbl; - fn vtbl() -> &'static IUnknownVtbl { - &FontFileStreamVtbl.parent + fn ReleaseFileFragment(&self,fragmentcontext: *mut core::ffi::c_void) { + todo!() + } + + fn GetFileSize(&self) -> windows_core::Result { + todo!() + } + + fn GetLastWriteTime(&self) -> windows_core::Result { + todo!() } } -struct FontFileStreamPtr(*mut IDWriteFontFileStream); +struct FontFileStreamPtr(IDWriteFontFileStream); unsafe impl Send for FontFileStreamPtr {} static mut FONT_FILE_KEY: atomic::AtomicUsize = AtomicUsize::new(0); #[derive(Clone)] -struct FontFileLoaderWrapper(ComPtr); +struct FontFileLoaderWrapper(IDWriteFontFileLoader); unsafe impl Send for FontFileLoaderWrapper {} unsafe impl Sync for FontFileLoaderWrapper {} @@ -182,10 +92,10 @@ lazy_static! { Mutex::new(HashMap::new()); static ref FONT_FILE_LOADER: Mutex = { unsafe { - let ffl_native = FontFileLoader::new(); - let ffl = ComPtr::::from_raw(ffl_native.into_interface()); - let hr = (*DWriteFactory()).RegisterFontFileLoader(ffl.as_raw()); - assert!(hr == 0); + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let ffl = FontFileLoader {}; + let ffl: IDWriteFontFileLoader = ffl.cast().unwrap(); + factory.RegisterFontFileLoader(&ffl).unwrap(); Mutex::new(FontFileLoaderWrapper(ffl)) } }; @@ -196,34 +106,26 @@ pub(crate) struct DataFontHelper; impl DataFontHelper { pub(crate) fn register_font_buffer( font_data: Arc + Sync + Send>, - ) -> ( - ComPtr, - ComPtr, - usize, - ) { + ) -> (IDWriteFontFile, IDWriteFontFileStream, 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::from_raw(font_file_stream_native.into_interface()); + let font_file_stream = FontFileStream::new(key, font_data); + let font_file_stream: IDWriteFontFileStream = font_file_stream.cast().unwrap(); { let mut map = FONT_FILE_STREAM_MAP.lock().unwrap(); - map.insert(key, FontFileStreamPtr(font_file_stream.as_raw())); + map.insert(key, FontFileStreamPtr(font_file_stream.clone())); } - let mut font_file: *mut IDWriteFontFile = ptr::null_mut(); - { - let loader = FONT_FILE_LOADER.lock().unwrap(); - let hr = (*DWriteFactory()).CreateCustomFontFileReference( + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let loader = FONT_FILE_LOADER.lock().unwrap(); + let font_file = factory + .CreateCustomFontFileReference( mem::transmute(&key), - mem::size_of::() as UINT32, - loader.0.as_raw(), - &mut font_file, - ); - assert!(hr == S_OK); - } - let font_file = ComPtr::from_raw(font_file); + mem::size_of::() as u32, + &loader.0, + ) + .unwrap(); (font_file, font_file_stream, key) } diff --git a/src/gdi_interop.rs b/src/gdi_interop.rs index fcf2794..3851567 100644 --- a/src/gdi_interop.rs +++ b/src/gdi_interop.rs @@ -2,45 +2,38 @@ * 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; -use winapi::um::dwrite::IDWriteBitmapRenderTarget; -use winapi::um::dwrite::IDWriteGdiInterop; -use wio::com::ComPtr; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteGdiInterop, DWRITE_FACTORY_TYPE_SHARED, +}; +use windows::Win32::Graphics::Gdi::HDC; -use super::{BitmapRenderTarget, DWriteFactory}; +use super::BitmapRenderTarget; pub struct GdiInterop { - native: UnsafeCell>, + native: IDWriteGdiInterop, } impl GdiInterop { pub fn create() -> GdiInterop { unsafe { - let mut native: *mut IDWriteGdiInterop = ptr::null_mut(); - let hr = (*DWriteFactory()).GetGdiInterop(&mut native); - assert!(hr == 0); - GdiInterop::take(ComPtr::from_raw(native)) + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let native = factory.GetGdiInterop().unwrap(); + GdiInterop::take(native) } } - pub fn take(native: ComPtr) -> GdiInterop { - GdiInterop { - native: UnsafeCell::new(native), - } + pub fn take(native: IDWriteGdiInterop) -> GdiInterop { + GdiInterop { native } } pub fn create_bitmap_render_target(&self, width: u32, height: u32) -> BitmapRenderTarget { unsafe { - let mut native: *mut IDWriteBitmapRenderTarget = ptr::null_mut(); - let hr = (*self.native.get()).CreateBitmapRenderTarget( - ptr::null_mut(), - width, - height, - &mut native, - ); - assert!(hr == 0); - BitmapRenderTarget::take(ComPtr::from_raw(native)) + let native = self + .native + .CreateBitmapRenderTarget(HDC(ptr::null_mut()), width, height) + .unwrap(); + BitmapRenderTarget::take(native) } } } diff --git a/src/geometry_sink_impl.rs b/src/geometry_sink_impl.rs index eae7e12..f0bdf70 100644 --- a/src/geometry_sink_impl.rs +++ b/src/geometry_sink_impl.rs @@ -6,16 +6,16 @@ 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::{ID2D1SimplifiedGeometrySink, ID2D1SimplifiedGeometrySinkVtbl}; -use winapi::um::d2d1::{D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END}; -use winapi::um::d2d1::{D2D1_FIGURE_END_CLOSED, D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D1_POINT_2F}; +use windows::Win32::Graphics::Direct2D::Common::{ID2D1SimplifiedGeometrySink, ID2D1SimplifiedGeometrySink_Vtbl}; +use windows::Win32::Graphics::Direct2D::Common::{D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END}; +use windows::Win32::Graphics::Direct2D::Common::{D2D1_FIGURE_END_CLOSED, D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D_POINT_2F}; use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; use winapi::um::winnt::HRESULT; use crate::com_helpers::Com; use crate::outline_builder::OutlineBuilder; -static GEOMETRY_SINK_VTBL: ID2D1SimplifiedGeometrySinkVtbl = ID2D1SimplifiedGeometrySinkVtbl { +static GEOMETRY_SINK_VTBL: ID2D1SimplifiedGeometrySink_Vtbl = ID2D1SimplifiedGeometrySink_Vtbl { parent: implement_iunknown!(static ID2D1SimplifiedGeometrySink, GeometrySinkImpl), BeginFigure: GeometrySinkImpl_BeginFigure, EndFigure: GeometrySinkImpl_EndFigure, @@ -34,9 +34,9 @@ pub struct GeometrySinkImpl { } impl Com for GeometrySinkImpl { - type Vtbl = ID2D1SimplifiedGeometrySinkVtbl; + type Vtbl = ID2D1SimplifiedGeometrySink_Vtbl; #[inline] - fn vtbl() -> &'static ID2D1SimplifiedGeometrySinkVtbl { + fn vtbl() -> &'static ID2D1SimplifiedGeometrySink_Vtbl { &GEOMETRY_SINK_VTBL } } @@ -45,7 +45,7 @@ impl Com for GeometrySinkImpl { type Vtbl = IUnknownVtbl; #[inline] fn vtbl() -> &'static IUnknownVtbl { - &GEOMETRY_SINK_VTBL.parent + &GEOMETRY_SINK_VTBL.base__ } } @@ -58,11 +58,7 @@ impl GeometrySinkImpl { } } -unsafe extern "system" fn GeometrySinkImpl_BeginFigure( - this: *mut ID2D1SimplifiedGeometrySink, - start_point: D2D1_POINT_2F, - _: D2D1_FIGURE_BEGIN, -) { +unsafe extern "system" fn GeometrySinkImpl_BeginFigure(*mut c_void this, D2D_POINT_2F, D2D1_FIGURE_BEGIN) { let this = GeometrySinkImpl::from_interface(this); this .outline_builder @@ -81,7 +77,7 @@ unsafe extern "system" fn GeometrySinkImpl_EndFigure( unsafe extern "system" fn GeometrySinkImpl_AddLines( this: *mut ID2D1SimplifiedGeometrySink, - points: *const D2D1_POINT_2F, + points: *const D2D_POINT_2F, points_count: UINT, ) { let this = GeometrySinkImpl::from_interface(this); diff --git a/src/glyph_run_analysis.rs b/src/glyph_run_analysis.rs index 5224c60..5403de4 100644 --- a/src/glyph_run_analysis.rs +++ b/src/glyph_run_analysis.rs @@ -2,22 +2,15 @@ * 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::mem; -use std::ptr; -use winapi::shared::windef::RECT; -use winapi::um::dcommon::DWRITE_MEASURING_MODE; -use winapi::um::dwrite::DWRITE_TEXTURE_CLEARTYPE_3x1; -use winapi::um::dwrite::IDWriteGlyphRunAnalysis; -use winapi::um::dwrite::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_GLYPH_RUN, DWRITE_TEXTURE_TYPE}; -use winapi::um::dwrite::{DWRITE_MATRIX, DWRITE_RENDERING_MODE}; -use winapi::um::winnt::HRESULT; -use wio::com::ComPtr; - -use super::DWriteFactory; +use windows::Win32::Foundation::RECT; +use windows::Win32::Graphics::DirectWrite::{ + DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1, DWriteCreateFactory, IDWriteFactory, + IDWriteGlyphRunAnalysis, DWRITE_FACTORY_TYPE_SHARED, DWRITE_GLYPH_RUN, DWRITE_MATRIX, + DWRITE_MEASURING_MODE, DWRITE_RENDERING_MODE, DWRITE_TEXTURE_TYPE, +}; pub struct GlyphRunAnalysis { - native: UnsafeCell>, + native: IDWriteGlyphRunAnalysis, } impl GlyphRunAnalysis { @@ -29,50 +22,33 @@ impl GlyphRunAnalysis { measuring_mode: DWRITE_MEASURING_MODE, baseline_x: f32, baseline_y: f32, - ) -> Result { + ) -> windows::core::Result { unsafe { - let mut native: *mut IDWriteGlyphRunAnalysis = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateGlyphRunAnalysis( + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)?; + let native = factory.CreateGlyphRunAnalysis( glyph_run as *const DWRITE_GLYPH_RUN, pixels_per_dip, - transform - .as_ref() - .map(|x| x as *const _) - .unwrap_or(ptr::null()), + transform.map(|t| &t as *const DWRITE_MATRIX), rendering_mode, measuring_mode, baseline_x, baseline_y, - &mut native, - ); - if hr != 0 { - Err(hr) - } else { - Ok(GlyphRunAnalysis::take(ComPtr::from_raw(native))) - } + )?; + Ok(GlyphRunAnalysis::take(native)) } } - pub fn take(native: ComPtr) -> GlyphRunAnalysis { - GlyphRunAnalysis { - native: UnsafeCell::new(native), - } + pub fn take(native: IDWriteGlyphRunAnalysis) -> GlyphRunAnalysis { + GlyphRunAnalysis { native } } pub fn get_alpha_texture_bounds( &self, texture_type: DWRITE_TEXTURE_TYPE, - ) -> Result { + ) -> windows::core::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) - } + let rect = self.native.GetAlphaTextureBounds(texture_type)?; + Ok(rect) } } @@ -80,7 +56,7 @@ impl GlyphRunAnalysis { &self, texture_type: DWRITE_TEXTURE_TYPE, rect: RECT, - ) -> Result, HRESULT> { + ) -> windows::core::Result> { unsafe { let rect_pixels = (rect.right - rect.left) * (rect.bottom - rect.top); let rect_bytes = rect_pixels @@ -91,17 +67,9 @@ impl GlyphRunAnalysis { }; 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) - } + self.native + .CreateAlphaTexture(texture_type, &rect, &mut out_bytes)?; + Ok(out_bytes) } } } diff --git a/src/helpers.rs b/src/helpers.rs index 45bf005..aeddcfd 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -4,45 +4,47 @@ use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; -use winapi::ctypes::wchar_t; -use winapi::shared::minwindef::{BOOL, FALSE}; -use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::IDWriteLocalizedStrings; -use winapi::um::winnls::GetUserDefaultLocaleName; -use wio::com::ComPtr; +use windows::core::HSTRING; +use windows::Win32::Foundation::{BOOL, FALSE}; +use windows::Win32::Globalization::GetUserDefaultLocaleName; +use windows::Win32::Graphics::DirectWrite::IDWriteLocalizedStrings; lazy_static! { - static ref SYSTEM_LOCALE: Vec = { + static ref EN_US_LOCALE: HSTRING = HSTRING::from("en-us"); + static ref SYSTEM_LOCALE: HSTRING = { unsafe { - let mut locale: Vec = vec![0; 85]; - GetUserDefaultLocaleName(locale.as_mut_ptr(), locale.len() as i32 - 1); - locale + let mut locale: Vec = vec![0; 85]; + let len = GetUserDefaultLocaleName(&mut locale); + if len <= 1 { // 0 is failure, 1 is empty string + EN_US_LOCALE.clone() + } else { + HSTRING::from_wide(&locale).unwrap_or(EN_US_LOCALE.clone()) + } } }; - static ref EN_US_LOCALE: Vec = OsStr::new("en-us").to_wide_null(); } -pub fn get_locale_string(strings: &mut ComPtr) -> String { +pub fn get_locale_string(strings: &IDWriteLocalizedStrings) -> 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 { + strings + .FindLocaleName::<&HSTRING>(&SYSTEM_LOCALE, &mut index, &mut exists) + .unwrap(); + if exists == FALSE { + strings + .FindLocaleName::<&HSTRING>(&EN_US_LOCALE, &mut index, &mut exists) + .unwrap(); + if exists == FALSE { // Ultimately fall back to first locale on list index = 0; } } + let length = strings.GetStringLength(index).unwrap() as usize; - 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); + let mut name: Vec = vec![0; length + 1]; + strings.GetString(index, &mut name).unwrap(); + name.set_len(length); String::from_utf16(&name).ok().unwrap() } diff --git a/src/lib.rs b/src/lib.rs index 07d73d1..43a4952 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,63 +13,32 @@ extern crate serde_derive; #[macro_use] extern crate lazy_static; extern crate libc; -extern crate winapi; +extern crate windows; include!("types.rs"); -use std::ffi::CString; -use std::ptr; -use winapi::shared::guiddef::REFIID; -use winapi::shared::winerror::S_OK; -use winapi::um::dwrite::IDWriteFactory; -use winapi::um::dwrite::IDWriteRenderingParams; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE; -use winapi::um::dwrite::DWRITE_FACTORY_TYPE_SHARED; -use winapi::um::unknwnbase::IUnknown; -use winapi::um::winnt::LPCSTR; -use winapi::Interface; - -pub use winapi::um::winnt::HRESULT; - 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::shared::windef::RECT; -pub use winapi::um::dcommon::DWRITE_MEASURING_MODE; -pub use winapi::um::dcommon::{ - DWRITE_MEASURING_MODE_GDI_CLASSIC, DWRITE_MEASURING_MODE_GDI_NATURAL, - DWRITE_MEASURING_MODE_NATURAL, -}; -pub use winapi::um::dwrite::DWRITE_FONT_METRICS as FontMetrics0; -pub use winapi::um::dwrite::DWRITE_FONT_SIMULATIONS; -pub use winapi::um::dwrite::DWRITE_GLYPH_OFFSET as GlyphOffset; -pub use winapi::um::dwrite::DWRITE_RENDERING_MODE; -pub use winapi::um::dwrite::DWRITE_TEXTURE_TYPE; -pub use winapi::um::dwrite::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1}; -pub use winapi::um::dwrite::{ - DWRITE_FONT_SIMULATIONS_BOLD, DWRITE_FONT_SIMULATIONS_NONE, DWRITE_FONT_SIMULATIONS_OBLIQUE, -}; -pub use winapi::um::dwrite::{DWRITE_GLYPH_RUN, DWRITE_MATRIX}; -pub use winapi::um::dwrite::{ +pub use windows::Win32::Foundation::RECT; +pub use windows::Win32::Graphics::DirectWrite::{ + DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1, DWRITE_FONT_AXIS_VALUE, + DWRITE_FONT_METRICS as FontMetrics0, DWRITE_FONT_METRICS1 as FontMetrics1, + DWRITE_FONT_SIMULATIONS, DWRITE_FONT_SIMULATIONS_BOLD, DWRITE_FONT_SIMULATIONS_NONE, + DWRITE_FONT_SIMULATIONS_OBLIQUE, DWRITE_GLYPH_OFFSET as GlyphOffset, DWRITE_GLYPH_RUN, + DWRITE_MATRIX, DWRITE_MEASURING_MODE, DWRITE_MEASURING_MODE_GDI_CLASSIC, + DWRITE_MEASURING_MODE_GDI_NATURAL, DWRITE_MEASURING_MODE_NATURAL, DWRITE_RENDERING_MODE, DWRITE_RENDERING_MODE_ALIASED, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, DWRITE_RENDERING_MODE_DEFAULT, 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_OUTLINE, DWRITE_TEXTURE_TYPE, }; -pub use winapi::um::dwrite_1::DWRITE_FONT_METRICS1 as FontMetrics1; -pub use winapi::um::dwrite_3::DWRITE_FONT_AXIS_VALUE; -use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryW}; - -#[macro_use] -mod com_helpers; mod bitmap_render_target; pub use bitmap_render_target::BitmapRenderTarget; @@ -113,55 +82,4 @@ pub use text_analysis_source_impl::{ // This is an internal implementation of `GeometrySink` so that we can // expose `IDWriteGeometrySink` in an idiomatic way. -mod geometry_sink_impl; - -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: *mut IDWriteFactory = ptr::null_mut(); - let hr = dwrite_create_factory( - DWRITE_FACTORY_TYPE_SHARED, - &IDWriteFactory::uuidof(), - &mut factory as *mut *mut IDWriteFactory as *mut *mut IUnknown, - ); - assert!(hr == S_OK); - factory as usize - } - }; - static ref DEFAULT_DWRITE_RENDERING_PARAMS_RAW_PTR: usize = { - unsafe { - let mut default_rendering_params: *mut IDWriteRenderingParams = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateRenderingParams(&mut default_rendering_params); - assert!(hr == S_OK); - default_rendering_params 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 -} +// mod geometry_sink_impl; diff --git a/src/rendering_params.rs b/src/rendering_params.rs index 977c38a..2f31291 100644 --- a/src/rendering_params.rs +++ b/src/rendering_params.rs @@ -2,34 +2,24 @@ * 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; -use winapi::um::dwrite::IDWriteRenderingParams; -use wio::com::ComPtr; - -use super::DWriteFactory; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteRenderingParams, DWRITE_FACTORY_TYPE_SHARED, +}; pub struct RenderingParams { - native: UnsafeCell>, + pub(crate) native: IDWriteRenderingParams, } impl RenderingParams { pub fn create_for_primary_monitor() -> RenderingParams { unsafe { - let mut native: *mut IDWriteRenderingParams = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateRenderingParams(&mut native); - assert!(hr == 0); - RenderingParams::take(ComPtr::from_raw(native)) - } - } - - pub fn take(native: ComPtr) -> RenderingParams { - RenderingParams { - native: UnsafeCell::new(native), + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let native = factory.CreateRenderingParams().unwrap(); + RenderingParams::take(native) } } - pub unsafe fn as_ptr(&self) -> *mut IDWriteRenderingParams { - (*self.native.get()).as_raw() + pub fn take(native: IDWriteRenderingParams) -> RenderingParams { + RenderingParams { native } } } diff --git a/src/test.rs b/src/test.rs index 8810f54..22fcd5e 100644 --- a/src/test.rs +++ b/src/test.rs @@ -10,9 +10,7 @@ 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() - .any(|f| f.name() == "Arial")); + assert!(system_fc.families_iter().any(|f| f.name() == "Arial")); } #[test] @@ -90,11 +88,6 @@ fn test_create_font_file_from_bytes() { let bytes = files[0].get_font_file_bytes(); assert!(!bytes.is_empty()); - // now go back - #[allow(deprecated)] - let new_font = FontFile::new_from_data(Arc::new(bytes.clone())); - assert!(new_font.is_some()); - let new_font = FontFile::new_from_buffer(Arc::new(bytes)); assert!(new_font.is_some()); @@ -119,10 +112,7 @@ fn test_glyph_image() { let device_pixel_ratio = 1.0f32; let em_size = 10.0f32; - let design_units_per_em = match face.metrics() { - FontMetrics::Metrics0(ref metrics) => metrics.designUnitsPerEm, - FontMetrics::Metrics1(ref metrics) => metrics.designUnitsPerEm, - }; + let design_units_per_em = face.metrics().metrics0().designUnitsPerEm; let design_units_per_pixel = design_units_per_em as f32 / 16.; let scaled_design_units_to_pixels = (em_size * device_pixel_ratio) / design_units_per_pixel; @@ -153,7 +143,7 @@ fn test_glyph_image() { rt.draw_glyph_run( x, y, - DWRITE_MEASURING_MODE_NATURAL, + windows::Win32::Graphics::DirectWrite::DWRITE_MEASURING_MODE_GDI_NATURAL, &face, em_size, &[a_index], diff --git a/src/text_analysis_source.rs b/src/text_analysis_source.rs index 7ef7688..34f1bf4 100644 --- a/src/text_analysis_source.rs +++ b/src/text_analysis_source.rs @@ -5,14 +5,15 @@ use std::borrow::Cow; use std::marker::PhantomData; use winapi::ctypes::wchar_t; -use winapi::um::dwrite::IDWriteTextAnalysisSource; -use wio::com::ComPtr; +use windows::core::Interface; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteTextAnalysisSource, DWRITE_FACTORY_TYPE_SHARED, +}; use super::*; -use crate::com_helpers::Com; pub struct TextAnalysisSource<'a> { - native: ComPtr, + pub(crate) native: IDWriteTextAnalysisSource, phantom: PhantomData>, } @@ -26,15 +27,19 @@ impl<'a> TextAnalysisSource<'a> { inner: Box, text: Cow<'a, [wchar_t]>, ) -> TextAnalysisSource<'a> { - let native = unsafe { - ComPtr::from_raw( - CustomTextAnalysisSourceImpl::from_text_native(inner, text).into_interface(), - ) - }; - TextAnalysisSource { - native, - phantom: PhantomData, - } + todo!(); + // unsafe { + // let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + // let analyzer = factory.CreateTextAnalyzer().unwrap(); + + // let native = IDWriteTextAnalysisSource::from_raw( + // CustomTextAnalysisSourceImpl::from_text_native(inner, text) as *mut _, + // ); + // TextAnalysisSource { + // native, + // phantom: PhantomData, + // } + // } } /// Create a new custom TextAnalysisSource for the given text and a trait @@ -47,23 +52,18 @@ impl<'a> TextAnalysisSource<'a> { text: Cow<'a, [wchar_t]>, number_subst: NumberSubstitution, ) -> TextAnalysisSource<'a> { - let native = unsafe { - ComPtr::from_raw( - CustomTextAnalysisSourceImpl::from_text_and_number_subst_native( - inner, - text, - number_subst, - ) - .into_interface(), - ) - }; - TextAnalysisSource { - native, - phantom: PhantomData, - } - } - - pub fn as_ptr(&self) -> *mut IDWriteTextAnalysisSource { - self.native.as_raw() + todo!(); + // let native = unsafe { + // CustomTextAnalysisSourceImpl::from_text_and_number_subst_native( + // inner, + // text, + // number_subst, + // ) + // .into_interface() + // }; + // TextAnalysisSource { + // native, + // phantom: PhantomData, + // } } } diff --git a/src/text_analysis_source_impl.rs b/src/text_analysis_source_impl.rs index c022d17..d18447b 100644 --- a/src/text_analysis_source_impl.rs +++ b/src/text_analysis_source_impl.rs @@ -8,29 +8,15 @@ #![allow(non_snake_case)] use std::borrow::Cow; -use std::ffi::OsStr; -use std::mem; -use std::os::windows::ffi::OsStrExt; -use std::ptr::{self, 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::{FALSE, TRUE, ULONG}; -use winapi::shared::ntdef::LOCALE_NAME_MAX_LENGTH; -use winapi::shared::winerror::{E_INVALIDARG, S_OK}; -use winapi::um::dwrite::IDWriteNumberSubstitution; -use winapi::um::dwrite::IDWriteTextAnalysisSource; -use winapi::um::dwrite::IDWriteTextAnalysisSourceVtbl; -use winapi::um::dwrite::DWRITE_NUMBER_SUBSTITUTION_METHOD; -use winapi::um::dwrite::DWRITE_READING_DIRECTION; -use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; -use winapi::um::winnt::HRESULT; -use wio::com::ComPtr; - -use super::DWriteFactory; -use crate::com_helpers::Com; -use crate::helpers::ToWide; +use windows::core::HSTRING; +use windows::Win32::Foundation::BOOL; +use windows::Win32::Graphics::DirectWrite::{ + DWriteCreateFactory, IDWriteFactory, IDWriteNumberSubstitution, DWRITE_FACTORY_TYPE_SHARED, + DWRITE_NUMBER_SUBSTITUTION_METHOD, DWRITE_READING_DIRECTION, +}; +use windows::Win32::System::SystemServices::LOCALE_NAME_MAX_LENGTH; /// The Rust side of a custom text analysis source implementation. pub trait TextAnalysisSourceMethods { @@ -51,24 +37,24 @@ pub struct CustomTextAnalysisSourceImpl<'a> { inner: Box, text: Cow<'a, [wchar_t]>, number_subst: Option, - locale_buf: [wchar_t; LOCALE_NAME_MAX_LENGTH], + locale_buf: [wchar_t; LOCALE_NAME_MAX_LENGTH as usize], } /// A wrapped version of an `IDWriteNumberSubstitution` object. pub struct NumberSubstitution { - native: ComPtr, + native: IDWriteNumberSubstitution, } // TODO: implement Clone, for convenience and efficiency? -static TEXT_ANALYSIS_SOURCE_VTBL: IDWriteTextAnalysisSourceVtbl = IDWriteTextAnalysisSourceVtbl { - parent: implement_iunknown!(static IDWriteTextAnalysisSource, CustomTextAnalysisSourceImpl), - GetLocaleName: CustomTextAnalysisSourceImpl_GetLocaleName, - GetNumberSubstitution: CustomTextAnalysisSourceImpl_GetNumberSubstitution, - GetParagraphReadingDirection: CustomTextAnalysisSourceImpl_GetParagraphReadingDirection, - GetTextAtPosition: CustomTextAnalysisSourceImpl_GetTextAtPosition, - GetTextBeforePosition: CustomTextAnalysisSourceImpl_GetTextBeforePosition, -}; +// static TEXT_ANALYSIS_SOURCE_VTBL: IDWriteTextAnalysisSourceVtbl = IDWriteTextAnalysisSourceVtbl { +// parent: implement_iunknown!(static IDWriteTextAnalysisSource, CustomTextAnalysisSourceImpl), +// GetLocaleName: CustomTextAnalysisSourceImpl_GetLocaleName, +// GetNumberSubstitution: CustomTextAnalysisSourceImpl_GetNumberSubstitution, +// GetParagraphReadingDirection: CustomTextAnalysisSourceImpl_GetParagraphReadingDirection, +// GetTextAtPosition: CustomTextAnalysisSourceImpl_GetTextAtPosition, +// GetTextBeforePosition: CustomTextAnalysisSourceImpl_GetTextBeforePosition, +// }; impl<'a> CustomTextAnalysisSourceImpl<'a> { /// Create a new custom TextAnalysisSource for the given text and a trait @@ -86,7 +72,7 @@ impl<'a> CustomTextAnalysisSourceImpl<'a> { inner, text, number_subst: None, - locale_buf: [0u16; LOCALE_NAME_MAX_LENGTH], + locale_buf: [0u16; LOCALE_NAME_MAX_LENGTH as usize], } } @@ -106,120 +92,120 @@ impl<'a> CustomTextAnalysisSourceImpl<'a> { inner, text, number_subst: Some(number_subst), - locale_buf: [0u16; LOCALE_NAME_MAX_LENGTH], - } - } -} - -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); - - // Copy the locale data into the buffer - for (i, c) in OsStr::new(&*locale) - .encode_wide() - .chain(Some(0)) - .enumerate() - { - // -1 here is deliberate: it ensures that we never write to the last character in - // this.locale_buf, so that the buffer is always null-terminated. - if i >= this.locale_buf.len() - 1 { - break; + locale_buf: [0u16; LOCALE_NAME_MAX_LENGTH as usize], } - - *this.locale_buf.get_unchecked_mut(i) = c; } - - *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; - } - - *text_length = (this.text.len() as UINT32) - text_position; - *number_substitution = match &this.number_subst { - Some(number_subst) => { - let com_ptr = &number_subst.native; - com_ptr.AddRef(); - com_ptr.as_raw() - } - None => std::ptr::null_mut(), - }; - - 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 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); + +// // Copy the locale data into the buffer +// for (i, c) in OsStr::new(&*locale) +// .encode_wide() +// .chain(Some(0)) +// .enumerate() +// { +// // -1 here is deliberate: it ensures that we never write to the last character in +// // this.locale_buf, so that the buffer is always null-terminated. +// if i >= this.locale_buf.len() - 1 { +// break; +// } + +// *this.locale_buf.get_unchecked_mut(i) = c; +// } + +// *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; +// } + +// *text_length = (this.text.len() as UINT32) - text_position; +// *number_substitution = match &this.number_subst { +// Some(number_subst) => { +// let com_ptr = &number_subst.native; +// com_ptr.AddRef(); +// com_ptr.as_raw() +// } +// None => std::ptr::null_mut(), +// }; + +// 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( @@ -228,17 +214,15 @@ impl NumberSubstitution { ignore_user_overrides: bool, ) -> NumberSubstitution { unsafe { - let mut native: *mut IDWriteNumberSubstitution = ptr::null_mut(); - let hr = (*DWriteFactory()).CreateNumberSubstitution( - subst_method, - locale.to_wide_null().as_ptr(), - if ignore_user_overrides { TRUE } else { FALSE }, - &mut native, - ); - assert_eq!(hr, 0, "error creating number substitution"); - NumberSubstitution { - native: ComPtr::from_raw(native), - } + let factory: IDWriteFactory = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).unwrap(); + let mut native = factory + .CreateNumberSubstitution( + subst_method, + &HSTRING::from(locale), + BOOL::from(ignore_user_overrides), + ) + .unwrap(); + NumberSubstitution { native } } } } diff --git a/src/types.rs b/src/types.rs index 6429fdc..a637f20 100644 --- a/src/types.rs +++ b/src/types.rs @@ -4,7 +4,8 @@ /* this is include!()'d in lib.rs */ use std::mem; -use winapi::um::dwrite::{DWRITE_FONT_STYLE, DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH}; +use std::convert::TryInto; +use windows::Win32::Graphics::DirectWrite::{DWRITE_FONT_STYLE, DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH}; // mirrors DWRITE_FONT_WEIGHT #[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))] @@ -25,9 +26,6 @@ pub enum FontWeight { } 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, @@ -46,19 +44,29 @@ impl FontWeight { } 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) - } + 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) + } + } +} +impl From for FontWeight { + fn from(v: DWRITE_FONT_WEIGHT) -> FontWeight { + FontWeight::from_u32(v.0.try_into().unwrap()) + } +} +impl Into for FontWeight { + fn into(self) -> DWRITE_FONT_WEIGHT { + DWRITE_FONT_WEIGHT(self.to_u32().try_into().unwrap()) } } @@ -80,12 +88,19 @@ pub enum FontStretch { } 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) } } } +impl From for FontStretch { + fn from(v: DWRITE_FONT_STRETCH) -> FontStretch { + FontStretch::from_u32(v.0.try_into().unwrap()) + } +} +impl Into for FontStretch { + fn into(self) -> DWRITE_FONT_STRETCH { + DWRITE_FONT_STRETCH(self.to_u32().try_into().unwrap()) + } +} // mirrors DWRITE_FONT_STYLE #[repr(u32)] @@ -98,22 +113,49 @@ pub enum FontStyle { } 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) } } } +impl From for FontStyle { + fn from(v: DWRITE_FONT_STYLE) -> FontStyle { + FontStyle::from_u32(v.0.try_into().unwrap()) + } +} +impl Into for FontStyle { + fn into(self) -> DWRITE_FONT_STYLE { + DWRITE_FONT_STYLE(self.to_u32().try_into().unwrap()) + } +} // 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, + None = 0b00, + Bold = 0b01, + Oblique = 0b10, + BoldOblique = 0b11, +} +impl From for FontSimulations { + fn from(v: DWRITE_FONT_SIMULATIONS) -> FontSimulations { + match v.0 { + 0b00 => FontSimulations::None, + 0b01 => FontSimulations::Bold, + 0b10 => FontSimulations::Oblique, + 0b11 => FontSimulations::BoldOblique, + _ => panic!("Invalid DWRITE_FONT_SIMULATIONS value") + } + } +} +impl Into for FontSimulations { + fn into(self) -> DWRITE_FONT_SIMULATIONS { + match self { + FontSimulations::None => DWRITE_FONT_SIMULATIONS_NONE, + FontSimulations::Bold => DWRITE_FONT_SIMULATIONS_BOLD, + FontSimulations::Oblique => DWRITE_FONT_SIMULATIONS_OBLIQUE, + FontSimulations::BoldOblique => DWRITE_FONT_SIMULATIONS_BOLD | DWRITE_FONT_SIMULATIONS_OBLIQUE, + } + } } #[cfg_attr(feature = "serde_serialization", derive(Deserialize, Serialize))]