public static IFontStyle GetStyleWithWeightNearestTo(
            this IFontFamily family,
            int weight,
            FontStyleType type = FontStyleType.Normal)
        {
            if (family == null)
            {
                return(null);
            }

            IFontStyle closest           = null;
            var        closestDifference = int.MaxValue;

            foreach (var font in family.GetFontStyles())
            {
                if (font.StyleType == type)
                {
                    var difference = Math.Abs(font.Weight - weight);
                    if (difference == 0)
                    {
                        return(font);
                    }

                    if (difference < closestDifference)
                    {
                        closest           = font;
                        closestDifference = difference;
                    }
                }
            }

            return(closest);
        }
Example #2
0
        /// <summary>
        /// Find the first valid IFontFamily, if any, for this FontFamily and sets the style, weight,
        /// and stretch to valies implied by the font family (e.g., "Arial Bold" implies FontWeight.Bold).
        /// </summary>
        internal IFontFamily FindFirstFontFamilyAndFace(
            ref FontStyle style,
            ref FontWeight weight,
            ref FontStretch stretch
            )
        {
            if (_familyIdentifier.Source == null)
            {
                Invariant.Assert(_firstFontFamily != null, "Unnamed FontFamily should have a non-null first font family");
                return(_firstFontFamily);
            }

            IFontFamily firstFontFamily = null;

            _familyIdentifier.Canonicalize();

            for (int i = 0, c = _familyIdentifier.Count; firstFontFamily == null && i < c; ++i)
            {
                firstFontFamily = LookupFontFamilyAndFace(
                    _familyIdentifier[i],
                    ref style,
                    ref weight,
                    ref stretch);
            }

            return(firstFontFamily);
        }
Example #3
0
 internal Font(IFontFamily fontFamily, int emSize, FontStyle fontStyle, GraphicsUnit graphicsUnit)
     : base(new System.Drawing.Font(fontFamily.Unwrap(),
                                    emSize,
                                    fontStyle.FromNPlot(),
                                    graphicsUnit.FromNPlot()))
 {
 }
Example #4
0
        public FontFace(IFontFamily family, IFontFace face)
        {
            _family = family;
            _face   = face;

            var fontMetrics = new FontMetrics();

            _face.get_FontMetrics(fontMetrics);
            FontMetrics = fontMetrics;

            GC.AddMemoryPressure(10240);
        }
Example #5
0
        internal CompositeFontFamily(
            string          friendlyName,
            IFontFamily     firstFontFamily
            ) :
            this()
        {
            FamilyMaps.Add(
                new FontFamilyMap(
                    0, FontFamilyMap.LastUnicodeScalar,
                    null, // any language
                    friendlyName,
                    1     // scaleInEm
                    )
                );


            _firstFontFamily = firstFontFamily;
        }
Example #6
0
        /// <summary>
        /// Construct a composite font family with a single target family name
        /// after the first font family in the target family is known
        /// </summary>
        internal CompositeFontFamily(
            string friendlyName,
            IFontFamily firstFontFamily
            ) :
            this()
        {
            FamilyMaps.Add(
                new FontFamilyMap(
                    0, FontFamilyMap.LastUnicodeScalar,
                    null, // any language
                    friendlyName,
                    1     // scaleInEm
                    )
                );


            _firstFontFamily = firstFontFamily;
        }
Example #7
0
        /// <summary>
        /// Get the first font family of the first target family name
        /// </summary>
        private IFontFamily GetFirstFontFamily()
        {
            if (_firstFontFamily == null)
            {
                if (_fontInfo.FamilyMaps.Count != 0)
                {
                    _firstFontFamily = FontFamily.FindFontFamilyFromFriendlyNameList(_fontInfo.FamilyMaps[0].Target);
                }
                else
                {
                    _firstFontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName);
                }

                Invariant.Assert(_firstFontFamily != null);
            }

            return(_firstFontFamily);
        }
Example #8
0
        /// <summary>
        /// Create font family from canonical family and ensure at least a
        /// fallback family is created if the specified name cannot be resolved.
        /// </summary>
        internal static IFontFamily SafeLookupFontFamily(
            CanonicalFontFamilyReference canonicalName,
            out bool nullFont
            )
        {
            nullFont = false;

            IFontFamily fontFamily = LookupFontFamily(canonicalName);

            if (fontFamily == null)
            {
                nullFont   = true;
                fontFamily = LookupFontFamily(NullFontFamilyCanonicalName);
                Invariant.Assert(fontFamily != null, "Unable to create null font family");
            }

            return(fontFamily);
        }
        /// <summary>
        /// Maps characters that could not be resolved to any font family either to the first
        /// valid physical font family or to the default font we use for display null glyphs.
        /// </summary>
        private int MapUnresolvedCharacters(
            CharacterBufferRange unicodeString,
            CultureInfo culture,
            CultureInfo digitCulture,
            PhysicalFontFamily firstValidFamily,
            ref int firstValidLength,
            SpanVector scaledTypefaceSpans,
            int firstCharIndex,
            out int nextValid
            )
        {
            // If we have a valid font family use it. We don't set nullFont to true in this case.
            // We may end up displaying missing glyphs, but we don't need to force it.
            IFontFamily fontFamily = firstValidFamily;
            bool        nullFont   = false;

            if (firstValidLength <= 0)
            {
                // We didn't find any valid physical font family so use the default "Arial", and
                // set nullFont to true to ensure that we always display missing glyphs.
                fontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName);
                Invariant.Assert(fontFamily != null);
                nullFont = true;
            }

            return(MapByFontFaceFamily(
                       unicodeString,
                       culture,
                       digitCulture,
                       fontFamily,
                       _canonicalStyle,
                       _canonicalWeight,
                       _canonicalStretch,
                       ref firstValidFamily,
                       ref firstValidLength,
                       null, // device font
                       nullFont,
                       1.0,
                       scaledTypefaceSpans,
                       firstCharIndex,
                       true, // ignore missing
                       out nextValid
                       ));
        }
        internal CachedTypeface(
            FontStyle        canonicalStyle,
            FontWeight       canonicalWeight,
            FontStretch      canonicalStretch,
            IFontFamily      firstFontFamily,
            ITypefaceMetrics typefaceMetrics,
            bool             nullFont
            )
        {
            _canonicalStyle   = canonicalStyle;
            _canonicalWeight  = canonicalWeight;
            _canonicalStretch = canonicalStretch;

            Invariant.Assert(firstFontFamily != null && typefaceMetrics != null);
            
            _firstFontFamily  = firstFontFamily;
            _typefaceMetrics  = typefaceMetrics;
            _nullFont         = nullFont;            
        }        
Example #11
0
        internal CachedTypeface(
            FontStyle canonicalStyle,
            FontWeight canonicalWeight,
            FontStretch canonicalStretch,
            IFontFamily firstFontFamily,
            ITypefaceMetrics typefaceMetrics,
            bool nullFont
            )
        {
            _canonicalStyle   = canonicalStyle;
            _canonicalWeight  = canonicalWeight;
            _canonicalStretch = canonicalStretch;

            Invariant.Assert(firstFontFamily != null && typefaceMetrics != null);

            _firstFontFamily = firstFontFamily;
            _typefaceMetrics = typefaceMetrics;
            _nullFont        = nullFont;
        }
Example #12
0
        private FontFamily CreateFontFamily(CompositeFontFamily compositeFontFamily, Uri fontFamilyBaseUri, string fontFamilyLocationReference)
        {
            IFontFamily          fontFamily  = (IFontFamily)compositeFontFamily;
            IEnumerator <string> familyNames = fontFamily.Names.Values.GetEnumerator();

            if (familyNames.MoveNext())
            {
                string ordinalName         = familyNames.Current;
                string fontFamilyReference = Util.ConvertFamilyNameAndLocationToFontFamilyReference(
                    ordinalName,
                    fontFamilyLocationReference
                    );

                string friendlyName = Util.ConvertFontFamilyReferenceToFriendlyName(fontFamilyReference);

                return(new FontFamily(fontFamilyBaseUri, friendlyName));
            }
            return(null);
        }
Example #13
0
        /// <summary>
        /// Creates a new object.
        /// </summary>
        public WebSiteGraphics()
        {
            _ImageFile    = Factory.ResolveSingleton <IImageFile>();
            _PenFactory   = Factory.ResolveSingleton <IPenFactory>();
            _BrushFactory = Factory.ResolveSingleton <IBrushFactory>();
            _FontFactory  = Factory.ResolveSingleton <IFontFactory>();

            _SplashFillBrush  = _BrushFactory.CreateBrush(255, 255, 255, 255, useCache: true);
            _SplashFontFamily = _FontFactory.GetFontFamilyOrFallback(
                _SplashFontStyle,
                "Tahoma",
                "Microsoft Sans Serif",
                "MS Reference Sans Serif",
                "Roboto",
                "Droid Sans",
                "MS Sans Serif",
                "Verdana",
                "Helvetica",
                "Sans Serif",
                "Sans"
                );
        }
Example #14
0
        /// <summary>
        /// Scan the friendly name string finding the first valid font family
        /// </summary>
        internal static IFontFamily FindFontFamilyFromFriendlyNameList(string friendlyNameList)
        {
            IFontFamily firstFontFamily = null;

            // Split limits the number of tokens in a family name.
            FontFamilyIdentifier identifier = new FontFamilyIdentifier(friendlyNameList, null);

            for (int i = 0, c = identifier.Count; firstFontFamily == null && i < c; i++)
            {
                firstFontFamily = LookupFontFamily(identifier[i]);
            }

            if (firstFontFamily == null)
            {
                // cannot find first font family, assume null font for first font family
                firstFontFamily = LookupFontFamily(NullFontFamilyCanonicalName);

                // null font family should always exist
                Invariant.Assert(firstFontFamily != null);
            }

            return(firstFontFamily);
        }
        /// <summary>
        /// Map characters by font face family
        /// </summary>
        private int MapByFontFaceFamily(
            CharacterBufferRange unicodeString,
            CultureInfo culture,
            CultureInfo digitCulture,
            IFontFamily fontFamily,
            FontStyle canonicalStyle,
            FontWeight canonicalWeight,
            FontStretch canonicalStretch,
            ref PhysicalFontFamily firstValidFamily,
            ref int firstValidLength,
            IDeviceFont deviceFont,
            bool nullFont,
            double scaleInEm,
            SpanVector scaledTypefaceSpans,
            int firstCharIndex,
            bool ignoreMissing,
            out int nextValid
            )
        {
            Invariant.Assert(fontFamily != null);

            PhysicalFontFamily fontFaceFamily = fontFamily as PhysicalFontFamily;

            Invariant.Assert(fontFaceFamily != null);

            int advance = unicodeString.Length;

            nextValid = 0;

            GlyphTypeface glyphTypeface = null;

            if (ignoreMissing)
            {
                glyphTypeface = fontFaceFamily.GetGlyphTypeface(canonicalStyle, canonicalWeight, canonicalStretch);
            }
            else if (nullFont)
            {
                glyphTypeface = fontFaceFamily.GetGlyphTypeface(canonicalStyle, canonicalWeight, canonicalStretch);

                advance   = 0; // by definition, null font always yields missing glyphs for whatever codepoint
                nextValid = unicodeString.Length;
            }
            else
            {
                glyphTypeface = fontFaceFamily.MapGlyphTypeface(
                    canonicalStyle,
                    canonicalWeight,
                    canonicalStretch,
                    unicodeString,
                    digitCulture,
                    ref advance,
                    ref nextValid
                    );
            }

            Invariant.Assert(glyphTypeface != null);

            int cch = unicodeString.Length;

            if (!ignoreMissing && advance > 0)
            {
                cch = advance;
            }

            // Do we need to set firstValidFamily?
            if (firstValidLength <= 0)
            {
                // Either firstValidFamily hasn't been set, or has "expired" (see below). The first valid
                // family is the first existing physical font in the font linking chain. We want to remember
                // it so we can use it to map any unresolved characters.
                firstValidFamily = fontFaceFamily;

                // Set the "expiration date" for firstValidFamily. We know that this is the first physical
                // font for the specified character range, but after that family map lookup may result in
                // a different first physical family.
                firstValidLength = unicodeString.Length;
            }

            // Each time we advance we near the expiration date for firstValidFamily.
            firstValidLength -= advance;


            Debug.Assert(cch > 0);
            scaledTypefaceSpans.SetValue(
                firstCharIndex,
                cch,
                new ScaledShapeTypeface(
                    glyphTypeface,
                    deviceFont,
                    scaleInEm,
                    nullFont
                    )
                );

            return(advance);
        }
 public static IFontStyle GetBoldStyle(
     this IFontFamily family,
     FontStyleType type = FontStyleType.Normal)
 {
     return(family?.GetStyleWithWeightNearestTo(500, type));
 }
Example #17
0
 internal Font(IFontFamily fontFamily, float emSize) : base(new System.Drawing.Font(fontFamily.Unwrap(), emSize))
 {
 }
 public static IFontFamily CreateRef(this IFontFamily objectRef) =>
 ((IFontFamily)objectRef.CreateRef(typeof(IFontFamily)));
Example #19
0
        internal static IFontFamily LookupFontFamilyAndFace(
            CanonicalFontFamilyReference canonicalFamilyReference,
            ref FontStyle style,
            ref FontWeight weight,
            ref FontStretch stretch
            )
        {
            if (canonicalFamilyReference == null || object.ReferenceEquals(canonicalFamilyReference, CanonicalFontFamilyReference.Unresolved))
            {
                // no canonical name, e.g., because the friendly name was an empty string
                // or could not be canonicalized
                return(null);
            }

            try
            {
                FamilyCollection familyCollection;

                if (canonicalFamilyReference.LocationUri == null && canonicalFamilyReference.EscapedFileName == null)
                {
                    // No explicit location; use the default family collection.
                    familyCollection = _defaultFamilyCollection;
                }
                else if (canonicalFamilyReference.LocationUri != null)
                {
                    // Look in the location specified by the font family reference.
                    familyCollection = FamilyCollection.FromUri(canonicalFamilyReference.LocationUri);
                }
                else // canonicalFamilyReference.EscapedFileName != null
                {
                    // Look in the specified file in the Windows Fonts folder
                    // Note: CanonicalFamilyReference.EscapedFileName is safe to combine with Util.WindowsFontsUriObject because CanonicalFamilyReference guarantees that it will be a simple filename
                    // without relative path or directory components.
                    Uri locationUri = new Uri(Util.WindowsFontsUriObject, canonicalFamilyReference.EscapedFileName);
                    familyCollection = FamilyCollection.FromWindowsFonts(locationUri);
                }

                IFontFamily fontFamily = familyCollection.LookupFamily(
                    canonicalFamilyReference.FamilyName,
                    ref style,
                    ref weight,
                    ref stretch
                    );
                return(fontFamily);
            }
            // The method returns null in case of malformed/non-existent fonts and we fall back to the next font.
            // Therefore, we can disable PreSharp warning about empty catch bodies.
#pragma warning disable 6502
            catch (FileFormatException)
            {
                // malformed font file
            }
            catch (IOException)
            {
                // canonical name points to a place that doesn't exist or can't be read for some reason
            }
            catch (UnauthorizedAccessException)
            {
                // canonical name points to a place caller doesn't have permission to access
            }
            catch (ArgumentException)
            {
                // canonical name points to a valid Uri that doesn't point to a well formed
                // OS local path
            }
            catch (NotSupportedException)
            {
                // canonical name points to a Uri that specifies an unregistered scheme
            }
            catch (UriFormatException)
            {
                // canonical name points to a malformed Uri
            }
#pragma warning restore 6502
            // we want to fall back to the default fallback font instead of crashing
            return(null);
        }
Example #20
0
        FontStyle GetFontStyleForFamily( IFontFamily family )
        {
            FontStyle style = 0;

            if ( family.IsStyleAvailable( FontStyle.Regular ) )
                style = FontStyle.Regular;

            foreach ( var ctl in _fontStyleControls )
            {
                if ( ctl.Control.Checked && family.IsStyleAvailable( style & ctl.Style ) )
                    style |= ctl.Style;
            }

            // If we still haven't arrived at a valid style, then let's just set any style this font will support.
            if ( !family.IsStyleAvailable( style ) )
            {
                int numFontStyleBits = 5;
                for ( int i=0; i < (int)Math.Pow( 2, numFontStyleBits ); i++ )
                {
                    style = (FontStyle)i;
                    if ( family.IsStyleAvailable( style ) )
                        break;
                }
            }

            return style;
        }
Example #21
0
 public static SD.FontFamily Unwrap(this IFontFamily obj) => ((FontFamily)obj)?.Inner;
Example #22
0
 /// <summary>
 /// Construct an anonymous font family, i.e., a composite font that is created
 /// programatically instead of referenced by name or URI.
 /// </summary>
 public FontFamily()
 {
     _familyIdentifier = new FontFamilyIdentifier(null, null);
     _firstFontFamily  = new CompositeFontFamily();
 }
Example #23
0
        /// <summary>
        /// Get the first font family of the first target family name
        /// </summary>
        private IFontFamily GetFirstFontFamily()
        {
            if(_firstFontFamily == null)
            {
                if (_fontInfo.FamilyMaps.Count != 0)
                {
                    _firstFontFamily = FontFamily.FindFontFamilyFromFriendlyNameList(_fontInfo.FamilyMaps[0].Target);
                }
                else
                {
                    _firstFontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName);
                }

                Invariant.Assert(_firstFontFamily != null);
            }

            return _firstFontFamily;
        }
Example #24
0
 /// <summary>
 /// Initializes a new instance of the FontFamily class with the specified handler
 /// </summary>
 /// <remarks>
 /// Used by platform implementations to create instances of the FontFamily class directly
 /// </remarks>
 /// <param name="generator">Generator for this instance</param>
 /// <param name="handler">Handler to use</param>
 public FontFamily(Generator generator, IFontFamily handler)
     : base(generator, handler, true)
 {
 }
Example #25
0
        /// <summary>
        /// Map characters by font face family 
        /// </summary> 
        private int MapByFontFaceFamily(
            CharacterBufferRange    unicodeString, 
            CultureInfo             culture,
            CultureInfo             digitCulture,
            IFontFamily             fontFamily,
            FontStyle               canonicalStyle, 
            FontWeight              canonicalWeight,
            FontStretch             canonicalStretch, 
            ref PhysicalFontFamily  firstValidFamily, 
            ref int                 firstValidLength,
            IDeviceFont             deviceFont, 
            bool                    nullFont,
            double                  scaleInEm,
            SpanVector              scaledTypefaceSpans,
            int                     firstCharIndex, 
            bool                    ignoreMissing,
            out int                 nextValid 
            ) 
        {
            Invariant.Assert(fontFamily != null); 

            PhysicalFontFamily fontFaceFamily = fontFamily as PhysicalFontFamily;
            Invariant.Assert(fontFaceFamily != null);
 
            int advance = unicodeString.Length;
            nextValid = 0; 
 
            GlyphTypeface glyphTypeface = null;
 
            if(ignoreMissing)
            {
                glyphTypeface = fontFaceFamily.GetGlyphTypeface(canonicalStyle, canonicalWeight, canonicalStretch);
            } 
            else if(nullFont)
            { 
                glyphTypeface = fontFaceFamily.GetGlyphTypeface(canonicalStyle, canonicalWeight, canonicalStretch); 

                advance = 0; // by definition, null font always yields missing glyphs for whatever codepoint 
                nextValid = unicodeString.Length;
            }
            else
            { 
                glyphTypeface = fontFaceFamily.MapGlyphTypeface(
                    canonicalStyle, 
                    canonicalWeight, 
                    canonicalStretch,
                    unicodeString, 
                    digitCulture,
                    ref advance,
                    ref nextValid
                    ); 
            }
 
            Invariant.Assert(glyphTypeface != null); 

            int cch = unicodeString.Length; 
            if(!ignoreMissing && advance > 0)
            {
                cch = advance;
            } 

            // Do we need to set firstValidFamily? 
            if (firstValidLength <= 0) 
            {
                // Either firstValidFamily hasn't been set, or has "expired" (see below). The first valid 
                // family is the first existing physical font in the font linking chain. We want to remember
                // it so we can use it to map any unresolved characters.
                firstValidFamily = fontFaceFamily;
 
                // Set the "expiration date" for firstValidFamily. We know that this is the first physical
                // font for the specified character range, but after that family map lookup may result in 
                // a different first physical family. 
                firstValidLength = unicodeString.Length;
            } 

            // Each time we advance we near the expiration date for firstValidFamily.
            firstValidLength -= advance;
 

            Debug.Assert(cch > 0); 
            scaledTypefaceSpans.SetValue( 
                firstCharIndex,
                cch, 
                new ScaledShapeTypeface(
                    glyphTypeface,
                    deviceFont,
                    scaleInEm, 
                    nullFont
                    ) 
                ); 

            return advance; 
        }
Example #26
0
        /// <summary>
        /// Map characters by font family 
        /// </summary>
        /// <remarks>
        /// Advance:
        ///     number of characters not mapped to missing glyph 
        ///
        /// NextValid: 
        ///     Offset to the nearest first character not mapped to missing glyph 
        ///
        /// [Number of invalid characters following valid ones] = NextValid - Advance 
        ///
        ///         A B C D E F G H x x x x x F G H I J
        ///         --------------->
        ///             Advance 
        ///
        ///         -------------------------> 
        ///                NextValid 
        ///
        /// </remarks> 
        private int MapByFontFamily(
            CharacterBufferRange            unicodeString,
            CultureInfo                     culture,
            CultureInfo                     digitCulture, 
            IFontFamily                     fontFamily,
            CanonicalFontFamilyReference    canonicalFamilyReference, 
            FontStyle                       canonicalStyle, 
            FontWeight                      canonicalWeight,
            FontStretch                     canonicalStretch, 
            ref PhysicalFontFamily          firstValidFamily,
            ref int                         firstValidLength,
            IDeviceFont                     deviceFont,
            double                          scaleInEm, 
            int                             recursionDepth,
            SpanVector                      scaledTypefaceSpans, 
            int                             firstCharIndex, 
            out int                         nextValid
            ) 
        {
            // This is the *one* place where we check for the font mapping depths of the font linking
            // process. This protects the linking process against extremely long chain of linking or
            // circular dependencies in the composite fonts. 
            if (recursionDepth >= MaxTypefaceMapDepths)
            { 
                // Stop the recursion. In effect, this FontFamily does not map any of the input. 
                // Higher-level code must map the input text to some other FontFamily, or to the
                // "null font" if there is no valid FontFamily. 
                nextValid = 0;
                return 0;
            }
 
            // If a device font is not already specified higher up the stack, look for a device font
            // for this font family that matches the typeface style, weight, and stretch. 
            if (deviceFont == null) 
            {
                deviceFont = fontFamily.GetDeviceFont(_canonicalStyle, _canonicalWeight, _canonicalStretch); 
            }

            DigitMap digitMap = new DigitMap(digitCulture);
 
            int advance = 0;
            int cchAdvance; 
            int cchNextValid; 
            int ich = 0;
 
            nextValid = 0;

            bool terminated = false;
 
            while (ich < unicodeString.Length  &&  !terminated)
            { 
                // Determine length of run with consistent mapping. Start by assuming we'll be able to 
                // use the whole string, then reduce to the length that can be mapped consistently.
                int cchMap = unicodeString.Length - ich; 

                // Determine whether the run is using a device font, and limit the run to the
                // first boundary between device/non-device font usage.
                bool useDeviceFont = false; 
                if (deviceFont != null)
                { 
                    // Determine whether the first run uses a device font by inspecting the first character. 
                    // We do not support device fonts for codepoints >= U+10000 (aka surrogates), so we
                    // don't need to call Classification.UnicodeScalar. 
                    useDeviceFont = deviceFont.ContainsCharacter(digitMap[unicodeString[ich]]);

                    // Advance as long as 'useDeviceFont' remains unchanged.
                    int i = ich + 1; 
                    while (    (i < unicodeString.Length)
                           &&  (useDeviceFont == deviceFont.ContainsCharacter(digitMap[unicodeString[i]]))) 
                    { 
                        i++;
                    } 

                    cchMap = i - ich;
                }
 

                // Map as many characters to a family as we can up to the limit (cchMap) just determined. 
                string targetFamilyName; 
                double mapSizeInEm;
 
                bool isCompositeFontFamily = fontFamily.GetMapTargetFamilyNameAndScale(
                    new CharacterBufferRange(
                        unicodeString,
                        ich, 
                        cchMap
                        ), 
                    culture, 
                    digitCulture,
                    scaleInEm, 
                    out cchMap,
                    out targetFamilyName,
                    out mapSizeInEm
                    ); 

                Debug.Assert(cchMap <= unicodeString.Length - ich); 
 
                CharacterBufferRange mappedString = new CharacterBufferRange(
                    unicodeString, 
                    ich,
                    cchMap
                    );
 

                if (!isCompositeFontFamily) 
                { 
                    // not a composite font family
                    cchAdvance = MapByFontFaceFamily( 
                        mappedString,
                        culture,
                        digitCulture,
                        fontFamily, 
                        canonicalStyle,
                        canonicalWeight, 
                        canonicalStretch, 
                        ref firstValidFamily,
                        ref firstValidLength, 
                        useDeviceFont ? deviceFont : null,
                        false, // nullFont
                        mapSizeInEm,
                        scaledTypefaceSpans, 
                        firstCharIndex + ich,
                        false, // ignoreMissing 
                        out cchNextValid 
                        );
                } 
                else if (!string.IsNullOrEmpty(targetFamilyName))
                {
                    // The base Uri used for resolving target family names is the Uri of the composite font.
                    Uri baseUri = (canonicalFamilyReference != null) ? canonicalFamilyReference.LocationUri : null; 

                    // map to the target of the family map 
                    cchAdvance = MapByFontFamilyName( 
                        mappedString,
                        culture, 
                        digitCulture,
                        targetFamilyName,
                        baseUri,
                        ref firstValidFamily, 
                        ref firstValidLength,
                        useDeviceFont ? deviceFont : null, 
                        mapSizeInEm, 
                        recursionDepth + 1, // increment the depth
                        scaledTypefaceSpans, 
                        firstCharIndex + ich,
                        out cchNextValid
                        );
                } 
                else
                { 
                    // family map lookup returned no target family 
                    cchAdvance = 0;
                    cchNextValid = cchMap; 
                }

                int cchValid = cchMap;
                int cchInvalid = 0; 

                cchValid = cchAdvance; 
                cchInvalid = cchNextValid; 

                if(cchValid < cchMap) 
                {
                    terminated = true;
                }
 
                advance += cchValid;
                nextValid = ich + cchInvalid; 
 
                ich += cchValid;
            } 

            return advance;
        }
Example #27
0
 public IFont CreateFont(IFontFamily fontFamily, int size) => new Font(fontFamily, size);
        private CachedTypeface ConstructCachedTypeface()
        {
            FontStyle   canonicalStyle   = _style;
            FontWeight  canonicalWeight  = _weight;
            FontStretch canonicalStretch = _stretch;

            //
            // We always call FontFamily.FindFirstFontFamilyAndFace() method to resolve the
            // canonical styles since the implied styles in FontFamily name will override
            // the given styles in the Typeface. But we don't always use the IFontFamily
            // instance returned from this method because an equal instance might already be
            // cached.
            //
            FontFamily sourceFontFamily = FontFamily;

            IFontFamily firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace(
                ref canonicalStyle,
                ref canonicalWeight,
                ref canonicalStretch
                );

            if (firstFontFamily == null)
            {
                if (FallbackFontFamily != null)
                {
                    sourceFontFamily = FallbackFontFamily;
                    firstFontFamily  = sourceFontFamily.FindFirstFontFamilyAndFace(
                        ref canonicalStyle,
                        ref canonicalWeight,
                        ref canonicalStretch
                        );
                }

                if (firstFontFamily == null)
                {
                    sourceFontFamily = null;
                    firstFontFamily  = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName);
                }
            }

            // If it's a named font, map all occurrences of the same name to one cached IFontFamily.
            if (sourceFontFamily != null && sourceFontFamily.Source != null)
            {
                // We lookup in the cache to see if there is cached IFontFamily instance of the source FontFamily. Otherwise,
                // this IFontFamily value is added to the TypefaceMetrics cache.
                IFontFamily cachedValue = TypefaceMetricsCache.ReadonlyLookup(sourceFontFamily.FamilyIdentifier) as IFontFamily;

                if (cachedValue != null)
                {
                    firstFontFamily = cachedValue;
                }
                else
                {
                    TypefaceMetricsCache.Add(sourceFontFamily.FamilyIdentifier, firstFontFamily);
                }
            }

            ITypefaceMetrics typefaceMetrics = firstFontFamily.GetTypefaceMetrics(canonicalStyle, canonicalWeight, canonicalStretch);

            return(new CachedTypeface(
                       canonicalStyle,
                       canonicalWeight,
                       canonicalStretch,
                       firstFontFamily,
                       typefaceMetrics,
                       sourceFontFamily == null
                       ));
        }
        /// <summary>
        /// Map characters by font family
        /// </summary>
        /// <remarks>
        /// Advance:
        ///     number of characters not mapped to missing glyph
        ///
        /// NextValid:
        ///     Offset to the nearest first character not mapped to missing glyph
        ///
        /// [Number of invalid characters following valid ones] = NextValid - Advance
        ///
        ///         A B C D E F G H x x x x x F G H I J
        ///         --------------->
        ///             Advance
        ///
        ///         ------------------------->
        ///                NextValid
        ///
        /// </remarks>
        private int MapByFontFamily(
            CharacterBufferRange unicodeString,
            CultureInfo culture,
            CultureInfo digitCulture,
            IFontFamily fontFamily,
            CanonicalFontFamilyReference canonicalFamilyReference,
            FontStyle canonicalStyle,
            FontWeight canonicalWeight,
            FontStretch canonicalStretch,
            ref PhysicalFontFamily firstValidFamily,
            ref int firstValidLength,
            IDeviceFont deviceFont,
            double scaleInEm,
            int recursionDepth,
            SpanVector scaledTypefaceSpans,
            int firstCharIndex,
            out int nextValid
            )
        {
            // This is the *one* place where we check for the font mapping depths of the font linking
            // process. This protects the linking process against extremely long chain of linking or
            // circular dependencies in the composite fonts.
            if (recursionDepth >= MaxTypefaceMapDepths)
            {
                // Stop the recursion. In effect, this FontFamily does not map any of the input.
                // Higher-level code must map the input text to some other FontFamily, or to the
                // "null font" if there is no valid FontFamily.
                nextValid = 0;
                return(0);
            }

            // If a device font is not already specified higher up the stack, look for a device font
            // for this font family that matches the typeface style, weight, and stretch.
            if (deviceFont == null)
            {
                deviceFont = fontFamily.GetDeviceFont(_canonicalStyle, _canonicalWeight, _canonicalStretch);
            }

            DigitMap digitMap = new DigitMap(digitCulture);

            int advance = 0;
            int cchAdvance;
            int cchNextValid;
            int ich = 0;

            nextValid = 0;

            bool terminated = false;

            while (ich < unicodeString.Length && !terminated)
            {
                // Determine length of run with consistent mapping. Start by assuming we'll be able to
                // use the whole string, then reduce to the length that can be mapped consistently.
                int cchMap = unicodeString.Length - ich;

                // Determine whether the run is using a device font, and limit the run to the
                // first boundary between device/non-device font usage.
                bool useDeviceFont = false;
                if (deviceFont != null)
                {
                    // Determine whether the first run uses a device font by inspecting the first character.
                    // We do not support device fonts for codepoints >= U+10000 (aka surrogates), so we
                    // don't need to call Classification.UnicodeScalar.
                    useDeviceFont = deviceFont.ContainsCharacter(digitMap[unicodeString[ich]]);

                    // Advance as long as 'useDeviceFont' remains unchanged.
                    int i = ich + 1;
                    while ((i < unicodeString.Length) &&
                           (useDeviceFont == deviceFont.ContainsCharacter(digitMap[unicodeString[i]])))
                    {
                        i++;
                    }

                    cchMap = i - ich;
                }


                // Map as many characters to a family as we can up to the limit (cchMap) just determined.
                string targetFamilyName;
                double mapSizeInEm;

                bool isCompositeFontFamily = fontFamily.GetMapTargetFamilyNameAndScale(
                    new CharacterBufferRange(
                        unicodeString,
                        ich,
                        cchMap
                        ),
                    culture,
                    digitCulture,
                    scaleInEm,
                    out cchMap,
                    out targetFamilyName,
                    out mapSizeInEm
                    );

                Debug.Assert(cchMap <= unicodeString.Length - ich);

                CharacterBufferRange mappedString = new CharacterBufferRange(
                    unicodeString,
                    ich,
                    cchMap
                    );


                if (!isCompositeFontFamily)
                {
                    // not a composite font family
                    cchAdvance = MapByFontFaceFamily(
                        mappedString,
                        culture,
                        digitCulture,
                        fontFamily,
                        canonicalStyle,
                        canonicalWeight,
                        canonicalStretch,
                        ref firstValidFamily,
                        ref firstValidLength,
                        useDeviceFont ? deviceFont : null,
                        false, // nullFont
                        mapSizeInEm,
                        scaledTypefaceSpans,
                        firstCharIndex + ich,
                        false, // ignoreMissing
                        out cchNextValid
                        );
                }
                else if (!string.IsNullOrEmpty(targetFamilyName))
                {
                    // The base Uri used for resolving target family names is the Uri of the composite font.
                    Uri baseUri = (canonicalFamilyReference != null) ? canonicalFamilyReference.LocationUri : null;

                    // map to the target of the family map
                    cchAdvance = MapByFontFamilyName(
                        mappedString,
                        culture,
                        digitCulture,
                        targetFamilyName,
                        baseUri,
                        ref firstValidFamily,
                        ref firstValidLength,
                        useDeviceFont ? deviceFont : null,
                        mapSizeInEm,
                        recursionDepth + 1, // increment the depth
                        scaledTypefaceSpans,
                        firstCharIndex + ich,
                        out cchNextValid
                        );
                }
                else
                {
                    // family map lookup returned no target family
                    cchAdvance   = 0;
                    cchNextValid = cchMap;
                }

                int cchValid   = cchMap;
                int cchInvalid = 0;

                cchValid   = cchAdvance;
                cchInvalid = cchNextValid;

                if (cchValid < cchMap)
                {
                    terminated = true;
                }

                advance  += cchValid;
                nextValid = ich + cchInvalid;

                ich += cchValid;
            }

            return(advance);
        }
Example #30
0
 /// <summary>
 /// Construct an anonymous font family, i.e., a composite font that is created
 /// programatically instead of referenced by name or URI.
 /// </summary> 
 public FontFamily()
 { 
     _familyIdentifier = new FontFamilyIdentifier(null, null); 
     _firstFontFamily = new CompositeFontFamily();
 } 
Example #31
0
 public IFont CreateFont(IFontFamily fontFamily, int emSize, FontStyle fontStyle, GraphicsUnit graphicsUnit)
 => new Font(fontFamily, emSize, fontStyle, graphicsUnit);