#region PDFsharp - A .NET library for processing PDF // // Authors: // Stefan Lange // // Copyright (c) 2005-2016 empira Software GmbH, Cologne Area (Germany) // // http://www.PdfSharp.com // http://sourceforge.net/projects/pdfsharp // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. #endregion // #??? Clean up using System; using System.Diagnostics; using System.Globalization; using System.ComponentModel; using PdfSharpCore.Fonts; using PdfSharpCore.Fonts.OpenType; using PdfSharpCore.Pdf; namespace PdfSharpCore.Drawing { /// /// Defines an object used to draw text. /// [DebuggerDisplay("{DebuggerDisplay}")] public sealed class XFont { /// /// Initializes a new instance of the class. /// /// Name of the font family. /// The em size. public XFont(string familyName, double emSize) : this(familyName, emSize, XFontStyle.Regular, new XPdfFontOptions(GlobalFontSettings.DefaultFontEncoding)) { } /// /// Initializes a new instance of the class. /// /// Name of the font family. /// The em size. /// The font style. public XFont(string familyName, double emSize, XFontStyle style) : this(familyName, emSize, style, new XPdfFontOptions(GlobalFontSettings.DefaultFontEncoding)) { } /// /// Initializes a new instance of the class. /// /// Name of the font family. /// The em size. /// The font style. /// Additional PDF options. public XFont(string familyName, double emSize, XFontStyle style, XPdfFontOptions pdfOptions) { _familyName = familyName; _emSize = emSize; _style = style; _pdfOptions = pdfOptions; Initialize(); } internal XFont(string familyName, double emSize, XFontStyle style, XPdfFontOptions pdfOptions, XStyleSimulations styleSimulations) { _familyName = familyName; _emSize = emSize; _style = style; _pdfOptions = pdfOptions; OverrideStyleSimulations = true; StyleSimulations = styleSimulations; Initialize(); } /// /// Initializes this instance by computing the glyph typeface, font family, font source and TrueType fontface. /// (PDFsharp currently only deals with TrueType fonts.) /// void Initialize() { #if DEBUG if (_familyName == "Segoe UI Semilight" && (_style & XFontStyle.BoldItalic) == XFontStyle.Italic) GetType(); #endif FontResolvingOptions fontResolvingOptions = OverrideStyleSimulations ? new FontResolvingOptions(_style, StyleSimulations) : new FontResolvingOptions(_style); // HACK: 'PlatformDefault' is used in unit test code. if (StringComparer.OrdinalIgnoreCase.Compare(_familyName, GlobalFontSettings.DefaultFontName) == 0) { } // In principle an XFont is an XGlyphTypeface plus an em-size. _glyphTypeface = XGlyphTypeface.GetOrCreateFrom(_familyName, fontResolvingOptions); CreateDescriptorAndInitializeFontMetrics(); } /// /// Code separated from Metric getter to make code easier to debug. /// (Setup properties in their getters caused side effects during debugging because Visual Studio calls a getter /// to early to show its value in a debugger window.) /// void CreateDescriptorAndInitializeFontMetrics() // TODO: refactor { Debug.Assert(_fontMetrics == null, "InitializeFontMetrics() was already called."); _descriptor = (OpenTypeDescriptor)FontDescriptorCache.GetOrCreateDescriptorFor(this); //_familyName, _style, _glyphTypeface.Fontface); _fontMetrics = new XFontMetrics(_descriptor.FontName, _descriptor.UnitsPerEm, _descriptor.Ascender, _descriptor.Descender, _descriptor.Leading, _descriptor.LineSpacing, _descriptor.CapHeight, _descriptor.XHeight, _descriptor.StemV, 0, 0, 0, _descriptor.UnderlinePosition, _descriptor.UnderlineThickness, _descriptor.StrikeoutPosition, _descriptor.StrikeoutSize); XFontMetrics fm = Metrics; // Already done in CreateDescriptorAndInitializeFontMetrics. //if (_descriptor == null) // _descriptor = (OpenTypeDescriptor)FontDescriptorStock.Global.CreateDescriptor(this); //(Name, (XGdiFontStyle)Font.Style); UnitsPerEm = _descriptor.UnitsPerEm; CellAscent = _descriptor.Ascender; CellDescent = _descriptor.Descender; CellSpace = _descriptor.LineSpacing; Debug.Assert(fm.UnitsPerEm == _descriptor.UnitsPerEm); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Gets the XFontFamily object associated with this XFont object. /// [Browsable(false)] public XFontFamily FontFamily { get { return _glyphTypeface.FontFamily; } } /// /// WRONG: Gets the face name of this Font object. /// Indeed it returns the font family name. /// // [Obsolete("This function returns the font family name, not the face name. Use xxx.FontFamily.Name or xxx.FaceName")] public string Name { get { return _glyphTypeface.FontFamily.Name; } } internal string FaceName { get { return _glyphTypeface.FaceName; } } /// /// Gets the em-size of this font measured in the unit of this font object. /// public double Size { get { return _emSize; } } readonly double _emSize; /// /// Gets style information for this Font object. /// [Browsable(false)] public XFontStyle Style { get { return _style; } } readonly XFontStyle _style; /// /// Indicates whether this XFont object is bold. /// public bool Bold { get { return (_style & XFontStyle.Bold) == XFontStyle.Bold; } } /// /// Indicates whether this XFont object is italic. /// public bool Italic { get { return (_style & XFontStyle.Italic) == XFontStyle.Italic; } } /// /// Indicates whether this XFont object is stroke out. /// public bool Strikeout { get { return (_style & XFontStyle.Strikeout) == XFontStyle.Strikeout; } } /// /// Indicates whether this XFont object is underlined. /// public bool Underline { get { return (_style & XFontStyle.Underline) == XFontStyle.Underline; } } /// /// Temporary HACK for XPS to PDF converter. /// internal bool IsVertical { get { return _isVertical; } set { _isVertical = value; } } bool _isVertical; /// /// Gets the PDF options of the font. /// public XPdfFontOptions PdfOptions { get { return _pdfOptions ?? (_pdfOptions = new XPdfFontOptions()); } } XPdfFontOptions _pdfOptions; /// /// Indicates whether this XFont is encoded as Unicode. /// internal bool Unicode { get { return _pdfOptions != null && _pdfOptions.FontEncoding == PdfFontEncoding.Unicode; } } /// /// Gets the cell space for the font. The CellSpace is the line spacing, the sum of CellAscent and CellDescent and optionally some extra space. /// public int CellSpace { get { return _cellSpace; } internal set { _cellSpace = value; } } int _cellSpace; /// /// Gets the cell ascent, the area above the base line that is used by the font. /// public int CellAscent { get { return _cellAscent; } internal set { _cellAscent = value; } } int _cellAscent; /// /// Gets the cell descent, the area below the base line that is used by the font. /// public int CellDescent { get { return _cellDescent; } internal set { _cellDescent = value; } } int _cellDescent; /// /// Gets the font metrics. /// /// The metrics. public XFontMetrics Metrics { get { // Code moved to InitializeFontMetrics(). //if (_fontMetrics == null) //{ // FontDescriptor descriptor = FontDescriptorStock.Global.CreateDescriptor(this); // _fontMetrics = new XFontMetrics(descriptor.FontName, descriptor.UnitsPerEm, descriptor.Ascender, descriptor.Descender, // descriptor.Leading, descriptor.LineSpacing, descriptor.CapHeight, descriptor.XHeight, descriptor.StemV, 0, 0, 0); //} Debug.Assert(_fontMetrics != null, "InitializeFontMetrics() not yet called."); return _fontMetrics; } } XFontMetrics _fontMetrics; /// /// Returns the line spacing, in pixels, of this font. The line spacing is the vertical distance /// between the base lines of two consecutive lines of text. Thus, the line spacing includes the /// blank space between lines along with the height of the character itself. /// public double GetHeight() { double value = CellSpace * _emSize / UnitsPerEm; return value; } /// /// Gets the line spacing of this font. /// [Browsable(false)] public int Height { // Implementation from System.Drawing.Font.cs get { return (int)Math.Ceiling(GetHeight()); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal XGlyphTypeface GlyphTypeface { get { return _glyphTypeface; } } XGlyphTypeface _glyphTypeface; internal OpenTypeDescriptor Descriptor { get { return _descriptor; } private set { _descriptor = value; } } OpenTypeDescriptor _descriptor; internal string FamilyName { get { return _familyName; } } string _familyName; internal int UnitsPerEm { get { return _unitsPerEm; } private set { _unitsPerEm = value; } } internal int _unitsPerEm; /// /// Override style simulations by using the value of StyleSimulations. /// internal bool OverrideStyleSimulations; /// /// Used to enforce style simulations by renderer. For development purposes only. /// internal XStyleSimulations StyleSimulations; /// /// Cache PdfFontTable.FontSelector to speed up finding the right PdfFont /// if this font is used more than once. /// internal string Selector { get { return _selector; } set { _selector = value; } } string _selector; /// /// Gets the DebuggerDisplayAttribute text. /// // ReSharper disable UnusedMember.Local string DebuggerDisplay // ReSharper restore UnusedMember.Local { get { return String.Format(CultureInfo.InvariantCulture, "font=('{0}' {1:0.##})", Name, Size); } } } }