/// <summary> /// Create a WPF GlyphTypeface and retrieve font data from it. /// </summary> internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, out WpfFontFamily wpfFontFamily, out WpfTypeface wpfTypeface, out WpfGlyphTypeface wpfGlyphTypeface, string typefaceKey) { if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } XFontStyle style = fontResolvingOptions.FontStyle; #if DEBUG if (StringComparer.OrdinalIgnoreCase.Compare(familyName, "Segoe UI Semilight") == 0 && (style & XFontStyle.BoldItalic) == XFontStyle.Italic) { familyName.GetType(); } #endif // Use WPF technique to create font data. wpfTypeface = XPrivateFontCollection.TryCreateTypeface(familyName, style, out wpfFontFamily); #if DEBUG__ if (wpfTypeface != null) { WpfGlyphTypeface glyphTypeface; ICollection <WpfTypeface> list = wpfFontFamily.GetTypefaces(); foreach (WpfTypeface tf in list) { if (!tf.TryGetGlyphTypeface(out glyphTypeface)) { Debug - Break.Break(); } } //if (!WpfTypeface.TryGetGlyphTypeface(out glyphTypeface)) // throw new InvalidOperationException(PSSR.CannotGetGlyphTypeface(familyName)); } #endif if (wpfFontFamily == null) { wpfFontFamily = new WpfFontFamily(familyName); } if (wpfTypeface == null) { wpfTypeface = FontHelper.CreateTypeface(wpfFontFamily, style); } // Let WPF choose the right glyph typeface. if (!wpfTypeface.TryGetGlyphTypeface(out wpfGlyphTypeface)) { throw new InvalidOperationException(PSSR.CannotGetGlyphTypeface(familyName)); } // Get or create the font source and cache it unter the specified typeface key. XFontSource fontSource = XFontSource.GetOrCreateFromWpf(typefaceKey, wpfGlyphTypeface); return(fontSource); }
internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey) { if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } if (fonts == null) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load("/system/etc/fonts.xml"); fonts = new Dictionary <AndroidFontInfo, string>(); var familyset = xmlDoc.DocumentElement; foreach (XmlNode family in familyset.ChildNodes) { if (family.Attributes != null && family.Attributes["name"] != null) { foreach (XmlNode font in family.ChildNodes) { if (font.Attributes["style"] != null && font.Attributes["weight"] != null) { var id = new AndroidFontInfo { FamilyName = family.Attributes["name"].Value, Italic = font.Attributes["style"].Value == "italic", Bold = int.Parse(font.Attributes["weight"].Value) > 500, }; fonts[id] = font.ChildNodes[0].Value; } } } } } XFontSource fontSource = null; string path; var searchId = new AndroidFontInfo { FamilyName = familyName, Italic = fontResolvingOptions.IsItalic, Bold = fontResolvingOptions.IsBold, }; if (fonts.TryGetValue(searchId, out path)) { fontSource = XFontSource.GetOrCreateFrom(typefaceKey, File.ReadAllBytes(Path.Combine("/system/fonts/", path))); } return(fontSource); }
/// <summary> /// Internal implementation. /// </summary> internal static FontResolverInfo ResolveTypeface(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey) { // Internally we often have the typeface key already. if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } // The user may call ResolveTypeface anytime from anywhere, so check cache in FontFactory in the first place. FontResolverInfo fontResolverInfo; if (FontFactory.TryGetFontResolverInfoByTypefaceKey(typefaceKey, out fontResolverInfo)) { return(fontResolverInfo); } // Let the platform create the requested font source and save both PlattformResolverInfo // and XFontSource in FontFactory cache. // It is possible that we already have the correct font source. E.g. we already have the regular typeface in cache // and looking now for the italic typeface, but no such font exists. In this case we get the regular font source // and cache again it with the italic typeface key. Furthermore in glyph typeface style simulation for italic is set. #if (CORE || GDI) && !WPF GdiFont gdiFont; XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, out gdiFont, typefaceKey); #endif #if WPF && !SILVERLIGHT WpfFontFamily wpfFontFamily; WpfTypeface wpfTypeface; WpfGlyphTypeface wpfGlyphTypeface; XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, out wpfFontFamily, out wpfTypeface, out wpfGlyphTypeface, typefaceKey); #endif #if SILVERLIGHT //GlyphTypeface wpfGlyphTypeface; XFontSource fontSource = null;//CreateFontSource(familyName, isBold, isItalic, out wpfGlyphTypeface, typefaceKey); #endif #if NETFX_CORE || UWP //GlyphTypeface wpfGlyphTypeface; XFontSource fontSource = null;//CreateFontSource(familyName, isBold, isItalic, out wpfGlyphTypeface, typefaceKey); #endif #if __IOS__ XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, typefaceKey); #endif #if __ANDROID__ XFontSource fontSource = CreateFontSource(familyName, fontResolvingOptions, typefaceKey); #endif #if PORTABLE XFontSource fontSource = null; #endif // If no such font exists return null. PDFsharp will fail. if (fontSource == null) { return(null); } //#if (CORE || GDI) && !WPF // // TODO: Support style simulation for GDI+ platform fonts. // fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, false, false, gdiFont); //#endif if (fontResolvingOptions.OverrideStyleSimulations) { #if (CORE || GDI) && !WPF // TODO: Support style simulation for GDI+ platform fonts. fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, fontResolvingOptions.MustSimulateBold, fontResolvingOptions.MustSimulateItalic, gdiFont); #endif #if WPF && !SILVERLIGHT fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, fontResolvingOptions.MustSimulateBold, fontResolvingOptions.MustSimulateItalic, wpfFontFamily, wpfTypeface, wpfGlyphTypeface); #endif } else { #if (CORE || GDI) && !WPF bool mustSimulateBold = gdiFont.Bold && !fontSource.Fontface.os2.IsBold; bool mustSimulateItalic = gdiFont.Italic && !fontSource.Fontface.os2.IsItalic; fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, mustSimulateBold, mustSimulateItalic, gdiFont); #endif #if WPF && !SILVERLIGHT // WPF knows what styles have to be simulated. bool mustSimulateBold = (wpfGlyphTypeface.StyleSimulations & WpfStyleSimulations.BoldSimulation) == WpfStyleSimulations.BoldSimulation; bool mustSimulateItalic = (wpfGlyphTypeface.StyleSimulations & WpfStyleSimulations.ItalicSimulation) == WpfStyleSimulations.ItalicSimulation; // Weird behavior of WPF is fixed here in case we request a bold italic typeface. // If only italic is available, bold is simulated based on italic. // If only bold is available, italic is simulated based on bold. // But if both bold and italic is available, italic face is used and bold is simulated. // The latter case is reversed here, i.e. bold face is used and italic is simulated. if (fontResolvingOptions.IsBoldItalic && mustSimulateBold && !mustSimulateItalic) { // Try to get the bold typeface. string typefaceKeyBold = XGlyphTypeface.ComputeKey(familyName, true, false); FontResolverInfo infoBold = ResolveTypeface(familyName, new FontResolvingOptions(FontHelper.CreateStyle(true, false)), typefaceKeyBold); // Use it if it does not base on simulateion. if (infoBold != null && infoBold.StyleSimulations == XStyleSimulations.None) { // Use existing bold typeface and simualte italic. fontResolverInfo = new PlatformFontResolverInfo(typefaceKeyBold, false, true, wpfFontFamily, wpfTypeface, wpfGlyphTypeface); } else { // Simulate both. fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, true, true, wpfFontFamily, wpfTypeface, wpfGlyphTypeface); } } else { fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, mustSimulateBold, mustSimulateItalic, wpfFontFamily, wpfTypeface, wpfGlyphTypeface); } #endif } #if SILVERLIGHT fontResolverInfo = null; //new PlattformResolverInfo(typefaceKey, false, false, wpfGlyphTypeface); #endif #if __IOS__ fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, false, false); #endif #if __ANDROID__ fontResolverInfo = new PlatformFontResolverInfo(typefaceKey, false, false); #endif FontFactory.CacheFontResolverInfo(typefaceKey, fontResolverInfo); // Register font data under the platform specific face name. // Already done in CreateFontSource. // FontFactory.CacheNewFontSource(typefaceKey, fontSource); return(fontResolverInfo); }
/// <summary> /// Resolves the typeface by generating a font resolver info. /// </summary> /// <param name="familyName">Name of the font family.</param> /// <param name="isBold">Indicates whether a bold font is requested.</param> /// <param name="isItalic">Indicates whether an italic font is requested.</param> public static FontResolverInfo ResolveTypeface(string familyName, bool isBold, bool isItalic) { FontResolvingOptions fontResolvingOptions = new FontResolvingOptions(FontHelper.CreateStyle(isBold, isItalic)); return(ResolveTypeface(familyName, fontResolvingOptions, XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions))); }
internal unsafe static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey) { if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } var descriptor = UIFont.FromName(familyName, 20.0f).FontDescriptor; UIFontDescriptorSymbolicTraits traits = 0; if (fontResolvingOptions.IsItalic) { traits |= UIFontDescriptorSymbolicTraits.Italic; } if (fontResolvingOptions.IsBold) { traits |= UIFontDescriptorSymbolicTraits.Bold; } var uifont = UIFont.FromDescriptor(descriptor.CreateWithTraits(traits), 20.0f); var cgFont = CGFont.CreateWithFontName(uifont.Name); IntPtr tags = CGFontCopyTableTags(cgFont.Handle); nint tableCount = CFArrayGetCount(tags); nint totalSize = sizeof(FontHeader) + sizeof(TableEntry) * tableCount; for (int index = 0; index < tableCount; ++index) { nint tableSize = 0; int aTag = (int)CFArrayGetValueAtIndex(tags, index); IntPtr tableDataRef = CGFontCopyTableForTag(cgFont.Handle, aTag); if (tableDataRef != IntPtr.Zero) { tableSize = CFDataGetLength(tableDataRef); CFRelease(tableDataRef); } totalSize += (tableSize + 3) & ~3; } var data = new byte[totalSize]; fixed(byte *dataStart = data) { byte *dataPtr = dataStart; UInt16 entrySelector = 0; UInt16 searchRange = 1; while (searchRange < tableCount >> 1) { entrySelector++; searchRange <<= 1; } searchRange <<= 4; UInt16 rangeShift = (UInt16)((tableCount << 4) - searchRange); FontHeader *offsetTable = (FontHeader *)dataPtr; offsetTable->fVersion = (Int32)SwapBytes((UInt16)1); offsetTable->fNumTables = SwapBytes((UInt16)tableCount); offsetTable->fSearchRange = SwapBytes((UInt16)searchRange); offsetTable->fEntrySelector = SwapBytes((UInt16)entrySelector); offsetTable->fRangeShift = SwapBytes((UInt16)rangeShift); dataPtr += sizeof(FontHeader); TableEntry *entry = (TableEntry *)dataPtr; dataPtr += sizeof(TableEntry) * tableCount; for (int index = 0; index < tableCount; ++index) { int aTag = (int)CFArrayGetValueAtIndex(tags, index); IntPtr tableDataRef = CGFontCopyTableForTag(cgFont.Handle, aTag); nint tableSize = 0; if (tableDataRef != IntPtr.Zero) { tableSize = CFDataGetLength(tableDataRef); Buffer.MemoryCopy((byte *)CFDataGetBytePtr(tableDataRef), dataPtr, tableSize, tableSize); entry->fTag = SwapBytes((UInt32)aTag); entry->fCheckSum = SwapBytes(CalcTableCheckSum((UInt32 *)dataPtr, tableSize)); UInt32 offset = (UInt32)(dataPtr - dataStart); entry->fOffset = SwapBytes((UInt32)offset); entry->fLength = SwapBytes((UInt32)tableSize); CFRelease(tableDataRef); } dataPtr += (tableSize + 3) & ~3; ++entry; } } var fontSource = XFontSource.GetOrCreateFrom(typefaceKey, data); return(fontSource); }
/// <summary> /// Create a GDI+ font and use its handle to retrieve font data using native calls. /// </summary> internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, out GdiFont font, string typefaceKey) { if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } #if true_ if (familyName == "Cambria") { Debug - Break.Break(); } #endif GdiFontStyle gdiStyle = (GdiFontStyle)(fontResolvingOptions.FontStyle & XFontStyle.BoldItalic); // Create a 10 point GDI+ font as an exemplar. XFontSource fontSource; font = FontHelper.CreateFont(familyName, 10, gdiStyle, out fontSource); if (fontSource != null) { Debug.Assert(font != null); // Case: Font was created by a GDI+ private font collection. #if true #if DEBUG XFontSource existingFontSource; Debug.Assert(FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out existingFontSource) && ReferenceEquals(fontSource, existingFontSource)); #endif #else // Win32 API cannot get font data from fonts created by private font collection, // because this is handled internally in GDI+. // Therefore the font source was created when the private font is added to the private font collection. if (!FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out fontSource)) { // Simplify styles. // (The code is written for clarity - do not rearrange for optimization) if (font.Bold && font.Italic) { if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, true, false), out fontSource)) { // Use bold font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, true), out fontSource)) { // Use italic font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { // Use regular font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } else if (font.Bold || font.Italic) { // Use regular font. if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } else { if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { // Should never come here... FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } } #endif } else { // Get or create the font source and cache it unter the specified typeface key. fontSource = XFontSource.GetOrCreateFromGdi(typefaceKey, font); } return(fontSource); }
//// Suffix for internal face names to indicate that the font data comes from the platform //// and not from the users font resolver. //public const string PlatformTag = "platform:"; /// <summary> /// Converts specified information about a required typeface into a specific font. /// </summary> /// <param name="familyName">Name of the font family.</param> /// <param name="fontResolvingOptions">The font resolving options.</param> /// <param name="typefaceKey">Typeface key if already known by caller, null otherwise.</param> /// <returns> /// Information about the typeface, or null if no typeface can be found. /// </returns> public static FontResolverInfo ResolveTypeface(string familyName, FontResolvingOptions fontResolvingOptions, string typefaceKey) { if (string.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } try { Lock.EnterFontFactory(); // Was this typeface requested before? FontResolverInfo fontResolverInfo; if (FontResolverInfosByName.TryGetValue(typefaceKey, out fontResolverInfo)) { return(fontResolverInfo); } // Case: This typeface was not resolved before. // Is there a custom font resolver available? IFontResolver customFontResolver = GlobalFontSettings.FontResolver; if (customFontResolver != null) { // Case: Use custom font resolver. fontResolverInfo = customFontResolver.ResolveTypeface(familyName, fontResolvingOptions.IsBold, fontResolvingOptions.IsItalic); // If resolved by custom font resolver register info and font source. if (fontResolverInfo != null && !(fontResolverInfo is PlatformFontResolverInfo)) { string resolverInfoKey = fontResolverInfo.Key; FontResolverInfo existingFontResolverInfo; if (FontResolverInfosByName.TryGetValue(resolverInfoKey, out existingFontResolverInfo)) { // Case: A new typeface was resolved with the same info as a previous one. // Discard new object an reuse previous one. fontResolverInfo = existingFontResolverInfo; // Associate with typeface key. FontResolverInfosByName.Add(typefaceKey, fontResolverInfo); #if DEBUG // The font source should exist. Debug.Assert(FontSourcesByName.ContainsKey(fontResolverInfo.FaceName)); #endif } else { // Case: No such font resolver info exists. // Add to both dictionaries. FontResolverInfosByName.Add(typefaceKey, fontResolverInfo); Debug.Assert(resolverInfoKey == fontResolverInfo.Key); FontResolverInfosByName.Add(resolverInfoKey, fontResolverInfo); // Create font source if not yet exists. XFontSource previousFontSource; if (FontSourcesByName.TryGetValue(fontResolverInfo.FaceName, out previousFontSource)) { // Case: The font source exists, because a previous font resolver info comes // with the same face name, but was different in style simulation flags. // Nothing to do. } else { // Case: Get font from custom font resolver and create font source. byte[] bytes = customFontResolver.GetFont(fontResolverInfo.FaceName); XFontSource fontSource = XFontSource.GetOrCreateFrom(bytes); // Add font source's font resolver name if it is different to the face name. if (string.Compare(fontResolverInfo.FaceName, fontSource.FontName, StringComparison.OrdinalIgnoreCase) != 0) { FontSourcesByName.Add(fontResolverInfo.FaceName, fontSource); } } } } } else { // Case: There was no custom font resolver set. // Use platform font resolver. // If it was successful resolver info and font source are cached // automatically by PlatformFontResolver.ResolveTypeface. fontResolverInfo = PlatformFontResolver.ResolveTypeface(familyName, fontResolvingOptions, typefaceKey); } // Return value is null if the typeface could not be resolved. // In this case PDFsharp stops. return(fontResolverInfo); } finally { Lock.ExitFontFactory(); } }