mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 07:45:30 +00:00
Bug 1455848 - use paths for WR font handles on Windows. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D16896
This commit is contained in:
parent
7ccb4bf803
commit
bd0b2ed9f0
@ -318,112 +318,65 @@ bool UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetDWriteName(RefPtr<IDWriteLocalizedStrings> aNames,
|
||||
std::vector<WCHAR>& 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<IDWriteFontFamily>& aFamily,
|
||||
std::vector<WCHAR>& aOutName) {
|
||||
RefPtr<IDWriteLocalizedStrings> names;
|
||||
HRESULT hr = aFamily->GetFamilyNames(getter_AddRefs(names));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
return GetDWriteName(names, aOutName);
|
||||
}
|
||||
|
||||
static void GetFontFileNames(RefPtr<IDWriteFontFace> aFontFace,
|
||||
std::vector<WCHAR>& aFamilyName,
|
||||
std::vector<WCHAR>& aFileNames) {
|
||||
MOZ_ASSERT(aFamilyName.size() >= 1 && aFamilyName.back() == 0);
|
||||
|
||||
static bool GetFontFileName(RefPtr<IDWriteFontFace> aFontFace,
|
||||
std::vector<WCHAR>& 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<RefPtr<IDWriteFontFile>> 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<IDWriteFontFileLoader> loader;
|
||||
hr = file->GetLoader(getter_AddRefs(loader));
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "Failed getting file loader for font \""
|
||||
<< &aFamilyName[0] << "\"";
|
||||
return;
|
||||
}
|
||||
RefPtr<IDWriteLocalFontFileLoader> 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<IDWriteFontFile> 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<IDWriteFontFileLoader> loader;
|
||||
hr = file->GetLoader(getter_AddRefs(loader));
|
||||
if (FAILED(hr)) {
|
||||
gfxDebug() << "Failed getting file loader for WR font";
|
||||
return false;
|
||||
}
|
||||
RefPtr<IDWriteLocalFontFileLoader> 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<IDWriteFontFamily> family;
|
||||
HRESULT hr = mFont->GetFontFamily(getter_AddRefs(family));
|
||||
if (FAILED(hr)) {
|
||||
std::vector<WCHAR> 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<IDWriteFont> 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<WCHAR> familyName;
|
||||
if (!GetDWriteFamilyName(family, familyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteFontCollection> 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<const uint8_t*>(familyName.data()),
|
||||
familyName.size() * sizeof(WCHAR), index, aBaton);
|
||||
aCb(reinterpret_cast<const uint8_t*>(fileName.data()),
|
||||
fileName.size() * sizeof(WCHAR), index, aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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<uint8_t> 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<uint8_t>(const_cast<uint8_t*>(aData), aLength),
|
||||
aIndex);
|
||||
|
@ -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<uint8_t>&& aData) {
|
||||
if (mDestroyed) {
|
||||
return IPC_OK();
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
nsTArray<uint8_t> 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<IDWriteFontCollection> 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<OpUpdateResource>&& aResourceUpdates,
|
||||
nsTArray<RefCountedShmem>&& aSmallShmems,
|
||||
|
@ -125,9 +125,6 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent,
|
||||
nsTArray<WebRenderParentCommand>&& commands) override;
|
||||
mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvValidateFontDescriptor(
|
||||
nsTArray<uint8_t>&& aData) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetLayersObserverEpoch(
|
||||
const LayersObserverEpoch& aChildEpoch) override;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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::<u16>();
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -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) };
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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<pf_freetype::FontDescriptor> 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)
|
||||
}
|
||||
}
|
||||
|
@ -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<FontKey, dwrote::FontFace>,
|
||||
fonts: FastHashMap<FontKey, FontFace>,
|
||||
variations: FastHashMap<(FontKey, dwrote::DWRITE_FONT_SIMULATIONS, Vec<FontVariation>), 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<Vec<u8>>, 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<dwrote::Font, String> {
|
||||
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<u32> {
|
||||
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<NativeFontHandleWrapper<'a>> for PathfinderComPtr<IDWriteFontFace> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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")))]
|
||||
|
@ -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<PathBuf>,
|
||||
) {
|
||||
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<PathBuf>,
|
||||
) {
|
||||
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(
|
||||
|
Loading…
Reference in New Issue
Block a user