123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- #region MIT License
- /*Copyright (c) 2012 Robert Rouhani <robert.rouhani@gmail.com>
- SharpFont based on Tao.FreeType, Copyright (c) 2003-2007 Tao Framework Team
- 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
- using System;
- using System.Collections.Generic;
- using SharpFont.Cache;
- using SharpFont.Internal;
- using SharpFont.TrueType;
- namespace SharpFont
- {
- /// <summary><para>
- /// A handle to a FreeType library instance. Each ‘library’ is completely independent from the others; it is the
- /// ‘root’ of a set of objects like fonts, faces, sizes, etc.
- /// </para><para>
- /// It also embeds a memory manager (see <see cref="Memory"/>), as well as a scan-line converter object (see
- /// <see cref="Raster"/>).
- /// </para><para>
- /// For multi-threading applications each thread should have its own <see cref="Library"/> object.
- /// </para></summary>
- public sealed class Library : IDisposable
- {
- #region Fields
- private IntPtr reference;
- private bool customMemory;
- private bool disposed;
- private List<Face> childFaces;
- private List<Glyph> childGlyphs;
- private List<Outline> childOutlines;
- private List<Stroker> childStrokers;
- private List<Manager> childManagers;
- #endregion
- #region Constructors
- /// <summary>
- /// Initializes a new instance of the <see cref="Library"/> class.
- /// </summary>
- public Library()
- : this(false)
- {
- IntPtr libraryRef;
- Error err = FT.FT_Init_FreeType(out libraryRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- Reference = libraryRef;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="Library"/> class.
- /// </summary>
- /// <param name="memory">A custom FreeType memory manager.</param>
- public Library(Memory memory)
- : this(false)
- {
- IntPtr libraryRef;
- Error err = FT.FT_New_Library(memory.Reference, out libraryRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- Reference = libraryRef;
- customMemory = true;
- }
- private Library(bool duplicate)
- {
- childFaces = new List<Face>();
- childGlyphs = new List<Glyph>();
- childOutlines = new List<Outline>();
- childStrokers = new List<Stroker>();
- childManagers = new List<Manager>();
- }
- /// <summary>
- /// Finalizes an instance of the <see cref="Library"/> class.
- /// </summary>
- ~Library()
- {
- Dispose(false);
- }
- #endregion
- #region Properties
- /// <summary>
- /// Gets a value indicating whether the object has been disposed.
- /// </summary>
- public bool IsDisposed
- {
- get
- {
- return disposed;
- }
- }
- /// <summary>
- /// Gets the version of the FreeType library being used.
- /// </summary>
- public Version Version
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException("Version", "Cannot access a disposed object.");
- int major, minor, patch;
- FT.FT_Library_Version(Reference, out major, out minor, out patch);
- return new Version(major, minor, patch);
- }
- }
- internal IntPtr Reference
- {
- get
- {
- if (disposed)
- throw new ObjectDisposedException("Reference", "Cannot access a disposed object.");
- return reference;
- }
- set
- {
- if (disposed)
- throw new ObjectDisposedException("Reference", "Cannot access a disposed object.");
- reference = value;
- }
- }
- #endregion
- #region Methods
- #region Base Interface
- /// <summary>
- /// This function calls <see cref="OpenFace"/> to open a font by its pathname.
- /// </summary>
- /// <param name="path">A path to the font file.</param>
- /// <param name="faceIndex">The index of the face within the font. The first face has index 0.</param>
- /// <returns>
- /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL.
- /// </returns>
- /// <see cref="OpenFace"/>
- public Face NewFace(string path, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- return new Face(this, path, faceIndex);
- }
- /// <summary>
- /// This function calls <see cref="OpenFace"/> to open a font which has been loaded into memory.
- /// </summary>
- /// <remarks>
- /// You must not deallocate the memory before calling <see cref="Face.Dispose()"/>.
- /// </remarks>
- /// <param name="file">A pointer to the beginning of the font data.</param>
- /// <param name="faceIndex">The index of the face within the font. The first face has index 0.</param>
- /// <returns>
- /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL.
- /// </returns>
- /// <see cref="OpenFace"/>
- public Face NewMemoryFace(byte[] file, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- return new Face(this, file, faceIndex);
- }
- /// <summary>
- /// Create a <see cref="Face"/> object from a given resource described by <see cref="OpenArgs"/>.
- /// </summary>
- /// <remarks><para>
- /// Unlike FreeType 1.x, this function automatically creates a glyph slot for the face object which can be
- /// accessed directly through <see cref="Face.Glyph"/>.
- /// </para><para>
- /// OpenFace can be used to quickly check whether the font format of a given font resource is supported by
- /// FreeType. If the ‘faceIndex’ field is negative, the function's return value is 0 if the font format is
- /// recognized, or non-zero otherwise; the function returns a more or less empty face handle in ‘*aface’ (if
- /// ‘aface’ isn't NULL). The only useful field in this special case is <see cref="Face.FaceCount"/> which gives
- /// the number of faces within the font file. After examination, the returned <see cref="Face"/> structure
- /// should be deallocated with a call to <see cref="Face.Dispose()"/>.
- /// </para><para>
- /// Each new face object created with this function also owns a default <see cref="FTSize"/> object, accessible
- /// as <see cref="Face.Size"/>.
- /// </para><para>
- /// See the discussion of reference counters in the description of FT_Reference_Face.
- /// </para></remarks>
- /// <param name="args">
- /// A pointer to an <see cref="OpenArgs"/> structure which must be filled by the caller.
- /// </param>
- /// <param name="faceIndex">The index of the face within the font. The first face has index 0.</param>
- /// <returns>
- /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL.
- /// </returns>
- public Face OpenFace(OpenArgs args, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- IntPtr faceRef;
- Error err = FT.FT_Open_Face(Reference, args.Reference, faceIndex, out faceRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- return new Face(faceRef, this);
- }
- #endregion
- #region Mac Specific Interface
- /// <summary>
- /// Create a new face object from a FOND resource.
- /// </summary>
- /// <remarks>
- /// This function can be used to create <see cref="Face"/> objects from fonts that are installed in the system
- /// as follows.
- /// <code>
- /// fond = GetResource( 'FOND', fontName );
- /// error = FT_New_Face_From_FOND( library, fond, 0, &face );
- /// </code>
- /// </remarks>
- /// <param name="fond">A FOND resource.</param>
- /// <param name="faceIndex">Only supported for the -1 ‘sanity check’ special case.</param>
- /// <returns>A handle to a new face object.</returns>
- public Face NewFaceFromFond(IntPtr fond, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- IntPtr faceRef;
- Error err = FT.FT_New_Face_From_FOND(Reference, fond, faceIndex, out faceRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- return new Face(faceRef, this);
- }
- /// <summary>
- /// Create a new face object from a given resource and typeface index using an FSSpec to the font file.
- /// </summary>
- /// <remarks>
- /// <see cref="NewFaceFromFSSpec"/> is identical to <see cref="NewFace"/> except it accepts an FSSpec instead
- /// of a path.
- /// </remarks>
- /// <param name="spec">FSSpec to the font file.</param>
- /// <param name="faceIndex">The index of the face within the resource. The first face has index 0.</param>
- /// <returns>A handle to a new face object.</returns>
- public Face NewFaceFromFSSpec(IntPtr spec, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- IntPtr faceRef;
- Error err = FT.FT_New_Face_From_FSSpec(Reference, spec, faceIndex, out faceRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- return new Face(faceRef, this);
- }
- /// <summary>
- /// Create a new face object from a given resource and typeface index using an FSRef to the font file.
- /// </summary>
- /// <remarks>
- /// <see cref="NewFaceFromFSRef"/> is identical to <see cref="NewFace"/> except it accepts an FSRef instead of
- /// a path.
- /// </remarks>
- /// <param name="ref">FSRef to the font file.</param>
- /// <param name="faceIndex">The index of the face within the resource. The first face has index 0.</param>
- /// <returns>A handle to a new face object.</returns>
- public Face NewFaceFromFSRef(IntPtr @ref, int faceIndex)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- IntPtr faceRef;
- Error err = FT.FT_New_Face_From_FSRef(Reference, @ref, faceIndex, out faceRef);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- return new Face(faceRef, this);
- }
- #endregion
- #region Module Management
- /// <summary>
- /// Add a new module to a given library instance.
- /// </summary>
- /// <remarks>
- /// An error will be returned if a module already exists by that name, or if the module requires a version of
- /// FreeType that is too great.
- /// </remarks>
- /// <param name="clazz">A pointer to class descriptor for the module.</param>
- public void AddModule(ModuleClass clazz)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- Error err = FT.FT_Add_Module(Reference, clazz.Reference);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- }
- /// <summary>
- /// Find a module by its name.
- /// </summary>
- /// <remarks>
- /// FreeType's internal modules aren't documented very well, and you should look up the source code for
- /// details.
- /// </remarks>
- /// <param name="moduleName">The module's name (as an ASCII string).</param>
- /// <returns>A module handle. 0 if none was found.</returns>
- public Module GetModule(string moduleName)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- return new Module(FT.FT_Get_Module(Reference, moduleName));
- }
- /// <summary>
- /// Remove a given module from a library instance.
- /// </summary>
- /// <remarks>
- /// The module object is destroyed by the function in case of success.
- /// </remarks>
- /// <param name="module">A handle to a module object.</param>
- public void RemoveModule(Module module)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- if (module == null)
- throw new ArgumentNullException("module");
- Error err = FT.FT_Remove_Module(Reference, module.Reference);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- }
- /// <summary>
- /// Set a debug hook function for debugging the interpreter of a font format.
- /// </summary>
- /// <remarks><para>
- /// Currently, four debug hook slots are available, but only two (for the TrueType and the Type 1 interpreter)
- /// are defined.
- /// </para><para>
- /// Since the internal headers of FreeType are no longer installed, the symbol ‘FT_DEBUG_HOOK_TRUETYPE’ isn't
- /// available publicly. This is a bug and will be fixed in a forthcoming release.
- /// </para></remarks>
- /// <param name="hookIndex">The index of the debug hook. You should use the values defined in ‘ftobjs.h’, e.g., ‘FT_DEBUG_HOOK_TRUETYPE’.</param>
- /// <param name="debugHook">The function used to debug the interpreter.</param>
- [CLSCompliant(false)]
- public void SetDebugHook(uint hookIndex, IntPtr debugHook)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- FT.FT_Set_Debug_Hook(Reference, hookIndex, debugHook);
- }
- /// <summary>
- /// Add the set of default drivers to a given library object. This is only useful when you create a library
- /// object with <see cref="Library(Memory)"/> (usually to plug a custom memory manager).
- /// </summary>
- public void AddDefaultModules()
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- FT.FT_Add_Default_Modules(Reference);
- }
- /// <summary>
- /// Retrieve the current renderer for a given glyph format.
- /// </summary>
- /// <remarks><para>
- /// An error will be returned if a module already exists by that name, or if the module requires a version of
- /// FreeType that is too great.
- /// </para><para>
- /// To add a new renderer, simply use <see cref="AddModule"/>. To retrieve a renderer by its name, use
- /// <see cref="GetModule"/>.
- /// </para></remarks>
- /// <param name="format">The glyph format.</param>
- /// <returns>A renderer handle. 0 if none found.</returns>
- [CLSCompliant(false)]
- public Renderer GetRenderer(GlyphFormat format)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- return new Renderer(FT.FT_Get_Renderer(Reference, format));
- }
- /// <summary>
- /// Set the current renderer to use, and set additional mode.
- /// </summary>
- /// <remarks><para>
- /// In case of success, the renderer will be used to convert glyph images in the renderer's known format into
- /// bitmaps.
- /// </para><para>
- /// This doesn't change the current renderer for other formats.
- /// </para><para>
- /// Currently, only the B/W renderer, if compiled with FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels
- /// anti-aliasing mode; this option must be set directly in ‘ftraster.c’ and is undefined by default) accepts a
- /// single tag ‘pal5’ to set its gray palette as a character string with 5 elements. Consequently, the third
- /// and fourth argument are zero normally.
- /// </para></remarks>
- /// <param name="renderer">A handle to the renderer object.</param>
- /// <param name="numParams">The number of additional parameters.</param>
- /// <param name="parameters">Additional parameters.</param>
- [CLSCompliant(false)]
- public unsafe void SetRenderer(Renderer renderer, uint numParams, Parameter[] parameters)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- if (renderer == null)
- throw new ArgumentNullException("renderer");
- if (parameters == null)
- throw new ArgumentNullException("parameters");
- ParameterRec[] paramRecs = Array.ConvertAll<Parameter, ParameterRec>(parameters, p => p.Record);
- fixed (void* ptr = paramRecs)
- {
- Error err = FT.FT_Set_Renderer(Reference, renderer.Reference, numParams, (IntPtr)ptr);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- }
- }
- #endregion
- #region LCD Filtering
- /// <summary>
- /// This function is used to apply color filtering to LCD decimated bitmaps, like the ones used when calling
- /// <see cref="GlyphSlot.RenderGlyph"/> with <see cref="RenderMode.Lcd"/> or
- /// <see cref="RenderMode.VerticalLcd"/>.
- /// </summary>
- /// <remarks><para>
- /// This feature is always disabled by default. Clients must make an explicit call to this function with a
- /// ‘filter’ value other than <see cref="LcdFilter.None"/> in order to enable it.
- /// </para><para>
- /// Due to <b>PATENTS</b> covering subpixel rendering, this function doesn't do anything except returning
- /// <see cref="Error.UnimplementedFeature"/> if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is
- /// not defined in your build of the library, which should correspond to all default builds of FreeType.
- /// </para><para>
- /// The filter affects glyph bitmaps rendered through <see cref="GlyphSlot.RenderGlyph"/>,
- /// <see cref="Outline.GetBitmap(FTBitmap)"/>, <see cref="Face.LoadGlyph"/>, and <see cref="Face.LoadChar"/>.
- /// </para><para>
- /// It does not affect the output of <see cref="Outline.Render(RasterParams)"/> and
- /// <see cref="Outline.GetBitmap(FTBitmap)"/>.
- /// </para><para>
- /// If this feature is activated, the dimensions of LCD glyph bitmaps are either larger or taller than the
- /// dimensions of the corresponding outline with regards to the pixel grid. For example, for
- /// <see cref="RenderMode.Lcd"/>, the filter adds up to 3 pixels to the left, and up to 3 pixels to the right.
- /// </para><para>
- /// The bitmap offset values are adjusted correctly, so clients shouldn't need to modify their layout and glyph
- /// positioning code when enabling the filter.
- /// </para></remarks>
- /// <param name="filter"><para>
- /// The filter type.
- /// </para><para>
- /// You can use <see cref="LcdFilter.None"/> here to disable this feature, or <see cref="LcdFilter.Default"/>
- /// to use a default filter that should work well on most LCD screens.
- /// </para></param>
- public void SetLcdFilter(LcdFilter filter)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- Error err = FT.FT_Library_SetLcdFilter(Reference, filter);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- }
- /// <summary>
- /// Use this function to override the filter weights selected by <see cref="SetLcdFilter"/>. By default,
- /// FreeType uses the quintuple (0x00, 0x55, 0x56, 0x55, 0x00) for <see cref="LcdFilter.Light"/>, and (0x10,
- /// 0x40, 0x70, 0x40, 0x10) for <see cref="LcdFilter.Default"/> and <see cref="LcdFilter.Legacy"/>.
- /// </summary>
- /// <remarks><para>
- /// Due to <b>PATENTS</b> covering subpixel rendering, this function doesn't do anything except returning
- /// <see cref="Error.UnimplementedFeature"/> if the configuration macro FT_CONFIG_OPTION_SUBPIXEL_RENDERING is
- /// not defined in your build of the library, which should correspond to all default builds of FreeType.
- /// </para><para>
- /// This function must be called after <see cref="SetLcdFilter"/> to have any effect.
- /// </para></remarks>
- /// <param name="weights">
- /// A pointer to an array; the function copies the first five bytes and uses them to specify the filter
- /// weights.
- /// </param>
- public void SetLcdFilterWeights(byte[] weights)
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- if (weights == null)
- throw new ArgumentNullException("weights");
- Error err = FT.FT_Library_SetLcdFilterWeights(Reference, weights);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- }
- #endregion
- #region The TrueType Engine
- /// <summary>
- /// Return an <see cref="EngineType"/> value to indicate which level of the TrueType virtual machine a given
- /// library instance supports.
- /// </summary>
- /// <returns>A value indicating which level is supported.</returns>
- public EngineType GetTrueTypeEngineType()
- {
- if (disposed)
- throw new ObjectDisposedException("Library", "Cannot access a disposed object.");
- return FT.FT_Get_TrueType_Engine_Type(Reference);
- }
- #endregion
- /// <summary>
- /// Disposes the Library.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- internal void AddChildFace(Face child)
- {
- childFaces.Add(child);
- }
- internal void RemoveChildFace(Face child)
- {
- childFaces.Remove(child);
- }
- internal void AddChildGlyph(Glyph child)
- {
- childGlyphs.Add(child);
- }
- internal void RemoveChildGlyph(Glyph child)
- {
- childGlyphs.Remove(child);
- }
- internal void AddChildOutline(Outline child)
- {
- childOutlines.Add(child);
- }
- internal void RemoveChildOutline(Outline child)
- {
- childOutlines.Remove(child);
- }
- internal void AddChildStroker(Stroker child)
- {
- childStrokers.Add(child);
- }
- internal void RemoveChildStroker(Stroker child)
- {
- childStrokers.Remove(child);
- }
- internal void AddChildManager(Manager child)
- {
- childManagers.Add(child);
- }
- internal void RemoveChildManager(Manager child)
- {
- childManagers.Remove(child);
- }
- private void Dispose(bool disposing)
- {
- if (!disposed)
- {
- disposed = true;
- //dipose all the children before disposing the library.
- foreach (Face f in childFaces)
- f.Dispose();
- foreach (Glyph g in childGlyphs)
- g.Dispose();
- foreach (Outline o in childOutlines)
- o.Dispose();
- foreach (Stroker s in childStrokers)
- s.Dispose();
- foreach (Manager m in childManagers)
- m.Dispose();
- childFaces.Clear();
- childGlyphs.Clear();
- childOutlines.Clear();
- childStrokers.Clear();
- childManagers.Clear();
- Error err = customMemory ? FT.FT_Done_Library(reference) : FT.FT_Done_FreeType(reference);
- if (err != Error.Ok)
- throw new FreeTypeException(err);
- reference = IntPtr.Zero;
- }
- }
- #endregion
- }
- }
|