/// <summary> /// Function to register a font within the font cache. /// </summary> /// <param name="font">The font to register.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="font"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown if the <paramref name="font"/> is already registered in the factory cache.</exception> internal void RegisterFont(GorgonFont font) { if (font == null) { throw new ArgumentNullException(nameof(font)); } if (font.Factory != this) { throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_ALREADY_REGISTERED, font.Name), nameof(font)); } lock (_syncLock) { if (_fontCache.TryGetValue(font.Name, out GorgonFont existing)) { // This is the exact same reference, so do nothing. if (existing == font) { return; } throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_ALREADY_REGISTERED, font.Name), nameof(font)); } _fontCache[font.Name] = font; } }
/// <summary> /// Function to unregister a font from the factory cache. /// </summary> /// <param name="font">The font to unregister.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="font"/> parameter is <b>null</b>.</exception> /// <remarks> /// <para> /// This will remove the specified <paramref name="font"/> from the cache, but it will not destroy the font. If a font with the same name exists, but the font is not the same reference as the font passed in /// then nothing is done and the function will exit, the same happens when the font does not exist in the cache. /// </para> /// </remarks> internal void UnregisterFont(GorgonFont font) { if (font == null) { throw new ArgumentException(nameof(font)); } // Don't allow fonts not registered with this factory to be removed from the cache. if (font.Factory != this) { return; } lock (_syncLock) { if (!_fontCache.TryGetValue(font.Name, out GorgonFont existing)) { return; } // If this font is not the same as the one we want, then do nothing. if (existing != font) { return; } _fontCache.Remove(font.Name); } }
/// <summary> /// Function to return or create a new <see cref="GorgonFont"/>. /// </summary> /// <param name="fontInfo">The information used to create the font.</param> /// <returns>A new or existing <see cref="GorgonFont"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="fontInfo"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown when the <see cref="IGorgonFontInfo.TextureWidth"/> or <see cref="IGorgonFontInfo.TextureHeight"/> parameters exceed the <see cref="IGorgonVideoAdapterInfo.MaxTextureWidth"/> or /// <see cref="IGorgonVideoAdapterInfo.MaxTextureHeight"/> available for the current <see cref="FeatureSet"/>. /// <para>-or-</para> /// <para>Thrown if the <see cref="IGorgonFontInfo.Characters"/> list does not contain the <see cref="IGorgonFontInfo.DefaultCharacter"/> character.</para> /// <para>-or-</para> /// <para>A font with the same name was already created by the factory, but does not have the same parameters.</para> /// </exception> /// <remarks> /// <para> /// This method creates an object that contains a group of textures with font glyphs. These textures can be used by another application to display text (or symbols) on the screen. /// Kerning information (the proper spacing for a glyph), advances, etc... are all included for the glyphs with font. /// </para> /// <para> /// The <see cref="IGorgonNamedObject.Name"/> value on the <paramref name="fontInfo"/> parameter is used in caching, and is user defined. It is not necessary to have it share the same name as the /// font family name in the <paramref name="fontInfo"/> parameter, however it is best practice to indicate the font family name in the name for ease of use. By default, this parameter is set to the /// font family, height and unit of measure. /// </para> /// <para> /// If a font with the same name was previously created by this factory, then that font will be returned if the <paramref name="fontInfo"/> is the same as the cached version. If the font was not /// found by its name, then a new font will be created. Otherwise, if a cached font with the same name exists, but its <see cref="IGorgonFontInfo"/> is different from the <paramref name="fontInfo"/> /// passed in, then an exception will be thrown. /// </para> /// </remarks> public GorgonFont GetFont(IGorgonFontInfo fontInfo) { if (fontInfo == null) { throw new ArgumentNullException(nameof(fontInfo)); } lock (_syncLock) { // Check the cache for a font with the same name. if ((_fontCache.TryGetValue(fontInfo.Name, out GorgonFont result)) && (!IsFontDifferent(fontInfo, result.Info))) { return(result); } if (result != null) { throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_EXISTS, fontInfo.Name), nameof(fontInfo)); } if ((fontInfo.TextureWidth > Graphics.VideoAdapter.MaxTextureWidth) || (fontInfo.TextureHeight > Graphics.VideoAdapter.MaxTextureHeight)) { throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_TEXTURE_SIZE_TOO_LARGE, fontInfo.TextureWidth, fontInfo.TextureHeight), nameof(fontInfo)); } if (!fontInfo.Characters.Contains(fontInfo.DefaultCharacter)) { throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_DEFAULT_CHAR_DOES_NOT_EXIST, fontInfo.DefaultCharacter)); } if (Convert.ToInt32(fontInfo.DefaultCharacter) < 32) { throw new ArgumentException(string.Format(Resources.GORGFX_ERR_FONT_DEFAULT_CHAR_NOT_VALID, Convert.ToInt32(fontInfo.DefaultCharacter))); } // Destroy the previous font if one exists with the same name. result?.Dispose(); // If not found, then create a new font and cache it. _fontCache[fontInfo.Name] = result = new GorgonFont(fontInfo.Name, this, fontInfo); result.GenerateFont(new[] { _externalFonts }); return(result); } }
/// <summary> /// Initializes a new instance of the <see cref="GorgonFontFactory"/> class. /// </summary> /// <param name="graphics">The graphics interface used to create the font data.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/> parameter is <b>null</b>.</exception> public GorgonFontFactory(GorgonGraphics graphics) { Graphics = graphics ?? throw new ArgumentNullException(nameof(graphics)); _defaultFont = new Lazy <GorgonFont>(() => { // Create the default font. var result = new GorgonFont("Gorgon.Font.Default.SegoeUI_9pt", this, new GorgonFontInfo("Segoe UI", 9, FontHeightMode.Points) { AntiAliasingMode = FontAntiAliasMode.AntiAlias, FontStyle = FontStyle.Bold, OutlineSize = 0 }); result.GenerateFont(new[] { _externalFonts }); return(result); }, true); }