File: Core\CSharp\MS\Internal\Shaping\GlyphingCache.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// Description: High level glyphing cache
//
// History: 5-19-2005 garyyang created
//
//---------------------------------------------------------------------------- 
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
 
using MS.Internal;
using MS.Internal.TextFormatting;
 
namespace MS.Internal.Shaping
{
    /// <summary>
    /// GlyphingCache stores the runtime state of shaping engines and the mapping between Unicode scalar
    /// value and the physical font being used to display it. This class is not thread-safe. The client is 
    /// responsible for synchronizing access from multiple threads. It is generally recommended that the client 
    /// manages a single instance of this class per text formatting session. 
    ///
    /// It currently only caches one key-value pair:
    /// o Typeface - TypefaceMap
    ///
    /// This pair is cached in SizeLimitedCache which implement LRU algorithm through 
    /// a linked list. When cache is full, the least used entry in the cache will be replaced 
    /// by the latest entry. 
    /// </summary>
    internal class GlyphingCache
    {
        private SizeLimitedCache<Typeface, TypefaceMap>  _sizeLimitedCache;
    
        internal GlyphingCache(int capacity)
        {
            _sizeLimitedCache  = new SizeLimitedCache<Typeface, TypefaceMap>(capacity);
        }
 
        internal void GetShapeableText(
            Typeface                    typeface,
            CharacterBufferReference    characterBufferReference,
            int                         stringLength,
            TextRunProperties           textRunProperties,
            CultureInfo                 digitCulture,
            bool                        isRightToLeftParagraph,
            IList<TextShapeableSymbols> shapeableList,
            IShapeableTextCollector     collector,
            TextFormattingMode              textFormattingMode
            )
        {
            if (!typeface.Symbol)
            {
                Lookup(typeface).GetShapeableText(
                    characterBufferReference,
                    stringLength,
                    textRunProperties,
                    digitCulture,
                    isRightToLeftParagraph,
                    shapeableList,
                    collector,
                    textFormattingMode
                    );
            }
            else
            {
                // It's a non-Unicode ("symbol") font, where code points have non-standard meanings. We
                // therefore want to bypass the usual itemization and font linking. Instead, just map
                // everything to the default script and first GlyphTypeface.
 
                ShapeTypeface shapeTypeface = new ShapeTypeface(
                    typeface.TryGetGlyphTypeface(),
                    null // device font
                    );
 
                collector.Add(
                    shapeableList,
                    new CharacterBufferRange(characterBufferReference, stringLength),
                    textRunProperties,
                    new MS.Internal.Text.TextInterface.ItemProps(),
                    shapeTypeface,
                    1.0,   // scale in Em
                    false,  // null shape
                    textFormattingMode
                    );
            }
        }
 
        /// <summary>
        /// Look up the font mapping data for a typeface.
        /// </summary>
        private TypefaceMap Lookup(Typeface key)
        {
            TypefaceMap typefaceMap = _sizeLimitedCache.Get(key);
            if (typefaceMap == null)
            {                
                typefaceMap = new TypefaceMap(
                    key.FontFamily, 
                    key.FallbackFontFamily,
                    key.CanonicalStyle,
                    key.CanonicalWeight,
                    key.CanonicalStretch,
                    key.NullFont
                    );
                
                _sizeLimitedCache.Add(
                    key, 
                    typefaceMap, 
                    false   // is not permanent in the cache.
                    );
            }   
            
            return typefaceMap;
        }  
    }
}