diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index f6fc29336cb5..be0ee2c64e93 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -318,112 +318,65 @@ bool UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, return true; } -static bool GetDWriteName(RefPtr aNames, - std::vector& aOutName) { - BOOL exists = false; - UINT32 index = 0; - HRESULT hr = aNames->FindLocaleName(L"en-us", &index, &exists); - if (FAILED(hr)) { - return false; - } - if (!exists) { - // No english found, use whatever is first in the list. - index = 0; - } - - UINT32 length; - hr = aNames->GetStringLength(index, &length); - if (FAILED(hr)) { - return false; - } - aOutName.resize(length + 1); - hr = aNames->GetString(index, aOutName.data(), length + 1); - return SUCCEEDED(hr); -} - -static bool GetDWriteFamilyName(const RefPtr& aFamily, - std::vector& aOutName) { - RefPtr names; - HRESULT hr = aFamily->GetFamilyNames(getter_AddRefs(names)); - if (FAILED(hr)) { - return false; - } - return GetDWriteName(names, aOutName); -} - -static void GetFontFileNames(RefPtr aFontFace, - std::vector& aFamilyName, - std::vector& aFileNames) { - MOZ_ASSERT(aFamilyName.size() >= 1 && aFamilyName.back() == 0); - +static bool GetFontFileName(RefPtr aFontFace, + std::vector& aFileName) { UINT32 numFiles; HRESULT hr = aFontFace->GetFiles(&numFiles, nullptr); if (FAILED(hr)) { - gfxCriticalNote << "Failed getting file count for font \"" - << &aFamilyName[0] << "\""; - return; - } else if (!numFiles) { - gfxCriticalNote << "No files found for font \"" << &aFamilyName[0] << "\""; - return; - } - std::vector> files; - files.resize(numFiles); - hr = aFontFace->GetFiles(&numFiles, getter_AddRefs(files[0])); - if (FAILED(hr)) { - gfxCriticalNote << "Failed getting files for font \"" << &aFamilyName[0] - << "\""; - return; + gfxDebug() << "Failed getting file count for WR font"; + return false; + } else if (numFiles != 1) { + gfxDebug() << "Invalid file count " << numFiles << " for WR font"; + return false; } - for (auto& file : files) { - const void* key; - UINT32 keySize; - hr = file->GetReferenceKey(&key, &keySize); - if (FAILED(hr)) { - gfxCriticalNote << "Failed getting file ref key for font \"" - << &aFamilyName[0] << "\""; - return; - } - RefPtr loader; - hr = file->GetLoader(getter_AddRefs(loader)); - if (FAILED(hr)) { - gfxCriticalNote << "Failed getting file loader for font \"" - << &aFamilyName[0] << "\""; - return; - } - RefPtr localLoader; - loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader), - (void**)getter_AddRefs(localLoader)); - if (!localLoader) { - gfxCriticalNote << "Failed querying loader interface for font \"" - << &aFamilyName[0] << "\""; - return; - } - UINT32 pathLen; - hr = localLoader->GetFilePathLengthFromKey(key, keySize, &pathLen); - if (FAILED(hr)) { - gfxCriticalNote << "Failed getting path length for font \"" - << &aFamilyName[0] << "\""; - return; - } - size_t offset = aFileNames.size(); - aFileNames.resize(offset + pathLen + 1); - hr = localLoader->GetFilePathFromKey(key, keySize, &aFileNames[offset], - pathLen + 1); - if (FAILED(hr)) { - aFileNames.resize(offset); - gfxCriticalNote << "Failed getting path for font \"" << &aFamilyName[0] - << "\""; - return; - } - MOZ_ASSERT(aFileNames.back() == 0); - DWORD attribs = GetFileAttributesW(&aFileNames[offset]); - if (attribs == INVALID_FILE_ATTRIBUTES) { - gfxCriticalNote << "sending font family \"" << &aFamilyName[0] - << "\" with invalid file \"" << &aFileNames[offset] - << "\""; - } + RefPtr file; + hr = aFontFace->GetFiles(&numFiles, getter_AddRefs(file)); + if (FAILED(hr)) { + gfxDebug() << "Failed getting file for WR font"; + return false; } + + const void* key; + UINT32 keySize; + hr = file->GetReferenceKey(&key, &keySize); + if (FAILED(hr)) { + gfxDebug() << "Failed getting file ref key for WR font"; + return false; + } + RefPtr loader; + hr = file->GetLoader(getter_AddRefs(loader)); + if (FAILED(hr)) { + gfxDebug() << "Failed getting file loader for WR font"; + return false; + } + RefPtr localLoader; + loader->QueryInterface(__uuidof(IDWriteLocalFontFileLoader), + (void**)getter_AddRefs(localLoader)); + if (!localLoader) { + gfxDebug() << "Failed querying loader interface for WR font"; + return false; + } + UINT32 pathLen; + hr = localLoader->GetFilePathLengthFromKey(key, keySize, &pathLen); + if (FAILED(hr)) { + gfxDebug() << "Failed getting path length for WR font"; + return false; + } + aFileName.resize(pathLen + 1); + hr = localLoader->GetFilePathFromKey(key, keySize, aFileName.data(), + pathLen + 1); + if (FAILED(hr) || aFileName.back() != 0) { + gfxDebug() << "Failed getting path for WR font"; + return false; + } + DWORD attribs = GetFileAttributesW(aFileName.data()); + if (attribs == INVALID_FILE_ATTRIBUTES) { + gfxDebug() << "Invalid file \"" << aFileName.data() << "\" for WR font"; + return false; + } + aFileName.pop_back(); + return true; } bool UnscaledFontDWrite::GetWRFontDescriptor(WRFontDescriptorOutput aCb, @@ -432,52 +385,14 @@ bool UnscaledFontDWrite::GetWRFontDescriptor(WRFontDescriptorOutput aCb, return false; } - RefPtr family; - HRESULT hr = mFont->GetFontFamily(getter_AddRefs(family)); - if (FAILED(hr)) { + std::vector fileName; + if (!GetFontFileName(mFontFace, fileName)) { return false; } + uint32_t index = mFontFace->GetIndex(); - DWRITE_FONT_WEIGHT weight = mFont->GetWeight(); - DWRITE_FONT_STRETCH stretch = mFont->GetStretch(); - DWRITE_FONT_STYLE style = mFont->GetStyle(); - - RefPtr match; - hr = family->GetFirstMatchingFont(weight, stretch, style, - getter_AddRefs(match)); - if (FAILED(hr) || match->GetWeight() != weight || - match->GetStretch() != stretch || match->GetStyle() != style) { - return false; - } - - std::vector familyName; - if (!GetDWriteFamilyName(family, familyName)) { - return false; - } - - RefPtr systemFonts = Factory::GetDWriteSystemFonts(); - if (!systemFonts) { - return false; - } - - UINT32 idx; - BOOL exists; - hr = systemFonts->FindFamilyName(familyName.data(), &idx, &exists); - if (FAILED(hr) || !exists) { - return false; - } - - // FIXME: Debugging kluge for bug 1455848. Remove once debugged! - GetFontFileNames(mFontFace, familyName, familyName); - - // The style information that identifies the font can be encoded easily in - // less than 32 bits. Since the index is needed for font descriptors, only - // the family name and style information, pass along the style in the index - // data to avoid requiring a more complicated structure packing for it in - // the data payload. - uint32_t index = weight | (stretch << 16) | (style << 24); - aCb(reinterpret_cast(familyName.data()), - familyName.size() * sizeof(WCHAR), index, aBaton); + aCb(reinterpret_cast(fileName.data()), + fileName.size() * sizeof(WCHAR), index, aBaton); return true; } diff --git a/gfx/layers/ipc/PWebRenderBridge.ipdl b/gfx/layers/ipc/PWebRenderBridge.ipdl index 9df01067cda0..b8f5016f18c1 100644 --- a/gfx/layers/ipc/PWebRenderBridge.ipdl +++ b/gfx/layers/ipc/PWebRenderBridge.ipdl @@ -82,9 +82,6 @@ parent: async FlushApzRepaints(); sync GetAPZTestData() returns (APZTestData data); - // Debugging routine for bug 1455848. - async ValidateFontDescriptor(uint8_t[] desc); - async Shutdown(); sync ShutdownSync(); child: diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index 6f707d19a2df..5945be1516f2 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -226,16 +226,6 @@ static void WriteFontDescriptor(const uint8_t* aData, uint32_t aLength, *sink->mFontKey = sink->mWrBridge->GetNextFontKey(); -#ifdef XP_WIN - // FIXME: Debugging kluge for bug 1455848. Remove once debugged! - nsTArray data; - data.AppendElements(aData, aLength); - sink->mWrBridge->SendValidateFontDescriptor(data); - aLength = - uint32_t(wcsnlen_s((const wchar_t*)aData, aLength / sizeof(wchar_t)) * - sizeof(wchar_t)); -#endif - sink->mResources->AddFontDescriptor( *sink->mFontKey, Range(const_cast(aData), aLength), aIndex); diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 03a891fc7cba..642edd4cfbc5 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -36,10 +36,6 @@ #include "mozilla/webrender/RenderThread.h" #include "mozilla/widget/CompositorWidget.h" -#ifdef XP_WIN -# include "dwrite.h" -#endif - #ifdef MOZ_GECKO_PROFILER # include "ProfilerMarkerPayload.h" #endif @@ -706,49 +702,6 @@ void WebRenderBridgeParent::ObserveSharedSurfaceRelease( } } -// Debugging kluge for bug 1455848. Remove once debugged! -mozilla::ipc::IPCResult WebRenderBridgeParent::RecvValidateFontDescriptor( - nsTArray&& aData) { - if (mDestroyed) { - return IPC_OK(); - } -#ifdef XP_WIN - nsTArray data(aData); - wchar_t* family = (wchar_t*)data.Elements(); - size_t remaining = data.Length() / sizeof(wchar_t); - size_t familyLength = wcsnlen_s(family, remaining); - MOZ_ASSERT(familyLength < remaining && family[familyLength] == 0); - remaining -= familyLength + 1; - wchar_t* files = family + familyLength + 1; - BOOL exists = FALSE; - if (RefPtr systemFonts = - Factory::GetDWriteSystemFonts()) { - UINT32 idx; - systemFonts->FindFamilyName(family, &idx, &exists); - } - if (!remaining) { - gfxCriticalNote << (exists ? "found" : "MISSING") << " font family \"" - << family << "\" has no files!"; - } - while (remaining > 0) { - size_t fileLength = wcsnlen_s(files, remaining); - MOZ_ASSERT(fileLength < remaining && files[fileLength] == 0); - DWORD attribs = GetFileAttributesW(files); - if (!exists || attribs == INVALID_FILE_ATTRIBUTES) { - gfxCriticalNote << (exists ? "found" : "MISSING") << " font family \"" - << family << "\" has " - << (attribs == INVALID_FILE_ATTRIBUTES ? "INVALID" - : "valid") - << "(" << hexa(attribs) << ")" - << " file \"" << files << "\""; - } - remaining -= fileLength + 1; - files += fileLength + 1; - } -#endif - return IPC_OK(); -} - mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources( nsTArray&& aResourceUpdates, nsTArray&& aSmallShmems, diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index 2e6f912b7bfc..3ff294393cd7 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -125,9 +125,6 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, nsTArray&& commands) override; mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override; - mozilla::ipc::IPCResult RecvValidateFontDescriptor( - nsTArray&& aData) override; - mozilla::ipc::IPCResult RecvSetLayersObserverEpoch( const LayersObserverEpoch& aChildEpoch) override; diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml index 34c02b2db347..1258ea2807b9 100644 --- a/gfx/webrender_bindings/Cargo.toml +++ b/gfx/webrender_bindings/Cargo.toml @@ -23,7 +23,7 @@ default-features = false features = ["capture", "serialize_program"] [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.7" +dwrote = "0.8" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.6" diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 42f35f3ca378..22d817e8b387 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -1,4 +1,10 @@ use std::ffi::{CStr, CString}; +#[cfg(not(target_os = "macos"))] +use std::ffi::OsString; +#[cfg(target_os = "windows")] +use std::os::windows::ffi::OsStringExt; +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +use std::os::unix::ffi::OsStringExt; use std::io::Cursor; use std::{mem, slice, ptr, env}; use std::path::PathBuf; @@ -28,9 +34,6 @@ use rayon; use euclid::SideOffsets2D; use nsstring::nsAString; -#[cfg(target_os = "windows")] -use dwrote::{FontDescriptor, FontWeight, FontStretch, FontStyle}; - #[cfg(target_os = "macos")] use core_foundation::string::CFString; #[cfg(target_os = "macos")] @@ -1713,11 +1716,9 @@ fn read_font_descriptor( index: u32 ) -> NativeFontHandle { let wchars = bytes.convert_into_vec::(); - FontDescriptor { - family_name: String::from_utf16(&wchars).unwrap(), - weight: FontWeight::from_u32(index & 0xffff), - stretch: FontStretch::from_u32((index >> 16) & 0xff), - style: FontStyle::from_u32((index >> 24) & 0xff), + NativeFontHandle { + path: PathBuf::from(OsString::from_wide(&wchars)), + index, } } @@ -1737,9 +1738,9 @@ fn read_font_descriptor( bytes: &mut WrVecU8, index: u32 ) -> NativeFontHandle { - let cstr = CString::new(bytes.flush_into_vec()).unwrap(); + let chars = bytes.flush_into_vec(); NativeFontHandle { - pathname: String::from(cstr.to_str().unwrap()), + path: PathBuf::from(OsString::from_vec(chars)), index, } } diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs index 6ee3ecc93bb8..7a776d31755d 100644 --- a/gfx/webrender_bindings/src/moz2d_renderer.rs +++ b/gfx/webrender_bindings/src/moz2d_renderer.rs @@ -30,6 +30,8 @@ use foreign_types::ForeignType; #[cfg(not(any(target_os = "macos", target_os = "windows")))] use std::ffi::CString; +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +use std::os::unix::ffi::OsStrExt; /// Local print-debugging utility macro_rules! dlog { @@ -655,9 +657,8 @@ impl Moz2dBlobImageHandler { fn prepare_request(&self, blob: &[u8], resources: &BlobImageResources) { #[cfg(target_os = "windows")] fn process_native_font_handle(key: FontKey, handle: &NativeFontHandle) { - let system_fc = dwrote::FontCollection::system(); - let font = system_fc.get_font_from_descriptor(handle).unwrap(); - let face = font.create_font_face(); + let file = dwrote::FontFile::new_from_path(&handle.path).unwrap(); + let face = file.create_face(handle.index, dwrote::DWRITE_FONT_SIMULATIONS_NONE).unwrap(); unsafe { AddNativeFontHandle(key, face.as_ptr() as *mut c_void, 0) }; } @@ -668,7 +669,7 @@ impl Moz2dBlobImageHandler { #[cfg(not(any(target_os = "macos", target_os = "windows")))] fn process_native_font_handle(key: FontKey, handle: &NativeFontHandle) { - let cstr = CString::new(handle.pathname.clone()).unwrap(); + let cstr = CString::new(handle.path.as_os_str().as_bytes()).unwrap(); unsafe { AddNativeFontHandle(key, cstr.as_ptr() as *mut c_void, handle.index) }; } diff --git a/gfx/wr/webrender/Cargo.toml b/gfx/wr/webrender/Cargo.toml index 0c2392405729..7d927b11f1cb 100644 --- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -81,7 +81,7 @@ freetype = { version = "0.4", default-features = false } libc = "0.2" [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.7" +dwrote = "0.8" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.6" diff --git a/gfx/wr/webrender/src/platform/unix/font.rs b/gfx/wr/webrender/src/platform/unix/font.rs index 646cb1e22b82..bef0c92c46de 100644 --- a/gfx/wr/webrender/src/platform/unix/font.rs +++ b/gfx/wr/webrender/src/platform/unix/font.rs @@ -319,7 +319,8 @@ impl FontContext { pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: NativeFontHandle) { if !self.faces.contains_key(&font_key) { - let file = FontFile::Pathname(CString::new(native_font_handle.pathname).unwrap()); + let cstr = CString::new(native_font_handle.path.as_os_str().to_str().unwrap()).unwrap(); + let file = FontFile::Pathname(cstr); let index = native_font_handle.index; if let Some(face) = new_ft_face(font_key, self.lib, &file, index) { self.faces.insert(*font_key, FontFace { file, index, face, mm_var: ptr::null_mut() }); @@ -965,6 +966,7 @@ impl Drop for FontContext { impl<'a> Into for NativeFontHandleWrapper<'a> { fn into(self) -> pf_freetype::FontDescriptor { let NativeFontHandleWrapper(font_handle) = self; - pf_freetype::FontDescriptor::new(font_handle.pathname.clone().into(), font_handle.index) + let str = font_handle.path.as_os_str().to_str().unwrap(); + pf_freetype::FontDescriptor::new(str.into(), font_handle.index) } } diff --git a/gfx/wr/webrender/src/platform/windows/font.rs b/gfx/wr/webrender/src/platform/windows/font.rs index c09e80f80a1a..2ec4b133de8a 100644 --- a/gfx/wr/webrender/src/platform/windows/font.rs +++ b/gfx/wr/webrender/src/platform/windows/font.rs @@ -3,13 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{FontInstanceFlags, FontKey, FontRenderMode, FontVariation}; -use api::{ColorU, GlyphDimensions}; +use api::{ColorU, GlyphDimensions, NativeFontHandle}; use dwrote; use gamma_lut::ColorLut; use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey}; use internal_types::{FastHashMap, ResourceCacheError}; use std::collections::hash_map::Entry; use std::sync::Arc; + cfg_if! { if #[cfg(feature = "pathfinder")] { use pathfinder_font_renderer::{PathfinderComPtr, IDWriteFontFace}; @@ -30,8 +31,14 @@ lazy_static! { }; } +struct FontFace { + file: dwrote::FontFile, + index: u32, + face: dwrote::FontFace, +} + pub struct FontContext { - fonts: FastHashMap, + fonts: FastHashMap, variations: FastHashMap<(FontKey, dwrote::DWRITE_FONT_SIMULATIONS, Vec), dwrote::FontFace>, #[cfg(not(feature = "pathfinder"))] gamma_luts: FastHashMap<(u16, u16), GammaLut>, @@ -110,68 +117,46 @@ impl FontContext { self.fonts.contains_key(font_key) } + fn add_font_descriptor(&mut self, font_key: &FontKey, desc: &dwrote::FontDescriptor) { + let system_fc = dwrote::FontCollection::get_system(false); + if let Some(font) = system_fc.get_font_from_descriptor(desc) { + let face = font.create_font_face(); + let file = face.get_files().pop().unwrap(); + let index = face.get_index(); + self.fonts.insert(*font_key, FontFace { file, index, face }); + } + } + pub fn add_raw_font(&mut self, font_key: &FontKey, data: Arc>, index: u32) { if self.fonts.contains_key(font_key) { return; } - if let Some(font_file) = dwrote::FontFile::new_from_data(data) { - let face = font_file.create_face(index, dwrote::DWRITE_FONT_SIMULATIONS_NONE); - self.fonts.insert(*font_key, face); - } else { - // XXX add_raw_font needs to have a way to return an error - debug!("DWrite WR failed to load font from data, using Arial instead"); - self.add_native_font(font_key, DEFAULT_FONT_DESCRIPTOR.clone()); - } - } - - pub fn load_system_font(font_handle: &dwrote::FontDescriptor, update: bool) -> Result { - let system_fc = dwrote::FontCollection::get_system(update); - // A version of get_font_from_descriptor() that panics early to help with bug 1455848 - if let Some(family) = system_fc.get_font_family_by_name(&font_handle.family_name) { - let font = family.get_first_matching_font(font_handle.weight, font_handle.stretch, font_handle.style); - // Exact matches only here - if font.weight() == font_handle.weight && - font.stretch() == font_handle.stretch && - font.style() == font_handle.style - { - Ok(font) - } else { - // We can't depend on the family's fonts being in a particular order, so the first match may not - // be an exact match, even though it is sufficiently close to be a match. As a slower fallback, - // try looking through all of the fonts in the family for an exact match. The caller should have - // verified that an exact match exists so that this search shouldn't fail. - (0 .. family.get_font_count()).filter_map(|idx| { - let alt = family.get_font(idx); - if alt.weight() == font_handle.weight && - alt.stretch() == font_handle.stretch && - alt.style() == font_handle.style - { - Some(alt) - } else { - None - } - }).next().ok_or_else(|| { - format!("font mismatch for descriptor {:?} {:?}", font_handle, font.to_descriptor()) - }) + if let Some(file) = dwrote::FontFile::new_from_data(data) { + if let Ok(face) = file.create_face(index, dwrote::DWRITE_FONT_SIMULATIONS_NONE) { + self.fonts.insert(*font_key, FontFace { file, index, face }); + return; } - } else { - Err(format!("missing font family for descriptor {:?}", font_handle)) } + // XXX add_raw_font needs to have a way to return an error + debug!("DWrite WR failed to load font from data, using Arial instead"); + self.add_font_descriptor(font_key, &DEFAULT_FONT_DESCRIPTOR); } - pub fn add_native_font(&mut self, font_key: &FontKey, font_handle: dwrote::FontDescriptor) { + pub fn add_native_font(&mut self, font_key: &FontKey, font_handle: NativeFontHandle) { if self.fonts.contains_key(font_key) { return; } - // First try to load the font without updating the system font collection. - // If the font can't be found, try again after updating the system font collection. - // If even that fails, panic... - let font = Self::load_system_font(&font_handle, false).unwrap_or_else(|_| { - Self::load_system_font(&font_handle, true).unwrap() - }); - let face = font.create_font_face(); - self.fonts.insert(*font_key, face); + if let Some(file) = dwrote::FontFile::new_from_path(font_handle.pathname) { + let index = font_handle.index; + if let Ok(face) = file.create_face(index, dwrote::DWRITE_FONT_SIMULATIONS_NONE) { + self.fonts.insert(*font_key, FontFace { file, index, face }); + return; + } + } + // XXX add_native_font needs to have a way to return an error + debug!("DWrite WR failed to load font from path, using Arial instead"); + self.add_font_descriptor(font_key, &DEFAULT_FONT_DESCRIPTOR); } pub fn delete_font(&mut self, font_key: &FontKey) { @@ -216,7 +201,7 @@ impl FontContext { ) -> &dwrote::FontFace { if !font.flags.contains(FontInstanceFlags::SYNTHETIC_BOLD) && font.variations.is_empty() { - return self.fonts.get(&font.font_key).unwrap(); + return &self.fonts.get(&font.font_key).unwrap().face; } let sims = if font.flags.contains(FontInstanceFlags::SYNTHETIC_BOLD) { dwrote::DWRITE_FONT_SIMULATIONS_BOLD @@ -228,7 +213,7 @@ impl FontContext { Entry::Vacant(entry) => { let normal_face = self.fonts.get(&font.font_key).unwrap(); if !font.variations.is_empty() { - if let Some(var_face) = normal_face.create_font_face_with_variations( + if let Some(var_face) = normal_face.face.create_font_face_with_variations( sims, &font.variations.iter().map(|var| { dwrote::DWRITE_FONT_AXIS_VALUE { @@ -241,7 +226,10 @@ impl FontContext { return entry.insert(var_face); } } - entry.insert(normal_face.create_font_face_with_simulations(sims)) + let var_face = normal_face.file + .create_face(normal_face.index, sims) + .unwrap_or_else(|_| normal_face.face.clone()); + entry.insert(var_face) } } } @@ -315,7 +303,7 @@ impl FontContext { } pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option { - let face = self.fonts.get(&font_key).unwrap(); + let face = &self.fonts.get(&font_key).unwrap().face; let indices = face.get_glyph_indices(&[ch as u32]); indices.first().map(|idx| *idx as u32) } @@ -547,12 +535,12 @@ impl FontContext { #[cfg(feature = "pathfinder")] impl<'a> From> for PathfinderComPtr { fn from(font_handle: NativeFontHandleWrapper<'a>) -> Self { - let system_fc = ::dwrote::FontCollection::system(); - let font = match system_fc.get_font_from_descriptor(&font_handle.0) { - Some(font) => font, - None => panic!("missing descriptor {:?}", font_handle.0), - }; - let face = font.create_font_face(); - unsafe { PathfinderComPtr::new(face.as_ptr()) } + if let Some(file) = dwrote::FontFile::new_from_path(font_handle.0.pathname) { + let index = font_handle.0.index; + if let Ok(face) = file.create_face(index, dwrote::DWRITE_FONT_SIMULATIONS_NONE) { + return unsafe { PathfinderComPtr::new(face.as_ptr()) }; + } + } + panic!("missing font {:?}", font_handle.0) } } diff --git a/gfx/wr/webrender_api/Cargo.toml b/gfx/wr/webrender_api/Cargo.toml index 04046b0305ff..967c8b14f477 100644 --- a/gfx/wr/webrender_api/Cargo.toml +++ b/gfx/wr/webrender_api/Cargo.toml @@ -30,6 +30,3 @@ wr_malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of" } [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.6" core-graphics = "0.17.1" - -[target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.7" diff --git a/gfx/wr/webrender_api/src/font.rs b/gfx/wr/webrender_api/src/font.rs index 8ab85721ae3e..f5469ed904fb 100644 --- a/gfx/wr/webrender_api/src/font.rs +++ b/gfx/wr/webrender_api/src/font.rs @@ -7,22 +7,22 @@ use app_units::Au; use core_foundation::string::CFString; #[cfg(target_os = "macos")] use core_graphics::font::CGFont; -#[cfg(target_os = "windows")] -pub use dwrote::FontDescriptor as NativeFontHandle; #[cfg(target_os = "macos")] use serde::de::{self, Deserialize, Deserializer}; #[cfg(target_os = "macos")] use serde::ser::{Serialize, Serializer}; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; +#[cfg(not(target_os = "macos"))] +use std::path::PathBuf; use std::sync::Arc; use {ColorU, IdNamespace, LayoutPoint}; -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(target_os = "macos"))] #[derive(Clone, Debug, Serialize, Deserialize)] pub struct NativeFontHandle { - pub pathname: String, + pub path: PathBuf, pub index: u32, } diff --git a/gfx/wr/webrender_api/src/lib.rs b/gfx/wr/webrender_api/src/lib.rs index 0f7960a722a0..404c0d3134b8 100644 --- a/gfx/wr/webrender_api/src/lib.rs +++ b/gfx/wr/webrender_api/src/lib.rs @@ -27,8 +27,6 @@ extern crate core_foundation; extern crate core_graphics; #[macro_use] extern crate derive_more; -#[cfg(target_os = "windows")] -extern crate dwrote; pub extern crate euclid; #[cfg(feature = "ipc")] extern crate ipc_channel; diff --git a/gfx/wr/wrench/Cargo.toml b/gfx/wr/wrench/Cargo.toml index a4c6aced1895..764742b4748b 100644 --- a/gfx/wr/wrench/Cargo.toml +++ b/gfx/wr/wrench/Cargo.toml @@ -39,7 +39,7 @@ headless = [ "osmesa-sys", "osmesa-src" ] pathfinder = [ "webrender/pathfinder" ] [target.'cfg(target_os = "windows")'.dependencies] -dwrote = "0.7" +dwrote = "0.8" mozangle = {version = "0.1.5", features = ["egl"]} [target.'cfg(all(unix, not(target_os = "android")))'.dependencies] diff --git a/gfx/wr/wrench/src/wrench.rs b/gfx/wr/wrench/src/wrench.rs index c4025c7d438a..7f03d815c2f4 100644 --- a/gfx/wr/wrench/src/wrench.rs +++ b/gfx/wr/wrench/src/wrench.rs @@ -391,15 +391,12 @@ impl Wrench { #[cfg(target_os = "windows")] pub fn font_key_from_name(&mut self, font_name: &str) -> FontKey { - let system_fc = dwrote::FontCollection::system(); - let family = system_fc.get_font_family_by_name(font_name).unwrap(); - let font = family.get_first_matching_font( - dwrote::FontWeight::Regular, - dwrote::FontStretch::Normal, - dwrote::FontStyle::Normal, - ); - let descriptor = font.to_descriptor(); - self.font_key_from_native_handle(&descriptor) + self.font_key_from_properties( + font_name, + dwrote::FontWeight::Regular.to_u32(), + dwrote::FontStretch::Normal.to_u32(), + dwrote::FontStyle::Normal.to_u32(), + ) } #[cfg(target_os = "windows")] @@ -413,14 +410,26 @@ impl Wrench { let weight = dwrote::FontWeight::from_u32(weight); let style = dwrote::FontStyle::from_u32(style); let stretch = dwrote::FontStretch::from_u32(stretch); - let desc = dwrote::FontDescriptor { family_name: family.to_owned(), weight, style, stretch, }; - self.font_key_from_native_handle(&desc) + let system_fc = dwrote::FontCollection::system(); + if let Some(font) = system_fc.get_font_from_descriptor(&desc) { + let face = font.create_font_face(); + let files = face.get_files(); + if files.len() == 1 { + if let Some(path) = files[0].get_font_file_path() { + return self.font_key_from_native_handle(&NativeFontHandle { + path, + index: face.get_index(), + }); + } + } + } + panic!("failed loading font from properties {:?}", desc) } #[cfg(all(unix, not(target_os = "android")))] diff --git a/gfx/wr/wrench/src/yaml_frame_writer.rs b/gfx/wr/wrench/src/yaml_frame_writer.rs index 9a504e359dc8..19c585a5d7dd 100644 --- a/gfx/wr/wrench/src/yaml_frame_writer.rs +++ b/gfx/wr/wrench/src/yaml_frame_writer.rs @@ -268,19 +268,6 @@ fn write_stacking_context( yaml_node(parent, "filters", Yaml::Array(filters)); } -#[cfg(target_os = "windows")] -fn native_font_handle_to_yaml( - _rsrc: &mut ResourceGenerator, - handle: &NativeFontHandle, - parent: &mut yaml_rust::yaml::Hash, - _: &mut Option, -) { - str_node(parent, "family", &handle.family_name); - u32_node(parent, "weight", handle.weight.to_u32()); - u32_node(parent, "style", handle.style.to_u32()); - u32_node(parent, "stretch", handle.stretch.to_u32()); -} - #[cfg(target_os = "macos")] fn native_font_handle_to_yaml( rsrc: &mut ResourceGenerator, @@ -307,14 +294,17 @@ fn native_font_handle_to_yaml( path_node(parent, "font", &path); } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[cfg(not(target_os = "macos"))] fn native_font_handle_to_yaml( _rsrc: &mut ResourceGenerator, handle: &NativeFontHandle, parent: &mut yaml_rust::yaml::Hash, _: &mut Option, ) { - str_node(parent, "font", &handle.pathname); + str_node(parent, "font", handle.path.as_os_str().to_str().unwrap()); + if handle.index != 0 { + u32_node(parent, "font-index", handle.index); + } } fn radial_gradient_to_yaml(