From d6c292a2ccb568e8e89f326b30fa9a3e08c39d6c Mon Sep 17 00:00:00 2001 From: juanjp600 Date: Tue, 7 Mar 2017 13:44:42 -0300 Subject: [PATCH] SharpFont + ScalableFont implementation https://github.com/Robmaister/SharpFont TODO: replace Code Bold.otf with the full version, fix any bugs, build on Linux, possibly move ToolBox string wrapping and limiting logic to ScalableFont class for better results. --- SharpFont/.gitignore | 52 + SharpFont/.gitmodules | 4 + .../freetype2/2.5.4-alldeps/README.md | 5 + .../patches/fttypes-h-win32.patch | 58 + .../freetype2/2.5.5-alldeps/README.md | 5 + SharpFont/Dependencies/freetype2/FTL.TXT | 169 ++ SharpFont/Dependencies/freetype2/README.md | 86 + SharpFont/Dependencies/freetype2/win64.patch | 71 + SharpFont/LICENSE | 21 + SharpFont/Makefile | 16 + SharpFont/README.md | 120 + SharpFont/Source/.editorconfig | 12 + SharpFont/Source/Settings.StyleCop | 97 + SharpFont/Source/SharpFont.dll.config | 6 + SharpFont/Source/SharpFont.sln | 45 + SharpFont/Source/SharpFont.snk | Bin 0 -> 596 bytes SharpFont/Source/SharpFont/SharpFont.csproj | 65 + .../SharpFontShared/AutoHinterScript.cs | 138 + SharpFont/Source/SharpFontShared/BBox.cs | 190 ++ .../Bdf/Internal/PropertyRec.cs | 45 + .../Source/SharpFontShared/Bdf/Property.cs | 121 + .../SharpFontShared/Bdf/PropertyType.cs | 46 + .../Source/SharpFontShared/BitmapGlyph.cs | 207 ++ .../Source/SharpFontShared/BitmapSize.cs | 145 + .../Source/SharpFontShared/Cache/CMapCache.cs | 100 + .../SharpFontShared/Cache/FaceRequester.cs | 47 + .../SharpFontShared/Cache/ImageCache.cs | 173 ++ .../Source/SharpFontShared/Cache/ImageType.cs | 116 + .../Cache/Internal/CMapCacheRec.cs | 34 + .../Cache/Internal/ImageCacheRec.cs | 34 + .../Cache/Internal/ImageTypeRec.cs | 38 + .../Cache/Internal/ManagerRec.cs | 34 + .../SharpFontShared/Cache/Internal/NodeRec.cs | 34 + .../Cache/Internal/SBitCacheRec.cs | 34 + .../SharpFontShared/Cache/Internal/SBitRec.cs | 46 + .../Cache/Internal/ScalerRec.cs | 40 + .../Source/SharpFontShared/Cache/Manager.cs | 274 ++ .../Source/SharpFontShared/Cache/Node.cs | 87 + .../Source/SharpFontShared/Cache/SBit.cs | 185 ++ .../Source/SharpFontShared/Cache/SBitCache.cs | 173 ++ .../Source/SharpFontShared/Cache/Scaler.cs | 146 + .../SharpFontShared/Cff/HintingEngine.cs | 40 + SharpFont/Source/SharpFontShared/CharMap.cs | 170 ++ .../ClassicKernValidationFlags.cs | 47 + SharpFont/Source/SharpFontShared/Data.cs | 89 + .../Source/SharpFontShared/EmbeddingTypes.cs | 88 + SharpFont/Source/SharpFontShared/Encoding.cs | 135 + SharpFont/Source/SharpFontShared/Error.cs | 298 ++ .../Source/SharpFontShared/FT.Internal.cs | 770 ++++++ SharpFont/Source/SharpFontShared/FT.Public.cs | 262 ++ SharpFont/Source/SharpFontShared/FTBitmap.cs | 546 ++++ SharpFont/Source/SharpFontShared/FTList.cs | 195 ++ SharpFont/Source/SharpFontShared/FTMatrix.cs | 250 ++ SharpFont/Source/SharpFontShared/FTSize.cs | 269 ++ SharpFont/Source/SharpFontShared/FTStream.cs | 315 +++ .../Source/SharpFontShared/FTUnitVector.cs | 46 + SharpFont/Source/SharpFontShared/FTVector.cs | 240 ++ .../Source/SharpFontShared/FTVector26Dot6.cs | 164 ++ SharpFont/Source/SharpFontShared/Face.cs | 2412 +++++++++++++++++ SharpFont/Source/SharpFontShared/FaceFlags.cs | 145 + .../Source/SharpFontShared/Fixed16Dot16.cs | 752 +++++ .../Source/SharpFontShared/Fixed26Dot6.cs | 579 ++++ .../Source/SharpFontShared/Fixed2Dot14.cs | 546 ++++ .../Source/SharpFontShared/Fnt/Header.cs | 594 ++++ .../SharpFontShared/Fnt/Internal/HeaderRec.cs | 77 + .../Source/SharpFontShared/Fnt/WinFntID.cs | 148 + .../SharpFontShared/FreeTypeException.cs | 153 ++ SharpFont/Source/SharpFontShared/Gasp.cs | 70 + SharpFont/Source/SharpFontShared/Generic.cs | 156 ++ SharpFont/Source/SharpFontShared/Glyph.cs | 444 +++ .../Source/SharpFontShared/GlyphBBoxMode.cs | 50 + .../Source/SharpFontShared/GlyphFormat.cs | 67 + .../Source/SharpFontShared/GlyphMetrics.cs | 180 ++ SharpFont/Source/SharpFontShared/GlyphSlot.cs | 475 ++++ .../GlyphToScriptMapProperty.cs | 96 + .../IncreaseXHeightProperty.cs | 97 + .../Internal/BitmapGlyphRec.cs | 38 + .../SharpFontShared/Internal/BitmapRec.cs | 48 + .../SharpFontShared/Internal/BitmapSizeRec.cs | 52 + .../SharpFontShared/Internal/CharMapRec.cs | 46 + .../SharpFontShared/Internal/FaceRec.cs | 90 + .../SharpFontShared/Internal/GenericRec.cs | 36 + .../Internal/GlyphMetricsRec.cs | 53 + .../SharpFontShared/Internal/GlyphRec.cs | 38 + .../SharpFontShared/Internal/GlyphSlotRec.cs | 74 + .../Internal/GlyphToScriptMapPropertyRec.cs | 36 + .../Internal/IncreaseXHeightPropertyRec.cs | 36 + .../SharpFontShared/Internal/ListNodeRec.cs | 39 + .../SharpFontShared/Internal/ListRec.cs | 36 + .../SharpFontShared/Internal/MemoryRec.cs | 40 + .../Internal/ModuleClassRec.cs | 50 + .../SharpFontShared/Internal/NativeObject.cs | 33 + .../Internal/NativeReference.cs | 58 + .../SharpFontShared/Internal/OpenArgsRec.cs | 48 + .../Internal/OutlineFuncsRec.cs | 43 + .../Internal/OutlineGlyphRec.cs | 36 + .../SharpFontShared/Internal/OutlineRec.cs | 42 + .../SharpFontShared/Internal/ParameterRec.cs | 41 + .../Internal/RasterFuncsRec.cs | 40 + .../Internal/RasterParamsRec.cs | 50 + .../Internal/RendererClassRec.cs | 44 + .../Internal/SizeMetricsRec.cs | 46 + .../SharpFontShared/Internal/SizeRec.cs | 39 + .../Internal/SizeRequestRec.cs | 48 + .../SharpFontShared/Internal/SpanRec.cs | 39 + .../SharpFontShared/Internal/StreamDescRec.cs | 42 + .../SharpFontShared/Internal/StreamRec.cs | 51 + .../Source/SharpFontShared/KerningMode.cs | 49 + SharpFont/Source/SharpFontShared/LcdFilter.cs | 61 + SharpFont/Source/SharpFontShared/Library.cs | 897 ++++++ SharpFont/Source/SharpFontShared/ListNode.cs | 108 + SharpFont/Source/SharpFontShared/LoadFlags.cs | 196 ++ .../Source/SharpFontShared/LoadTarget.cs | 88 + SharpFont/Source/SharpFontShared/Memory.cs | 174 ++ SharpFont/Source/SharpFontShared/Module.cs | 43 + .../Source/SharpFontShared/ModuleClass.cs | 194 ++ .../MultipleMasters/Internal/MMAxisRec.cs | 42 + .../MultipleMasters/Internal/MMVarRec.cs | 39 + .../Internal/MultiMasterRec.cs | 39 + .../MultipleMasters/Internal/VarAxisRec.cs | 46 + .../Internal/VarNamedStyleRec.cs | 36 + .../SharpFontShared/MultipleMasters/MMAxis.cs | 111 + .../SharpFontShared/MultipleMasters/MMVar.cs | 134 + .../MultipleMasters/MultiMaster.cs | 114 + .../MultipleMasters/VarAxis.cs | 140 + .../MultipleMasters/VarNamedStyle.cs | 96 + SharpFont/Source/SharpFontShared/OpenArgs.cs | 204 ++ SharpFont/Source/SharpFontShared/OpenFlags.cs | 54 + .../OpenTypeValidationFlags.cs | 58 + .../Source/SharpFontShared/Orientation.cs | 66 + SharpFont/Source/SharpFontShared/Outline.cs | 698 +++++ .../Source/SharpFontShared/OutlineFlags.cs | 102 + .../Source/SharpFontShared/OutlineFuncs.cs | 404 +++ .../Source/SharpFontShared/OutlineGlyph.cs | 177 ++ .../Source/SharpFontShared/PInvokeHelper.cs | 78 + SharpFont/Source/SharpFontShared/ParamTag.cs | 62 + SharpFont/Source/SharpFontShared/Parameter.cs | 106 + SharpFont/Source/SharpFontShared/PixelMode.cs | 87 + .../SharpFontShared/PostScript/BlendFlags.cs | 105 + .../PostScript/DictionaryKeys.cs | 271 ++ .../PostScript/EncodingType.cs | 55 + .../SharpFontShared/PostScript/FaceDict.cs | 209 ++ .../SharpFontShared/PostScript/FaceInfo.cs | 267 ++ .../SharpFontShared/PostScript/FontInfo.cs | 157 ++ .../PostScript/Internal/FaceDictRec.cs | 54 + .../PostScript/Internal/FaceInfoRec.cs | 69 + .../PostScript/Internal/FontInfoRec.cs | 56 + .../PostScript/Internal/PrivateRec.cs | 82 + .../SharpFontShared/PostScript/Private.cs | 346 +++ .../Properties/AssemblyInfo.cs | 67 + SharpFont/Source/SharpFontShared/Raster.cs | 44 + .../Source/SharpFontShared/RasterFlags.cs | 64 + .../Source/SharpFontShared/RasterFuncs.cs | 210 ++ .../Source/SharpFontShared/RasterParams.cs | 237 ++ .../Source/SharpFontShared/RenderMode.cs | 80 + SharpFont/Source/SharpFontShared/Renderer.cs | 69 + .../Source/SharpFontShared/RendererClass.cs | 150 + .../Source/SharpFontShared/Settings.StyleCop | 97 + .../SharpFontShared/SharpFontShared.projitems | 187 ++ .../SharpFontShared/SharpFontShared.shproj | 12 + .../Source/SharpFontShared/SizeMetrics.cs | 167 ++ .../Source/SharpFontShared/SizeRequest.cs | 205 ++ .../Source/SharpFontShared/SizeRequestType.cs | 70 + SharpFont/Source/SharpFontShared/Span.cs | 112 + .../Source/SharpFontShared/StreamDesc.cs | 94 + SharpFont/Source/SharpFontShared/Stroker.cs | 392 +++ .../Source/SharpFontShared/StrokerBorder.cs | 53 + .../Source/SharpFontShared/StrokerLineCap.cs | 49 + .../Source/SharpFontShared/StrokerLineJoin.cs | 69 + .../Source/SharpFontShared/StyleFlags.cs | 49 + SharpFont/Source/SharpFontShared/SubGlyph.cs | 73 + .../Source/SharpFontShared/SubGlyphFlags.cs | 71 + .../SharpFontShared/TrueType/EncodingId.cs | 230 ++ .../SharpFontShared/TrueType/EngineType.cs | 55 + .../Source/SharpFontShared/TrueType/Header.cs | 396 +++ .../SharpFontShared/TrueType/HoriHeader.cs | 274 ++ .../TrueType/Internal/HeaderRec.cs | 65 + .../TrueType/Internal/HoriHeaderRec.cs | 73 + .../TrueType/Internal/MaxProfileRec.cs | 52 + .../TrueType/Internal/OS2Rec.cs | 113 + .../TrueType/Internal/PCLTRec.cs | 85 + .../TrueType/Internal/PostscriptRec.cs | 46 + .../TrueType/Internal/SfntNameRec.cs | 41 + .../TrueType/Internal/VertHeaderRec.cs | 73 + .../SharpFontShared/TrueType/MaxProfile.cs | 258 ++ .../Source/SharpFontShared/TrueType/OS2.cs | 532 ++++ .../Source/SharpFontShared/TrueType/Pclt.cs | 251 ++ .../SharpFontShared/TrueType/PlatformId.cs | 74 + .../SharpFontShared/TrueType/Postscript.cs | 179 ++ .../SharpFontShared/TrueType/SfntName.cs | 152 ++ .../SharpFontShared/TrueType/SfntTag.cs | 70 + .../SharpFontShared/TrueType/VertHeader.cs | 273 ++ .../TrueTypeValidationFlags.cs | 70 + Subsurface/Barotrauma.csproj | 17 + Subsurface/Content/CODE Bold.otf | Bin 0 -> 24108 bytes Subsurface/Content/Exo2-Light.otf | Bin 0 -> 65156 bytes Subsurface/Content/Exo2-Medium.otf | Bin 0 -> 65720 bytes .../Source/Characters/AI/EnemyAIController.cs | 10 +- .../Source/Characters/AI/HumanAIController.cs | 2 +- Subsurface/Source/Characters/Character.cs | 6 +- Subsurface/Source/Characters/CharacterInfo.cs | 2 +- Subsurface/Source/DebugConsole.cs | 4 +- Subsurface/Source/Fonts/ScalableFont.cs | 287 ++ Subsurface/Source/GUI/GUI.cs | 33 +- Subsurface/Source/GUI/GUIButton.cs | 2 +- Subsurface/Source/GUI/GUIComponent.cs | 2 +- Subsurface/Source/GUI/GUITextBlock.cs | 15 +- Subsurface/Source/GUI/GUITextBox.cs | 10 +- Subsurface/Source/GUI/GUITickBox.cs | 2 +- Subsurface/Source/GUI/LoadingScreen.cs | 2 +- Subsurface/Source/GameMain.cs | 10 +- .../Items/Components/Machines/Engine.cs | 2 +- .../Source/Items/Components/Machines/Pump.cs | 2 +- .../Items/Components/Machines/Reactor.cs | 12 +- .../Items/Components/Power/PowerContainer.cs | 4 +- .../Items/Components/Power/PowerTransfer.cs | 4 +- .../Items/Components/Signal/Connection.cs | 2 +- Subsurface/Source/Items/Inventory.cs | 2 +- Subsurface/Source/Map/Hull.cs | 4 +- Subsurface/Source/Map/MapEntityPrefab.cs | 2 +- Subsurface/Source/Map/WayPoint.cs | 4 +- Subsurface/Source/Networking/GameClient.cs | 14 +- Subsurface/Source/Networking/GameServer.cs | 18 +- Subsurface/Source/Networking/NetStats.cs | 8 +- Subsurface/Source/Program.cs | 4 +- Subsurface/Source/Screens/LobbyScreen.cs | 2 +- Subsurface/Source/Screens/MainMenuScreen.cs | 2 +- Subsurface/Source/Screens/ServerListScreen.cs | 2 +- Subsurface/Source/Utils/ToolBox.cs | 8 +- Subsurface/freetype6.dll | Bin 0 -> 452096 bytes Subsurface_Solution.sln | 69 +- 231 files changed, 28528 insertions(+), 94 deletions(-) create mode 100644 SharpFont/.gitignore create mode 100644 SharpFont/.gitmodules create mode 100644 SharpFont/Dependencies/freetype2/2.5.4-alldeps/README.md create mode 100644 SharpFont/Dependencies/freetype2/2.5.4-alldeps/patches/fttypes-h-win32.patch create mode 100644 SharpFont/Dependencies/freetype2/2.5.5-alldeps/README.md create mode 100644 SharpFont/Dependencies/freetype2/FTL.TXT create mode 100644 SharpFont/Dependencies/freetype2/README.md create mode 100644 SharpFont/Dependencies/freetype2/win64.patch create mode 100644 SharpFont/LICENSE create mode 100644 SharpFont/Makefile create mode 100644 SharpFont/README.md create mode 100644 SharpFont/Source/.editorconfig create mode 100644 SharpFont/Source/Settings.StyleCop create mode 100644 SharpFont/Source/SharpFont.dll.config create mode 100644 SharpFont/Source/SharpFont.sln create mode 100644 SharpFont/Source/SharpFont.snk create mode 100644 SharpFont/Source/SharpFont/SharpFont.csproj create mode 100644 SharpFont/Source/SharpFontShared/AutoHinterScript.cs create mode 100644 SharpFont/Source/SharpFontShared/BBox.cs create mode 100644 SharpFont/Source/SharpFontShared/Bdf/Internal/PropertyRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Bdf/Property.cs create mode 100644 SharpFont/Source/SharpFontShared/Bdf/PropertyType.cs create mode 100644 SharpFont/Source/SharpFontShared/BitmapGlyph.cs create mode 100644 SharpFont/Source/SharpFontShared/BitmapSize.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/CMapCache.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/FaceRequester.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/ImageCache.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/ImageType.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/CMapCacheRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/ImageCacheRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/ImageTypeRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/ManagerRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/NodeRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/SBitCacheRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/SBitRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Internal/ScalerRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Manager.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Node.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/SBit.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/SBitCache.cs create mode 100644 SharpFont/Source/SharpFontShared/Cache/Scaler.cs create mode 100644 SharpFont/Source/SharpFontShared/Cff/HintingEngine.cs create mode 100644 SharpFont/Source/SharpFontShared/CharMap.cs create mode 100644 SharpFont/Source/SharpFontShared/ClassicKernValidationFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/Data.cs create mode 100644 SharpFont/Source/SharpFontShared/EmbeddingTypes.cs create mode 100644 SharpFont/Source/SharpFontShared/Encoding.cs create mode 100644 SharpFont/Source/SharpFontShared/Error.cs create mode 100644 SharpFont/Source/SharpFontShared/FT.Internal.cs create mode 100644 SharpFont/Source/SharpFontShared/FT.Public.cs create mode 100644 SharpFont/Source/SharpFontShared/FTBitmap.cs create mode 100644 SharpFont/Source/SharpFontShared/FTList.cs create mode 100644 SharpFont/Source/SharpFontShared/FTMatrix.cs create mode 100644 SharpFont/Source/SharpFontShared/FTSize.cs create mode 100644 SharpFont/Source/SharpFontShared/FTStream.cs create mode 100644 SharpFont/Source/SharpFontShared/FTUnitVector.cs create mode 100644 SharpFont/Source/SharpFontShared/FTVector.cs create mode 100644 SharpFont/Source/SharpFontShared/FTVector26Dot6.cs create mode 100644 SharpFont/Source/SharpFontShared/Face.cs create mode 100644 SharpFont/Source/SharpFontShared/FaceFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/Fixed16Dot16.cs create mode 100644 SharpFont/Source/SharpFontShared/Fixed26Dot6.cs create mode 100644 SharpFont/Source/SharpFontShared/Fixed2Dot14.cs create mode 100644 SharpFont/Source/SharpFontShared/Fnt/Header.cs create mode 100644 SharpFont/Source/SharpFontShared/Fnt/Internal/HeaderRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Fnt/WinFntID.cs create mode 100644 SharpFont/Source/SharpFontShared/FreeTypeException.cs create mode 100644 SharpFont/Source/SharpFontShared/Gasp.cs create mode 100644 SharpFont/Source/SharpFontShared/Generic.cs create mode 100644 SharpFont/Source/SharpFontShared/Glyph.cs create mode 100644 SharpFont/Source/SharpFontShared/GlyphBBoxMode.cs create mode 100644 SharpFont/Source/SharpFontShared/GlyphFormat.cs create mode 100644 SharpFont/Source/SharpFontShared/GlyphMetrics.cs create mode 100644 SharpFont/Source/SharpFontShared/GlyphSlot.cs create mode 100644 SharpFont/Source/SharpFontShared/GlyphToScriptMapProperty.cs create mode 100644 SharpFont/Source/SharpFontShared/IncreaseXHeightProperty.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/BitmapGlyphRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/BitmapRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/BitmapSizeRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/CharMapRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/FaceRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/GenericRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/GlyphMetricsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/GlyphRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/GlyphSlotRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/GlyphToScriptMapPropertyRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/IncreaseXHeightPropertyRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/ListNodeRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/ListRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/MemoryRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/ModuleClassRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/NativeObject.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/NativeReference.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/OpenArgsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/OutlineFuncsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/OutlineGlyphRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/OutlineRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/ParameterRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/RasterFuncsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/RasterParamsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/RendererClassRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/SizeMetricsRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/SizeRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/SizeRequestRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/SpanRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/StreamDescRec.cs create mode 100644 SharpFont/Source/SharpFontShared/Internal/StreamRec.cs create mode 100644 SharpFont/Source/SharpFontShared/KerningMode.cs create mode 100644 SharpFont/Source/SharpFontShared/LcdFilter.cs create mode 100644 SharpFont/Source/SharpFontShared/Library.cs create mode 100644 SharpFont/Source/SharpFontShared/ListNode.cs create mode 100644 SharpFont/Source/SharpFontShared/LoadFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/LoadTarget.cs create mode 100644 SharpFont/Source/SharpFontShared/Memory.cs create mode 100644 SharpFont/Source/SharpFontShared/Module.cs create mode 100644 SharpFont/Source/SharpFontShared/ModuleClass.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMAxisRec.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMVarRec.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MultiMasterRec.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarAxisRec.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarNamedStyleRec.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/MMAxis.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/MMVar.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/MultiMaster.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/VarAxis.cs create mode 100644 SharpFont/Source/SharpFontShared/MultipleMasters/VarNamedStyle.cs create mode 100644 SharpFont/Source/SharpFontShared/OpenArgs.cs create mode 100644 SharpFont/Source/SharpFontShared/OpenFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/OpenTypeValidationFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/Orientation.cs create mode 100644 SharpFont/Source/SharpFontShared/Outline.cs create mode 100644 SharpFont/Source/SharpFontShared/OutlineFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/OutlineFuncs.cs create mode 100644 SharpFont/Source/SharpFontShared/OutlineGlyph.cs create mode 100644 SharpFont/Source/SharpFontShared/PInvokeHelper.cs create mode 100644 SharpFont/Source/SharpFontShared/ParamTag.cs create mode 100644 SharpFont/Source/SharpFontShared/Parameter.cs create mode 100644 SharpFont/Source/SharpFontShared/PixelMode.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/BlendFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/DictionaryKeys.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/EncodingType.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/FaceDict.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/FaceInfo.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/FontInfo.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/Internal/FaceDictRec.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/Internal/FaceInfoRec.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/Internal/FontInfoRec.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/Internal/PrivateRec.cs create mode 100644 SharpFont/Source/SharpFontShared/PostScript/Private.cs create mode 100644 SharpFont/Source/SharpFontShared/Properties/AssemblyInfo.cs create mode 100644 SharpFont/Source/SharpFontShared/Raster.cs create mode 100644 SharpFont/Source/SharpFontShared/RasterFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/RasterFuncs.cs create mode 100644 SharpFont/Source/SharpFontShared/RasterParams.cs create mode 100644 SharpFont/Source/SharpFontShared/RenderMode.cs create mode 100644 SharpFont/Source/SharpFontShared/Renderer.cs create mode 100644 SharpFont/Source/SharpFontShared/RendererClass.cs create mode 100644 SharpFont/Source/SharpFontShared/Settings.StyleCop create mode 100644 SharpFont/Source/SharpFontShared/SharpFontShared.projitems create mode 100644 SharpFont/Source/SharpFontShared/SharpFontShared.shproj create mode 100644 SharpFont/Source/SharpFontShared/SizeMetrics.cs create mode 100644 SharpFont/Source/SharpFontShared/SizeRequest.cs create mode 100644 SharpFont/Source/SharpFontShared/SizeRequestType.cs create mode 100644 SharpFont/Source/SharpFontShared/Span.cs create mode 100644 SharpFont/Source/SharpFontShared/StreamDesc.cs create mode 100644 SharpFont/Source/SharpFontShared/Stroker.cs create mode 100644 SharpFont/Source/SharpFontShared/StrokerBorder.cs create mode 100644 SharpFont/Source/SharpFontShared/StrokerLineCap.cs create mode 100644 SharpFont/Source/SharpFontShared/StrokerLineJoin.cs create mode 100644 SharpFont/Source/SharpFontShared/StyleFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/SubGlyph.cs create mode 100644 SharpFont/Source/SharpFontShared/SubGlyphFlags.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/EncodingId.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/EngineType.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Header.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/HoriHeader.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/HeaderRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/HoriHeaderRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/MaxProfileRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/OS2Rec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/PCLTRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/PostscriptRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/SfntNameRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Internal/VertHeaderRec.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/MaxProfile.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/OS2.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Pclt.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/PlatformId.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/Postscript.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/SfntName.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/SfntTag.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueType/VertHeader.cs create mode 100644 SharpFont/Source/SharpFontShared/TrueTypeValidationFlags.cs create mode 100644 Subsurface/Content/CODE Bold.otf create mode 100644 Subsurface/Content/Exo2-Light.otf create mode 100644 Subsurface/Content/Exo2-Medium.otf create mode 100644 Subsurface/Source/Fonts/ScalableFont.cs create mode 100644 Subsurface/freetype6.dll diff --git a/SharpFont/.gitignore b/SharpFont/.gitignore new file mode 100644 index 000000000..18d28f582 --- /dev/null +++ b/SharpFont/.gitignore @@ -0,0 +1,52 @@ +#Output Directory +/[Bb]inaries + +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.lib +*.sbr +*.sdf +ipch/ +obj/ +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad + +#Tooling +_ReSharper*/ +*.resharper +[Tt]est[Rr]esult* + +#Subversion files +.svn + +# Office Temp Files +~$* + +#MonoDevelop files +*.userprefs +*.pidb + +#NuGet +*.nupkg diff --git a/SharpFont/.gitmodules b/SharpFont/.gitmodules new file mode 100644 index 000000000..89d13d9b2 --- /dev/null +++ b/SharpFont/.gitmodules @@ -0,0 +1,4 @@ +[submodule "Dependencies"] + path = Dependencies + url = https://github.com/Robmaister/SharpFont.Dependencies.git + ignore = dirty diff --git a/SharpFont/Dependencies/freetype2/2.5.4-alldeps/README.md b/SharpFont/Dependencies/freetype2/2.5.4-alldeps/README.md new file mode 100644 index 000000000..205b22174 --- /dev/null +++ b/SharpFont/Dependencies/freetype2/2.5.4-alldeps/README.md @@ -0,0 +1,5 @@ +# Notes about these builds + +These builds are statically linked with Zlib 1.2.8, LibPNG 1.6.16, BZip2 1.0.6, and HarfBuzz 0.9.36 (From the ShiftMedia Project). + +The Freetype sources were patched with the fttypes-h-win32.patch file in the patches directory. This patch changes the fttypes.h file's usage of long to __int64 on Windows. diff --git a/SharpFont/Dependencies/freetype2/2.5.4-alldeps/patches/fttypes-h-win32.patch b/SharpFont/Dependencies/freetype2/2.5.4-alldeps/patches/fttypes-h-win32.patch new file mode 100644 index 000000000..20bfc2590 --- /dev/null +++ b/SharpFont/Dependencies/freetype2/2.5.4-alldeps/patches/fttypes-h-win32.patch @@ -0,0 +1,58 @@ +--- .\freetype-2.5.4\include\fttypes.h Tue Dec 2 07:12:12 2014 ++++ .\freetype-2.5.4-patched\include\fttypes.h Sun Dec 28 13:54:21 2014 +@@ -239,9 +239,12 @@ + /* */ + /* A typedef for signed long. */ + /* */ ++#ifdef _WIN32 ++ typedef signed __int64 FT_Long; ++#else + typedef signed long FT_Long; ++#endif + +- + /*************************************************************************/ + /* */ + /* */ +@@ -250,9 +253,12 @@ + /* */ + /* A typedef for unsigned long. */ + /* */ ++#ifdef _WIN32 ++ typedef unsigned __int64 FT_ULong; ++#else + typedef unsigned long FT_ULong; ++#endif + +- + /*************************************************************************/ + /* */ + /* */ +@@ -273,9 +279,12 @@ + /* A signed 26.6 fixed-point type used for vectorial pixel */ + /* coordinates. */ + /* */ ++#ifdef _WIN32 ++ typedef signed __int64 FT_F26Dot6; ++#else + typedef signed long FT_F26Dot6; ++#endif + +- + /*************************************************************************/ + /* */ + /* */ +@@ -285,9 +294,12 @@ + /* This type is used to store 16.16 fixed-point values, like scaling */ + /* values or matrix coefficients. */ + /* */ ++#ifdef _WIN32 ++ typedef signed __int64 FT_Fixed; ++#else + typedef signed long FT_Fixed; ++#endif + +- + /*************************************************************************/ + /* */ + /* */ diff --git a/SharpFont/Dependencies/freetype2/2.5.5-alldeps/README.md b/SharpFont/Dependencies/freetype2/2.5.5-alldeps/README.md new file mode 100644 index 000000000..88b40a02b --- /dev/null +++ b/SharpFont/Dependencies/freetype2/2.5.5-alldeps/README.md @@ -0,0 +1,5 @@ +# Notes about these builds + +These builds are statically linked with Zlib 1.2.8, LibPNG 1.6.16, BZip2 1.0.6, and HarfBuzz 0.9.36 (From the ShiftMedia Project). + +The Freetype sources were patched with the fttypes-h-win32.patch file in the ../2.5.4-alldeps/patches directory. This patch changes the fttypes.h file's usage of long to __int64 on Windows. \ No newline at end of file diff --git a/SharpFont/Dependencies/freetype2/FTL.TXT b/SharpFont/Dependencies/freetype2/FTL.TXT new file mode 100644 index 000000000..bbaba33f4 --- /dev/null +++ b/SharpFont/Dependencies/freetype2/FTL.TXT @@ -0,0 +1,169 @@ + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + + +--- end of FTL.TXT --- diff --git a/SharpFont/Dependencies/freetype2/README.md b/SharpFont/Dependencies/freetype2/README.md new file mode 100644 index 000000000..44673889a --- /dev/null +++ b/SharpFont/Dependencies/freetype2/README.md @@ -0,0 +1,86 @@ +FreeType2 +========= + +This directory contains all of the FreeType2 builds, a copy of the FreeType +Project License, and a patch file for when compiling new versions of freetype +for 64-bit Windows. + +**WARNING**: These are not standard builds of FreeType on Windows (for 64-bit) +and will not work as a drop-in replacement for someone else's build. This is +why the package is distributed on NuGet as *SharpFont.Dependencies* instead of +*freetype2.redist* or something similar. + +##Compiling FreeType on Windows + +The copies of `freetype6.dll` that the Examples project uses by default are +chosen based on what works on my machine, and I will probably update it as +soon as a new version of FreeType is released. This means that it may not work +on older versions of Windows. If this is the case, you can either modify +the project file to point to another included version of freetype or you can +compile FreeType yourself from source. + +**Note**: Any 32-bit copy of `freetype6.dll` works as a drop-in replacement, +including [this copy][1] from the GnuWin32 project. Older versions such as +that one may crash with a `EntryPointException` when using newer APIs. **This +is not true of 64-bit copies currently** + +Thanks to [this StackOverflow answer][2] for the directions: + + 1. Download the latest [FreeType source code][3]. + 2. Open `builds\win32\vc2010\freetype.sln` (or whatever version of Visual + Studio you have) in Visual Studio. + 3. Change the compile configuration from Debug to Release. + 4. Open the project properties window through Project -> Properties. + 5. In the `General` selection, change the `Target Name` to `freetype6` and + the `Configuration Type` to `Dynamic Library (.dll)`. + 6. **If compiling for 64-bit** + - Apply a patch to the source code (see [Known Issues](#known-issues)). + - Open up Configuration Manager (the last option in the dropdown menu when + changing your compile configuration) and change `Platform` to `x64`. + 7. Open up `ftoption.h` (in the project's `Header Files` section) and add the + following three lines near the `DLL export compilation` section: + +```C +#define FT_EXPORT(x) __declspec(dllexport) x +#define FT_EXPORT_DEF(x) __declspec(dllexport) x +#define FT_BASE(x) __declspec(dllexport) x +``` + +Finally, complile the project (`F6` or Build -> Build Solution). +`freetype6.dll` will be output to `objs\win32\vc2010`. If this is a build that +isn't included in [Dependencies][4], consider forking and submitting a pull +request with your new build. + +## Windows x64 + +A patch file, [win64.patch][5], is included in this directory that will force +several types to be 64 bits wide. On Linux and OS X, the native `long` type is +64 bits wide on x64, but on Windows, it's still 32 bits wide for backwards +compatibility of applications assuming `sizeof(long) == sizeof(int)`. A list +of the affected types: + + - `FT_Long` + - `FT_ULong` + - `FT_Fixed` + - `FT_F26Dot6` + - `FT_Pos` + +To apply the patch file, you need a copy of the `patch` utility built for +Windows. If using msysgit, it is already installed and is available from Git +Bash. Otherwise, a build is available from [GnuWin32][6]. Utilities such as +TortoiseDiff can provide a graphical way to do this same task. + +After downloading and decompressing FreeType2, copy `win64.patch` into the +root folder (i.e. the folder containing `builds/`, `/include`, `/src`, etc.) +and run the following command: + +``` +patch -p0 < win64.patch +``` + +[1]: http://gnuwin32.sourceforge.net/packages/freetype.htm +[2]: http://stackoverflow.com/a/7387618/1122135 +[3]: http://sourceforge.net/projects/freetype/files/freetype2/ +[4]: https://github.com/Robmaister/SharpFont.Dependencies +[5]: https://github.com/Robmaister/SharpFont.Dependencies/blob/master/freetype2/win64.patch +[6]: http://gnuwin32.sourceforge.net/packages/patch.htm diff --git a/SharpFont/Dependencies/freetype2/win64.patch b/SharpFont/Dependencies/freetype2/win64.patch new file mode 100644 index 000000000..a7da056a2 --- /dev/null +++ b/SharpFont/Dependencies/freetype2/win64.patch @@ -0,0 +1,71 @@ +diff -pNaur include_old/ftimage.h include/ftimage.h +--- include_old/ftimage.h Sat Mar 7 18:56:10 2015 ++++ include/ftimage.h Sat Mar 7 22:12:11 2015 +@@ -55,7 +55,11 @@ FT_BEGIN_HEADER + /* on the context, these can represent distances in integer font */ + /* units, or 16.16, or 26.6 fixed-point pixel coordinates. */ + /* */ +- typedef signed long FT_Pos; ++#if _WIN64 ++ typedef signed __int64 FT_Pos; ++#else ++ typedef signed long FT_Pos; ++#endif + + + /*************************************************************************/ +diff -pNaur include_old/fttypes.h include/fttypes.h +--- include_old/fttypes.h Sat Mar 7 21:46:14 2015 ++++ include/fttypes.h Sat Mar 7 21:52:41 2015 +@@ -239,7 +239,11 @@ FT_BEGIN_HEADER + /* */ + /* A typedef for signed long. */ + /* */ +- typedef signed long FT_Long; ++#if _WIN64 ++ typedef signed __int64 FT_Long; ++#else ++ typedef signed long FT_Long; ++#endif + + + /*************************************************************************/ +@@ -250,7 +254,11 @@ FT_BEGIN_HEADER + /* */ + /* A typedef for unsigned long. */ + /* */ +- typedef unsigned long FT_ULong; ++#if _WIN64 ++ typedef unsigned __int64 FT_ULong; ++#else ++ typedef unsigned long FT_ULong; ++#endif + + + /*************************************************************************/ +@@ -273,7 +281,11 @@ FT_BEGIN_HEADER + /* A signed 26.6 fixed-point type used for vectorial pixel */ + /* coordinates. */ + /* */ +- typedef signed long FT_F26Dot6; ++#if _WIN64 ++ typedef signed __int64 FT_F26Dot6; ++#else ++ typedef unsigned long FT_F26Dot6; ++#endif + + + /*************************************************************************/ +@@ -285,7 +297,11 @@ FT_BEGIN_HEADER + /* This type is used to store 16.16 fixed-point values, like scaling */ + /* values or matrix coefficients. */ + /* */ +- typedef signed long FT_Fixed; ++#if _WIN64 ++ typedef signed __int64 FT_Fixed; ++#else ++ typedef unsigned long FT_Fixed; ++#endif + + + /*************************************************************************/ diff --git a/SharpFont/LICENSE b/SharpFont/LICENSE new file mode 100644 index 000000000..9ee67879e --- /dev/null +++ b/SharpFont/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2012-2016 Robert Rouhani + +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. \ No newline at end of file diff --git a/SharpFont/Makefile b/SharpFont/Makefile new file mode 100644 index 000000000..55320feea --- /dev/null +++ b/SharpFont/Makefile @@ -0,0 +1,16 @@ +XBUILD := xbuild +XBUILDFLAGS_RELEASE := /p:Configuration=Release +XBUILDFLAGS_DEBUG := /p:Configuration=Debug + +SOLUTION := Source/SharpFont.sln + +release: + $(XBUILD) $(XBUILDFLAGS_RELEASE) $(SOLUTION) +debug: + $(XBUILD) $(XBUILDFLAGS_DEBUG) $(SOLUTION) +clean: + $(XBUILD) $(XBUILDFLAGS_DEBUG) $(SOLUTION) /t:Clean + $(XBUILD) $(XBUILDFLAGS_RELEASE) $(SOLUTION) /t:Clean + +.SUFFIXES: +.PHONY: release debug clean diff --git a/SharpFont/README.md b/SharpFont/README.md new file mode 100644 index 000000000..8054930b6 --- /dev/null +++ b/SharpFont/README.md @@ -0,0 +1,120 @@ +SharpFont [![NuGet Version](https://img.shields.io/nuget/vpre/SharpFont.svg)](https://www.nuget.org/packages/SharpFont) [![Gratipay Tips](https://img.shields.io/gratipay/Robmaister.svg)](https://gratipay.com/Robmaister) +========= +### Cross-platform FreeType bindings for .NET + +SharpFont is a library that provides FreeType bindings for .NET. It's MIT +licensed to make sure licensing doesn't get in the way of using the library in +your own projects. Unlike [Tao.FreeType][1], SharpFont provides the full +public API and not just the basic methods needed to render simple text. +Everything from format-specific APIs to the caching subsystem are included. + +SharpFont simplifies the FreeType API in a few ways: + + - The error codes that most FreeType methods return are converted to + exceptions. + - Since the return values are no longer error codes, methods with a single + `out` parameter are returned instead. + - Most methods are instance methods instead of static methods. This avoids + unnecessary redundancy in method calls and creates an API with a .NET + look-and-feel. + +For example, a regular FreeType method looks like this: + +```C +Face face; +int err = FT_New_Face(library, "./myfont.ttf", 0, &face); +``` + +The equivalent code in C# with SharpFont is: + +```CSharp +Face face = new Face(library, "./myfont.ttf"); +``` + +##Quick Start + +###NuGet +SharpFont is available on [NuGet][2]. It can be installed by issuing the +following command in the package manager console: + +``` +PM> Install-Package SharpFont +``` + +###From Source +Clone the repository and compile the solution. Copy `SharpFont.dll` to your +project and include it as a reference. On Windows, you must include a compiled +copy of FreeType2 as `freetype6.dll` in the project's output directory. It is +possible to rename the file by changing the filename constant in +[FT.Internal.cs][3] and recompile. On Linux and OSX (and any other Mono +supported platform), you must also copy `SharpFont.dll.config` to the +project's output directory. + +Two extensions for Visual Studio make it easy to follow the coding format in +this project and prevent lots of spurious whitespace changes. +The [.editorconfig](http://editorconfig.org/) file in the project works with the +[EditorConfig](https://visualstudiogallery.msdn.microsoft.com/c8bccfe2-650c-4b42-bc5c-845e21f96328) +extension and the [Format document on Save](https://visualstudiogallery.msdn.microsoft.com/3ea1c920-69c4-441f-9979-ccc2752dac56) +extension makes it basically automatic. + +####Mono +With the removal of the `WIN64` configurations, the included `Makefile` is +effectively redundant. However, you can still build SharpFont by calling +`make` while in the root directory of this project. + +####FreeType +A large number of FreeType builds for Windows are now available in the +[SharpFont.Dependencies][4] repository. + +##Known Issues + +While SharpFont is fully compatible with and runs on 64-bit Windows, it relies +on a patch for FreeType to do this. This patch is already included in +[SharpFont.Dependencies/freetype2][5]. You do not need to worry about this as +a user of the library. If you are compiling FreeType from source, you can find +the patch and instructions at the same location. + +##License + +As metioned earlier, SharpFont is licensed under the MIT License. The terms of +the MIT license are included in both the [LICENSE][6] file and below: + +``` +Copyright (c) 2012-2016 Robert Rouhani + +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. +``` + +The Windows binary of FreeType that is included in the Examples project and in +the NuGet package is redistributed under the FreeType License (FTL). + +``` +Portions of this software are copyright (c) 2016 The FreeType Project +(www.freetype.org). All rights reserved. +``` + + +[1]: http://taoframework.svn.sourceforge.net/viewvc/taoframework/trunk/src/Tao.FreeType/ +[2]: https://nuget.org/packages/SharpFont/ +[3]: SharpFont/FT.Internal.cs +[4]: https://github.com/Robmaister/SharpFont.Dependencies +[5]: https://github.com/Robmaister/SharpFont.Dependencies/tree/master/freetype2 +[6]: LICENSE diff --git a/SharpFont/Source/.editorconfig b/SharpFont/Source/.editorconfig new file mode 100644 index 000000000..54d45caba --- /dev/null +++ b/SharpFont/Source/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = crlf +indent_style = tab +insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = true diff --git a/SharpFont/Source/Settings.StyleCop b/SharpFont/Source/Settings.StyleCop new file mode 100644 index 000000000..2c2aa1c55 --- /dev/null +++ b/SharpFont/Source/Settings.StyleCop @@ -0,0 +1,97 @@ + + + + + + Rec\.cs$ + Marhsaler\.cs$ + + + + + + + + + + False + + + + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + True + True + + + + + + + False + + + + + + + + + + False + + + + + + + \ No newline at end of file diff --git a/SharpFont/Source/SharpFont.dll.config b/SharpFont/Source/SharpFont.dll.config new file mode 100644 index 000000000..c216adda3 --- /dev/null +++ b/SharpFont/Source/SharpFont.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/SharpFont/Source/SharpFont.sln b/SharpFont/Source/SharpFont.sln new file mode 100644 index 000000000..7d3f623da --- /dev/null +++ b/SharpFont/Source/SharpFont.sln @@ -0,0 +1,45 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpFont", "SharpFont\SharpFont.csproj", "{C293DB32-FA42-486D-B128-5A12522FAE4E}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SharpFontShared", "SharpFontShared\SharpFontShared.shproj", "{2E4773B7-961A-4328-9D77-9749F9071CA2}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + SharpFontShared\SharpFontShared.projitems*{2e4773b7-961a-4328-9d77-9749f9071ca2}*SharedItemsImports = 13 + SharpFontShared\SharpFontShared.projitems*{c293db32-fa42-486d-b128-5a12522fae4e}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Examples\Examples.csproj + Policies = $0 + $0.DotNetNamingPolicy = $1 + $1.DirectoryNamespaceAssociation = None + $1.ResourceNamePolicy = FileFormatDefault + $0.StandardHeader = $2 + $2.Text = + $2.IncludeInNewFiles = True + $0.VersionControlPolicy = $3 + $3.inheritsSet = Mono + $0.ChangeLogPolicy = $4 + $4.UpdateMode = None + $4.MessageStyle = $5 + $5.LineAlign = 0 + $4.inheritsSet = Mono + EndGlobalSection +EndGlobal diff --git a/SharpFont/Source/SharpFont.snk b/SharpFont/Source/SharpFont.snk new file mode 100644 index 0000000000000000000000000000000000000000..552a3332a087ef2024bcafec022ab09d6aec06b5 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50097{oLb3gsQ8(6vVPKx=0R&vY$&znmLiHh zsKdw8u&;#RIF-nfrvy2geVDXd22xb^_2dbj|DlzhyomE(bve_H<%(u7KkU(` z&T^6wug5euU7X4rP%=an68iS#aU8ONgKwG;t_nfLK4Z&jmz@qFdlkn+8$7iO=@-;v^e*W$*m0F(L2lPF zmVTI9%G>`F9b@$|&sZAadSB~e^0J{jaG^ly*!0y20gGllp7(YCm}N1I>AGJUl51gH z2fk + + + Release + AnyCPU + 8.0.30703 + 2.0 + {C293DB32-FA42-486D-B128-5A12522FAE4E} + Library + Properties + SharpFont + SharpFont + v4.5 + 512 + + + true + full + false + ..\..\Binaries\SharpFont\Debug\ + TRACE;DEBUG + prompt + 4 + bin\Debug\SharpFont.xml + true + AnyCPU + + + pdbonly + true + ..\..\Binaries\SharpFont\Release\ + TRACE + prompt + 4 + bin\Release\SharpFont.xml + true + AnyCPU + + + true + + + ..\SharpFont.snk + + + + + + + + PreserveNewest + + + + + + + + diff --git a/SharpFont/Source/SharpFontShared/AutoHinterScript.cs b/SharpFont/Source/SharpFontShared/AutoHinterScript.cs new file mode 100644 index 000000000..71bc7448f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/AutoHinterScript.cs @@ -0,0 +1,138 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of constants used for the glyph-to-script-map property to specify the script submodule the auto-hinter + /// should use for hinting a particular glyph. + /// + public enum AutoHinterScript + { + /// + /// Don't auto-hint this glyph. + /// + None = 0, + + /// + /// Apply the latin auto-hinter. For the auto-hinter, ‘latin’ is a very broad term, including Cyrillic and + /// Greek also since characters from those scripts share the same design constraints. + /// + /// + /// By default, characters from the following Unicode ranges are assigned to this submodule. + /// + /// U+0020 - U+007F // Basic Latin (no control characters) + /// U+00A0 - U+00FF // Latin-1 Supplement (no control characters) + /// U+0100 - U+017F // Latin Extended-A + /// U+0180 - U+024F // Latin Extended-B + /// U+0250 - U+02AF // IPA Extensions + /// U+02B0 - U+02FF // Spacing Modifier Letters + /// U+0300 - U+036F // Combining Diacritical Marks + /// U+0370 - U+03FF // Greek and Coptic + /// U+0400 - U+04FF // Cyrillic + /// U+0500 - U+052F // Cyrillic Supplement + /// U+1D00 - U+1D7F // Phonetic Extensions + /// U+1D80 - U+1DBF // Phonetic Extensions Supplement + /// U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement + /// U+1E00 - U+1EFF // Latin Extended Additional + /// U+1F00 - U+1FFF // Greek Extended + /// U+2000 - U+206F // General Punctuation + /// U+2070 - U+209F // Superscripts and Subscripts + /// U+20A0 - U+20CF // Currency Symbols + /// U+2150 - U+218F // Number Forms + /// U+2460 - U+24FF // Enclosed Alphanumerics + /// U+2C60 - U+2C7F // Latin Extended-C + /// U+2DE0 - U+2DFF // Cyrillic Extended-A + /// U+2E00 - U+2E7F // Supplemental Punctuation + /// U+A640 - U+A69F // Cyrillic Extended-B + /// U+A720 - U+A7FF // Latin Extended-D + /// U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures) + /// U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols + /// U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement + /// + Latin = 1, + + /// + /// Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old Vietnamese, and some other scripts. + /// + /// + /// By default, characters from the following Unicode ranges are assigned to this submodule. + /// + /// U+1100 - U+11FF // Hangul Jamo + /// U+2E80 - U+2EFF // CJK Radicals Supplement + /// U+2F00 - U+2FDF // Kangxi Radicals + /// U+2FF0 - U+2FFF // Ideographic Description Characters + /// U+3000 - U+303F // CJK Symbols and Punctuation + /// U+3040 - U+309F // Hiragana + /// U+30A0 - U+30FF // Katakana + /// U+3100 - U+312F // Bopomofo + /// U+3130 - U+318F // Hangul Compatibility Jamo + /// U+3190 - U+319F // Kanbun + /// U+31A0 - U+31BF // Bopomofo Extended + /// U+31C0 - U+31EF // CJK Strokes + /// U+31F0 - U+31FF // Katakana Phonetic Extensions + /// U+3200 - U+32FF // Enclosed CJK Letters and Months + /// U+3300 - U+33FF // CJK Compatibility + /// U+3400 - U+4DBF // CJK Unified Ideographs Extension A + /// U+4DC0 - U+4DFF // Yijing Hexagram Symbols + /// U+4E00 - U+9FFF // CJK Unified Ideographs + /// U+A960 - U+A97F // Hangul Jamo Extended-A + /// U+AC00 - U+D7AF // Hangul Syllables + /// U+D7B0 - U+D7FF // Hangul Jamo Extended-B + /// U+F900 - U+FAFF // CJK Compatibility Ideographs + /// U+FE10 - U+FE1F // Vertical forms + /// U+FE30 - U+FE4F // CJK Compatibility Forms + /// U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms + /// U+1B000 - U+1B0FF // Kana Supplement + /// U+1D300 - U+1D35F // Tai Xuan Hing Symbols + /// U+1F200 - U+1F2FF // Enclosed Ideographic Supplement + /// U+20000 - U+2A6DF // CJK Unified Ideographs Extension B + /// U+2A700 - U+2B73F // CJK Unified Ideographs Extension C + /// U+2B740 - U+2B81F // CJK Unified Ideographs Extension D + /// U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement + /// + Cjk = 2, + + /// + /// Apply the indic auto-hinter, covering all major scripts from the Indian sub-continent and some other + /// related scripts like Thai, Lao, or Tibetan. + /// + /// + /// By default, characters from the following Unicode ranges are assigned to this submodule. + /// + /// U+0900 - U+0DFF // Indic Range + /// U+0F00 - U+0FFF // Tibetan + /// U+1900 - U+194F // Limbu + /// U+1B80 - U+1BBF // Sundanese + /// U+1C80 - U+1CDF // Meetei Mayak + /// U+A800 - U+A82F // Syloti Nagri + /// U+11800 - U+118DF // Sharada + /// + /// Note that currently Indic support is rudimentary only, missing blue zone support. + /// + Indic = 3 + } +} diff --git a/SharpFont/Source/SharpFontShared/BBox.cs b/SharpFont/Source/SharpFontShared/BBox.cs new file mode 100644 index 000000000..50df52ccc --- /dev/null +++ b/SharpFont/Source/SharpFontShared/BBox.cs @@ -0,0 +1,190 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont +{ + /// + /// A structure used to hold an outline's bounding box, i.e., the + /// coordinates of its extrema in the horizontal and vertical directions. + /// + [StructLayout(LayoutKind.Sequential)] + public struct BBox : IEquatable + { + #region Fields + + private FT_Long xMin, yMin; + private FT_Long xMax, yMax; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// The left bound. + /// The bottom bound. + /// The right bound. + /// The upper bound. + public BBox(int left, int bottom, int right, int top) + { + xMin = (IntPtr)left; + yMin = (IntPtr)bottom; + xMax = (IntPtr)right; + yMax = (IntPtr)top; + } + + #endregion + + #region Properties + + /// + /// Gets the horizontal minimum (left-most). + /// + public int Left + { + get + { + return (int)xMin; + } + } + + /// + /// Gets the vertical minimum (bottom-most). + /// + public int Bottom + { + get + { + return (int)yMin; + } + } + + /// + /// Gets the horizontal maximum (right-most). + /// + public int Right + { + get + { + return (int)xMax; + } + } + + /// + /// Gets the vertical maximum (top-most). + /// + public int Top + { + get + { + return (int)yMax; + } + } + + #endregion + + #region Operators + + /// + /// Compares two instances of for equality. + /// + /// A . + /// Another . + /// A value indicating equality. + public static bool operator ==(BBox left, BBox right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// A . + /// Another . + /// A value indicating inequality. + public static bool operator !=(BBox left, BBox right) + { + return !left.Equals(right); + } + + #endregion + + #region Methods + + /// + /// Compares this instance of to another for equality. + /// + /// A . + /// A value indicating equality. + public bool Equals(BBox other) + { + return + xMin == other.xMin && + yMin == other.yMin && + xMax == other.xMax && + yMax == other.yMax; + } + + /// + /// Compares this instance of to an object for equality. + /// + /// An object. + /// A value indicating equality. + public override bool Equals(object obj) + { + if (obj is BBox) + return this.Equals((BBox)obj); + + return false; + } + + /// + /// Gets a unique hash code for this instance. + /// + /// A hash code. + public override int GetHashCode() + { + //TODO better hash algo + return xMin.GetHashCode() ^ yMin.GetHashCode() ^ xMax.GetHashCode() ^ yMax.GetHashCode(); + } + + /// + /// Gets a string that represents this instance. + /// + /// A string representation of this instance. + public override string ToString() + { + return "Min: (" + (int)xMin + ", " + (int)yMin + "), Max: (" + (int)xMax + ", " + (int)yMax + ")"; + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Bdf/Internal/PropertyRec.cs b/SharpFont/Source/SharpFontShared/Bdf/Internal/PropertyRec.cs new file mode 100644 index 000000000..e62293bd0 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Bdf/Internal/PropertyRec.cs @@ -0,0 +1,45 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Bdf.Internal +{ + [StructLayout(LayoutKind.Explicit, Pack = 0)] + internal struct PropertyRec + { + [FieldOffset(0)] + internal PropertyType type; + + [FieldOffset(4)] + internal IntPtr atom; + + [FieldOffset(4)] + internal int integer; + + [FieldOffset(4)] + internal uint cardinal; + } +} diff --git a/SharpFont/Source/SharpFontShared/Bdf/Property.cs b/SharpFont/Source/SharpFontShared/Bdf/Property.cs new file mode 100644 index 000000000..35f3f3b84 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Bdf/Property.cs @@ -0,0 +1,121 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Bdf.Internal; + +namespace SharpFont.Bdf +{ + /// + /// This structure models a given BDF/PCF property. + /// + public class Property + { + #region Fields + + private IntPtr reference; + private PropertyRec rec; + + #endregion + + #region Constructors + + internal Property(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the property type. + /// + public PropertyType Type + { + get + { + return rec.type; + } + } + + /// + /// Gets the atom string, if type is . + /// + public string Atom + { + get + { + // only this property throws an exception because the pointer could be to unmanaged memory not owned by + // the process. + if (rec.type != PropertyType.Atom) + throw new InvalidOperationException("The property type is not Atom."); + + return Marshal.PtrToStringAnsi(rec.atom); + } + } + + /// + /// Gets a signed integer, if type is . + /// + public int Integer + { + get + { + return rec.integer; + } + } + + /// + /// Gets an unsigned integer, if type is . + /// + [CLSCompliant(false)] + public uint Cardinal + { + get + { + return rec.cardinal; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Bdf/PropertyType.cs b/SharpFont/Source/SharpFontShared/Bdf/PropertyType.cs new file mode 100644 index 000000000..be90669d5 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Bdf/PropertyType.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Bdf +{ + /// + /// A list of BDF property types. + /// + public enum PropertyType + { + /// Value 0 is used to indicate a missing property. + None = 0, + + /// Property is a string atom. + Atom = 1, + + /// Property is a 32-bit signed integer. + Integer = 2, + + /// Property is a 32-bit unsigned integer. + Cardinal = 3 + } +} diff --git a/SharpFont/Source/SharpFontShared/BitmapGlyph.cs b/SharpFont/Source/SharpFontShared/BitmapGlyph.cs new file mode 100644 index 000000000..98c399ceb --- /dev/null +++ b/SharpFont/Source/SharpFontShared/BitmapGlyph.cs @@ -0,0 +1,207 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used for bitmap glyph images. This really is a ‘sub-class’ of . + /// + /// + /// You can typecast an to if you have ‘ == + /// ’. This lets you access the bitmap's contents easily. + /// + /// The corresponding pixel buffer is always owned by and is thus created and destroyed + /// with it. + /// + public sealed class BitmapGlyph : IDisposable + { + #region Fields + + private Glyph original; + private BitmapGlyphRec rec; + + #endregion + + #region Constructors + + internal BitmapGlyph(Glyph original) + { + this.original = original; + Reference = original.Reference; //generates the rec. + } + + /// + /// Finalizes an instance of the class. + /// + ~BitmapGlyph() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return original.IsDisposed; + } + } + + /// + /// Gets the root fields. + /// + public Glyph Root + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Root", "Cannot access a disposed object."); + + return original; + } + } + + /// + /// Gets the left-side bearing, i.e., the horizontal distance from the current pen position to the left border + /// of the glyph bitmap. + /// + public int Left + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Left", "Cannot access a disposed object."); + + return rec.left; + } + } + + /// + /// Gets the top-side bearing, i.e., the vertical distance from the current pen position to the top border of + /// the glyph bitmap. This distance is positive for upwards y! + /// + public int Top + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Top", "Cannot access a disposed object."); + + return rec.top; + } + } + + /// + /// Gets a descriptor for the bitmap. + /// + public FTBitmap Bitmap + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Bitmap", "Cannot access a disposed object."); + + return new FTBitmap(PInvokeHelper.AbsoluteOffsetOf(Reference, "bitmap"), rec.bitmap, null); + } + } + + internal IntPtr Reference + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + return original.Reference; + } + + set + { + if (IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot modify a disposed object."); + + rec = PInvokeHelper.PtrToStructure(original.Reference); + } + } + + #endregion + + #region Operators + + /// + /// Casts a back up to a . The eqivalent of + /// . + /// + /// A . + /// A . + public static implicit operator Glyph(BitmapGlyph g) + { + return g.original; + } + + #endregion + + #region Methods + + /// + /// A CLS-compliant version of the implicit cast to . + /// + /// A . + public Glyph ToGlyph() + { + return (Glyph)this; + } + + /// + /// Disposes an instance of the class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + { + original.Dispose(); + original = null; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/BitmapSize.cs b/SharpFont/Source/SharpFontShared/BitmapSize.cs new file mode 100644 index 000000000..ff2fdbc72 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/BitmapSize.cs @@ -0,0 +1,145 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// This structure models the metrics of a bitmap strike (i.e., a set of + /// glyphs for a given point size and resolution) in a bitmap font. It is + /// used for the field of + /// . + /// + /// + /// Windows FNT: The nominal size given in a FNT font is not reliable. Thus + /// when the driver finds it incorrect, it sets ‘size’ to some calculated + /// values and sets ‘x_ppem’ and ‘y_ppem’ to the pixel width and height + /// given in the font, respectively. + /// + /// TrueType embedded bitmaps: ‘size’, ‘width’, and ‘height’ values are not + /// contained in the bitmap strike itself. They are computed from the + /// global font parameters. + /// + public sealed class BitmapSize + { + #region Fields + + private IntPtr reference; + private BitmapSizeRec rec; + + #endregion + + #region Constructors + + internal BitmapSize(IntPtr reference) + { + Reference = reference; + } + + internal BitmapSize(BitmapSizeRec bmpSizeInt) + { + this.rec = bmpSizeInt; + } + + #endregion + + #region Properties + + /// + /// Gets the vertical distance, in pixels, between two consecutive + /// baselines. It is always positive. + /// + public short Height + { + get + { + return rec.height; + } + } + + /// + /// Gets the average width, in pixels, of all glyphs in the strike. + /// + public short Width + { + get + { + return rec.width; + } + } + + /// + /// Gets the nominal size of the strike in 26.6 fractional points. This + /// field is not very useful. + /// + public Fixed26Dot6 Size + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.size); + } + } + + /// + /// Gets the horizontal ppem (nominal width) in 26.6 fractional pixels. + /// + public Fixed26Dot6 NominalWidth + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.x_ppem); + } + } + + /// + /// Gets the vertical ppem (nominal height) in 26.6 fractional pixels. + /// + public Fixed26Dot6 NominalHeight + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.y_ppem); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/CMapCache.cs b/SharpFont/Source/SharpFontShared/Cache/CMapCache.cs new file mode 100644 index 000000000..f4dc0ef20 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/CMapCache.cs @@ -0,0 +1,100 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Cache +{ + /// + /// An opaque handle used to model a charmap cache. This cache is to hold character codes -> glyph indices + /// mappings. + /// + public class CMapCache + { + #region Fields + + private IntPtr reference; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// Like all other caches, this one will be destroyed with the cache manager. + /// + /// A handle to the cache manager. + public CMapCache(Manager manager) + { + IntPtr cacheRef; + Error err = FT.FTC_CMapCache_New(manager.Reference, out cacheRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = cacheRef; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + + #region Methods + + /// + /// Translate a character code into a glyph index, using the charmap cache. + /// + /// The source face ID. + /// + /// The index of the charmap in the source face. Any negative value means to use the cache 's + /// default charmap. + /// + /// The character code (in the corresponding charmap). + /// Glyph index. 0 means ‘no glyph’. + [CLSCompliant(false)] + public uint Lookup(IntPtr faceId, int cmapIndex, uint charCode) + { + return FT.FTC_CMapCache_Lookup(Reference, faceId, cmapIndex, charCode); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/FaceRequester.cs b/SharpFont/Source/SharpFontShared/Cache/FaceRequester.cs new file mode 100644 index 000000000..5081858f7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/FaceRequester.cs @@ -0,0 +1,47 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache +{ + /// + /// A callback function provided by client applications. It is used by the cache manager to translate a given + /// FTC_FaceID into a new valid object, on demand. + /// + /// + /// The third parameter ‘req_data’ is the same as the one passed by the client when + /// is called. + /// + /// The face requester should not perform funny things on the returned face object, like creating a new + /// for it, or setting a transformation through ! + /// + /// The face ID to resolve. + /// A handle to a FreeType library object. + /// Application-provided request data (see note below). + /// A new handle. + /// FreeType error code. 0 means success. + public delegate Error FaceRequester(IntPtr faceId, IntPtr library, IntPtr requestData, out IntPtr aface); +} diff --git a/SharpFont/Source/SharpFontShared/Cache/ImageCache.cs b/SharpFont/Source/SharpFontShared/Cache/ImageCache.cs new file mode 100644 index 000000000..f581b31e8 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/ImageCache.cs @@ -0,0 +1,173 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Cache +{ + /// + /// A handle to an glyph image cache object. They are designed to hold many distinct glyph images while not + /// exceeding a certain memory threshold. + /// + public class ImageCache + { + #region Fields + + private IntPtr reference; + private Manager parentManager; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The parent manager for the image cache. + public ImageCache(Manager manager) + { + if (manager == null) + throw new ArgumentNullException("manager"); + + IntPtr cacheRef; + Error err = FT.FTC_ImageCache_New(manager.Reference, out cacheRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + parentManager = manager; + Reference = cacheRef; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + return reference; + } + + set + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + reference = value; + } + } + + #endregion + + #region Methods + + /// + /// Retrieve a given glyph image from a glyph image cache. + /// + /// + /// The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it + /// manually! You can however create a copy with and modify the new one. + /// + /// If ‘node’ is not NULL, it receives the address of the cache node containing the glyph image, + /// after increasing its reference count. This ensures that the node (as well as the ) will + /// always be kept in the cache until you call to ‘release’ it. + /// + /// If ‘node’ is NULL, the cache node is left unchanged, which means that the + /// could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that + /// it is persistent! + /// + /// A pointer to a glyph image type descriptor. + /// The glyph index to retrieve. + /// + /// Used to return the address of of the corresponding cache node after incrementing its reference count (see + /// note below). + /// + /// The corresponding object. 0 in case of failure. + [CLSCompliant(false)] + public Glyph Lookup(ImageType type, uint gIndex, out Node node) + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + IntPtr glyphRef, nodeRef; + Error err = FT.FTC_ImageCache_Lookup(Reference, type.Reference, gIndex, out glyphRef, out nodeRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + node = new Node(nodeRef); + return new Glyph(glyphRef, null); + } + + /// + /// A variant of that uses a to specify the face ID and its + /// size. + /// + /// + /// The returned glyph is owned and managed by the glyph image cache. Never try to transform or discard it + /// manually! You can however create a copy with and modify the new one. + /// + /// If ‘node’ is not NULL, it receives the address of the cache node containing the glyph image, + /// after increasing its reference count. This ensures that the node (as well as the ) will + /// always be kept in the cache until you call to ‘release’ it. + /// + /// If ‘node’ is NULL, the cache node is left unchanged, which means that the + /// could be flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that + /// it is persistent! + /// + /// Calls to and friends have no effect on cached glyphs; you should always use + /// the FreeType cache API instead. + /// + /// A pointer to a scaler descriptor. + /// The corresponding load flags. + /// The glyph index to retrieve. + /// + /// Used to return the address of of the corresponding cache node after incrementing its reference count (see + /// note below). + /// + /// The corresponding object. 0 in case of failure. + [CLSCompliant(false)] + public Glyph LookupScaler(Scaler scaler, LoadFlags loadFlags, uint gIndex, out Node node) + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + IntPtr glyphRef, nodeRef; + Error err = FT.FTC_ImageCache_LookupScaler(Reference, scaler.Reference, loadFlags, gIndex, out glyphRef, out nodeRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + node = new Node(nodeRef); + return new Glyph(glyphRef, null); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/ImageType.cs b/SharpFont/Source/SharpFontShared/Cache/ImageType.cs new file mode 100644 index 000000000..f9c0e9016 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/ImageType.cs @@ -0,0 +1,116 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Cache.Internal; + +namespace SharpFont.Cache +{ + /// + /// A structure used to model the type of images in a glyph cache. + /// + public class ImageType + { + #region Fields + + private IntPtr reference; + private ImageTypeRec rec; + + #endregion + + #region Constructors + + internal ImageType(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the face ID. + /// + public IntPtr FaceId + { + get + { + return rec.face_id; + } + } + + /// + /// Gets the width in pixels. + /// + public int Width + { + get + { + return rec.width; + } + } + + /// + /// Gets the height in pixels. + /// + public int Height + { + get + { + return rec.height; + } + } + + /// + /// Gets the load flags, as in + /// + [CLSCompliant(false)] + public LoadFlags Flags + { + get + { + return rec.flags; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/CMapCacheRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/CMapCacheRec.cs new file mode 100644 index 000000000..fc170624a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/CMapCacheRec.cs @@ -0,0 +1,34 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct CMapCacheRec + { + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/ImageCacheRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/ImageCacheRec.cs new file mode 100644 index 000000000..97bbd7684 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/ImageCacheRec.cs @@ -0,0 +1,34 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ImageCacheRec + { + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/ImageTypeRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/ImageTypeRec.cs new file mode 100644 index 000000000..9da34c39c --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/ImageTypeRec.cs @@ -0,0 +1,38 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ImageTypeRec + { + internal IntPtr face_id; + internal int width; + internal int height; + internal LoadFlags flags; + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/ManagerRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/ManagerRec.cs new file mode 100644 index 000000000..aaa02a762 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/ManagerRec.cs @@ -0,0 +1,34 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ManagerRec + { + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/NodeRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/NodeRec.cs new file mode 100644 index 000000000..4f26d1145 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/NodeRec.cs @@ -0,0 +1,34 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct NodeRec + { + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/SBitCacheRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/SBitCacheRec.cs new file mode 100644 index 000000000..9b95b407f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/SBitCacheRec.cs @@ -0,0 +1,34 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SBitCacheRec + { + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/SBitRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/SBitRec.cs new file mode 100644 index 000000000..b631065cd --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/SBitRec.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SBitRec + { + internal byte width; + internal byte height; + internal byte left; + internal byte top; + + internal byte format; + internal byte max_grays; + internal short pitch; + internal byte xadvance; + internal byte yadvance; + + internal IntPtr buffer; + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Internal/ScalerRec.cs b/SharpFont/Source/SharpFontShared/Cache/Internal/ScalerRec.cs new file mode 100644 index 000000000..afc4a2197 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Internal/ScalerRec.cs @@ -0,0 +1,40 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ScalerRec + { + internal IntPtr face_id; + internal uint width; + internal uint height; + internal int pixel; + internal uint x_res; + internal uint y_res; + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Manager.cs b/SharpFont/Source/SharpFontShared/Cache/Manager.cs new file mode 100644 index 000000000..82455004f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Manager.cs @@ -0,0 +1,274 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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; + +namespace SharpFont.Cache +{ + /// + /// This object corresponds to one instance of the cache-subsystem. It is used to cache one or more + /// objects, along with corresponding objects. + /// + /// The manager intentionally limits the total number of opened and objects + /// to control memory usage. See the ‘max_faces’ and ‘max_sizes’ parameters of + /// . + /// + /// The manager is also used to cache ‘nodes’ of various types while limiting their total memory usage. + /// + /// All limitations are enforced by keeping lists of managed objects in most-recently-used order, and flushing old + /// nodes to make room for new ones. + /// + public sealed class Manager : IDisposable + { + #region Fields + + private IntPtr reference; + private Library parentLibrary; + + private bool disposed; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the Manager class. + /// + /// The parent FreeType library handle to use. + /// + /// Maximum number of opened objects managed by this cache instance. Use 0 for defaults. + /// + /// + /// Maximum number of opened objects managed by this cache instance. Use 0 for defaults. + /// + /// + /// Maximum number of bytes to use for cached data nodes. Use 0 for defaults. Note that this value does not + /// account for managed and objects. + /// + /// + /// An application-provided callback used to translate face IDs into real objects. + /// + /// + /// A generic pointer that is passed to the requester each time it is called (see ). + /// + [CLSCompliant(false)] + public Manager(Library library, uint maxFaces, uint maxSizes, ulong maxBytes, FaceRequester requester, IntPtr requestData) + { + if (library == null) + throw new ArgumentNullException("library"); + + IntPtr mgrRef; + Error err = FT.FTC_Manager_New(library.Reference, maxFaces, maxSizes, maxBytes, requester, requestData, out mgrRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = mgrRef; + + this.parentLibrary = library; + library.AddChildManager(this); + } + + /// + /// Finalizes an instance of the Manager class. + /// + ~Manager() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + 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 Public Members + + /// + /// Empty a given cache manager. This simply gets rid of all the currently cached and + /// objects within the manager. + /// + public void Reset() + { + if (disposed) + throw new ObjectDisposedException("Manager", "Cannot access a disposed object."); + + FT.FTC_Manager_Reset(Reference); + } + + /// + /// Retrieve the object that corresponds to a given face ID through a cache manager. + /// + /// + /// The returned object is always owned by the manager. You should never try to discard it + /// yourself. + /// + /// The object doesn't necessarily have a current size object (i.e., + /// can be 0). If you need a specific ‘font size’, use instead. + /// + /// Never change the face's transformation matrix (i.e., never call the + /// function) on a returned face! If you need to transform glyphs, do it yourself after glyph loading. + /// + /// When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental + /// flushes of the cache until enough memory is released for the lookup to succeed. + /// + /// If a lookup fails with the cache has already been completely flushed, and + /// still no memory was available for the operation. + /// + /// The ID of the face object. + /// A handle to the face object. + public Face LookupFace(IntPtr faceId) + { + if (disposed) + throw new ObjectDisposedException("Manager", "Cannot access a disposed object."); + + IntPtr faceRef; + Error err = FT.FTC_Manager_LookupFace(Reference, faceId, out faceRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + //HACK fix this later. + return new Face(faceRef, null); + } + + /// + /// Retrieve the object that corresponds to a given pointer through a + /// cache manager. + /// + /// + /// The returned object is always owned by the/ manager. You should never try to discard + /// it by yourself. + /// + /// You can access the parent object simply as if you need it. + /// Note that this object is also owned by the manager. + /// + /// When you perform a lookup, out-of-memory errors are detected within the lookup and force incremental + /// flushes of the cache until enough memory is released for the lookup to succeed. + /// + /// If a lookup fails with the cache has already been completely flushed, and + /// still no memory is available for the operation. + /// + /// A scaler handle. + /// A handle to the size object. + public FTSize LookupSize(Scaler scaler) + { + if (disposed) + throw new ObjectDisposedException("Manager", "Cannot access a disposed object."); + + IntPtr sizeRef; + Error err = FT.FTC_Manager_LookupSize(Reference, scaler.Reference, out sizeRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + //HACK fix this later. + return new FTSize(sizeRef, false, null); + } + + /// + /// A special function used to indicate to the cache manager that a given FTC_FaceID is no longer valid, either + /// because its content changed, or because it was deallocated or uninstalled. + /// + /// + /// This function flushes all nodes from the cache corresponding to this ‘faceID’, with the + /// exception of nodes with a non-null reference count. + /// + /// Such nodes are however modified internally so as to never appear in later lookups with the same + /// ‘faceID’ value, and to be immediately destroyed when released by all their users. + /// + /// The FTC_FaceID to be removed. + public void RemoveFaceId(IntPtr faceId) + { + if (disposed) + throw new ObjectDisposedException("Manager", "Cannot access a disposed object."); + + FT.FTC_Manager_RemoveFaceID(Reference, faceId); + } + + #endregion + + #region IDisposable Members + + /// + /// Disposes the Manager. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + FT.FTC_Manager_Done(reference); + reference = IntPtr.Zero; + + // removes itself from the parent Library, with a check to prevent this from happening when Library is + // being disposed (Library disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (!parentLibrary.IsDisposed) + parentLibrary.RemoveChildManager(this); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Node.cs b/SharpFont/Source/SharpFontShared/Cache/Node.cs new file mode 100644 index 000000000..a3f03d60c --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Node.cs @@ -0,0 +1,87 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Cache +{ + /// + /// An opaque handle to a cache node object. Each cache node is reference-counted. A node with a count of 0 might + /// be flushed out of a full cache whenever a lookup request is performed. + /// + /// If you look up nodes, you have the ability to ‘acquire’ them, i.e., to increment their reference count. This + /// will prevent the node from being flushed out of the cache until you explicitly ‘release’ it. + /// + /// + /// + /// + public class Node + { + #region Fields + + private IntPtr reference; + + #endregion + + #region Constructors + + internal Node(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + + #region Public Methods + + /// + /// Decrement a cache node's internal reference count. When the count reaches 0, it is not destroyed but + /// becomes eligible for subsequent cache flushes. + /// + /// The cache manager handle. + public void Unref(Manager manager) + { + FT.FTC_Node_Unref(Reference, manager.Reference); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/SBit.cs b/SharpFont/Source/SharpFontShared/Cache/SBit.cs new file mode 100644 index 000000000..706de0491 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/SBit.cs @@ -0,0 +1,185 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Cache.Internal; + +namespace SharpFont.Cache +{ + /// + /// A handle to a small bitmap cache. These are special cache objects used to store small glyph bitmaps (and + /// anti-aliased pixmaps) in a much more efficient way than the traditional glyph image cache implemented by + /// . + /// + public class SBit + { + #region Fields + + private IntPtr reference; + private SBitRec rec; + + #endregion + + #region Constructors + + internal SBit(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the bitmap width in pixels. + /// + public byte Width + { + get + { + return rec.width; + } + } + + /// + /// Gets the bitmap height in pixels. + /// + public byte Height + { + get + { + return rec.height; + } + } + + /// + /// Gets the horizontal distance from the pen position to the left bitmap border (a.k.a. ‘left side bearing’, + /// or ‘lsb’). + /// + public byte Left + { + get + { + return rec.left; + } + } + + /// + /// Gets the vertical distance from the pen position (on the baseline) to the upper bitmap border (a.k.a. ‘top + /// side bearing’). The distance is positive for upwards y coordinates. + /// + public byte Top + { + get + { + return rec.top; + } + } + + /// + /// Gets the format of the glyph bitmap (monochrome or gray). + /// + public byte Format + { + get + { + return rec.format; + } + } + + /// + /// Gets the maximum gray level value (in the range 1 to 255). + /// + public byte MaxGrays + { + get + { + return rec.max_grays; + } + } + + /// + /// Gets the number of bytes per bitmap line. May be positive or negative. + /// + public short Pitch + { + get + { + return rec.pitch; + } + } + + /// + /// Gets the horizontal advance width in pixels. + /// + public byte AdvanceX + { + get + { + return rec.xadvance; + } + } + + /// + /// Gets the vertical advance height in pixels. + /// + public byte AdvanceY + { + get + { + return rec.yadvance; + } + } + + /// + /// Gets a pointer to the bitmap pixels. + /// + public IntPtr Buffer + { + get + { + return rec.buffer; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/SBitCache.cs b/SharpFont/Source/SharpFontShared/Cache/SBitCache.cs new file mode 100644 index 000000000..b53436a71 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/SBitCache.cs @@ -0,0 +1,173 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Cache +{ + /// + /// A handle to a small bitmap cache. These are special cache objects used to store small glyph bitmaps (and + /// anti-aliased pixmaps) in a much more efficient way than the traditional glyph image cache implemented by + /// . + /// + public class SBitCache + { + #region Fields + + private IntPtr reference; + private Manager parentManager; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// A handle to the source cache manager. + public SBitCache(Manager manager) + { + if (manager == null) + throw new ArgumentNullException("manager"); + + IntPtr cacheRef; + Error err = FT.FTC_SBitCache_New(manager.Reference, out cacheRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = cacheRef; + parentManager = manager; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + + #region Methods + + /// + /// Look up a given small glyph bitmap in a given sbit cache and ‘lock’ it to prevent its flushing from the + /// cache until needed. + /// + /// + /// The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the + /// application. They might as well disappear from memory on the next cache lookup, so don't treat them as + /// persistent data. + /// + /// The descriptor's ‘buffer’ field is set to 0 to indicate a missing glyph bitmap. + /// + /// If ‘node’ is not NULL, it receives the address of the cache node containing the bitmap, after + /// increasing its reference count. This ensures that the node (as well as the image) will always be kept in + /// the cache until you call to ‘release’ it. + /// + /// If ‘node’ is NULL, the cache node is left unchanged, which means that the bitmap could be + /// flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is + /// persistent! + /// + /// A pointer to the glyph image type descriptor. + /// The glyph index. + /// + /// Used to return the address of of the corresponding cache node after incrementing its reference count (see + /// note below). + /// + /// A handle to a small bitmap descriptor. + [CLSCompliant(false)] + public SBit Lookup(ImageType type, uint gIndex, out Node node) + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + IntPtr sbitRef, nodeRef; + Error err = FT.FTC_SBitCache_Lookup(Reference, type.Reference, gIndex, out sbitRef, out nodeRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + node = new Node(nodeRef); + return new SBit(sbitRef); + } + + /// + /// A variant of that uses a to specify the face ID and its + /// size. + /// + /// + /// The small bitmap descriptor and its bit buffer are owned by the cache and should never be freed by the + /// application. They might as well disappear from memory on the next cache lookup, so don't treat them as + /// persistent data. + /// + /// The descriptor's ‘buffer’ field is set to 0 to indicate a missing glyph bitmap. + /// + /// If ‘node’ is not NULL, it receives the address of the cache node containing the bitmap, after + /// increasing its reference count. This ensures that the node (as well as the image) will always be kept in + /// the cache until you call to ‘release’ it. + /// + /// If ‘node’ is NULL, the cache node is left unchanged, which means that the bitmap could be + /// flushed out of the cache on the next call to one of the caching sub-system APIs. Don't assume that it is + /// persistent! + /// + /// A pointer to the scaler descriptor. + /// The corresponding load flags. + /// The glyph index. + /// + /// Used to return the address of of the corresponding cache node after incrementing its reference count (see + /// note below). + /// + /// A handle to a small bitmap descriptor. + [CLSCompliant(false)] + public SBit LookupScaler(Scaler scaler, LoadFlags loadFlags, uint gIndex, out Node node) + { + if (parentManager.IsDisposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + IntPtr sbitRef, nodeRef; + Error err = FT.FTC_SBitCache_LookupScaler(Reference, scaler.Reference, loadFlags, gIndex, out sbitRef, out nodeRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + node = new Node(nodeRef); + return new SBit(sbitRef); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cache/Scaler.cs b/SharpFont/Source/SharpFontShared/Cache/Scaler.cs new file mode 100644 index 000000000..17c5a795a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cache/Scaler.cs @@ -0,0 +1,146 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Cache.Internal; + +namespace SharpFont.Cache +{ + /// + /// A structure used to describe a given character size in either pixels or points to the cache manager. + /// + /// + /// This type is mainly used to retrieve objects through the cache manager. + /// + /// + public class Scaler + { + #region Fields + + private IntPtr reference; + private ScalerRec rec; + + #endregion + + #region Constructors + + internal Scaler(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the source face ID. + /// + public IntPtr FaceId + { + get + { + return rec.face_id; + } + } + + /// + /// Gets the character width. + /// + [CLSCompliant(false)] + public uint Width + { + get + { + return rec.width; + } + } + + /// + /// Gets the character height. + /// + [CLSCompliant(false)] + public uint Height + { + get + { + return rec.height; + } + } + + /// + /// Gets a value indicating whether the ‘width’ and ‘height’ fields are interpreted as integer pixel character + /// sizes. Otherwise, they are expressed as 1/64th of points. + /// + public bool Pixel + { + get + { + return rec.pixel == 1; + } + } + + /// + /// Gets the horizontal resolution in dpi; only used when ‘pixel’ is value 0. + /// + [CLSCompliant(false)] + public uint ResolutionX + { + get + { + return rec.x_res; + } + } + + /// + /// Gets the vertical resolution in dpi; only used when ‘pixel’ is value 0. + /// + [CLSCompliant(false)] + public uint ResolutionY + { + get + { + return rec.y_res; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Cff/HintingEngine.cs b/SharpFont/Source/SharpFontShared/Cff/HintingEngine.cs new file mode 100644 index 000000000..1370df9d0 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Cff/HintingEngine.cs @@ -0,0 +1,40 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Cff +{ + /// + /// A list of constants used for the hinting-engine property to select the hinting engine for CFF fonts. + /// + public enum HintingEngine + { + /// Use the old FreeType hinting engine. + FreeType = 0, + + /// Use the hinting engine contributed by Adobe. + Adobe = 1 + } +} diff --git a/SharpFont/Source/SharpFontShared/CharMap.cs b/SharpFont/Source/SharpFontShared/CharMap.cs new file mode 100644 index 000000000..6d4c78b1e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/CharMap.cs @@ -0,0 +1,170 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; +using SharpFont.TrueType; + +namespace SharpFont +{ + /// + /// The base charmap structure. + /// + public sealed class CharMap + { + #region Fields + + private IntPtr reference; + private CharMapRec rec; + + private Face parentFace; + + #endregion + + #region Constructors + + internal CharMap(IntPtr reference, Face parent) + { + Reference = reference; + this.parentFace = parent; + } + + #endregion + + #region Properties + + /// + /// Gets a handle to the parent face object. + /// + public Face Face + { + get + { + return parentFace; + } + } + + /// + /// Gets an tag identifying the charmap. Use this with + /// . + /// + [CLSCompliant(false)] + public Encoding Encoding + { + get + { + return rec.encoding; + } + } + + /// + /// Gets an ID number describing the platform for the following encoding ID. This comes directly from the + /// TrueType specification and should be emulated for other formats. + /// + [CLSCompliant(false)] + public PlatformId PlatformId + { + get + { + return rec.platform_id; + } + } + + /// + /// Gets a platform specific encoding number. This also comes from the TrueType specification and should be + /// emulated similarly. + /// + [CLSCompliant(false)] + public ushort EncodingId + { + get + { + //TODO find some way of getting a proper encoding ID enum... + return rec.encoding_id; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Methods + + #region Base Interface + + /// + /// Retrieve index of a given charmap. + /// + /// The index into the array of character maps within the face to which ‘charmap’ belongs. + public int GetCharmapIndex() + { + return FT.FT_Get_Charmap_Index(Reference); + } + + #endregion + + #region TrueType Tables + + /// + /// Return TrueType/sfnt specific cmap language ID. Definitions of language ID values are in + /// ‘freetype/ttnameid.h’. + /// + /// + /// The language ID of ‘charmap’. If ‘charmap’ doesn't belong to a TrueType/sfnt face, just return 0 as the + /// default value. + /// + [CLSCompliant(false)] + public uint GetCMapLanguageId() + { + return FT.FT_Get_CMap_Language_ID(Reference); + } + + /// + /// Return TrueType/sfnt specific cmap format. + /// + /// The format of ‘charmap’. If ‘charmap’ doesn't belong to a TrueType/sfnt face, return -1. + public int GetCMapFormat() + { + return FT.FT_Get_CMap_Format(Reference); + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/ClassicKernValidationFlags.cs b/SharpFont/Source/SharpFontShared/ClassicKernValidationFlags.cs new file mode 100644 index 000000000..27fe3a079 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/ClassicKernValidationFlags.cs @@ -0,0 +1,47 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants used with to indicate the classic kern + /// dialect or dialects. If the selected type doesn't fit, regards the table + /// as invalid. + /// + [Flags] + [CLSCompliant(false)] + public enum ClassicKernValidationFlags : uint + { + /// Handle the ‘kern’ table as a classic Microsoft kern table. + Microsoft = 0x4000 << 0, + + /// Handle the ‘kern’ table as a classic Apple kern table. + Apple = 0x4000 << 1, + + /// Handle the ‘kern’ as either classic Apple or Microsoft kern table. + All = Microsoft | Apple + } +} diff --git a/SharpFont/Source/SharpFontShared/Data.cs b/SharpFont/Source/SharpFontShared/Data.cs new file mode 100644 index 000000000..712b757ca --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Data.cs @@ -0,0 +1,89 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// Read-only binary data represented as a pointer and a length. + /// + public sealed class Data + { + #region Fields + + private IntPtr reference; + + #endregion + + #region Constructors + + internal Data(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the data. + /// + public IntPtr Pointer + { + get + { + return Marshal.ReadIntPtr(reference, 0); + } + } + + /// + /// Gets the length of the data in bytes. + /// + public int Length + { + get + { + return Marshal.ReadInt32(reference, IntPtr.Size); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/EmbeddingTypes.cs b/SharpFont/Source/SharpFontShared/EmbeddingTypes.cs new file mode 100644 index 000000000..35b0844be --- /dev/null +++ b/SharpFont/Source/SharpFontShared/EmbeddingTypes.cs @@ -0,0 +1,88 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit flags used in the ‘fsType’ field of the OS/2 table in a + /// TrueType or OpenType font and the ‘FSType’ entry in a PostScript font. + /// These bit flags are returned by FT_Get_FSType_Flags; they inform client + /// applications of embedding and subsetting restrictions associated with a + /// font. + /// + /// + /// While the fsType flags can indicate that a font may be embedded, a + /// license with the font vendor may be separately required to use the font + /// in this way. + /// + /// + [Flags] + [CLSCompliant(false)] + public enum EmbeddingTypes : ushort + { + /// + /// Fonts with no fsType bit set may be embedded and permanently + /// installed on the remote system by an application. + /// + Installable = 0x0000, + + /// + /// Fonts that have only this bit set must not be modified, embedded + /// or exchanged in any manner without first obtaining permission of + /// the font software copyright owner. + /// + RestrictedLicense = 0x0002, + + /// + /// If this bit is set, the font may be embedded and temporarily loaded + /// on the remote system. Documents containing Preview & Print + /// fonts must be opened ‘read-only’; no edits can be applied to the + /// document. + /// + PreviewAndPrint = 0x0004, + + /// + /// If this bit is set, the font may be embedded but must only be + /// installed temporarily on other systems. In contrast to Preview + /// & Print fonts, documents containing editable fonts may be + /// opened for reading, editing is permitted, and changes may be saved. + /// + Editable = 0x0008, + + /// + /// If this bit is set, the font may not be subsetted prior to + /// embedding. + /// + NoSubsetting = 0x0100, + + /// + /// If this bit is set, only bitmaps contained in the font may be + /// embedded; no outline data may be embedded. If there are no bitmaps + /// available in the font, then the font is unembeddable. + /// + BitmapOnly = 0x0200 + } +} diff --git a/SharpFont/Source/SharpFontShared/Encoding.cs b/SharpFont/Source/SharpFontShared/Encoding.cs new file mode 100644 index 000000000..284555973 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Encoding.cs @@ -0,0 +1,135 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration used to specify character sets supported by charmaps. + /// Used in the FT_Select_Charmap API function. + /// + /// + /// Despite the name, this enumeration lists specific character repertories + /// (i.e., charsets), and not text encoding methods (e.g., UTF-8, UTF-16, + /// etc.). + /// + /// Other encodings might be defined in the future. + /// + [CLSCompliant(false)] + public enum Encoding : uint + { + /// + /// The encoding value 0 is reserved. + /// + None = 0, + + /// + /// Corresponds to the Microsoft Symbol encoding, used to encode + /// mathematical symbols in the 32..255 character code range. + /// + /// + MicrosoftSymbol = ('s' << 24 | 'y' << 16 | 'm' << 8 | 'b'), + + /// + /// Corresponds to the Unicode character set. This value covers all + /// versions of the Unicode repertoire, including ASCII and Latin-1. + /// Most fonts include a Unicode charmap, but not all of them. + /// + /// For example, if you want to access Unicode value U+1F028 (and the + /// font contains it), use value 0x1F028 as the input value for + /// FT_Get_Char_Index. + /// + Unicode = ('u' << 24 | 'n' << 16 | 'i' << 8 | 'c'), + + /// + /// Corresponds to Japanese SJIS encoding. + /// + /// + Sjis = ('s' << 24 | 'j' << 16 | 'i' << 8 | 's'), + + /// + /// Corresponds to an encoding system for Simplified Chinese as used + /// used in mainland China. + /// + GB2312 = ('g' << 24 | 'b' << 16 | ' ' << 8 | ' '), + + /// + /// Corresponds to an encoding system for Traditional Chinese as used + /// in Taiwan and Hong Kong. + /// + Big5 = ('b' << 24 | 'i' << 16 | 'g' << 8 | '5'), + + /// + /// Corresponds to the Korean encoding system known as Wansung. + /// + /// + Wansung = ('w' << 24 | 'a' << 16 | 'n' << 8 | 's'), + + /// + /// The Korean standard character set (KS C 5601-1992), which + /// corresponds to MS Windows code page 1361. This character set + /// includes all possible Hangeul character combinations. + /// + Johab = ('j' << 24 | 'o' << 16 | 'h' << 8 | 'a'), + + /// + /// Corresponds to the Adobe Standard encoding, as found in Type 1, + /// CFF, and OpenType/CFF fonts. It is limited to 256 character codes. + /// + AdobeStandard = ('A' << 24 | 'D' << 16 | 'O' << 8 | 'B'), + + /// + /// Corresponds to the Adobe Expert encoding, as found in Type 1, CFF, + /// and OpenType/CFF fonts. It is limited to 256 character codes. + /// + AdobeExpert = ('A' << 24 | 'D' << 16 | 'B' << 8 | 'E'), + + /// + /// Corresponds to a custom encoding, as found in Type 1, CFF, and + /// OpenType/CFF fonts. It is limited to 256 character codes. + /// + AdobeCustom = ('A' << 24 | 'D' << 16 | 'B' << 8 | 'C'), + + /// + /// Corresponds to a Latin-1 encoding as defined in a Type 1 PostScript + /// font. It is limited to 256 character codes. + /// + AdobeLatin1 = ('l' << 24 | 'a' << 16 | 't' << 8 | '1'), + + /// + /// This value is deprecated and was never used nor reported by + /// FreeType. Don't use or test for it. + /// + [Obsolete("Never used nor reported by FreeType")] + OldLatin2 = ('l' << 24 | 'a' << 16 | 't' << 8 | '2'), + + /// + /// Corresponds to the 8-bit Apple roman encoding. Many TrueType and + /// OpenType fonts contain a charmap for this encoding, since older + /// versions of Mac OS are able to use it. + /// + AppleRoman = ('a' << 24 | 'r' << 16 | 'm' << 8 | 'n'), + } +} diff --git a/SharpFont/Source/SharpFontShared/Error.cs b/SharpFont/Source/SharpFontShared/Error.cs new file mode 100644 index 000000000..9811e7a16 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Error.cs @@ -0,0 +1,298 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// FreeType error codes. + /// + public enum Error + { + /// No error. + Ok = 0x00, + + /// Cannot open resource. + CannotOpenResource = 0x01, + + /// Unknown file format. + UnknownFileFormat = 0x02, + + /// Broken file. + InvalidFileFormat = 0x03, + + /// Invalid FreeType version. + InvalidVersion = 0x04, + + /// Module version is too low. + LowerModuleVersion = 0x05, + + /// Invalid argument. + InvalidArgument = 0x06, + + /// Unimplemented feature. + UnimplementedFeature = 0x07, + + /// Broken table. + InvalidTable = 0x08, + + /// Broken offset within table. + InvalidOffset = 0x09, + + /// Array allocation size too large. + ArrayTooLarge = 0x0A, + + /// Invalid glyph index. + InvalidGlyphIndex = 0x10, + + /// Invalid character code. + InvalidCharacterCode = 0x11, + + /// Unsupported glyph image format. + InvalidGlyphFormat = 0x12, + + /// Cannot render this glyph format. + CannotRenderGlyph = 0x13, + + /// Invalid outline. + InvalidOutline = 0x14, + + /// Invalid composite glyph. + InvalidComposite = 0x15, + + /// Too many hints. + TooManyHints = 0x16, + + /// Invalid pixel size. + InvalidPixelSize = 0x17, + + /// Invalid object handle. + InvalidHandle = 0x20, + + /// Invalid library handle. + InvalidLibraryHandle = 0x21, + + /// Invalid module handle. + InvalidDriverHandle = 0x22, + + /// Invalid face handle. + InvalidFaceHandle = 0x23, + + /// Invalid size handle. + InvalidSizeHandle = 0x24, + + /// Invalid glyph slot handle. + InvalidSlotHandle = 0x25, + + /// Invalid charmap handle. + InvalidCharMapHandle = 0x26, + + /// Invalid cache manager handle. + InvalidCacheHandle = 0x27, + + /// Invalid stream handle. + InvalidStreamHandle = 0x28, + + /// Too many modules. + TooManyDrivers = 0x30, + + /// Too many extensions. + TooManyExtensions = 0x31, + + /// Out of memory. + OutOfMemory = 0x40, + + /// Unlisted object. + UnlistedObject = 0x41, + + /// Cannot open stream. + CannotOpenStream = 0x51, + + /// Invalid stream seek. + InvalidStreamSeek = 0x52, + + /// Invalid stream skip. + InvalidStreamSkip = 0x53, + + /// Invalid stream read. + InvalidStreamRead = 0x54, + + /// Invalid stream operation. + InvalidStreamOperation = 0x55, + + /// Invalid frame operation. + InvalidFrameOperation = 0x56, + + /// Nested frame access. + NestedFrameAccess = 0x57, + + /// Invalid frame read. + InvalidFrameRead = 0x58, + + /// Raster uninitialized. + RasterUninitialized = 0x60, + + /// Raster corrupted. + RasterCorrupted = 0x61, + + /// Raster overflow. + RasterOverflow = 0x62, + + /// Negative height while rastering. + RasterNegativeHeight = 0x63, + + /// Too many registered caches. + TooManyCaches = 0x70, + + /// Invalid opcode. + InvalidOpCode = 0x80, + + /// Too few arguments. + TooFewArguments = 0x81, + + /// Stack overflow. + StackOverflow = 0x82, + + /// Code overflow. + CodeOverflow = 0x83, + + /// Bad argument. + BadArgument = 0x84, + + /// Division by zero. + DivideByZero = 0x85, + + /// Invalid reference. + InvalidReference = 0x86, + + /// Found debug opcode. + DebugOpCode = 0x87, + + /// Found ENDF opcode in execution stream. + EndfInExecStream = 0x88, + + /// Nested DEFS. + NestedDefs = 0x89, + + /// Invalid code range. + InvalidCodeRange = 0x8A, + + /// Execution context too long. + ExecutionTooLong = 0x8B, + + /// Too many function definitions. + TooManyFunctionDefs = 0x8C, + + /// Too many instruction definitions. + TooManyInstructionDefs = 0x8D, + + /// SFNT font table missing. + TableMissing = 0x8E, + + /// Horizontal header (hhea) table missing. + HorizHeaderMissing = 0x8F, + + /// Locations (loca) table missing. + LocationsMissing = 0x90, + + /// Name table missing. + NameTableMissing = 0x91, + + /// Character map (cmap) table missing. + CMapTableMissing = 0x92, + + /// Horizontal metrics (hmtx) table missing. + HmtxTableMissing = 0x93, + + /// PostScript (post) table missing. + PostTableMissing = 0x94, + + /// Invalid horizontal metrics. + InvalidHorizMetrics = 0x95, + + /// Invalid character map (cmap) format. + InvalidCharMapFormat = 0x96, + + /// Invalid ppem value. + InvalidPPem = 0x97, + + /// Invalid vertical metrics. + InvalidVertMetrics = 0x98, + + /// Could not find context. + CouldNotFindContext = 0x99, + + /// Invalid PostScript (post) table format. + InvalidPostTableFormat = 0x9A, + + /// Invalid PostScript (post) table. + InvalidPostTable = 0x9B, + + /// Opcode syntax error. + SyntaxError = 0xA0, + + /// Argument stack underflow. + StackUnderflow = 0xA1, + + /// Ignore this error. + Ignore = 0xA2, + + /// No Unicode glyph name found. + NoUnicodeGlyphName = 0xA3, + + /// `STARTFONT' field missing. + MissingStartfontField = 0xB0, + + /// `FONT' field missing. + MissingFontField = 0xB1, + + /// `SIZE' field missing. + MissingSizeField = 0xB2, + + /// `FONTBOUNDINGBOX' field missing. + MissingFontboudingboxField = 0xB3, + + /// `CHARS' field missing. + MissingCharsField = 0xB4, + + /// `STARTCHAR' field missing. + MissingStartcharField = 0xB5, + + /// `ENCODING' field missing. + MissingEncodingField = 0xB6, + + /// `BBX' field missing. + MissingBbxField = 0xB7, + + /// `BBX' too big. + BbxTooBig = 0xB8, + + /// Font header corrupted or missing fields. + CorruptedFontHeader = 0xB9, + + /// Font glyphs corrupted or missing fields. + CorruptedFontGlyphs = 0xBA + } +} diff --git a/SharpFont/Source/SharpFontShared/FT.Internal.cs b/SharpFont/Source/SharpFontShared/FT.Internal.cs new file mode 100644 index 000000000..b73d35947 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FT.Internal.cs @@ -0,0 +1,770 @@ +#region MIT License +/*Copyright (c) 2012-2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Cache; +using SharpFont.Internal; +using SharpFont.PostScript; +using SharpFont.TrueType; + +namespace SharpFont +{ + /// + /// This file contains all the raw FreeType2 function signatures. + /// + public static partial class FT + { + /// + /// Defines the location of the FreeType DLL. Update SharpFont.dll.config if you change this! + /// +#if SHARPFONT_PLATFORM_IOS + private const string FreetypeDll = "__Internal"; +#else + private const string FreetypeDll = "freetype6"; +#endif + + /// + /// Defines the calling convention for P/Invoking the native freetype methods. + /// + private const CallingConvention CallConvention = CallingConvention.Cdecl; + + #region Core API + + #region FreeType Version + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Library_Version(IntPtr library, out int amajor, out int aminor, out int apatch); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool FT_Face_CheckTrueTypePatents(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool FT_Face_SetUnpatentedHinting(IntPtr face, [MarshalAs(UnmanagedType.U1)] bool value); + + #endregion + + #region Base Interface + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Init_FreeType(out IntPtr alibrary); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Done_FreeType(IntPtr library); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_New_Face(IntPtr library, string filepathname, int face_index, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Memory_Face(IntPtr library, IntPtr file_base, int file_size, int face_index, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Open_Face(IntPtr library, IntPtr args, int face_index, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Attach_File(IntPtr face, string filepathname); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Attach_Stream(IntPtr face, IntPtr parameters); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Reference_Face(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Done_Face(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Select_Size(IntPtr face, int strike_index); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Request_Size(IntPtr face, IntPtr req); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Char_Size(IntPtr face, IntPtr char_width, IntPtr char_height, uint horz_resolution, uint vert_resolution); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Pixel_Sizes(IntPtr face, uint pixel_width, uint pixel_height); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Load_Glyph(IntPtr face, uint glyph_index, int load_flags); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Load_Char(IntPtr face, uint char_code, int load_flags); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Set_Transform(IntPtr face, IntPtr matrix, IntPtr delta); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Render_Glyph(IntPtr slot, RenderMode render_mode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Kerning(IntPtr face, uint left_glyph, uint right_glyph, uint kern_mode, out FTVector26Dot6 akerning); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Track_Kerning(IntPtr face, IntPtr point_size, int degree, out IntPtr akerning); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Glyph_Name(IntPtr face, uint glyph_index, IntPtr buffer, uint buffer_max); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Get_Postscript_Name(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Select_Charmap(IntPtr face, Encoding encoding); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Charmap(IntPtr face, IntPtr charmap); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern int FT_Get_Charmap_Index(IntPtr charmap); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_Char_Index(IntPtr face, uint charcode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_First_Char(IntPtr face, out uint agindex); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_Next_Char(IntPtr face, uint char_code, out uint agindex); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_Name_Index(IntPtr face, IntPtr glyph_name); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_SubGlyph_Info(IntPtr glyph, uint sub_index, out int p_index, out SubGlyphFlags p_flags, out int p_arg1, out int p_arg2, out FTMatrix p_transform); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern EmbeddingTypes FT_Get_FSType_Flags(IntPtr face); + + #endregion + + #region Glyph Variants + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Face_GetCharVariantIndex(IntPtr face, uint charcode, uint variantSelector); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern int FT_Face_GetCharVariantIsDefault(IntPtr face, uint charcode, uint variantSelector); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Face_GetVariantSelectors(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Face_GetVariantsOfChar(IntPtr face, uint charcode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Face_GetCharsOfVariant(IntPtr face, uint variantSelector); + + #endregion + + #region Glyph Management + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Glyph(IntPtr slot, out IntPtr aglyph); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Glyph_Copy(IntPtr source, out IntPtr target); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Glyph_Transform(IntPtr glyph, ref FTMatrix matrix, ref FTVector delta); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Glyph_Get_CBox(IntPtr glyph, GlyphBBoxMode bbox_mode, out BBox acbox); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Glyph_To_Bitmap(ref IntPtr the_glyph, RenderMode render_mode, ref FTVector26Dot6 origin, [MarshalAs(UnmanagedType.U1)] bool destroy); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Done_Glyph(IntPtr glyph); + + #endregion + +#if !SHARPFONT_PLATFORM_IOS + #region Mac Specific Interface + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Face_From_FOND(IntPtr library, IntPtr fond, int face_index, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_GetFile_From_Mac_Name(string fontName, out IntPtr pathSpec, out int face_index); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_GetFile_From_Mac_ATS_Name(string fontName, out IntPtr pathSpec, out int face_index); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_GetFilePath_From_Mac_ATS_Name(string fontName, IntPtr path, int maxPathSize, out int face_index); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Face_From_FSSpec(IntPtr library, IntPtr spec, int face_index, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Face_From_FSRef(IntPtr library, IntPtr @ref, int face_index, out IntPtr aface); + #endregion +#endif + + #region Size Management + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Size(IntPtr face, out IntPtr size); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Done_Size(IntPtr size); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Activate_Size(IntPtr size); + + #endregion + + #endregion + + #region Format-Specific API + + #region Multiple Masters + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Multi_Master(IntPtr face, out IntPtr amaster); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_MM_Var(IntPtr face, out IntPtr amaster); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_MM_Design_Coordinates(IntPtr face, uint num_coords, IntPtr coords); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Var_Design_Coordinates(IntPtr face, uint num_coords, IntPtr coords); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_MM_Blend_Coordinates(IntPtr face, uint num_coords, IntPtr coords); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Var_Blend_Coordinates(IntPtr face, uint num_coords, IntPtr coords); + + #endregion + + #region TrueType Tables + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Get_Sfnt_Table(IntPtr face, SfntTag tag); + + //TODO find FT_TRUETYPE_TAGS_H and create an enum for "tag" + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Load_Sfnt_Table(IntPtr face, uint tag, int offset, IntPtr buffer, ref uint length); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static unsafe extern Error FT_Sfnt_Table_Info(IntPtr face, uint table_index, SfntTag* tag, out uint length); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_CMap_Language_ID(IntPtr charmap); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern int FT_Get_CMap_Format(IntPtr charmap); + + #endregion + + #region Type 1 Tables + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool FT_Has_PS_Glyph_Names(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_PS_Font_Info(IntPtr face, out PostScript.Internal.FontInfoRec afont_info); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_PS_Font_Private(IntPtr face, out PostScript.Internal.PrivateRec afont_private); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern int FT_Get_PS_Font_Value(IntPtr face, DictionaryKeys key, uint idx, ref IntPtr value, int value_len); + + #endregion + + #region SFNT Names + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FT_Get_Sfnt_Name_Count(IntPtr face); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Sfnt_Name(IntPtr face, uint idx, out TrueType.Internal.SfntNameRec aname); + + #endregion + + #region BDF and PCF Files + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Get_BDF_Charset_ID(IntPtr face, out string acharset_encoding, out string acharset_registry); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Get_BDF_Property(IntPtr face, string prop_name, out IntPtr aproperty); + + #endregion + + #region CID Fonts + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Get_CID_Registry_Ordering_Supplement(IntPtr face, out string registry, out string ordering, out int aproperty); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_CID_Is_Internally_CID_Keyed(IntPtr face, out byte is_cid); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_CID_From_Glyph_Index(IntPtr face, uint glyph_index, out uint cid); + + #endregion + + #region PFR Fonts + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_PFR_Metrics(IntPtr face, out uint aoutline_resolution, out uint ametrics_resolution, out IntPtr ametrics_x_scale, out IntPtr ametrics_y_scale); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_PFR_Kerning(IntPtr face, uint left, uint right, out FTVector avector); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_PFR_Advance(IntPtr face, uint gindex, out int aadvance); + + #endregion + + #region Window FNT Files + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_WinFNT_Header(IntPtr face, out IntPtr aheader); + + #endregion + + #region Font Formats + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Get_X11_Font_Format(IntPtr face); + + #endregion + + #region Gasp Table + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Gasp FT_Get_Gasp(IntPtr face, uint ppem); + + #endregion + + #endregion + + #region Support API + + #region Computations + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_MulDiv(IntPtr a, IntPtr b, IntPtr c); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_MulFix(IntPtr a, IntPtr b); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_DivFix(IntPtr a, IntPtr b); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_RoundFix(IntPtr a); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_CeilFix(IntPtr a); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_FloorFix(IntPtr a); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Vector_Transform(ref FTVector vec, ref FTMatrix matrix); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Matrix_Multiply(ref FTMatrix a, ref FTMatrix b); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Matrix_Invert(ref FTMatrix matrix); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Sin(IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Cos(IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Tan(IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Atan2(IntPtr x, IntPtr y); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Angle_Diff(IntPtr angle1, IntPtr angle2); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Vector_Unit(out FTVector vec, IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Vector_Rotate(ref FTVector vec, IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Vector_Length(ref FTVector vec); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Vector_Polarize(ref FTVector vec, out IntPtr length, out IntPtr angle); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Vector_From_Polar(out FTVector vec, IntPtr length, IntPtr angle); + + #endregion + + #region List Processing + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_List_Find(IntPtr list, IntPtr data); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_List_Add(IntPtr list, IntPtr node); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_List_Insert(IntPtr list, IntPtr node); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_List_Remove(IntPtr list, IntPtr node); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_List_Up(IntPtr list, IntPtr node); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_List_Iterate(IntPtr list, ListIterator iterator, IntPtr user); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_List_Finalize(IntPtr list, ListDestructor destroy, IntPtr memory, IntPtr user); + + #endregion + + #region Outline Processing + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_New(IntPtr library, uint numPoints, int numContours, out IntPtr anoutline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_New_Internal(IntPtr memory, uint numPoints, int numContours, out IntPtr anoutline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Done(IntPtr library, IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Done_Internal(IntPtr memory, IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Copy(IntPtr source, ref IntPtr target); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Outline_Translate(IntPtr outline, int xOffset, int yOffset); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Outline_Transform(IntPtr outline, ref FTMatrix matrix); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Embolden(IntPtr outline, IntPtr strength); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_EmboldenXY(IntPtr outline, int xstrength, int ystrength); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Outline_Reverse(IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Check(IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Get_BBox(IntPtr outline, out BBox abbox); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Decompose(IntPtr outline, ref OutlineFuncsRec func_interface, IntPtr user); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Outline_Get_CBox(IntPtr outline, out BBox acbox); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Get_Bitmap(IntPtr library, IntPtr outline, IntPtr abitmap); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Outline_Render(IntPtr library, IntPtr outline, IntPtr @params); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Orientation FT_Outline_Get_Orientation(IntPtr outline); + + #endregion + + #region Quick retrieval of advance values + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Advance(IntPtr face, uint gIndex, LoadFlags load_flags, out IntPtr padvance); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Get_Advances(IntPtr face, uint start, uint count, LoadFlags load_flags, out IntPtr padvance); + + #endregion + + #region Bitmap Handling + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Bitmap_New(IntPtr abitmap); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Bitmap_Copy(IntPtr library, IntPtr source, IntPtr target); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Bitmap_Embolden(IntPtr library, IntPtr bitmap, IntPtr xStrength, IntPtr yStrength); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Bitmap_Convert(IntPtr library, IntPtr source, IntPtr target, int alignment); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_GlyphSlot_Own_Bitmap(IntPtr slot); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Bitmap_Done(IntPtr library, IntPtr bitmap); + + #endregion + + #region Glyph Stroker + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern StrokerBorder FT_Outline_GetInsideBorder(IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern StrokerBorder FT_Outline_GetOutsideBorder(IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_New(IntPtr library, out IntPtr astroker); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Stroker_Set(IntPtr stroker, int radius, StrokerLineCap line_cap, StrokerLineJoin line_join, IntPtr miter_limit); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Stroker_Rewind(IntPtr stroker); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_ParseOutline(IntPtr stroker, IntPtr outline, [MarshalAs(UnmanagedType.U1)] bool opened); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_BeginSubPath(IntPtr stroker, ref FTVector to, [MarshalAs(UnmanagedType.U1)] bool open); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_EndSubPath(IntPtr stroker); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_LineTo(IntPtr stroker, ref FTVector to); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_ConicTo(IntPtr stroker, ref FTVector control, ref FTVector to); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_CubicTo(IntPtr stroker, ref FTVector control1, ref FTVector control2, ref FTVector to); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_GetBorderCounts(IntPtr stroker, StrokerBorder border, out uint anum_points, out uint anum_contours); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Stroker_ExportBorder(IntPtr stroker, StrokerBorder border, IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stroker_GetCounts(IntPtr stroker, out uint anum_points, out uint anum_contours); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Stroker_Export(IntPtr stroker, IntPtr outline); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Stroker_Done(IntPtr stroker); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Glyph_Stroke(ref IntPtr pglyph, IntPtr stoker, [MarshalAs(UnmanagedType.U1)] bool destroy); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Glyph_StrokeBorder(ref IntPtr pglyph, IntPtr stoker, [MarshalAs(UnmanagedType.U1)] bool inside, [MarshalAs(UnmanagedType.U1)] bool destroy); + + #endregion + + #region Module Management + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Add_Module(IntPtr library, IntPtr clazz); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern IntPtr FT_Get_Module(IntPtr library, string module_name); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Remove_Module(IntPtr library, IntPtr module); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Property_Set(IntPtr library, string module_name, string property_name, IntPtr value); + + [DllImport(FreetypeDll, CallingConvention = CallConvention, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern Error FT_Property_Get(IntPtr library, string module_name, string property_name, IntPtr value); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Reference_Library(IntPtr library); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_New_Library(IntPtr memory, out IntPtr alibrary); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Done_Library(IntPtr library); + + //TODO figure out the method signature for debug_hook. (FT_DebugHook_Func) + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Set_Debug_Hook(IntPtr library, uint hook_index, IntPtr debug_hook); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_Add_Default_Modules(IntPtr library); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern IntPtr FT_Get_Renderer(IntPtr library, GlyphFormat format); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Set_Renderer(IntPtr library, IntPtr renderer, uint num_params, IntPtr parameters); + + #endregion + + #region GZIP Streams + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stream_OpenGzip(IntPtr stream, IntPtr source); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Gzip_Uncompress(IntPtr memory, IntPtr output, ref IntPtr output_len, IntPtr input, IntPtr input_len); + + #endregion + + #region LZW Streams + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stream_OpenLZW(IntPtr stream, IntPtr source); + + #endregion + + #region BZIP2 Streams + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Stream_OpenBzip2(IntPtr stream, IntPtr source); + + #endregion + + #region LCD Filtering + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Library_SetLcdFilter(IntPtr library, LcdFilter filter); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_Library_SetLcdFilterWeights(IntPtr library, byte[] weights); + + #endregion + + #endregion + + #region Caching Sub-system + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_Manager_New(IntPtr library, uint max_faces, uint max_sizes, ulong maxBytes, FaceRequester requester, IntPtr req_data, out IntPtr amanager); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FTC_Manager_Reset(IntPtr manager); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FTC_Manager_Done(IntPtr manager); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_Manager_LookupFace(IntPtr manager, IntPtr face_id, out IntPtr aface); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_Manager_LookupSize(IntPtr manager, IntPtr scaler, out IntPtr asize); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FTC_Node_Unref(IntPtr node, IntPtr manager); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FTC_Manager_RemoveFaceID(IntPtr manager, IntPtr face_id); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_CMapCache_New(IntPtr manager, out IntPtr acache); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern uint FTC_CMapCache_Lookup(IntPtr cache, IntPtr face_id, int cmap_index, uint char_code); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_ImageCache_New(IntPtr manager, out IntPtr acache); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_ImageCache_Lookup(IntPtr cache, IntPtr type, uint gindex, out IntPtr aglyph, out IntPtr anode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_ImageCache_LookupScaler(IntPtr cache, IntPtr scaler, LoadFlags load_flags, uint gindex, out IntPtr aglyph, out IntPtr anode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_SBitCache_New(IntPtr manager, out IntPtr acache); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_SBitCache_Lookup(IntPtr cache, IntPtr type, uint gindex, out IntPtr sbit, out IntPtr anode); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FTC_SBitCache_LookupScaler(IntPtr cache, IntPtr scaler, LoadFlags load_flags, uint gindex, out IntPtr sbit, out IntPtr anode); + + #endregion + + #region Miscellaneous + + #region OpenType Validation + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_OpenType_Validate(IntPtr face, OpenTypeValidationFlags validation_flags, out IntPtr base_table, out IntPtr gdef_table, out IntPtr gpos_table, out IntPtr gsub_table, out IntPtr jsft_table); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern void FT_OpenType_Free(IntPtr face, IntPtr table); + + #endregion + + #region The TrueType Engine + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern EngineType FT_Get_TrueType_Engine_Type(IntPtr library); + + #endregion + + #region TrueTypeGX/AAT Validation + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_TrueTypeGX_Validate(IntPtr face, TrueTypeValidationFlags validation_flags, byte[][] tables, uint tableLength); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_TrueTypeGX_Free(IntPtr face, IntPtr table); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_ClassicKern_Validate(IntPtr face, ClassicKernValidationFlags validation_flags, out IntPtr ckern_table); + + [DllImport(FreetypeDll, CallingConvention = CallConvention)] + internal static extern Error FT_ClassicKern_Free(IntPtr face, IntPtr table); + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FT.Public.cs b/SharpFont/Source/SharpFontShared/FT.Public.cs new file mode 100644 index 000000000..676d60162 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FT.Public.cs @@ -0,0 +1,262 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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 System.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// Miscellaneous FreeType2 functions that don't fit anywhere else. + /// + public static partial class FT + { + #region Computations + + /// + /// A very simple function used to perform the computation ‘(a*b)/c’ with maximal accuracy (it uses a 64-bit + /// intermediate integer whenever necessary). + /// + /// This function isn't necessarily as fast as some processor specific operations, but is at least completely + /// portable. + /// + /// The first multiplier. + /// The second multiplier. + /// The divisor. + /// + /// The result of ‘(a*b)/c’. This function never traps when trying to divide by zero; it simply returns + /// ‘MaxInt’ or ‘MinInt’ depending on the signs of ‘a’ and ‘b’. + /// + [Obsolete("Use Fixed16Dot16.MultiplyDivide() instead.")] + public static Fixed16Dot16 MulDiv(Fixed16Dot16 a, Fixed16Dot16 b, Fixed16Dot16 c) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_MulDiv((IntPtr)a.Value, (IntPtr)b.Value, (IntPtr)c.Value)); + } + + /// + /// A very simple function used to perform the computation ‘(a*b)/0x10000’ with maximal accuracy. Most of the + /// time this is used to multiply a given value by a 16.16 fixed float factor. + /// + /// + /// This function has been optimized for the case where the absolute value of ‘a’ is less than 2048, and ‘b’ is + /// a 16.16 scaling factor. As this happens mainly when scaling from notional units to fractional pixels in + /// FreeType, it resulted in noticeable speed improvements between versions 2.x and 1.x. + /// + /// As a conclusion, always try to place a 16.16 factor as the second argument of this function; this can make + /// a great difference. + /// + /// The first multiplier. + /// The second multiplier. Use a 16.16 factor here whenever possible (see note below). + /// The result of ‘(a*b)/0x10000’. + [Obsolete("Use Fixed16Dot16.MultiplyFix() instead.")] + public static Fixed16Dot16 MulFix(int a, Fixed16Dot16 b) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_MulFix((IntPtr)a, (IntPtr)b.Value)); + } + + /// + /// A very simple function used to perform the computation ‘(a*0x10000)/b’ with maximal accuracy. Most of the + /// time, this is used to divide a given value by a 16.16 fixed float factor. + /// + /// + /// The optimization for is simple: If (a << 16) fits in 32 bits, then the division + /// is computed directly. Otherwise, we use a specialized version of . + /// + /// The first multiplier. + /// The second multiplier. Use a 16.16 factor here whenever possible (see note below). + /// The result of ‘(a*0x10000)/b’. + [Obsolete("Use Fixed16Dot16.DivideFix() instead.")] + public static Fixed16Dot16 DivFix(int a, Fixed16Dot16 b) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_DivFix((IntPtr)a, (IntPtr)b.Value)); + } + + /// + /// A very simple function used to round a 16.16 fixed number. + /// + /// The number to be rounded. + /// The result of ‘(a + 0x8000) & -0x10000’. + [Obsolete("Use Fixed16Dot16.RoundFix() instead.")] + public static Fixed16Dot16 RoundFix(Fixed16Dot16 a) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_RoundFix((IntPtr)a.Value)); + } + + /// + /// A very simple function used to compute the ceiling function of a 16.16 fixed number. + /// + /// The number for which the ceiling function is to be computed. + /// The result of ‘(a + 0x10000 - 1) & -0x10000’. + [Obsolete("Use Fixed16Dot16.CeilingFix() instead.")] + public static Fixed16Dot16 CeilFix(Fixed16Dot16 a) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_CeilFix((IntPtr)a.Value)); + } + + /// + /// A very simple function used to compute the floor function of a 16.16 fixed number. + /// + /// The number for which the floor function is to be computed. + /// The result of ‘a & -0x10000’. + [Obsolete("Use Fixed16Dot16.FloorFix() instead.")] + public static Fixed16Dot16 FloorFix(Fixed16Dot16 a) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_FloorFix((IntPtr)a.Value)); + } + + /// + /// Return the sinus of a given angle in fixed point format. + /// + /// + /// If you need both the sinus and cosinus for a given angle, use the function . + /// + /// The input angle. + /// The sinus value. + [Obsolete("Use Fixed16Dot16.Sin() instead.")] + public static Fixed16Dot16 Sin(Fixed16Dot16 angle) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Sin((IntPtr)angle.Value)); + } + + /// + /// Return the cosinus of a given angle in fixed point format. + /// + /// + /// If you need both the sinus and cosinus for a given angle, use the function . + /// + /// The input angle. + /// The cosinus value. + [Obsolete("Use Fixed16Dot16.Cos() instead.")] + public static Fixed16Dot16 Cos(Fixed16Dot16 angle) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Cos((IntPtr)angle.Value)); + } + + /// + /// Return the tangent of a given angle in fixed point format. + /// + /// The input angle. + /// The tangent value. + [Obsolete("Use Fixed16Dot16.Tan() instead.")] + public static Fixed16Dot16 Tan(Fixed16Dot16 angle) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Tan((IntPtr)angle.Value)); + } + + /// + /// Return the arc-tangent corresponding to a given vector (x,y) in the 2d plane. + /// + /// The horizontal vector coordinate. + /// The vertical vector coordinate. + /// The arc-tangent value (i.e. angle). + [Obsolete("Use Fixed16Dot16.Atan2() instead.")] + public static Fixed16Dot16 Atan2(Fixed16Dot16 x, Fixed16Dot16 y) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Atan2((IntPtr)x.Value, (IntPtr)y.Value)); + } + + /// + /// Return the difference between two angles. The result is always constrained to the [-PI..PI] interval. + /// + /// First angle. + /// Second angle. + /// Constrained value of ‘value2-value1’. + [Obsolete("Use Fixed16Dot16.AngleDiff() instead.")] + public static Fixed16Dot16 AngleDiff(Fixed16Dot16 angle1, Fixed16Dot16 angle2) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Angle_Diff((IntPtr)angle1.Value, (IntPtr)angle2.Value)); + } + + #endregion + +#if !SHARPFONT_PLATFORM_IOS + #region Mac Specific Interface + + /// + /// Return an FSSpec for the disk file containing the named font. + /// + /// Mac OS name of the font (e.g., Times New Roman Bold). + /// Index of the face. For passing to . + /// FSSpec to the file. For passing to . + public static IntPtr GetFileFromMacName(string fontName, out int faceIndex) + { + IntPtr fsspec; + + Error err = FT_GetFile_From_Mac_Name(fontName, out fsspec, out faceIndex); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return fsspec; + } + + /// + /// Return an FSSpec for the disk file containing the named font. + /// + /// Mac OS name of the font in ATS framework. + /// Index of the face. For passing to . + /// FSSpec to the file. For passing to . + public static IntPtr GetFileFromMacAtsName(string fontName, out int faceIndex) + { + IntPtr fsspec; + + Error err = FT_GetFile_From_Mac_ATS_Name(fontName, out fsspec, out faceIndex); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return fsspec; + } + + /// + /// Return a pathname of the disk file and face index for given font name which is handled by ATS framework. + /// + /// Mac OS name of the font in ATS framework. + /// + /// Buffer to store pathname of the file. For passing to . The client must + /// allocate this buffer before calling this function. + /// + /// Index of the face. For passing to . + public static unsafe int GetFilePathFromMacAtsName(string fontName, byte[] path) + { + int faceIndex; + + fixed (void* ptr = path) + { + Error err = FT_GetFilePath_From_Mac_ATS_Name(fontName, (IntPtr)ptr, path.Length, out faceIndex); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + return faceIndex; + } + + #endregion +#endif + } +} diff --git a/SharpFont/Source/SharpFontShared/FTBitmap.cs b/SharpFont/Source/SharpFontShared/FTBitmap.cs new file mode 100644 index 000000000..5b2ad7271 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTBitmap.cs @@ -0,0 +1,546 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015-2016 Robert Rouhani + +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; +#if !SHARPFONT_PORTABLE +using System.Drawing; +using System.Drawing.Imaging; +#endif +using System.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used to describe a bitmap or pixmap to the raster. Note that we now manage pixmaps of various + /// depths through the field. + /// + /// + /// For now, the only pixel modes supported by FreeType are mono and grays. However, drivers might be added in the + /// future to support more ‘colorful’ options. + /// + public sealed class FTBitmap : IDisposable + { + #region Fields + + private IntPtr reference; + private BitmapRec rec; + + private Library library; + + private bool disposed; + + //If the bitmap was generated with FT_Bitmap_New. + private bool user; + + //HACK these variables exist to reduce the cost of reflection at runtime. + //Meant to be a temporary fix to https://github.com/Robmaister/SharpFont/issues/62 + //until libgdiplus gets patched. +#if !SHARPFONT_PORTABLE + private bool hasCheckedForMono; + private bool isRunningOnMono; + private System.Reflection.FieldInfo monoPaletteFlagsField; +#endif + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The parent . + public FTBitmap(Library library) + { + IntPtr bitmapRef = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BitmapRec))); + FT.FT_Bitmap_New(bitmapRef); + Reference = bitmapRef; + + this.library = library; + this.user = true; + } + + internal FTBitmap(IntPtr reference, Library library) + { + Reference = reference; + this.library = library; + } + + internal FTBitmap(IntPtr reference, BitmapRec bmpInt, Library library) + { + this.reference = reference; + this.rec = bmpInt; + this.library = library; + } + + /// + /// Finalizes an instance of the class. + /// + ~FTBitmap() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets the number of bitmap rows. + /// + public int Rows + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.rows; + } + } + + /// + /// Gets the number of pixels in bitmap row. + /// + public int Width + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.width; + } + } + + /// + /// Gets the pitch's absolute value is the number of bytes taken by one bitmap row, including padding. However, + /// the pitch is positive when the bitmap has a ‘down’ flow, and negative when it has an ‘up’ flow. In all + /// cases, the pitch is an offset to add to a bitmap pointer in order to go down one row. + /// + /// Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType functions normally align + /// to the smallest possible integer value. + /// + /// For the B/W rasterizer, ‘pitch’ is always an even number. + /// + /// To change the pitch of a bitmap (say, to make it a multiple of 4), use . + /// Alternatively, you might use callback functions to directly render to the application's surface; see the + /// file ‘example2.cpp’ in the tutorial for a demonstration. + /// + public int Pitch + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.pitch; + } + } + + /// + /// Gets a typeless pointer to the bitmap buffer. This value should be aligned on 32-bit boundaries in most + /// cases. + /// + public IntPtr Buffer + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.buffer; + } + } + + /// + /// Gets the number of gray levels used in the bitmap. This field is only used with + /// . + /// + public short GrayLevels + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.num_grays; + } + } + + /// + /// Gets the pixel mode, i.e., how pixel bits are stored. + /// + public PixelMode PixelMode + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.pixel_mode; + } + } + + /// + /// Gets how the palette is stored. This field is intended for paletted pixel modes. + /// + [Obsolete("Not used currently.")] + public byte PaletteMode + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.palette_mode; + } + } + + /// + /// Gets a typeless pointer to the bitmap palette; this field is intended for paletted pixel modes. + /// + [Obsolete("Not used currently.")] + public IntPtr Palette + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return rec.palette; + } + } + + /// + /// Gets the 's buffer as a byte array. + /// + public byte[] BufferData + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + //TODO deal with negative pitch + byte[] data = new byte[rec.rows * rec.pitch]; + Marshal.Copy(rec.buffer, data, 0, data.Length); + return data; + } + } + + internal IntPtr Reference + { + get + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + return reference; + } + + set + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Methods + + /// + /// Copy a bitmap into another one. + /// + /// A handle to a library object. + /// A handle to the target bitmap. + public FTBitmap Copy(Library library) + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + if (library == null) + throw new ArgumentNullException("library"); + + FTBitmap newBitmap = new FTBitmap(library); + IntPtr bmpRef = newBitmap.reference; + Error err = FT.FT_Bitmap_Copy(library.Reference, Reference, bmpRef); + newBitmap.Reference = bmpRef; + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return newBitmap; + } + + /// + /// Embolden a bitmap. The new bitmap will be about ‘xStrength’ pixels wider and ‘yStrength’ pixels higher. The + /// left and bottom borders are kept unchanged. + /// + /// + /// The current implementation restricts ‘xStrength’ to be less than or equal to 8 if bitmap is of pixel_mode + /// . + /// + /// If you want to embolden the bitmap owned by a , you should call + /// on the slot first. + /// + /// A handle to a library object. + /// + /// How strong the glyph is emboldened horizontally. Expressed in 26.6 pixel format. + /// + /// + /// How strong the glyph is emboldened vertically. Expressed in 26.6 pixel format. + /// + public void Embolden(Library library, Fixed26Dot6 xStrength, Fixed26Dot6 yStrength) + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + if (library == null) + throw new ArgumentNullException("library"); + + Error err = FT.FT_Bitmap_Embolden(library.Reference, Reference, (IntPtr)xStrength.Value, (IntPtr)yStrength.Value); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a bitmap object with depth 8bpp, making the + /// number of used bytes per line (a.k.a. the ‘pitch’) a multiple of ‘alignment’. + /// + /// + /// It is possible to call multiple times without calling + /// (the memory is simply reallocated). + /// + /// Use to finally remove the bitmap object. + /// + /// The ‘library’ argument is taken to have access to FreeType's memory handling functions. + /// + /// A handle to a library object. + /// + /// The pitch of the bitmap is a multiple of this parameter. Common values are 1, 2, or 4. + /// + /// The target bitmap. + public FTBitmap Convert(Library library, int alignment) + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + if (library == null) + throw new ArgumentNullException("library"); + + FTBitmap newBitmap = new FTBitmap(library); + IntPtr bmpRef = newBitmap.reference; + Error err = FT.FT_Bitmap_Convert(library.Reference, Reference, bmpRef, alignment); + newBitmap.Reference = bmpRef; + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return newBitmap; + } + +#if !SHARPFONT_PORTABLE + /// + /// Copies the contents of the to a GDI+ . + /// + /// A GDI+ containing this bitmap's data. + public Bitmap ToGdipBitmap() + { + return ToGdipBitmap(Color.Black); + } + + /// + /// Copies the contents of the to a GDI+ . + /// + /// The color of the text. + /// A GDI+ containing this bitmap's data with a transparent background. + public Bitmap ToGdipBitmap(Color color) + { + if (disposed) + throw new ObjectDisposedException("FTBitmap", "Cannot access a disposed object."); + + if (rec.width == 0 || rec.rows == 0) + throw new InvalidOperationException("Invalid image size - one or both dimensions are 0."); + + //TODO deal with negative pitch + switch (rec.pixel_mode) + { + case PixelMode.Mono: + { + Bitmap bmp = new Bitmap(rec.width, rec.rows, PixelFormat.Format1bppIndexed); + var locked = bmp.LockBits(new Rectangle(0, 0, rec.width, rec.rows), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed); + + for (int i = 0; i < rec.rows; i++) + PInvokeHelper.Copy(Buffer, i * rec.pitch, locked.Scan0, i * locked.Stride, locked.Stride); + + bmp.UnlockBits(locked); + + ColorPalette palette = bmp.Palette; + palette.Entries[0] = Color.FromArgb(0, color); + palette.Entries[1] = Color.FromArgb(255, color); + + bmp.Palette = palette; + return bmp; + } + + case PixelMode.Gray4: + { + Bitmap bmp = new Bitmap(rec.width, rec.rows, PixelFormat.Format4bppIndexed); + var locked = bmp.LockBits(new Rectangle(0, 0, rec.width, rec.rows), ImageLockMode.ReadWrite, PixelFormat.Format4bppIndexed); + + for (int i = 0; i < rec.rows; i++) + PInvokeHelper.Copy(Buffer, i * rec.pitch, locked.Scan0, i * locked.Stride, locked.Stride); + + bmp.UnlockBits(locked); + + ColorPalette palette = bmp.Palette; + for (int i = 0; i < palette.Entries.Length; i++) + { + float a = (i * 17) / 255f; + palette.Entries[i] = Color.FromArgb(i * 17, (int)(color.R * a), (int)(color.G * a), (int)(color.B * a)); + } + + bmp.Palette = palette; + return bmp; + } + + case PixelMode.Gray: + { + Bitmap bmp = new Bitmap(rec.width, rec.rows, PixelFormat.Format8bppIndexed); + var locked = bmp.LockBits(new Rectangle(0, 0, rec.width, rec.rows), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); + + for (int i = 0; i < rec.rows; i++) + PInvokeHelper.Copy(Buffer, i * rec.pitch, locked.Scan0, i * locked.Stride, locked.Stride); + + bmp.UnlockBits(locked); + + ColorPalette palette = bmp.Palette; + for (int i = 0; i < palette.Entries.Length; i++) + { + float a = i / 255f; + palette.Entries[i] = Color.FromArgb(i, (int)(color.R * a), (int)(color.G * a), (int)(color.B * a)); + } + + //HACK There's a bug in Mono's libgdiplus requiring the "PaletteHasAlpha" flag to be set for transparency to work properly + //See https://github.com/Robmaister/SharpFont/issues/62 + if (!hasCheckedForMono) + { + hasCheckedForMono = true; + isRunningOnMono = Type.GetType("Mono.Runtime") != null; + if (isRunningOnMono) + { + monoPaletteFlagsField = typeof(ColorPalette).GetField("flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + } + } + + if (isRunningOnMono) + monoPaletteFlagsField.SetValue(palette, palette.Flags | 1); + + bmp.Palette = palette; + return bmp; + } + + case PixelMode.Lcd: + { + //TODO apply color + int bmpWidth = rec.width / 3; + Bitmap bmp = new Bitmap(bmpWidth, rec.rows, PixelFormat.Format24bppRgb); + var locked = bmp.LockBits(new Rectangle(0, 0, bmpWidth, rec.rows), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + + for (int i = 0; i < rec.rows; i++) + PInvokeHelper.Copy(Buffer, i * rec.pitch, locked.Scan0, i * locked.Stride, locked.Stride); + + bmp.UnlockBits(locked); + + return bmp; + } + /*case PixelMode.VerticalLcd: + { + int bmpHeight = rec.rows / 3; + Bitmap bmp = new Bitmap(rec.width, bmpHeight, PixelFormat.Format24bppRgb); + var locked = bmp.LockBits(new Rectangle(0, 0, rec.width, bmpHeight), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); + for (int i = 0; i < bmpHeight; i++) + PInvokeHelper.Copy(Buffer, i * rec.pitch, locked.Scan0, i * locked.Stride, rec.width); + bmp.UnlockBits(locked); + + return bmp; + }*/ + + default: + throw new InvalidOperationException("System.Drawing.Bitmap does not support this pixel mode."); + } + } +#endif + + #region IDisposable + + /// + /// Disposes an instance of the class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + if (user) + { + FT.FT_Bitmap_Done(library.Reference, reference); + Marshal.FreeHGlobal(reference); + } + + reference = IntPtr.Zero; + library = null; + } + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTList.cs b/SharpFont/Source/SharpFontShared/FTList.cs new file mode 100644 index 000000000..d0597664f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTList.cs @@ -0,0 +1,195 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// An iterator function which is called during a list parse by . + /// + /// The current iteration list node. + /// + /// A typeless pointer passed to . Can be used to point to the iteration's state. + /// + /// Error code. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Error ListIterator(NativeReference node, IntPtr user); + + /// + /// An iterator function which is called during a list finalization by + /// to destroy all elements in a given list. + /// + /// The current system object. + /// The current object to destroy. + /// + /// A typeless pointer passed to . It can be used to point to the iteration's state. + /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ListDestructor(NativeReference memory, IntPtr data, IntPtr user); + + /// + /// A structure used to hold a simple doubly-linked list. These are used in many parts of FreeType. + /// + public sealed class FTList + { + #region Fields + + private IntPtr reference; + private ListRec rec; + + #endregion + + #region Constructors + + internal FTList(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the head (first element) of doubly-linked list. + /// + public ListNode Head + { + get + { + return new ListNode(rec.head); + } + } + + /// + /// Gets the tail (last element) of doubly-linked list. + /// + public ListNode Tail + { + get + { + return new ListNode(rec.tail); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Methods + + /// + /// Find the list node for a given listed object. + /// + /// The address of the listed object. + /// List node. NULL if it wasn't found. + public ListNode Find(IntPtr data) + { + return new ListNode(FT.FT_List_Find(Reference, data)); + } + + /// + /// Append an element to the end of a list. + /// + /// The node to append. + public void Add(ListNode node) + { + FT.FT_List_Add(Reference, node.Reference); + } + + /// + /// Insert an element at the head of a list. + /// + /// The node to insert. + public void Insert(ListNode node) + { + FT.FT_List_Insert(Reference, node.Reference); + } + + /// + /// Remove a node from a list. This function doesn't check whether the node is in the list! + /// + /// The node to remove. + public void Remove(ListNode node) + { + FT.FT_List_Remove(Reference, node.Reference); + } + + /// + /// Move a node to the head/top of a list. Used to maintain LRU lists. + /// + /// The node to move. + public void Up(ListNode node) + { + FT.FT_List_Up(Reference, node.Reference); + } + + /// + /// Parse a list and calls a given iterator function on each element. Note that parsing is stopped as soon as + /// one of the iterator calls returns a non-zero value. + /// + /// An iterator function, called on each node of the list. + /// A user-supplied field which is passed as the second argument to the iterator. + public void Iterate(ListIterator iterator, IntPtr user) + { + Error err = FT.FT_List_Iterate(Reference, iterator, user); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Destroy all elements in the list as well as the list itself. + /// + /// + /// This function expects that all nodes added by or have been + /// dynamically allocated. + /// + /// A list destructor that will be applied to each element of the list. + /// The current memory object which handles deallocation. + /// A user-supplied field which is passed as the last argument to the destructor. + public void Finalize(ListDestructor destroy, Memory memory, IntPtr user) + { + FT.FT_List_Finalize(Reference, destroy, memory.Reference, user); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTMatrix.cs b/SharpFont/Source/SharpFontShared/FTMatrix.cs new file mode 100644 index 000000000..f724f95c6 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTMatrix.cs @@ -0,0 +1,250 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A simple structure used to store a 2x2 matrix. Coefficients are in 16.16 fixed float format. The computation + /// performed is: + /// + /// x' = x*xx + y*xy + /// y' = x*yx + y*yy + /// + /// + [StructLayout(LayoutKind.Sequential)] + public struct FTMatrix : IEquatable + { + #region Fields + + private IntPtr xx, xy; + private IntPtr yx, yy; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// Matrix coefficient XX. + /// Matrix coefficient XY. + /// Matrix coefficient YX. + /// Matrix coefficient YY. + public FTMatrix(int xx, int xy, int yx, int yy) + : this() + { + this.xx = (IntPtr)xx; + this.xy = (IntPtr)xy; + this.yx = (IntPtr)yx; + this.yy = (IntPtr)yy; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Matrix coefficients XX, XY. + /// Matrix coefficients YX, YY. + public FTMatrix(FTVector row0, FTVector row1) + : this(row0.X.Value, row0.Y.Value, row1.X.Value, row1.Y.Value) + { + } + + #endregion + + #region Properties + + /// + /// Gets or sets the matrix coefficient. + /// + public Fixed16Dot16 XX + { + get + { + return Fixed16Dot16.FromRawValue((int)xx); + } + + set + { + xx = (IntPtr)value.Value; + } + } + + /// + /// Gets or sets the matrix coefficient. + /// + public Fixed16Dot16 XY + { + get + { + return Fixed16Dot16.FromRawValue((int)xy); + } + + set + { + xy = (IntPtr)value.Value; + } + } + + /// + /// Gets or sets the matrix coefficient. + /// + public Fixed16Dot16 YX + { + get + { + return Fixed16Dot16.FromRawValue((int)yx); + } + + set + { + yx = (IntPtr)value.Value; + } + } + + /// + /// Gets or sets the matrix coefficient. + /// + public Fixed16Dot16 YY + { + get + { + return Fixed16Dot16.FromRawValue((int)yy); + } + + set + { + yy = (IntPtr)value.Value; + } + } + + #endregion + + #region Operators + + /// + /// Compares two instances of for equality. + /// + /// A . + /// Another . + /// A value indicating equality. + public static bool operator ==(FTMatrix left, FTMatrix right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// A . + /// Another . + /// A value indicating inequality. + public static bool operator !=(FTMatrix left, FTMatrix right) + { + return !left.Equals(right); + } + + #endregion + + #region Methods + + /// + /// Perform the matrix operation ‘b = a*b’. + /// + /// + /// The result is undefined if either ‘a’ or ‘b’ is zero. + /// + /// A pointer to matrix ‘a’. + /// A pointer to matrix ‘b’. + public static void Multiply(FTMatrix a, FTMatrix b) + { + FT.FT_Matrix_Multiply(ref a, ref b); + } + + /// + /// Perform the matrix operation ‘b = a*b’. + /// + /// + /// The result is undefined if either ‘a’ or ‘b’ is zero. + /// + /// A pointer to matrix ‘b’. + public void Multiply(FTMatrix b) + { + FT.FT_Matrix_Multiply(ref this, ref b); + } + + /// + /// Invert a 2x2 matrix. Return an error if it can't be inverted. + /// + public void Invert() + { + Error err = FT.FT_Matrix_Invert(ref this); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Compares this instance of to another for equality. + /// + /// A . + /// A value indicating equality. + public bool Equals(FTMatrix other) + { + return + xx == other.xx && + xy == other.xy && + yx == other.yx && + yy == other.yy; + } + + /// + /// Compares this instance of to an object for equality. + /// + /// An object. + /// A value indicating equality. + public override bool Equals(object obj) + { + if (obj is FTMatrix) + return this.Equals((FTMatrix)obj); + else + return false; + } + + /// + /// Gets a unique hash code for this instance. + /// + /// A hash code. + public override int GetHashCode() + { + return xx.GetHashCode() ^ xy.GetHashCode() ^ yx.GetHashCode() ^ yy.GetHashCode(); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTSize.cs b/SharpFont/Source/SharpFontShared/FTSize.cs new file mode 100644 index 000000000..ce07d745d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTSize.cs @@ -0,0 +1,269 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015-2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// FreeType root size class structure. A size object models a face object at a given size. + /// + public sealed class FTSize : IDisposable + { + #region Fields + + private bool userAlloc; + private bool disposed; + private bool duplicate; + + private IntPtr reference; + private SizeRec rec; + + private Face parentFace; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The parent face. + public FTSize(Face parent) + { + IntPtr reference; + Error err = FT.FT_New_Size(parent.Reference, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = reference; + userAlloc = true; + } + + internal FTSize(IntPtr reference, bool userAlloc, Face parentFace) + { + Reference = reference; + + this.userAlloc = userAlloc; + + if (parentFace != null) + { + this.parentFace = parentFace; + parentFace.AddChildSize(this); + } + else + { + duplicate = true; + } + } + + /// + /// Finalizes an instance of the FTSize class. + /// + ~FTSize() + { + Dispose(false); + } + + #endregion + + #region Events + + /// + /// Occurs when the size is disposed. + /// + public event EventHandler Disposed; + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets a handle to the parent face object. + /// + public Face Face + { + get + { + if (disposed) + throw new ObjectDisposedException("Face", "Cannot access a disposed object."); + + return parentFace; + } + } + + /// + /// Gets or sets a typeless pointer, which is unused by the FreeType library or any of its drivers. It can be used by + /// client applications to link their own data to each size object. + /// + [Obsolete("Use the Tag property and Disposed event instead.")] + public Generic Generic + { + get + { + if (disposed) + throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); + + return new Generic(rec.generic); + } + + set + { + if (disposed) + throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); + + value.WriteToUnmanagedMemory(PInvokeHelper.AbsoluteOffsetOf(Reference, "generic")); + Reference = reference; //update rec. + } + } + + /// + /// Gets metrics for this size object. This field is read-only. + /// + public SizeMetrics Metrics + { + get + { + if (disposed) + throw new ObjectDisposedException("Metrics", "Cannot access a disposed object."); + + return new SizeMetrics(rec.metrics); + } + } + + /// + /// Gets or sets an object used to identify this instance of . This object will not be + /// modified or accessed internally. + /// + /// + /// This is a replacement for FT_Generic in FreeType. If you are retrieving the same object multiple times + /// from functions, this object will not appear in new copies. + /// + public object Tag { get; set; } + + 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; + this.rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Public Methods + + /// + /// Even though it is possible to create several size objects for a given face (see + /// for details), functions like or + /// only use the one which has been activated last to determine the + /// ‘current character pixel size’. + /// + /// This function can be used to ‘activate’ a previously created size object. + /// + /// + /// If ‘face’ is the size's parent face object, this function changes the value of ‘face->size’ to the input + /// size handle. + /// + public void Activate() + { + if (disposed) + throw new ObjectDisposedException("Activate", "Cannot access a disposed object."); + + Error err = FT.FT_Activate_Size(Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Diposes the FTSize. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region Private Methods + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + //only dispose the user allocated sizes that are not duplicates. + if (userAlloc && !duplicate) + { + FT.FT_Done_Size(reference); + } + + // removes itself from the parent Face, with a check to prevent this from happening when Face is + // being disposed (Face disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (parentFace != null && !parentFace.IsDisposed) + parentFace.RemoveChildSize(this); + + reference = IntPtr.Zero; + rec = new SizeRec(); + + EventHandler handler = Disposed; + if (handler != null) + handler(this, EventArgs.Empty); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTStream.cs b/SharpFont/Source/SharpFontShared/FTStream.cs new file mode 100644 index 000000000..927c6e072 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTStream.cs @@ -0,0 +1,315 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function used to seek and read data from a given input stream. + /// + /// + /// This function might be called to perform a seek or skip operation with a ‘count’ of 0. A non-zero return value + /// then indicates an error. + /// + /// A handle to the source stream. + /// The offset of read in stream (always from start). + /// The address of the read buffer. + /// The number of bytes to read from the stream. + /// The number of bytes effectively read by the stream. + [CLSCompliant(false)] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint StreamIOFunc(NativeReference stream, uint offset, IntPtr buffer, uint count); + + /// + /// A function used to close a given input stream. + /// + /// A handle to the target stream. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void StreamCloseFunc(NativeReference stream); + + /// + /// A handle to an input stream. + /// + public sealed class FTStream : NativeObject + { + #region Fields + + private StreamRec rec; + + #endregion + + #region Constructors + + internal FTStream(IntPtr reference): base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets base. For memory-based streams, this is the address of the first stream byte in memory. This field + /// should always be set to NULL for disk-based streams. + /// + public IntPtr Base + { + get + { + return rec.@base; + } + } + + /// + /// Gets the stream size in bytes. + /// + [CLSCompliant(false)] + public uint Size + { + get + { + return (uint)rec.size; + } + } + + /// + /// Gets the current position within the stream. + /// + [CLSCompliant(false)] + public uint Position + { + get + { + return (uint)rec.pos; + } + } + + /// + /// Gets the descriptor. This field is a union that can hold an integer or a pointer. It is used by stream + /// implementations to store file descriptors or ‘FILE*’ pointers. + /// + public StreamDesc Descriptor + { + get + { + return new StreamDesc(PInvokeHelper.AbsoluteOffsetOf(Reference, "descriptor")); + } + } + + /// + /// Gets the path name. This field is completely ignored by FreeType. However, it is often useful during + /// debugging to use it to store the stream's filename (where available). + /// + public StreamDesc PathName + { + get + { + return new StreamDesc(PInvokeHelper.AbsoluteOffsetOf(Reference, "pathname")); + } + } + + /// + /// Gets the stream's input function. + /// + [CLSCompliant(false)] + public StreamIOFunc Read + { + get + { + return rec.read; + } + } + + /// + /// Gets the stream's close function. + /// + public StreamCloseFunc Close + { + get + { + return rec.close; + } + } + + /// + /// Gets the memory manager to use to preload frames. This is set internally by FreeType and shouldn't be + /// touched by stream implementations. + /// + public Memory Memory + { + get + { + return new Memory(PInvokeHelper.AbsoluteOffsetOf(Reference, "memory")); + } + } + + /// + /// Gets the cursor. This field is set and used internally by FreeType when parsing frames. + /// + public IntPtr Cursor + { + get + { + return rec.cursor; + } + } + + /// + /// Gets the limit. This field is set and used internally by FreeType when parsing frames. + /// + public IntPtr Limit + { + get + { + return rec.limit; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + + #region Methods + + #region GZIP Streams + + /// + /// Open a new stream to parse gzip-compressed font files. This is mainly used to support the compressed + /// ‘*.pcf.gz’ fonts that come with XFree86. + /// + /// + /// The source stream must be opened before calling this function. + /// + /// Calling the internal function ‘FT_Stream_Close’ on the new stream will not call ‘FT_Stream_Close’ on the + /// source stream. None of the stream objects will be released to the heap. + /// + /// The stream implementation is very basic and resets the decompression process each time seeking backwards is + /// needed within the stream. + /// + /// In certain builds of the library, gzip compression recognition is automatically handled when calling + /// or . This means that if no font driver is + /// capable of handling the raw compressed file, the library will try to open a gzipped stream from it and + /// re-open the face with it. + /// + /// This function may return if your build of FreeType was not + /// compiled with zlib support. + /// + /// The source stream. + public void OpenGzip(FTStream source) + { + Error err = FT.FT_Stream_OpenGzip(Reference, source.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #endregion + + #region LZW Streams + + /// + /// Open a new stream to parse LZW-compressed font files. This is mainly used to support the compressed + /// ‘*.pcf.Z’ fonts that come with XFree86. + /// + /// + /// The source stream must be opened before calling this function. + /// + /// Calling the internal function ‘FT_Stream_Close’ on the new stream will not call ‘FT_Stream_Close’ on the + /// source stream. None of the stream objects will be released to the heap. + /// + /// The stream implementation is very basic and resets the decompression process each time seeking backwards is + /// needed within the stream. + /// + /// In certain builds of the library, LZW compression recognition is automatically handled when calling + /// or . This means that if no font driver is + /// capable of handling the raw compressed file, the library will try to open a LZW stream from it and re-open + /// the face with it. + /// + /// This function may return if your build of FreeType was not + /// compiled with LZW support. + /// + /// The source stream. + public void OpenLzw(FTStream source) + { + Error err = FT.FT_Stream_OpenLZW(Reference, source.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #endregion + + #region BZIP2 Streams + + /// + /// Open a new stream to parse bzip2-compressed font files. This is mainly used to support the compressed + /// ‘*.pcf.bz2’ fonts that come with XFree86. + /// + /// + /// The source stream must be opened before calling this function. + /// + /// Calling the internal function ‘FT_Stream_Close’ on the new stream will not call ‘FT_Stream_Close’ on the + /// source stream. None of the stream objects will be released to the heap. + /// + /// The stream implementation is very basic and resets the decompression process each time seeking backwards is + /// needed within the stream. + /// + /// In certain builds of the library, bzip2 compression recognition is automatically handled when calling + /// or . This means that if no font driver is + /// capable of handling the raw compressed file, the library will try to open a bzip2 stream from it and + /// re-open the face with it. + /// + /// This function may return if your build of FreeType was not + /// compiled with bzip2 support. + /// + /// The source stream. + public void StreamOpenBzip2(FTStream source) + { + Error err = FT.FT_Stream_OpenBzip2(Reference, source.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTUnitVector.cs b/SharpFont/Source/SharpFontShared/FTUnitVector.cs new file mode 100644 index 000000000..88a0c78fc --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTUnitVector.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// A simple structure used to store a 2D vector unit vector. Uses types. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct FTUnitVector + { + /// + /// Horizontal coordinate. + /// + public Fixed2Dot14 X; + + /// + /// Vertical coordinate. + /// + public Fixed2Dot14 Y; + } +} diff --git a/SharpFont/Source/SharpFontShared/FTVector.cs b/SharpFont/Source/SharpFontShared/FTVector.cs new file mode 100644 index 000000000..543fff43d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTVector.cs @@ -0,0 +1,240 @@ +#region MIT License +/*Copyright (c) 2012-2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A simple structure used to store a 2D vector. + /// + [StructLayout(LayoutKind.Sequential)] + public struct FTVector : IEquatable + { + #region Fields + + private IntPtr x; + private IntPtr y; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// The horizontal coordinate. + /// The vertical coordinate. + public FTVector(Fixed16Dot16 x, Fixed16Dot16 y) + : this() + { + this.x = (IntPtr)x.Value; + this.y = (IntPtr)y.Value; + } + + internal FTVector(IntPtr reference) + : this() + { + this.x = Marshal.ReadIntPtr(reference); + this.y = Marshal.ReadIntPtr(reference, IntPtr.Size); + } + + #endregion + + #region Properties + + /// + /// Gets or sets the horizontal coordinate. + /// + public Fixed16Dot16 X + { + get + { + return Fixed16Dot16.FromRawValue((int)x); + } + + set + { + x = (IntPtr)value.Value; + } + } + + /// + /// Gets or sets the vertical coordinate. + /// + public Fixed16Dot16 Y + { + get + { + return Fixed16Dot16.FromRawValue((int)y); + } + + set + { + y = (IntPtr)value.Value; + } + } + + #endregion + + #region Operators + + /// + /// Compares two instances of for equality. + /// + /// A . + /// Another . + /// A value indicating equality. + public static bool operator ==(FTVector left, FTVector right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// A . + /// Another . + /// A value indicating inequality. + public static bool operator !=(FTVector left, FTVector right) + { + return !left.Equals(right); + } + + #endregion + + #region Methods + + /// + /// Return the unit vector corresponding to a given angle. After the call, the value of ‘vec.x’ will be + /// ‘sin(angle)’, and the value of ‘vec.y’ will be ‘cos(angle)’. + /// + /// This function is useful to retrieve both the sinus and cosinus of a given angle quickly. + /// + /// The address of angle. + /// The address of target vector. + public static FTVector Unit(Fixed16Dot16 angle) + { + FTVector vec; + FT.FT_Vector_Unit(out vec, (IntPtr)angle.Value); + + return vec; + } + + /// + /// Compute vector coordinates from a length and angle. + /// + /// The vector length. + /// The vector angle. + /// The address of source vector. + public static FTVector FromPolar(Fixed16Dot16 length, Fixed16Dot16 angle) + { + FTVector vec; + FT.FT_Vector_From_Polar(out vec, (IntPtr)length.Value, (IntPtr)angle.Value); + + return vec; + } + + /// + /// Transform a single vector through a 2x2 matrix. + /// + /// + /// The result is undefined if either ‘vector’ or ‘matrix’ is invalid. + /// + /// A pointer to the source 2x2 matrix. + public void Transform(FTMatrix matrix) + { + FT.FT_Vector_Transform(ref this, ref matrix); + } + + /// + /// Rotate a vector by a given angle. + /// + /// The address of angle. + public void Rotate(Fixed16Dot16 angle) + { + FT.FT_Vector_Rotate(ref this, (IntPtr)angle.Value); + } + + /// + /// Return the length of a given vector. + /// + /// The vector length, expressed in the same units that the original vector coordinates. + public Fixed16Dot16 Length() + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Vector_Length(ref this)); + } + + /// + /// Compute both the length and angle of a given vector. + /// + /// The vector length. + /// The vector angle. + public void Polarize(out Fixed16Dot16 length, out Fixed16Dot16 angle) + { + IntPtr tmpLength, tmpAngle; + FT.FT_Vector_Polarize(ref this, out tmpLength, out tmpAngle); + + length = Fixed16Dot16.FromRawValue((int)tmpLength); + angle = Fixed16Dot16.FromRawValue((int)tmpAngle); + } + + /// + /// Compares this instance of to another for equality. + /// + /// A . + /// A value indicating equality. + public bool Equals(FTVector other) + { + return x == other.x && y == other.y; + } + + /// + /// Compares this instance of to an object for equality. + /// + /// An object. + /// A value indicating equality. + public override bool Equals(object obj) + { + if (obj is FTVector) + return this.Equals((FTVector)obj); + else + return false; + } + + /// + /// Gets a unique hash code for this instance. + /// + /// A hash code. + public override int GetHashCode() + { + return x.GetHashCode() ^ y.GetHashCode(); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FTVector26Dot6.cs b/SharpFont/Source/SharpFontShared/FTVector26Dot6.cs new file mode 100644 index 000000000..cf89ac38e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FTVector26Dot6.cs @@ -0,0 +1,164 @@ +#region MIT License +/*Copyright (c) 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// A simple structure used to store a 2D vector. + /// + [StructLayout(LayoutKind.Sequential)] + public struct FTVector26Dot6 : IEquatable + { + #region Fields + + private IntPtr x; + private IntPtr y; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// The horizontal coordinate. + /// The vertical coordinate. + public FTVector26Dot6(Fixed26Dot6 x, Fixed26Dot6 y) + : this() + { + this.x = (IntPtr)x.Value; + this.y = (IntPtr)y.Value; + } + + internal FTVector26Dot6(IntPtr reference) + : this() + { + this.x = Marshal.ReadIntPtr(reference); + this.y = Marshal.ReadIntPtr(reference, IntPtr.Size); + } + + #endregion + + #region Properties + + /// + /// Gets or sets the horizontal coordinate. + /// + public Fixed26Dot6 X + { + get + { + return Fixed26Dot6.FromRawValue((int)x); + } + + set + { + x = (IntPtr)value.Value; + } + } + + /// + /// Gets or sets the vertical coordinate. + /// + public Fixed26Dot6 Y + { + get + { + return Fixed26Dot6.FromRawValue((int)y); + } + + set + { + y = (IntPtr)value.Value; + } + } + + #endregion + + #region Operators + + /// + /// Compares two instances of for equality. + /// + /// A . + /// Another . + /// A value indicating equality. + public static bool operator ==(FTVector26Dot6 left, FTVector26Dot6 right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// A . + /// Another . + /// A value indicating inequality. + public static bool operator !=(FTVector26Dot6 left, FTVector26Dot6 right) + { + return !left.Equals(right); + } + + #endregion + + #region Methods + + /// + /// Compares this instance of to another for equality. + /// + /// A . + /// A value indicating equality. + public bool Equals(FTVector26Dot6 other) + { + return x == other.x && y == other.y; + } + + /// + /// Compares this instance of to an object for equality. + /// + /// An object. + /// A value indicating equality. + public override bool Equals(object obj) + { + if (obj is FTVector26Dot6) + return this.Equals((FTVector26Dot6)obj); + else + return false; + } + + /// + /// Gets a unique hash code for this instance. + /// + /// A hash code. + public override int GetHashCode() + { + return x.GetHashCode() ^ y.GetHashCode(); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Face.cs b/SharpFont/Source/SharpFontShared/Face.cs new file mode 100644 index 000000000..fea801bdf --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Face.cs @@ -0,0 +1,2412 @@ +#region MIT License +/*Copyright (c) 2012-2016 Robert Rouhani + +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 System.Runtime.InteropServices; + +using SharpFont.Bdf; +using SharpFont.Internal; +using SharpFont.MultipleMasters; +using SharpFont.PostScript; +using SharpFont.TrueType; + +namespace SharpFont +{ + /// + /// FreeType root face class structure. A face object models a typeface in a font file. + /// + /// + /// Fields may be changed after a call to or . + /// + public sealed class Face : NativeObject, IDisposable + { + #region Fields + + private FaceRec rec; + + private bool disposed; + + private GCHandle memoryFaceHandle; + + private Library parentLibrary; + private List childSizes; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class with a default faceIndex of 0. + /// + /// The parent library. + /// The path of the font file. + public Face(Library library, string path) + : this(library, path, 0) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The parent library. + /// The path of the font file. + /// The index of the face to take from the file. + public Face(Library library, string path, int faceIndex) + : this(library) + { + IntPtr reference; + Error err = FT.FT_New_Face(library.Reference, path, faceIndex, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = reference; + } + + //TODO make an overload with a FileStream instead of a byte[] + + /// + /// Initializes a new instance of the class from a file that's already loaded into memory. + /// + /// The parent library. + /// The loaded file. + /// The index of the face to take from the file. + public Face(Library library, byte[] file, int faceIndex) + : this(library) + { + IntPtr reference; + memoryFaceHandle = GCHandle.Alloc(file, GCHandleType.Pinned); + Error err = FT.FT_New_Memory_Face(library.Reference, memoryFaceHandle.AddrOfPinnedObject(), file.Length, faceIndex, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = reference; + } + + /// + /// Initializes a new instance of the class from a file that's already loaded into memory. + /// + /// The parent library. + /// A pointer to a buffer of a loaded file. Must not be freed before . + /// The length of bufferPtr. + /// The index of the face to take from the file. + public Face(Library library, IntPtr bufferPtr, int length, int faceIndex) + : this(library) + { + IntPtr reference; + Error err = FT.FT_New_Memory_Face(library.Reference, bufferPtr, length, faceIndex, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = reference; + } + + /// + /// Initializes a new instance of the class. + /// + /// A pointer to the unmanaged memory containing the Face. + /// The parent . + internal Face(IntPtr reference, Library parent) + : this(parent) + { + Reference = reference; + } + + private Face(Library parent): base(IntPtr.Zero) + { + childSizes = new List(); + + if (parent != null) + { + parentLibrary = parent; + parentLibrary.AddChildFace(this); + } + else + { + //if there's no parent, this is a marshalled duplicate. + FT.FT_Reference_Face(Reference); + } + } + + /// + /// Finalizes an instance of the class. + /// + ~Face() + { + Dispose(false); + } + + #endregion + + #region Events + + /// + /// Occurs when the face is disposed. + /// + public event EventHandler Disposed; + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets the number of faces in the font file. Some font formats can have multiple faces in a font file. + /// + public int FaceCount + { + get + { + if (disposed) + throw new ObjectDisposedException("FaceCount", "Cannot access a disposed object."); + + return (int)rec.num_faces; + } + } + + /// + /// Gets the index of the face in the font file. It is set to 0 if there is only one face in the font file. + /// + public int FaceIndex + { + get + { + if (disposed) + throw new ObjectDisposedException("FaceIndex", "Cannot access a disposed object."); + + return (int)rec.face_index; + } + } + + /// + /// Gets a set of bit flags that give important information about the face. + /// + /// + public FaceFlags FaceFlags + { + get + { + if (disposed) + throw new ObjectDisposedException("FaceFlags", "Cannot access a disposed object."); + + return (FaceFlags)rec.face_flags; + } + } + + /// + /// Gets a set of bit flags indicating the style of the face. + /// + /// + public StyleFlags StyleFlags + { + get + { + if (disposed) + throw new ObjectDisposedException("StyleFlags", "Cannot access a disposed object."); + + return (StyleFlags)rec.style_flags; + } + } + + /// + /// Gets the number of glyphs in the face. If the face is scalable and has sbits (see ‘num_fixed_sizes’), it is + /// set to the number of outline glyphs. + /// + /// For CID-keyed fonts, this value gives the highest CID used in the font. + /// + public int GlyphCount + { + get + { + if (disposed) + throw new ObjectDisposedException("GlyphCount", "Cannot access a disposed object."); + + return (int)rec.num_glyphs; + } + } + + /// + /// Gets the face's family name. This is an ASCII string, usually in English, which describes the typeface's + /// family (like ‘Times New Roman’, ‘Bodoni’, ‘Garamond’, etc). This is a least common denominator used to list + /// fonts. Some formats (TrueType & OpenType) provide localized and Unicode versions of this string. + /// Applications should use the format specific interface to access them. Can be NULL (e.g., in fonts embedded + /// in a PDF file). + /// + public string FamilyName + { + get + { + if (disposed) + throw new ObjectDisposedException("FamilyName", "Cannot access a disposed object."); + + return Marshal.PtrToStringAnsi(rec.family_name); + } + } + + /// + /// Gets the face's style name. This is an ASCII string, usually in English, which describes the typeface's + /// style (like ‘Italic’, ‘Bold’, ‘Condensed’, etc). Not all font formats provide a style name, so this field + /// is optional, and can be set to NULL. As for ‘family_name’, some formats provide localized and Unicode + /// versions of this string. Applications should use the format specific interface to access them. + /// + public string StyleName + { + get + { + if (disposed) + throw new ObjectDisposedException("StyleName", "Cannot access a disposed object."); + + return Marshal.PtrToStringAnsi(rec.style_name); + } + } + + /// + /// Gets the number of bitmap strikes in the face. Even if the face is scalable, there might still be bitmap + /// strikes, which are called ‘sbits’ in that case. + /// + public int FixedSizesCount + { + get + { + if (disposed) + throw new ObjectDisposedException("FixedSizesCount", "Cannot access a disposed object."); + + return rec.num_fixed_sizes; + } + } + + /// + /// Gets an array of FT_Bitmap_Size for all bitmap strikes in the face. It is set to NULL if there is no bitmap + /// strike. + /// + public BitmapSize[] AvailableSizes + { + get + { + if (disposed) + throw new ObjectDisposedException("AvailableSizes", "Cannot access a disposed object."); + + int count = FixedSizesCount; + + if (count == 0) + return null; + + BitmapSize[] sizes = new BitmapSize[count]; + IntPtr array = rec.available_sizes; + + for (int i = 0; i < count; i++) + { + sizes[i] = new BitmapSize(new IntPtr(array.ToInt64() + IntPtr.Size * i)); + } + + return sizes; + } + } + + /// + /// Gets the number of charmaps in the face. + /// + public int CharmapsCount + { + get + { + if (disposed) + throw new ObjectDisposedException("CharmapsCount", "Cannot access a disposed object."); + + return rec.num_charmaps; + } + } + + /// + /// Gets an array of the charmaps of the face. + /// + public CharMap[] CharMaps + { + get + { + if (disposed) + throw new ObjectDisposedException("CharMaps", "Cannot access a disposed object."); + + int count = CharmapsCount; + + if (count == 0) + return null; + + CharMap[] charmaps = new CharMap[count]; + + unsafe + { + IntPtr* array = (IntPtr*)rec.charmaps; + + for (int i = 0; i < count; i++) + { + charmaps[i] = new CharMap(*array, this); + array++; + } + } + + return charmaps; + } + } + + /// + /// Gets or sets a field reserved for client uses. + /// + /// + [Obsolete("Use the Tag property and Disposed event.")] + public Generic Generic + { + get + { + if (disposed) + throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); + + return new Generic(rec.generic); + } + + set + { + if (disposed) + throw new ObjectDisposedException("Generic", "Cannot access a disposed object."); + + IntPtr reference = Reference; + value.WriteToUnmanagedMemory(PInvokeHelper.AbsoluteOffsetOf(reference, "generic")); + Reference = reference; + } + } + + /// + /// Gets the font bounding box. Coordinates are expressed in font units (see ‘units_per_EM’). The box is large + /// enough to contain any glyph from the font. Thus, ‘bbox.yMax’ can be seen as the ‘maximal ascender’, and + /// ‘bbox.yMin’ as the ‘minimal descender’. Only relevant for scalable formats. + /// + /// Note that the bounding box might be off by (at least) one pixel for hinted fonts. See FT_Size_Metrics for + /// further discussion. + /// + public BBox BBox + { + get + { + if (disposed) + throw new ObjectDisposedException("BBox", "Cannot access a disposed object."); + + return rec.bbox; + } + } + + /// + /// Gets the number of font units per EM square for this face. This is typically 2048 for TrueType fonts, and + /// 1000 for Type 1 fonts. Only relevant for scalable formats. + /// + [CLSCompliant(false)] + public ushort UnitsPerEM + { + get + { + if (disposed) + throw new ObjectDisposedException("UnitsPerEM", "Cannot access a disposed object."); + + return rec.units_per_EM; + } + } + + /// + /// Gets the typographic ascender of the face, expressed in font units. For font formats not having this + /// information, it is set to ‘bbox.yMax’. Only relevant for scalable formats. + /// + public short Ascender + { + get + { + if (disposed) + throw new ObjectDisposedException("Ascender", "Cannot access a disposed object."); + + return rec.ascender; + } + } + + /// + /// Gets the typographic descender of the face, expressed in font units. For font formats not having this + /// information, it is set to ‘bbox.yMin’.Note that this field is usually negative. Only relevant for scalable + /// formats. + /// + public short Descender + { + get + { + if (disposed) + throw new ObjectDisposedException("Descender", "Cannot access a disposed object."); + + return rec.descender; + } + } + + /// + /// Gets the height is the vertical distance between two consecutive baselines, expressed in font units. It is + /// always positive. Only relevant for scalable formats. + /// + public short Height + { + get + { + if (disposed) + throw new ObjectDisposedException("Height", "Cannot access a disposed object."); + + return rec.height; + } + } + + /// + /// Gets the maximal advance width, in font units, for all glyphs in this face. This can be used to make word + /// wrapping computations faster. Only relevant for scalable formats. + /// + public short MaxAdvanceWidth + { + get + { + if (disposed) + throw new ObjectDisposedException("MaxAdvanceWidth", "Cannot access a disposed object."); + + return rec.max_advance_width; + } + } + + /// + /// Gets the maximal advance height, in font units, for all glyphs in this face. This is only relevant for + /// vertical layouts, and is set to ‘height’ for fonts that do not provide vertical metrics. Only relevant for + /// scalable formats. + /// + public short MaxAdvanceHeight + { + get + { + if (disposed) + throw new ObjectDisposedException("MaxAdvanceHeight", "Cannot access a disposed object."); + + return rec.max_advance_height; + } + } + + /// + /// Gets the position, in font units, of the underline line for this face. It is the center of the underlining + /// stem. Only relevant for scalable formats. + /// + public short UnderlinePosition + { + get + { + if (disposed) + throw new ObjectDisposedException("UnderlinePosition", "Cannot access a disposed object."); + + return rec.underline_position; + } + } + + /// + /// Gets the thickness, in font units, of the underline for this face. Only relevant for scalable formats. + /// + public short UnderlineThickness + { + get + { + if (disposed) + throw new ObjectDisposedException("UnderlineThickness", "Cannot access a disposed object."); + + return rec.underline_thickness; + } + } + + /// + /// Gets the face's associated glyph slot(s). + /// + public GlyphSlot Glyph + { + get + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + return new GlyphSlot(rec.glyph, this, parentLibrary); + } + } + + /// + /// Gets the current active size for this face. + /// + public FTSize Size + { + get + { + if (disposed) + throw new ObjectDisposedException("Size", "Cannot access a disposed object."); + + return new FTSize(rec.size, false, this); + } + } + + /// + /// Gets the current active charmap for this face. + /// + public CharMap CharMap + { + get + { + if (disposed) + throw new ObjectDisposedException("CharMap", "Cannot access a disposed object."); + + if (rec.charmap == IntPtr.Zero) + return null; + + return new CharMap(rec.charmap, this); + } + } + + /// + /// Gets a value indicating whether a face object contains horizontal metrics (this is true for all font + /// formats though). + /// + public bool HasHoriziontal + { + get + { + return (FaceFlags & FaceFlags.Horizontal) == FaceFlags.Horizontal; + } + } + + /// + /// Gets a value indicating whether a face object contains vertical metrics. + /// + public bool HasVertical + { + get + { + return (FaceFlags & FaceFlags.Vertical) == FaceFlags.Vertical; + } + } + + /// + /// Gets a value indicating whether a face object contains kerning data that can be accessed with + /// . + /// + public bool HasKerning + { + get + { + return (FaceFlags & FaceFlags.Kerning) == FaceFlags.Kerning; + } + } + + /// + /// Gets a value indicating whether a face object contains a scalable font face (true for TrueType, Type 1, + /// Type 42, CID, OpenType/CFF, and PFR font formats. + /// + public bool IsScalable + { + get + { + return (FaceFlags & FaceFlags.Scalable) == FaceFlags.Scalable; + } + } + + /// + /// Gets a value indicating whether a face object contains a font whose format is based on the SFNT storage + /// scheme. This usually means: TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap fonts. + /// + /// If this macro is true, all functions defined in FT_SFNT_NAMES_H and FT_TRUETYPE_TABLES_H are available. + /// + public bool IsSfnt + { + get + { + return (FaceFlags & FaceFlags.Sfnt) == FaceFlags.Sfnt; + } + } + + /// + /// Gets a value indicating whether a face object contains a font face that contains fixed-width (or + /// ‘monospace’, ‘fixed-pitch’, etc.) glyphs. + /// + public bool IsFixedWidth + { + get + { + return (FaceFlags & FaceFlags.FixedWidth) == FaceFlags.FixedWidth; + } + } + + /// + /// Gets a value indicating whether a face object contains some embedded bitmaps. + /// + /// + public bool HasFixedSizes + { + get + { + return (FaceFlags & FaceFlags.FixedSizes) == FaceFlags.FixedSizes; + } + } + + /// + /// Gets a value indicating whether a face object contains some glyph names that can be accessed through + /// . + /// + public bool HasGlyphNames + { + get + { + return (FaceFlags & FaceFlags.GlyphNames) == FaceFlags.GlyphNames; + } + } + + /// + /// Gets a value indicating whether a face object contains some multiple masters. The functions provided by + /// FT_MULTIPLE_MASTERS_H are then available to choose the exact design you want. + /// + public bool HasMultipleMasters + { + get + { + return (FaceFlags & FaceFlags.MultipleMasters) == FaceFlags.MultipleMasters; + } + } + + /// + /// Gets a value indicating whether a face object contains a CID-keyed font. See the discussion of + /// FT_FACE_FLAG_CID_KEYED for more details. + /// + /// If this macro is true, all functions defined in FT_CID_H are available. + /// + public bool IsCidKeyed + { + get + { + return (FaceFlags & FaceFlags.CidKeyed) == FaceFlags.CidKeyed; + } + } + + /// + /// Gets a value indicating whether a face represents a ‘tricky’ font. See the discussion of + /// FT_FACE_FLAG_TRICKY for more details. + /// + public bool IsTricky + { + get + { + return (FaceFlags & FaceFlags.Tricky) == FaceFlags.Tricky; + } + } + + /// + /// Gets a value indicating whether the font has color glyph tables. + /// + public bool HasColor + { + get + { + return (FaceFlags & FaceFlags.Color) == FaceFlags.Color; + } + } + + /// + /// Gets or sets an object used to identify this instance of . This object will not be + /// modified or accessed internally. + /// + /// + /// This is a replacement for FT_Generic in FreeType. If you are retrieving the same object multiple times + /// from functions, this object will not appear in new copies. + /// + public object Tag { get; set; } + + internal override IntPtr Reference + { + get + { + if (disposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + return base.Reference; + } + + set + { + if (disposed) + throw new ObjectDisposedException("Reference", "Cannot access a disposed object."); + + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + + #region Methods + + #region FreeType Version + + /// + /// Parse all bytecode instructions of a TrueType font file to check whether any of the patented opcodes are + /// used. This is only useful if you want to be able to use the unpatented hinter with fonts that do not use + /// these opcodes. + /// + /// Note that this function parses all glyph instructions in the font file, which may be slow. + /// + /// + /// Since May 2010, TrueType hinting is no longer patented. + /// + /// True if this is a TrueType font that uses one of the patented opcodes, false otherwise. + public bool CheckTrueTypePatents() + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Face_CheckTrueTypePatents(Reference); + } + + /// + /// Enable or disable the unpatented hinter for a given . Only enable it if you have + /// determined that the face doesn't use any patented opcodes. + /// + /// + /// Since May 2010, TrueType hinting is no longer patented. + /// + /// New boolean setting. + /// + /// The old setting value. This will always be false if this is not an SFNT font, or if the unpatented hinter + /// is not compiled in this instance of the library. + /// + /// + public bool SetUnpatentedHinting(bool value) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Face_SetUnpatentedHinting(Reference, value); + } + + #endregion + + #region Base Interface + + /// + /// This function calls to attach a file. + /// + /// The pathname. + public void AttachFile(string path) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Attach_File(Reference, path); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// ‘Attach’ data to a face object. Normally, this is used to read additional information for the face object. + /// For example, you can attach an AFM file that comes with a Type 1 font to get the kerning values and other + /// metrics. + /// + /// + /// The meaning of the ‘attach’ (i.e., what really happens when the new file is read) is not fixed by FreeType + /// itself. It really depends on the font format (and thus the font driver). + /// + /// Client applications are expected to know what they are doing when invoking this function. Most drivers + /// simply do not implement file attachments. + /// + /// A pointer to which must be filled by the caller. + public void AttachStream(OpenArgs parameters) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Attach_Stream(Reference, parameters.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Select a bitmap strike. + /// + /// + /// The index of the bitmap strike in the field of + /// structure. + /// + public void SelectSize(int strikeIndex) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Select_Size(Reference, strikeIndex); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Resize the scale of the active object in a face. + /// + /// A pointer to a . + public unsafe void RequestSize(SizeRequest request) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Request_Size(Reference, (IntPtr)(&request)); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// This function calls to request the nominal size (in points). + /// + /// + /// If either the character width or height is zero, it is set equal to the other value. + /// + /// If either the horizontal or vertical resolution is zero, it is set equal to the other value. + /// + /// A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are + /// set to 72dpi. + /// + /// The nominal width, in 26.6 fractional points. + /// The nominal height, in 26.6 fractional points. + /// The horizontal resolution in dpi. + /// The vertical resolution in dpi. + [CLSCompliant(false)] + public void SetCharSize(Fixed26Dot6 width, Fixed26Dot6 height, uint horizontalResolution, uint verticalResolution) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Set_Char_Size(Reference, (IntPtr)width.Value, (IntPtr)height.Value, horizontalResolution, verticalResolution); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// This function calls to request the nominal size (in pixels). + /// + /// The nominal width, in pixels. + /// The nominal height, in pixels + [CLSCompliant(false)] + public void SetPixelSizes(uint width, uint height) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Set_Pixel_Sizes(Reference, width, height); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// A function used to load a single glyph into the glyph slot of a face object. + /// + /// + /// The loaded glyph may be transformed. See for the details. + /// + /// For subsetted CID-keyed fonts, is returned for invalid CID values (this + /// is, for CID values which don't have a corresponding glyph in the font). See the discussion of the + /// flag for more details. + /// + /// + /// The index of the glyph in the font file. For CID-keyed fonts (either in PS or in CFF format) this argument + /// specifies the CID value. + /// + /// + /// A flag indicating what to load for this glyph. The constants can be used to control + /// the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, + /// whether to hint the outline, etc). + /// + /// The target to OR with the flags. + [CLSCompliant(false)] + public void LoadGlyph(uint glyphIndex, LoadFlags flags, LoadTarget target) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Load_Glyph(Reference, glyphIndex, (int)flags | (int)target); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// A function used to load a single glyph into the glyph slot of a face object, according to its character + /// code. + /// + /// + /// This function simply calls and + /// + /// + /// The glyph's character code, according to the current charmap used in the face. + /// + /// + /// A flag indicating what to load for this glyph. The constants can be used to control + /// the glyph loading process (e.g., whether the outline should be scaled, whether to load bitmaps or not, + /// whether to hint the outline, etc). + /// + /// The target to OR with the flags. + [CLSCompliant(false)] + public void LoadChar(uint charCode, LoadFlags flags, LoadTarget target) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Load_Char(Reference, charCode, (int)flags | (int)target); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// A function used to set the transformation that is applied to glyph images when they are loaded into a glyph + /// slot through . + /// + /// + /// The transformation is only applied to scalable image formats after the glyph has been loaded. It means that + /// hinting is unaltered by the transformation and is performed on the character size given in the last call to + /// or . + /// + /// Note that this also transforms the ‘face.glyph.advance’ field, but not the values in ‘face.glyph.metrics’. + /// + /// + /// A pointer to the transformation's 2x2 matrix. Use the method overloads for the identity matrix. + /// + /// + /// A pointer to the translation vector. Use the method overloads for the null vector. + /// + public unsafe void SetTransform(FTMatrix matrix, FTVector delta) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + FT.FT_Set_Transform(Reference, (IntPtr)(&matrix), (IntPtr)(&delta)); + } + + /// + /// A function used to set the transformation that is applied to glyph images when they are loaded into a glyph + /// slot through with the identity matrix. + /// + /// + /// The transformation is only applied to scalable image formats after the glyph has been loaded. It means that + /// hinting is unaltered by the transformation and is performed on the character size given in the last call to + /// or . + /// + /// Note that this also transforms the ‘face.glyph.advance’ field, but not the values in ‘face.glyph.metrics’. + /// + /// + /// A pointer to the translation vector. Use the method overloads for the null vector. + /// + public unsafe void SetTransform(FTVector delta) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + FT.FT_Set_Transform(Reference, IntPtr.Zero, (IntPtr)(&delta)); + } + + /// + /// A function used to set the transformation that is applied to glyph images when they are loaded into a glyph + /// slot through with the null vector. + /// + /// + /// The transformation is only applied to scalable image formats after the glyph has been loaded. It means that + /// hinting is unaltered by the transformation and is performed on the character size given in the last call to + /// or . + /// + /// Note that this also transforms the ‘face.glyph.advance’ field, but not the values in ‘face.glyph.metrics’. + /// + /// + /// A pointer to the transformation's 2x2 matrix. Use the method overloads for the identity matrix. + /// + public unsafe void SetTransform(FTMatrix matrix) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + FT.FT_Set_Transform(Reference, (IntPtr)(&matrix), IntPtr.Zero); + } + + /// + /// A function used to set the transformation that is applied to glyph images when they are loaded into a glyph + /// slot through with the null vector and the identity matrix. + /// + /// + /// The transformation is only applied to scalable image formats after the glyph has been loaded. It means that + /// hinting is unaltered by the transformation and is performed on the character size given in the last call to + /// or . + /// + /// Note that this also transforms the ‘face.glyph.advance’ field, but not the values in ‘face.glyph.metrics’. + /// + public unsafe void SetTransform() + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + FT.FT_Set_Transform(Reference, IntPtr.Zero, IntPtr.Zero); + } + + /// + /// Return the kerning vector between two glyphs of a same face. + /// + /// + /// Only horizontal layouts (left-to-right & right-to-left) are supported by this method. Other layouts, or + /// more sophisticated kernings, are out of the scope of this API function -- they can be implemented through + /// format-specific interfaces. + /// + /// The index of the left glyph in the kern pair. + /// The index of the right glyph in the kern pair. + /// Determines the scale and dimension of the returned kerning vector. + /// + /// The kerning vector. This is either in font units or in pixels (26.6 format) for scalable formats, and in + /// pixels for fixed-sizes formats. + /// + [CLSCompliant(false)] + public FTVector26Dot6 GetKerning(uint leftGlyph, uint rightGlyph, KerningMode mode) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + FTVector26Dot6 kern; + Error err = FT.FT_Get_Kerning(Reference, leftGlyph, rightGlyph, (uint)mode, out kern); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return kern; + } + + /// + /// Return the track kerning for a given face object at a given size. + /// + /// The point size in 16.16 fractional points. + /// The degree of tightness. + /// The kerning in 16.16 fractional points. + public Fixed16Dot16 GetTrackKerning(Fixed16Dot16 pointSize, int degree) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + IntPtr kerning; + + Error err = FT.FT_Get_Track_Kerning(Reference, (IntPtr)pointSize.Value, degree, out kerning); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return Fixed16Dot16.FromRawValue((int)kerning); + } + + /// + /// Retrieve the ASCII name of a given glyph in a face. This only works for those faces where + /// returns 1. + /// + /// + /// An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases + /// of failure, the first byte of ‘buffer’ is set to 0 to indicate an empty name. + /// + /// The glyph name is truncated to fit within the buffer if it is too long. The returned string is always + /// zero-terminated. + /// + /// Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the + /// ‘missing glyph’ (called ‘.notdef’). + /// + /// This function is not compiled within the library if the config macro ‘FT_CONFIG_OPTION_NO_GLYPH_NAMES’ is + /// defined in ‘include/freetype/config/ftoptions.h’. + /// + /// The glyph index. + /// The maximal number of bytes available in the buffer. + /// The ASCII name of a given glyph in a face. + [CLSCompliant(false)] + public string GetGlyphName(uint glyphIndex, int bufferSize) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return GetGlyphName(glyphIndex, new byte[bufferSize]); + } + + /// + /// Retrieve the ASCII name of a given glyph in a face. This only works for those faces where + /// returns 1. + /// + /// + /// An error is returned if the face doesn't provide glyph names or if the glyph index is invalid. In all cases + /// of failure, the first byte of ‘buffer’ is set to 0 to indicate an empty name. + /// + /// The glyph name is truncated to fit within the buffer if it is too long. The returned string is always + /// zero-terminated. + /// + /// Be aware that FreeType reorders glyph indices internally so that glyph index 0 always corresponds to the + /// ‘missing glyph’ (called ‘.notdef’). + /// + /// This function is not compiled within the library if the config macro ‘FT_CONFIG_OPTION_NO_GLYPH_NAMES’ is + /// defined in ‘include/freetype/config/ftoptions.h’. + /// + /// The glyph index. + /// The target buffer where the name is copied to. + /// The ASCII name of a given glyph in a face. + [CLSCompliant(false)] + public unsafe string GetGlyphName(uint glyphIndex, byte[] buffer) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + fixed (byte* ptr = buffer) + { + IntPtr intptr = new IntPtr(ptr); + Error err = FT.FT_Get_Glyph_Name(Reference, glyphIndex, intptr, (uint)buffer.Length); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return Marshal.PtrToStringAnsi(intptr); + } + } + + /// + /// Retrieve the ASCII Postscript name of a given face, if available. This only works with Postscript and + /// TrueType fonts. + /// + /// + /// The returned pointer is owned by the face and is destroyed with it. + /// + /// A pointer to the face's Postscript name. NULL if unavailable. + public string GetPostscriptName() + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return Marshal.PtrToStringAnsi(FT.FT_Get_Postscript_Name(Reference)); + } + + /// + /// Select a given charmap by its encoding tag (as listed in ‘freetype.h’). + /// + /// + /// This function returns an error if no charmap in the face corresponds to the encoding queried here. + /// + /// Because many fonts contain more than a single cmap for Unicode encoding, this function has some special + /// code to select the one which covers Unicode best. It is thus preferable to in + /// this case. + /// + /// A handle to the selected encoding. + [CLSCompliant(false)] + public void SelectCharmap(Encoding encoding) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Select_Charmap(Reference, encoding); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Select a given charmap for character code to glyph index mapping. + /// + /// + /// This function returns an error if the charmap is not part of the face (i.e., if it is not listed in the + /// ’ table). + /// + /// A handle to the selected charmap. + public void SetCharmap(CharMap charmap) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + Error err = FT.FT_Set_Charmap(Reference, charmap.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Return the glyph index of a given character code. This function uses a charmap object to do the mapping. + /// + /// + /// If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index + /// returned by this function doesn't always correspond to the internal indices used within the file. This is + /// done to ensure that value 0 always corresponds to the ‘missing glyph’. + /// + /// The character code. + /// The glyph index. 0 means ‘undefined character code’. + [CLSCompliant(false)] + public uint GetCharIndex(uint charCode) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Get_Char_Index(Reference, charCode); + } + + /// + /// This function is used to return the first character code in the current charmap of a given face. It also + /// returns the corresponding glyph index. + /// + /// + /// You should use this function with to be able to parse all character codes + /// available in a given charmap. + /// + /// Note that ‘agindex’ is set to 0 if the charmap is empty. The result itself can be 0 in two cases: if the + /// charmap is empty or when the value 0 is the first valid character code. + /// + /// Glyph index of first character code. 0 if charmap is empty. + /// The charmap's first character code. + [CLSCompliant(false)] + public uint GetFirstChar(out uint glyphIndex) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Get_First_Char(Reference, out glyphIndex); + } + + /// + /// This function is used to return the next character code in the current charmap of a given face following + /// the value ‘charCode’, as well as the corresponding glyph index. + /// + /// + /// You should use this function with to walk over all character codes available + /// in a given charmap. See the note for this function for a simple code example. + /// + /// Note that ‘*agindex’ is set to 0 when there are no more codes in the charmap. + /// + /// The starting character code. + /// Glyph index of first character code. 0 if charmap is empty. + /// The charmap's next character code. + [CLSCompliant(false)] + public uint GetNextChar(uint charCode, out uint glyphIndex) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Get_Next_Char(Reference, charCode, out glyphIndex); + } + + /// + /// Return the glyph index of a given glyph name. This function uses driver specific objects to do the + /// translation. + /// + /// The glyph name. + /// The glyph index. 0 means ‘undefined character code’. + [CLSCompliant(false)] + public uint GetNameIndex(string name) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Get_Name_Index(Reference, Marshal.StringToHGlobalAnsi(name)); + } + + /// + /// Return the flags for a font. + /// + /// + /// Use this function rather than directly reading the ‘fs_type’ field in the + /// structure which is only guaranteed to return the correct results for Type 1 fonts. + /// + /// The fsType flags, . + [CLSCompliant(false)] + public EmbeddingTypes GetFSTypeFlags() + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Get_FSType_Flags(Reference); + } + + #endregion + + #region Glyph Variants + + /// + /// Return the glyph index of a given character code as modified by the variation selector. + /// + /// + /// If you use FreeType to manipulate the contents of font files directly, be aware that the glyph index + /// returned by this function doesn't always correspond to the internal indices used within the file. This is + /// done to ensure that value 0 always corresponds to the ‘missing glyph’. + /// + /// This function is only meaningful if a) the font has a variation selector cmap sub table, and b) the current + /// charmap has a Unicode encoding. + /// + /// The character code point in Unicode. + /// The Unicode code point of the variation selector. + /// + /// The glyph index. 0 means either ‘undefined character code’, or ‘undefined selector code’, or ‘no variation + /// selector cmap subtable’, or ‘current CharMap is not Unicode’. + /// + [CLSCompliant(false)] + public uint GetCharVariantIndex(uint charCode, uint variantSelector) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Face_GetCharVariantIndex(Reference, charCode, variantSelector); + } + + /// + /// Check whether this variant of this Unicode character is the one to be found in the ‘cmap’. + /// + /// + /// This function is only meaningful if the font has a variation selector cmap subtable. + /// + /// The character codepoint in Unicode. + /// The Unicode codepoint of the variation selector. + /// + /// 1 if found in the standard (Unicode) cmap, 0 if found in the variation selector cmap, or -1 if it is not a + /// variant. + /// + [CLSCompliant(false)] + public int GetCharVariantIsDefault(uint charCode, uint variantSelector) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + return FT.FT_Face_GetCharVariantIsDefault(Reference, charCode, variantSelector); + } + + /// + /// Return a zero-terminated list of Unicode variant selectors found in the font. + /// + /// + /// The last item in the array is 0; the array is owned by the object but can be overwritten + /// or released on the next call to a FreeType function. + /// + /// + /// A pointer to an array of selector code points, or NULL if there is no valid variant selector cmap subtable. + /// + [CLSCompliant(false)] + public uint[] GetVariantSelectors() + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + IntPtr ptr = FT.FT_Face_GetVariantSelectors(Reference); + + List list = new List(); + + //temporary non-zero value to prevent complaining about uninitialized variable. + uint curValue = 1; + + for (int i = 0; curValue != 0; i++) + { + curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); + list.Add(curValue); + } + + return list.ToArray(); + } + + /// + /// Return a zero-terminated list of Unicode variant selectors found in the font. + /// + /// + /// The last item in the array is 0; the array is owned by the object but can be overwritten + /// or released on the next call to a FreeType function. + /// + /// The character codepoint in Unicode. + /// + /// A pointer to an array of variant selector code points which are active for the given character, or NULL if + /// the corresponding list is empty. + /// + [CLSCompliant(false)] + public uint[] GetVariantsOfChar(uint charCode) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + IntPtr ptr = FT.FT_Face_GetVariantsOfChar(Reference, charCode); + + List list = new List(); + + //temporary non-zero value to prevent complaining about uninitialized variable. + uint curValue = 1; + + for (int i = 0; curValue != 0; i++) + { + curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); + list.Add(curValue); + } + + return list.ToArray(); + } + + /// + /// Return a zero-terminated list of Unicode character codes found for the specified variant selector. + /// + /// + /// The last item in the array is 0; the array is owned by the object but can be overwritten + /// or released on the next call to a FreeType function. + /// + /// The variant selector code point in Unicode. + /// + /// A list of all the code points which are specified by this selector (both default and non-default codes are + /// returned) or NULL if there is no valid cmap or the variant selector is invalid. + /// + [CLSCompliant(false)] + public uint[] GetCharsOfVariant(uint variantSelector) + { + if (disposed) + throw new ObjectDisposedException("face", "Cannot access a disposed object."); + + IntPtr ptr = FT.FT_Face_GetCharsOfVariant(Reference, variantSelector); + + List list = new List(); + + //temporary non-zero value to prevent complaining about uninitialized variable. + uint curValue = 1; + + for (int i = 0; curValue != 0; i++) + { + curValue = (uint)Marshal.ReadInt32(Reference, sizeof(uint) * i); + list.Add(curValue); + } + + return list.ToArray(); + } + + #endregion + + #region Size Management + + /// + /// Create a new size object from a given face object. + /// + /// + /// You need to call in order to select the new size for upcoming calls to + /// , , , , + /// etc. + /// + /// A handle to a new size object. + public FTSize NewSize() + { + return new FTSize(this); + } + + #endregion + + #region Multiple Masters + + /// + /// Retrieve the Multiple Master descriptor of a given font. + /// + /// This function can't be used with GX fonts. + /// + /// The Multiple Masters descriptor. + public MultiMaster GetMultiMaster() + { + IntPtr masterRef; + Error err = FT.FT_Get_Multi_Master(Reference, out masterRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new MultiMaster(masterRef); + } + + /// + /// Retrieve the Multiple Master/GX var descriptor of a given font. + /// + /// + /// The Multiple Masters/GX var descriptor. Allocates a data structure, which the user must free (a single call + /// to FT_FREE will do it). + /// + public MMVar GetMMVar() + { + IntPtr varRef; + Error err = FT.FT_Get_MM_Var(Reference, out varRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new MMVar(varRef); + } + + /// + /// For Multiple Masters fonts, choose an interpolated font design through design coordinates. + /// + /// This function can't be used with GX fonts. + /// + /// An array of design coordinates. + public unsafe void SetMMDesignCoordinates(long[] coords) + { + fixed (void* ptr = coords) + { + IntPtr coordsPtr = (IntPtr)ptr; + Error err = FT.FT_Set_MM_Design_Coordinates(Reference, (uint)coords.Length, coordsPtr); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + } + + /// + /// For Multiple Master or GX Var fonts, choose an interpolated font design through design coordinates. + /// + /// An array of design coordinates. + public unsafe void SetVarDesignCoordinates(long[] coords) + { + fixed (void* ptr = coords) + { + IntPtr coordsPtr = (IntPtr)ptr; + Error err = FT.FT_Set_Var_Design_Coordinates(Reference, (uint)coords.Length, coordsPtr); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + } + + /// + /// For Multiple Masters and GX var fonts, choose an interpolated font design through normalized blend + /// coordinates. + /// + /// The design coordinates array (each element must be between 0 and 1.0). + public unsafe void SetMMBlendCoordinates(long[] coords) + { + fixed (void* ptr = coords) + { + IntPtr coordsPtr = (IntPtr)ptr; + Error err = FT.FT_Set_MM_Blend_Coordinates(Reference, (uint)coords.Length, coordsPtr); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + } + + /// + /// This is another name of . + /// + /// The design coordinates array (each element must be between 0 and 1.0). + public unsafe void SetVarBlendCoordinates(long[] coords) + { + fixed (void* ptr = coords) + { + IntPtr coordsPtr = (IntPtr)ptr; + Error err = FT.FT_Set_Var_Blend_Coordinates(Reference, (uint)coords.Length, coordsPtr); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + } + + #endregion + + #region TrueType Tables + + /// + /// Return a pointer to a given SFNT table within a face. + /// + /// + /// The table is owned by the face object and disappears with it. + /// + /// This function is only useful to access SFNT tables that are loaded by the sfnt, truetype, and opentype + /// drivers. See for a list. + /// + /// The index of the SFNT table. + /// + /// A type-less pointer to the table. This will be 0 in case of error, or if the corresponding table was not + /// found OR loaded from the file. + /// + /// Use a typecast according to ‘tag’ to access the structure elements. + /// + public object GetSfntTable(SfntTag tag) + { + IntPtr tableRef = FT.FT_Get_Sfnt_Table(Reference, tag); + + if (tableRef == IntPtr.Zero) + return null; + + switch (tag) + { + case SfntTag.Header: + return new Header(tableRef); + case SfntTag.HorizontalHeader: + return new HoriHeader(tableRef); + case SfntTag.MaxProfile: + return new MaxProfile(tableRef); + case SfntTag.OS2: + return new OS2(tableRef); + case SfntTag.Pclt: + return new Pclt(tableRef); + case SfntTag.Postscript: + return new Postscript(tableRef); + case SfntTag.VertHeader: + return new VertHeader(tableRef); + default: + return null; + } + } + + /// + /// Load any font table into client memory. + /// + /// + /// If you need to determine the table's length you should first call this function with ‘*length’ set to 0, as + /// in the following example: + /// + /// FT_ULong length = 0; + /// + /// + /// error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); + /// if ( error ) { ... table does not exist ... } + /// + /// buffer = malloc( length ); + /// if ( buffer == NULL ) { ... not enough memory ... } + /// + /// error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length ); + /// if ( error ) { ... could not load table ... } + /// + /// + /// + /// The four-byte tag of the table to load. Use the value 0 if you want to access the whole font file. + /// Otherwise, you can use one of the definitions found in the FT_TRUETYPE_TAGS_H file, or forge a new one with + /// FT_MAKE_TAG. + /// + /// The starting offset in the table (or file if tag == 0). + /// + /// The target buffer address. The client must ensure that the memory array is big enough to hold the data. + /// + /// + /// If the ‘length’ parameter is NULL, then try to load the whole table. Return an error code if it fails. + /// + /// Else, if ‘*length’ is 0, exit immediately while returning the table's (or file) full size in it. + /// + /// Else the number of bytes to read from the table or file, from the starting offset. + /// + [CLSCompliant(false)] + public void LoadSfntTable(uint tag, int offset, IntPtr buffer, ref uint length) + { + Error err = FT.FT_Load_Sfnt_Table(Reference, tag, offset, buffer, ref length); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Return information on an SFNT table. + /// + /// + /// The index of an SFNT table. The function returns for an invalid value. + /// + /// + /// The name tag of the SFNT table. If the value is NULL, ‘table_index’ is ignored, and ‘length’ returns the + /// number of SFNT tables in the font. + /// + /// The length of the SFNT table (or the number of SFNT tables, depending on ‘tag’). + [CLSCompliant(false)] + public unsafe uint SfntTableInfo(uint tableIndex, SfntTag tag) + { + uint length; + Error err = FT.FT_Sfnt_Table_Info(Reference, tableIndex, &tag, out length); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return length; + } + + /// + /// Only gets the number of SFNT tables. + /// + /// The number of SFNT tables. + [CLSCompliant(false)] + public unsafe uint SfntTableInfo() + { + uint length; + Error err = FT.FT_Sfnt_Table_Info(Reference, 0, null, out length); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return length; + } + + #endregion + + #region Type 1 Tables + + /// + /// Return true if a given face provides reliable PostScript glyph names. This is similar to using the + /// macro, except that certain fonts (mostly TrueType) contain incorrect + /// glyph name tables. + /// + /// When this function returns true, the caller is sure that the glyph names returned by + /// are reliable. + /// + /// Boolean. True if glyph names are reliable. + public bool HasPSGlyphNames() + { + return FT.FT_Has_PS_Glyph_Names(Reference); + } + + /// + /// Retrieve the structure corresponding to a given PostScript font. + /// + /// + /// The string pointers within the font info structure are owned by the face and don't need to be freed by the + /// caller. + /// + /// If the font's format is not PostScript-based, this function will return the + /// error code. + /// + /// Output font info structure pointer. + public FontInfo GetPSFontInfo() + { + PostScript.Internal.FontInfoRec fontInfoRec; + Error err = FT.FT_Get_PS_Font_Info(Reference, out fontInfoRec); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new FontInfo(fontInfoRec); + } + + /// + /// Retrieve the structure corresponding to a given PostScript font. + /// + /// + /// The string pointers within the structure are owned by the face and don't + /// need to be freed by the caller. + /// + /// If the font's format is not PostScript-based, this function returns the + /// error code. + /// + /// Output private dictionary structure pointer. + public Private GetPSFontPrivate() + { + PostScript.Internal.PrivateRec privateRec; + Error err = FT.FT_Get_PS_Font_Private(Reference, out privateRec); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new Private(privateRec); + } + + /// + /// Retrieve the value for the supplied key from a PostScript font. + /// + /// + /// The values returned are not pointers into the internal structures of the face, but are ‘fresh’ copies, so + /// that the memory containing them belongs to the calling application. This also enforces the ‘read-only’ + /// nature of these values, i.e., this function cannot be used to manipulate the face. + /// + /// ‘value’ is a void pointer because the values returned can be of various types. + /// + /// If either ‘value’ is NULL or ‘value_len’ is too small, just the required memory size for the requested + /// entry is returned. + /// + /// The ‘idx’ parameter is used, not only to retrieve elements of, for example, the FontMatrix or FontBBox, but + /// also to retrieve name keys from the CharStrings dictionary, and the charstrings themselves. It is ignored + /// for atomic values. + /// + /// returns a value that is scaled up by 1000. To get the + /// value as in the font stream, you need to divide by 65536000.0 (to remove the FT_Fixed scale, and the x1000 + /// scale). + /// + /// IMPORTANT: Only key/value pairs read by the FreeType interpreter can be retrieved. So, for example, + /// PostScript procedures such as NP, ND, and RD are not available. Arbitrary keys are, obviously, not be + /// available either. + /// + /// If the font's format is not PostScript-based, this function returns the + /// error code. + /// + /// An enumeration value representing the dictionary key to retrieve. + /// For array values, this specifies the index to be returned. + /// A pointer to memory into which to write the value. + /// The size, in bytes, of the memory supplied for the value. + /// + /// The amount of memory (in bytes) required to hold the requested value (if it exists, -1 otherwise). + /// + [CLSCompliant(false)] + public int GetPSFontValue(DictionaryKeys key, uint idx, ref IntPtr value, int valueLength) + { + return FT.FT_Get_PS_Font_Value(Reference, key, idx, ref value, valueLength); + } + + #endregion + + #region SFNT Names + + /// + /// Retrieve the number of name strings in the SFNT ‘name’ table. + /// + /// The number of strings in the ‘name’ table. + [CLSCompliant(false)] + public uint GetSfntNameCount() + { + return FT.FT_Get_Sfnt_Name_Count(Reference); + } + + /// + /// Retrieve a string of the SFNT ‘name’ table for a given index. + /// + /// + /// The ‘string’ array returned in the ‘aname’ structure is not null-terminated. The application should + /// deallocate it if it is no longer in use. + /// + /// Use to get the total number of available ‘name’ table entries, then do a + /// loop until you get the right platform, encoding, and name ID. + /// + /// The index of the ‘name’ string. + /// The indexed structure. + [CLSCompliant(false)] + public SfntName GetSfntName(uint idx) + { + TrueType.Internal.SfntNameRec nameRec; + + Error err = FT.FT_Get_Sfnt_Name(Reference, idx, out nameRec); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new SfntName(nameRec); + } + + #endregion + + #region BDF and PCF Files + + /// + /// Retrieve a BDF font character set identity, according to the BDF specification. + /// + /// + /// This function only works with BDF faces, returning an error otherwise. + /// + /// Charset encoding, as a C string, owned by the face. + /// Charset registry, as a C string, owned by the face. + public void GetBdfCharsetId(out string encoding, out string registry) + { + Error err = FT.FT_Get_BDF_Charset_ID(Reference, out encoding, out registry); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Retrieve a BDF property from a BDF or PCF font file. + /// + /// + /// This function works with BDF and PCF fonts. It returns an error otherwise. It also returns an error if the + /// property is not in the font. + /// + /// A ‘property’ is a either key-value pair within the STARTPROPERTIES ... ENDPROPERTIES block of a BDF font or + /// a key-value pair from the ‘info->props’ array within a ‘FontRec’ structure of a PCF font. + /// + /// Integer properties are always stored as ‘signed’ within PCF fonts; consequently, + /// is a possible return value for BDF fonts only. + /// + /// In case of error, ‘aproperty->type’ is always set to . + /// + /// The property name. + /// The property. + public Property GetBdfProperty(string propertyName) + { + IntPtr propertyRef; + + Error err = FT.FT_Get_BDF_Property(Reference, propertyName, out propertyRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new Property(propertyRef); + } + + #endregion + + #region CID Fonts + + /// + /// Retrieve the Registry/Ordering/Supplement triple (also known as the "R/O/S") from a CID-keyed font. + /// + /// + /// This function only works with CID faces, returning an error otherwise. + /// + /// The registry, as a C string, owned by the face. + /// The ordering, as a C string, owned by the face. + /// The supplement. + public void GetCidRegistryOrderingSupplement(out string registry, out string ordering, out int supplement) + { + Error err = FT.FT_Get_CID_Registry_Ordering_Supplement(Reference, out registry, out ordering, out supplement); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Retrieve the type of the input face, CID keyed or not. In constrast to the + /// macro this function returns successfully also for CID-keyed fonts in an + /// SNFT wrapper. + /// + /// + /// This function only works with CID faces and OpenType fonts, returning an error otherwise. + /// + /// The type of the face as an FT_Bool. + public bool GetCidIsInternallyCidKeyed() + { + byte is_cid; + Error err = FT.FT_Get_CID_Is_Internally_CID_Keyed(Reference, out is_cid); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return is_cid == 1; + } + + /// + /// Retrieve the CID of the input glyph index. + /// + /// + /// This function only works with CID faces and OpenType fonts, returning an error otherwise. + /// + /// The input glyph index. + /// The CID as an uint. + [CLSCompliant(false)] + public uint GetCidFromGlyphIndex(uint glyphIndex) + { + uint cid; + Error err = FT.FT_Get_CID_From_Glyph_Index(Reference, glyphIndex, out cid); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return cid; + } + + #endregion + + #region PFR Fonts + + /// + /// Return the outline and metrics resolutions of a given PFR face. + /// + /// + /// If the input face is not a PFR, this function will return an error. However, in all cases, it will return + /// valid values. + /// + /// + /// Outline resolution. This is equivalent to ‘face->units_per_EM’ for non-PFR fonts. Optional (parameter can + /// be NULL). + /// + /// + /// Metrics resolution. This is equivalent to ‘outline_resolution’ for non-PFR fonts. Optional (parameter can + /// be NULL). + /// + /// + /// A 16.16 fixed-point number used to scale distance expressed in metrics units to device sub-pixels. This is + /// equivalent to ‘face->size->x_scale’, but for metrics only. Optional (parameter can be NULL). + /// + /// + /// Same as ‘ametrics_x_scale’ but for the vertical direction. optional (parameter can be NULL). + /// + [CLSCompliant(false)] + public void GetPfrMetrics(out uint outlineResolution, out uint metricsResolution, out Fixed16Dot16 metricsXScale, out Fixed16Dot16 metricsYScale) + { + IntPtr tmpXScale, tmpYScale; + Error err = FT.FT_Get_PFR_Metrics(Reference, out outlineResolution, out metricsResolution, out tmpXScale, out tmpYScale); + + metricsXScale = Fixed16Dot16.FromRawValue((int)tmpXScale); + metricsYScale = Fixed16Dot16.FromRawValue((int)tmpYScale); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Return the kerning pair corresponding to two glyphs in a PFR face. The distance is expressed in metrics + /// units, unlike the result of . + /// + /// + /// This function always return distances in original PFR metrics units. This is unlike + /// with the mode, which always returns + /// distances converted to outline units. + /// + /// You can use the value of the ‘x_scale’ and ‘y_scale’ parameters returned by to + /// scale these to device sub-pixels. + /// + /// Index of the left glyph. + /// Index of the right glyph. + /// A kerning vector. + [CLSCompliant(false)] + public FTVector GetPfrKerning(uint left, uint right) + { + FTVector vector; + Error err = FT.FT_Get_PFR_Kerning(Reference, left, right, out vector); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return vector; + } + + /// + /// Return a given glyph advance, expressed in original metrics units, from a PFR font. + /// + /// + /// You can use the ‘x_scale’ or ‘y_scale’ results of to convert the advance to + /// device sub-pixels (i.e., 1/64th of pixels). + /// + /// The glyph index. + /// The glyph advance in metrics units. + [CLSCompliant(false)] + public int GetPfrAdvance(uint glyphIndex) + { + int advance; + Error err = FT.FT_Get_PFR_Advance(Reference, glyphIndex, out advance); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return advance; + } + + #endregion + + #region Windows FNT Files + + /// + /// Retrieve a Windows FNT font info header. + /// + /// + /// This function only works with Windows FNT faces, returning an error otherwise. + /// + /// The WinFNT header. + public Fnt.Header GetWinFntHeader() + { + IntPtr headerRef; + Error err = FT.FT_Get_WinFNT_Header(Reference, out headerRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new Fnt.Header(headerRef); + } + + #endregion + + #region Font Formats + + /// + /// Return a string describing the format of a given face, using values which can be used as an X11 + /// FONT_PROPERTY. Possible values are ‘TrueType’, ‘Type 1’, ‘BDF’, ‘PCF’, ‘Type 42’, ‘CID Type 1’, ‘CFF’, + /// ‘PFR’, and ‘Windows FNT’. + /// + /// Font format string. NULL in case of error. + public string GetX11FontFormat() + { + return Marshal.PtrToStringAnsi(FT.FT_Get_X11_Font_Format(Reference)); + } + + #endregion + + #region Gasp Table + + /// + /// Read the ‘gasp’ table from a TrueType or OpenType font file and return the entry corresponding to a given + /// character pixel size. + /// + /// The vertical character pixel size. + /// + /// Bit flags (see ), or if there is no ‘gasp’ table in the face. + /// + [CLSCompliant(false)] + public Gasp GetGasp(uint ppem) + { + return FT.FT_Get_Gasp(Reference, ppem); + } + + #endregion + + #region Quick retrieval of advance values + + /// + /// Retrieve the advance value of a given glyph outline in a . By default, the unhinted + /// advance is returned in font units. + /// + /// + /// This function may fail if you use and if the corresponding font + /// backend doesn't have a quick way to retrieve the advances. + /// + /// A scaled advance is returned in 16.16 format but isn't transformed by the affine transformation specified + /// by . + /// + /// The glyph index. + /// + /// A set of bit flags similar to those used when calling , used to determine what kind + /// of advances you need. + /// + /// + /// The advance value, in either font units or 16.16 format. + /// + /// If is set, this is the vertical advance corresponding to a vertical + /// layout. Otherwise, it is the horizontal advance in a horizontal layout. + /// + [CLSCompliant(false)] + public Fixed16Dot16 GetAdvance(uint glyphIndex, LoadFlags flags) + { + IntPtr padvance; + Error err = FT.FT_Get_Advance(Reference, glyphIndex, flags, out padvance); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return Fixed16Dot16.FromRawValue((int)padvance); + } + + /// + /// Retrieve the advance values of several glyph outlines in an + /// . By default, the unhinted advances are returned + /// in font units. + /// + /// + /// This function may fail if you use + /// and if the + /// corresponding font backend doesn't have a quick way to retrieve the + /// advances. + /// + /// Scaled advances are returned in 16.16 format but aren't transformed + /// by the affine transformation specified by + /// . + /// + /// The first glyph index. + /// The number of advance values you want to retrieve. + /// A set of bit flags similar to those used when calling . + /// The advances, in either font units or 16.16 format. This array must contain at least ‘count’ elements. + /// + /// If is set, these are the vertical advances corresponding to a vertical layout. Otherwise, they are the horizontal advances in a horizontal layout. + [CLSCompliant(false)] + public unsafe Fixed16Dot16[] GetAdvances(uint start, uint count, LoadFlags flags) + { + IntPtr advPtr; + Error err = FT.FT_Get_Advances(Reference, start, count, flags, out advPtr); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + //create a new array and copy the data from the pointer over + Fixed16Dot16[] advances = new Fixed16Dot16[count]; + IntPtr* ptr = (IntPtr*)advPtr; + + for (int i = 0; i < count; i++) + advances[i] = Fixed16Dot16.FromRawValue((int)ptr[i]); + + return advances; + } + + #endregion + + #region OpenType Validation + + /// + /// Validate various OpenType tables to assure that all offsets and indices are valid. The idea is that a + /// higher-level library which actually does the text layout can access those tables without error checking + /// (which can be quite time consuming). + /// + /// + /// This function only works with OpenType fonts, returning an error otherwise. + /// + /// After use, the application should deallocate the five tables with . A NULL value + /// indicates that the table either doesn't exist in the font, or the application hasn't asked for validation. + /// + /// A bit field which specifies the tables to be validated. + /// A pointer to the BASE table. + /// A pointer to the GDEF table. + /// A pointer to the GPOS table. + /// A pointer to the GSUB table. + /// A pointer to the JSTF table. + [CLSCompliant(false)] + public void OpenTypeValidate(OpenTypeValidationFlags flags, out IntPtr baseTable, out IntPtr gdefTable, out IntPtr gposTable, out IntPtr gsubTable, out IntPtr jstfTable) + { + Error err = FT.FT_OpenType_Validate(Reference, flags, out baseTable, out gdefTable, out gposTable, out gsubTable, out jstfTable); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Free the buffer allocated by OpenType validator. + /// + /// + /// This function must be used to free the buffer allocated by only. + /// + /// The pointer to the buffer that is allocated by . + public void OpenTypeFree(IntPtr table) + { + FT.FT_OpenType_Free(Reference, table); + } + + #endregion + + #region TrueTypeGX/AAT Validation + + /// + /// Validate various TrueTypeGX tables to assure that all offsets and indices are valid. The idea is that a + /// higher-level library which actually does the text layout can access those tables without error checking + /// (which can be quite time consuming). + /// + /// + /// This function only works with TrueTypeGX fonts, returning an error otherwise. + /// + /// After use, the application should deallocate the buffers pointed to by each ‘tables’ element, by calling + /// . A NULL value indicates that the table either doesn't exist in the font, the + /// application hasn't asked for validation, or the validator doesn't have the ability to validate the sfnt + /// table. + /// + /// A bit field which specifies the tables to be validated. + /// + /// The array where all validated sfnt tables are stored. The array itself must be allocated by a client. + /// + /// + /// The size of the ‘tables’ array. Normally, FT_VALIDATE_GX_LENGTH should be passed. + /// + [CLSCompliant(false)] + public void TrueTypeGXValidate(TrueTypeValidationFlags flags, byte[][] tables, uint tableLength) + { + FT.FT_TrueTypeGX_Validate(Reference, flags, tables, tableLength); + } + + /// + /// Free the buffer allocated by TrueTypeGX validator. + /// + /// + /// This function must be used to free the buffer allocated by only. + /// + /// The pointer to the buffer allocated by . + public void TrueTypeGXFree(IntPtr table) + { + FT.FT_TrueTypeGX_Free(Reference, table); + } + + /// + /// Validate classic (16-bit format) kern table to assure that the offsets and indices are valid. The idea is + /// that a higher-level library which actually does the text layout can access those tables without error + /// checking (which can be quite time consuming). + /// + /// The ‘kern’ table validator in deals with both the new 32-bit format and + /// the classic 16-bit format, while only supports the classic 16-bit format. + /// + /// + /// After use, the application should deallocate the buffers pointed to by ‘ckern_table’, by calling + /// . A NULL value indicates that the table doesn't exist in the font. + /// + /// A bit field which specifies the dialect to be validated. + /// A pointer to the kern table. + [CLSCompliant(false)] + public IntPtr ClassicKernValidate(ClassicKernValidationFlags flags) + { + IntPtr ckernRef; + FT.FT_ClassicKern_Validate(Reference, flags, out ckernRef); + return ckernRef; + } + + /// + /// Free the buffer allocated by classic Kern validator. + /// + /// + /// This function must be used to free the buffer allocated by only. + /// + /// + /// The pointer to the buffer that is allocated by . + /// + public void ClassicKernFree(IntPtr table) + { + FT.FT_ClassicKern_Free(Reference, table); + } + + #endregion + + /// + /// Disposes the Face. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + internal void AddChildSize(FTSize child) + { + childSizes.Add(child); + } + + internal void RemoveChildSize(FTSize child) + { + childSizes.Remove(child); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + foreach (FTSize s in childSizes) + s.Dispose(); + + childSizes.Clear(); + + FT.FT_Done_Face(base.Reference); + + // removes itself from the parent Library, with a check to prevent this from happening when Library is + // being disposed (Library disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (!parentLibrary.IsDisposed) + parentLibrary.RemoveChildFace(this); + + base.Reference = IntPtr.Zero; + rec = new FaceRec(); + + if (memoryFaceHandle.IsAllocated) + memoryFaceHandle.Free(); + + EventHandler handler = Disposed; + if (handler != null) + handler(this, EventArgs.Empty); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/FaceFlags.cs b/SharpFont/Source/SharpFontShared/FaceFlags.cs new file mode 100644 index 000000000..6d25d76f7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FaceFlags.cs @@ -0,0 +1,145 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit flags used in the ‘face_flags’ field of the structure. They inform client + /// applications of properties of the corresponding face. + /// + [Flags] + public enum FaceFlags : long + { + /// + /// No style flags. + /// + None = 0x0000, + + /// + /// Indicates that the face contains outline glyphs. This doesn't prevent bitmap strikes, i.e., a face can have + /// both this and and set. + /// + Scalable = 0x0001, + + /// + /// Indicates that the face contains bitmap strikes. See also and + /// . + /// + FixedSizes = 0x0002, + + /// + /// Indicates that the face contains fixed-width characters (like Courier, Lucido, MonoType, etc.). + /// + FixedWidth = 0x0004, + + /// + /// Indicates that the face uses the ‘sfnt’ storage scheme. For now, this means TrueType and OpenType. + /// + Sfnt = 0x0008, + + /// + /// Indicates that the face contains horizontal glyph metrics. This should be set for all common formats. + /// + Horizontal = 0x0010, + + /// + /// Indicates that the face contains vertical glyph metrics. This is only available in some formats, not all of + /// them. + /// + Vertical = 0x0020, + + /// + /// Indicates that the face contains kerning information. If set, the kerning distance can be retrieved through + /// the function . Otherwise the function always return the vector (0,0). Note + /// that FreeType doesn't handle kerning data from the ‘GPOS’ table (as present in some OpenType fonts). + /// + Kerning = 0x0040, + + /// + /// THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. + /// + [Obsolete("THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT.")] + FastGlyphs = 0x0080, + + /// + /// Indicates that the font contains multiple masters and is capable of interpolating between them. See the + /// multiple-masters specific API for details. + /// + MultipleMasters = 0x0100, + + /// + /// Indicates that the font contains glyph names that can be retrieved through + /// . Note that some TrueType fonts contain broken glyph name + /// tables. Use the function when needed. + /// + GlyphNames = 0x0200, + + /// + /// Used internally by FreeType to indicate that a face's stream was provided by the client application and + /// should not be destroyed when is called. Don't read or test this flag. + /// + ExternalStream = 0x0400, + + /// + /// Set if the font driver has a hinting machine of its own. For example, with TrueType fonts, it makes sense + /// to use data from the SFNT ‘gasp’ table only if the native TrueType hinting engine (with the bytecode + /// interpreter) is available and active. + /// + Hinter = 0x0800, + + /// + /// Set if the font is CID-keyed. In that case, the font is not accessed by glyph indices but by CID values. + /// For subsetted CID-keyed fonts this has the consequence that not all index values are a valid argument to + /// . Only the CID values for which corresponding glyphs in the subsetted font + /// exist make return successfully; in all other cases you get an + /// error. + /// + /// Note that CID-keyed fonts which are in an SFNT wrapper don't have this flag set since the glyphs are + /// accessed in the normal way (using contiguous indices); the ‘CID-ness’ isn't visible to the application. + /// + CidKeyed = 0x1000, + + /// + /// Set if the font is ‘tricky’, this is, it always needs the font format's native hinting engine to get a + /// reasonable result. A typical example is the Chinese font ‘mingli.ttf’ which uses TrueType bytecode + /// instructions to move and scale all of its subglyphs. + /// + /// It is not possible to autohint such fonts using ; it will also ignore + /// . You have to set both and + /// to really disable hinting; however, you probably never want this + /// except for demonstration purposes. + /// + /// Currently, there are about a dozen TrueType fonts in the list of tricky fonts; they are hard-coded in file + /// ‘ttobjs.c’. + /// + Tricky = 0x2000, + + /// + /// Set if the font has color glyph tables. To access color glyphs use . + /// + Color = 0x4000, + } +} diff --git a/SharpFont/Source/SharpFontShared/Fixed16Dot16.cs b/SharpFont/Source/SharpFontShared/Fixed16Dot16.cs new file mode 100644 index 000000000..f43e26849 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fixed16Dot16.cs @@ -0,0 +1,752 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// Represents a fixed-point decimal value with 16 bits of decimal precision. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Fixed16Dot16 : IEquatable, IComparable + { + #region Fields + + /// + /// The angle pi expressed in FT_Angle units. + /// + public static readonly Fixed16Dot16 AnglePI = new Fixed16Dot16(180); + + /// + /// The angle 2*pi expressed in FT_Angle units. + /// + public static readonly Fixed16Dot16 Angle2PI = new Fixed16Dot16(360); + + /// + /// The angle pi/2 expressed in FT_Angle units. + /// + public static readonly Fixed16Dot16 AnglePI2 = new Fixed16Dot16(90); + + /// + /// The angle pi/4 expressed in FT_Angle units. + /// + public static readonly Fixed16Dot16 AnglePI4 = new Fixed16Dot16(45); + + /// + /// The raw 16.16 integer. + /// + private int value; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// An integer value. + public Fixed16Dot16(int value) + { + this.value = value << 16; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed16Dot16(float value) + { + this.value = (int)(value * 65536); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed16Dot16(double value) + { + this.value = (int)(value * 65536); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed16Dot16(decimal value) + { + this.value = (int)(value * 65536); + } + + #endregion + + #region Properties + + /// + /// Gets the raw 16.16 integer. + /// + public int Value + { + get + { + return value; + } + } + + #endregion + + #region Methods + + #region Static + + /// + /// Creates a from an int containing a 16.16 value. + /// + /// A 16.16 value. + /// An instance of . + public static Fixed16Dot16 FromRawValue(int value) + { + Fixed16Dot16 f = new Fixed16Dot16(); + f.value = value; + return f; + } + + /// + /// Creates a new from a + /// + /// A value. + /// The equivalent value. + public static Fixed16Dot16 FromInt32(int value) + { + return new Fixed16Dot16(value); + } + + /// + /// Creates a new from . + /// + /// A floating-point value. + /// A fixed 16.16 value. + public static Fixed16Dot16 FromSingle(float value) + { + return new Fixed16Dot16(value); + } + + /// + /// Creates a new from a . + /// + /// A floating-point value. + /// A fixed 16.16 value. + public static Fixed16Dot16 FromDouble(double value) + { + return new Fixed16Dot16(value); + } + + /// + /// Creates a new from a . + /// + /// A floating-point value. + /// A fixed 16.16 value. + public static Fixed16Dot16 FromDecimal(decimal value) + { + return new Fixed16Dot16(value); + } + + /// + /// Adds two 16.16 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed16Dot16 Add(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Fixed16Dot16.FromRawValue(left.value + right.value); + } + + /// + /// Subtacts one 16.16 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed16Dot16 Subtract(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Fixed16Dot16.FromRawValue(left.value - right.value); + } + + /// + /// Multiplies two 16.16 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed16Dot16 Multiply(Fixed16Dot16 left, Fixed16Dot16 right) + { + long mul = (long)left.value * (long)right.value; + Fixed16Dot16 ans = new Fixed16Dot16(); + ans.value = (int)(mul >> 16); + return ans; + } + + /// + /// A very simple function used to perform the computation ‘(a*b)/0x10000’ with maximal accuracy. Most of the + /// time this is used to multiply a given value by a 16.16 fixed float factor. + /// + /// + /// NOTE: This is a native FreeType function. + /// + /// This function has been optimized for the case where the absolute value of ‘a’ is less than 2048, and ‘b’ is + /// a 16.16 scaling factor. As this happens mainly when scaling from notional units to fractional pixels in + /// FreeType, it resulted in noticeable speed improvements between versions 2.x and 1.x. + /// + /// As a conclusion, always try to place a 16.16 factor as the second argument of this function; this can make + /// a great difference. + /// + /// The first multiplier. + /// The second multiplier. Use a 16.16 factor here whenever possible (see note below). + /// The result of ‘(a*b)/0x10000’. + public static Fixed16Dot16 MultiplyFix(int a, Fixed16Dot16 b) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_MulFix((IntPtr)a, (IntPtr)b.Value)); + } + + /// + /// Divides one 16.16 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed16Dot16 Divide(Fixed16Dot16 left, Fixed16Dot16 right) + { + long div = ((long)left.Value << 16) / right.value; + Fixed16Dot16 ans = new Fixed16Dot16(); + ans.value = (int)div; + return ans; + } + + /// + /// A very simple function used to perform the computation ‘(a*0x10000)/b’ with maximal accuracy. Most of the + /// time, this is used to divide a given value by a 16.16 fixed float factor. + /// + /// + /// NOTE: This is a native FreeType function. + /// + /// The optimization for is simple: If (a << 16) fits in 32 bits, then the division + /// is computed directly. Otherwise, we use a specialized version of . + /// + /// The first multiplier. + /// The second multiplier. Use a 16.16 factor here whenever possible (see note below). + /// The result of ‘(a*0x10000)/b’. + public static Fixed16Dot16 DivideFix(int a, Fixed16Dot16 b) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_DivFix((IntPtr)a, (IntPtr)b.Value)); + } + + /// + /// A very simple function used to perform the computation ‘(a*b)/c’ with maximal accuracy (it uses a 64-bit + /// intermediate integer whenever necessary). + /// + /// This function isn't necessarily as fast as some processor specific operations, but is at least completely + /// portable. + /// + /// This is a native FreeType function. + /// The first multiplier. + /// The second multiplier. + /// The divisor. + /// + /// The result of ‘(a*b)/c’. This function never traps when trying to divide by zero; it simply returns + /// ‘MaxInt’ or ‘MinInt’ depending on the signs of ‘a’ and ‘b’. + /// + public static Fixed16Dot16 MultiplyDivide(Fixed16Dot16 a, Fixed16Dot16 b, Fixed16Dot16 c) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_MulDiv((IntPtr)a.Value, (IntPtr)b.Value, (IntPtr)c.Value)); + } + + /// + /// Return the arc-tangent corresponding to a given vector (x,y) in the 2d plane. + /// + /// This is a native FreeType function. + /// The horizontal vector coordinate. + /// The vertical vector coordinate. + /// The arc-tangent value (i.e. angle). + public static Fixed16Dot16 Atan2(Fixed16Dot16 x, Fixed16Dot16 y) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Atan2((IntPtr)x.Value, (IntPtr)y.Value)); + } + + /// + /// Return the difference between two angles. The result is always constrained to the [-PI..PI] interval. + /// + /// This is a native FreeType function. + /// First angle. + /// Second angle. + /// Constrained value of ‘value2-value1’. + public static Fixed16Dot16 AngleDiff(Fixed16Dot16 angle1, Fixed16Dot16 angle2) + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Angle_Diff((IntPtr)angle1.Value, (IntPtr)angle2.Value)); + } + + #endregion + + #region Operators + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed16Dot16(short value) + { + return new Fixed16Dot16(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed16Dot16(int value) + { + return new Fixed16Dot16(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed16Dot16(float value) + { + return new Fixed16Dot16(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed16Dot16(double value) + { + return new Fixed16Dot16(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed16Dot16(decimal value) + { + return new Fixed16Dot16(value); + } + + /// + /// Casts a to a . + /// + /// + /// This operation can result in a loss of data. + /// + /// A value. + /// The equivalent value. + public static explicit operator int(Fixed16Dot16 value) + { + return value.ToInt32(); + } + + /// + /// Casts a to a . + /// + /// + /// This operation can result in a loss of data. + /// + /// A value. + /// The equivalent value. + public static explicit operator float(Fixed16Dot16 value) + { + return value.ToSingle(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator double(Fixed16Dot16 value) + { + return value.ToDouble(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator decimal(Fixed16Dot16 value) + { + return value.ToDecimal(); + } + + /// + /// Adds two 16.16 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed16Dot16 operator +(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Add(left, right); + } + + /// + /// Subtacts one 16.16 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed16Dot16 operator -(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Subtract(left, right); + } + + /// + /// Multiplies two 16.16 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed16Dot16 operator *(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Multiply(left, right); + } + + /// + /// Divides one 16.16 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed16Dot16 operator /(Fixed16Dot16 left, Fixed16Dot16 right) + { + return Divide(left, right); + } + + /// + /// Compares two instances of for equality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are equal. + public static bool operator ==(Fixed16Dot16 left, Fixed16Dot16 right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are not equal. + public static bool operator !=(Fixed16Dot16 left, Fixed16Dot16 right) + { + return !(left == right); + } + + /// + /// Checks if the left operand is less than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than right. + public static bool operator <(Fixed16Dot16 left, Fixed16Dot16 right) + { + return left.CompareTo(right) < 0; + } + + /// + /// Checks if the left operand is less than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than or equal to right. + public static bool operator <=(Fixed16Dot16 left, Fixed16Dot16 right) + { + return left.CompareTo(right) <= 0; + } + + /// + /// Checks if the left operand is greater than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than right. + public static bool operator >(Fixed16Dot16 left, Fixed16Dot16 right) + { + return left.CompareTo(right) > 0; + } + + /// + /// Checks if the left operand is greater than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than or equal to right. + public static bool operator >=(Fixed16Dot16 left, Fixed16Dot16 right) + { + return left.CompareTo(right) >= 0; + } + + #endregion + + #region Instance + + /// + /// Removes the decimal part of the value. + /// + /// The truncated number. + public int Floor() + { + return value >> 16; + } + + /// + /// A very simple function used to compute the floor function of a 16.16 fixed number. + /// + /// This is a native FreeType function. + /// The result of ‘a & -0x10000’. + public Fixed16Dot16 FloorFix() + { + //TODO does the P/Invoke overhead make this slower than re-implementing in C#? Test it + return FromRawValue((int)FT.FT_FloorFix((IntPtr)this.Value)); + } + + /// + /// Rounds to the nearest whole number. + /// + /// The nearest whole number. + public int Round() + { + //add 2^15, rounds the integer part up if the decimal value is >= 0.5 + return (value + 32768) >> 16; + } + + /// + /// A very simple function used to round a 16.16 fixed number. + /// + /// This is a native FreeType function. + /// The result of ‘(a + 0x8000) & -0x10000’. + public Fixed16Dot16 RoundFix() + { + return FromRawValue((int)FT.FT_RoundFix((IntPtr)this.Value)); + } + + /// + /// Rounds up to the next whole number. + /// + /// The next whole number. + public int Ceiling() + { + //add 2^16 - 1, rounds the integer part up if there's any decimal value + return (value + 65535) >> 16; + } + + /// + /// A very simple function used to compute the ceiling function of a 16.16 fixed number. + /// + /// This is a native FreeType function. + /// The result of ‘(a + 0x10000 - 1) & -0x10000’. + public Fixed16Dot16 CeilingFix() + { + return FromRawValue((int)FT.FT_CeilFix((IntPtr)this.Value)); + } + + /// + /// Return the sinus of a given angle in fixed point format. + /// + /// + /// NOTE: This is a native FreeType function. + /// + /// If you need both the sinus and cosinus for a given angle, use the function . + /// + /// The sinus value. + public Fixed16Dot16 Sin() + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Sin((IntPtr)this.Value)); + } + + /// + /// Return the cosinus of a given angle in fixed point format. + /// + /// + /// NOTE: This is a native FreeType function. + /// + /// If you need both the sinus and cosinus for a given angle, use the function . + /// + /// The cosinus value. + public Fixed16Dot16 Cos() + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Cos((IntPtr)this.Value)); + } + + /// + /// Return the tangent of a given angle in fixed point format. + /// + /// This is a native FreeType function. + /// The tangent value. + public Fixed16Dot16 Tan() + { + return Fixed16Dot16.FromRawValue((int)FT.FT_Tan((IntPtr)this.Value)); + } + + /// + /// Converts the value to a . The value is floored. + /// + /// An integer value. + public int ToInt32() + { + return Floor(); + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public float ToSingle() + { + return value / 65536f; + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public double ToDouble() + { + return value / 65536d; + } + + /// + /// Converts the value to a . + /// + /// A decimal value. + public decimal ToDecimal() + { + return value / 65536m; + } + + /// + /// Compares this instance to another for equality. + /// + /// A . + /// A value indicating whether the two instances are equal. + public bool Equals(Fixed16Dot16 other) + { + return value == other.value; + } + + /// + /// Compares this instnace with another and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other . + /// + /// A . + /// A value indicating the relative order of the instances. + public int CompareTo(Fixed16Dot16 other) + { + return value.CompareTo(other.value); + } + + #endregion + + #region Overrides + + /// + /// Returns a string that represents the current object. + /// + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(IFormatProvider provider) + { + return ToDecimal().ToString(provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// A string that represents the current object. + public string ToString(string format) + { + return ToDecimal().ToString(format); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(string format, IFormatProvider provider) + { + return ToDecimal().ToString(format, provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + public override string ToString() + { + return ToDecimal().ToString(); + } + + /// + /// Calculates a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return value.GetHashCode(); + } + + /// + /// Determines whether the specified object isequal to the current object. + /// + /// The object to compare with the current object. + /// A value indicating equality between the two objects. + public override bool Equals(object obj) + { + if (obj is Fixed16Dot16) + return this.Equals((Fixed16Dot16)obj); + else if (obj is int) + return value == ((Fixed16Dot16)obj).value; + else + return false; + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Fixed26Dot6.cs b/SharpFont/Source/SharpFontShared/Fixed26Dot6.cs new file mode 100644 index 000000000..a83e21bfa --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fixed26Dot6.cs @@ -0,0 +1,579 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015-2016 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// Represents a fixed-point decimal value with 6 bits of decimal precision. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Fixed26Dot6 : IEquatable, IComparable + { + #region Fields + + /// + /// The raw 26.6 integer. + /// + private int value; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// An integer value. + public Fixed26Dot6(int value) + { + this.value = value << 6; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed26Dot6(float value) + { + this.value = (int)(value * 64); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed26Dot6(double value) + { + this.value = (int)(value * 64); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed26Dot6(decimal value) + { + this.value = (int)(value * 64); + } + + #endregion + + #region Properties + + /// + /// Gets the raw 26.6 integer. + /// + public int Value + { + get + { + return value; + } + } + + #endregion + + #region Methods + + #region Static + + /// + /// Creates a from an int containing a 26.6 value. + /// + /// A 26.6 value. + /// An instance of . + public static Fixed26Dot6 FromRawValue(int value) + { + Fixed26Dot6 f = new Fixed26Dot6(); + f.value = value; + return f; + } + + /// + /// Creates a new from a + /// + /// A value. + /// The equivalent value. + public static Fixed26Dot6 FromInt32(int value) + { + return new Fixed26Dot6(value); + } + + /// + /// Creates a new from . + /// + /// A floating-point value. + /// A fixed 26.6 value. + public static Fixed26Dot6 FromSingle(float value) + { + return new Fixed26Dot6(value); + } + + /// + /// Creates a new from a . + /// + /// A floating-point value. + /// A fixed 26.6 value. + public static Fixed26Dot6 FromDouble(double value) + { + return new Fixed26Dot6(value); + } + + /// + /// Creates a new from a . + /// + /// A floating-point value. + /// A fixed 26.6 value. + public static Fixed26Dot6 FromDecimal(decimal value) + { + return new Fixed26Dot6(value); + } + + /// + /// Adds two 26.6 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed26Dot6 Add(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Fixed26Dot6.FromRawValue(left.value + right.value); + } + + /// + /// Subtacts one 26.6 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed26Dot6 Subtract(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Fixed26Dot6.FromRawValue(left.value - right.value); + } + + /// + /// Multiplies two 26.6 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed26Dot6 Multiply(Fixed26Dot6 left, Fixed26Dot6 right) + { + long mul = (long)left.value * (long)right.value; + Fixed26Dot6 ans = new Fixed26Dot6(); + ans.value = (int)(mul >> 6); + return ans; + } + + /// + /// Divides one 26.6 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed26Dot6 Divide(Fixed26Dot6 left, Fixed26Dot6 right) + { + long div = ((long)left.Value << 6) / right.value; + Fixed26Dot6 ans = new Fixed26Dot6(); + ans.value = (int)div; + return ans; + } + + #endregion + + #region Operators + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed26Dot6(short value) + { + return new Fixed26Dot6(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed26Dot6(int value) + { + return new Fixed26Dot6(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed26Dot6(float value) + { + return new Fixed26Dot6(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed26Dot6(double value) + { + return new Fixed26Dot6(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator Fixed26Dot6(decimal value) + { + return new Fixed26Dot6(value); + } + + /// + /// Casts a to a . + /// + /// + /// This operation can result in a loss of data. + /// + /// A value. + /// The equivalent value. + public static explicit operator int(Fixed26Dot6 value) + { + return value.ToInt32(); + } + + /// + /// Casts a to a . + /// + /// + /// This operation can result in a loss of data. + /// + /// A value. + /// The equivalent value. + public static explicit operator float(Fixed26Dot6 value) + { + return value.ToSingle(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator double(Fixed26Dot6 value) + { + return value.ToDouble(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator decimal(Fixed26Dot6 value) + { + return value.ToDecimal(); + } + + /// + /// Adds two 26.6 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed26Dot6 operator +(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Add(left, right); + } + + /// + /// Subtacts one 26.6 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed26Dot6 operator -(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Subtract(left, right); + } + + /// + /// Multiplies two 26.6 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed26Dot6 operator *(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Multiply(left, right); + } + + /// + /// Divides one 26.6 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed26Dot6 operator /(Fixed26Dot6 left, Fixed26Dot6 right) + { + return Divide(left, right); + } + + /// + /// Compares two instances of for equality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are equal. + public static bool operator ==(Fixed26Dot6 left, Fixed26Dot6 right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are not equal. + public static bool operator !=(Fixed26Dot6 left, Fixed26Dot6 right) + { + return !(left == right); + } + + /// + /// Checks if the left operand is less than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than right. + public static bool operator <(Fixed26Dot6 left, Fixed26Dot6 right) + { + return left.CompareTo(right) < 0; + } + + /// + /// Checks if the left operand is less than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than or equal to right. + public static bool operator <=(Fixed26Dot6 left, Fixed26Dot6 right) + { + return left.CompareTo(right) <= 0; + } + + /// + /// Checks if the left operand is greater than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than right. + public static bool operator >(Fixed26Dot6 left, Fixed26Dot6 right) + { + return left.CompareTo(right) > 0; + } + + /// + /// Checks if the left operand is greater than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than or equal to right. + public static bool operator >=(Fixed26Dot6 left, Fixed26Dot6 right) + { + return left.CompareTo(right) >= 0; + } + + #endregion + + #region Instance + + /// + /// Removes the decimal part of the value. + /// + /// The truncated number. + public int Floor() + { + return value >> 6; + } + + /// + /// Rounds to the nearest whole number. + /// + /// The nearest whole number. + public int Round() + { + //add 2^5, rounds the integer part up if the decimal value is >= 0.5 + return (value + 32) >> 6; + } + + /// + /// Rounds up to the next whole number. + /// + /// The next whole number. + public int Ceiling() + { + //add 2^6 - 1, rounds the integer part up if there's any decimal value + return (value + 63) >> 6; + } + + /// + /// Converts the value to a . The value is floored. + /// + /// An integer value. + public int ToInt32() + { + return Floor(); + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public float ToSingle() + { + return value / 64f; + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public double ToDouble() + { + return value / 64d; + } + + /// + /// Converts the value to a . + /// + /// A decimal value. + public decimal ToDecimal() + { + return value / 64m; + } + + /// + /// Compares this instance to another for equality. + /// + /// A . + /// A value indicating whether the two instances are equal. + public bool Equals(Fixed26Dot6 other) + { + return value == other.value; + } + + /// + /// Compares this instnace with another and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other . + /// + /// A . + /// A value indicating the relative order of the instances. + public int CompareTo(Fixed26Dot6 other) + { + return value.CompareTo(other.value); + } + + #endregion + + #region Overrides + + /// + /// Returns a string that represents the current object. + /// + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(IFormatProvider provider) + { + return ToDecimal().ToString(provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// A string that represents the current object. + public string ToString(string format) + { + return ToDecimal().ToString(format); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(string format, IFormatProvider provider) + { + return ToDecimal().ToString(format, provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + public override string ToString() + { + return ToDecimal().ToString(); + } + + /// + /// Calculates a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return value.GetHashCode(); + } + + /// + /// Determines whether the specified object isequal to the current object. + /// + /// The object to compare with the current object. + /// A value indicating equality between the two objects. + public override bool Equals(object obj) + { + if (obj is Fixed26Dot6) + return this.Equals((Fixed26Dot6)obj); + else if (obj is int) + return value == ((Fixed26Dot6)obj).value; + else + return false; + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Fixed2Dot14.cs b/SharpFont/Source/SharpFontShared/Fixed2Dot14.cs new file mode 100644 index 000000000..75460763f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fixed2Dot14.cs @@ -0,0 +1,546 @@ +#region MIT License +/*Copyright (c) 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// Represents a fixed-point decimal value with 14 bits of decimal precision. + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Fixed2Dot14 : IEquatable, IComparable + { + #region Fields + + /// + /// The raw 2.14 short. + /// + private short value; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the struct. + /// + /// An integer value. + public Fixed2Dot14(short value) + { + this.value = (short)(value << 14); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed2Dot14(float value) + { + this.value = (short)(value * 16384); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed2Dot14(double value) + { + this.value = (short)(value * 16384); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A floating point value. + public Fixed2Dot14(decimal value) + { + this.value = (short)(value * 16384); + } + + #endregion + + #region Properties + + /// + /// Gets the raw 2.14 integer. + /// + public int Value + { + get + { + return value; + } + } + + #endregion + + #region Methods + + #region Static + + /// + /// Creates a from an int containing a 2.14 value. + /// + /// A 2.14 value. + /// An instance of . + public static Fixed2Dot14 FromRawValue(short value) + { + Fixed2Dot14 f = new Fixed2Dot14(); + f.value = value; + return f; + } + + /// + /// Creates a new from a + /// + /// A value. + /// The equivalent value. + public static Fixed2Dot14 FromInt16(short value) + { + return new Fixed2Dot14(value); + } + + /// + /// Creates a new from . + /// + /// A floating-point value. + /// A fixed 2.14 value. + public static Fixed2Dot14 FromSingle(float value) + { + return new Fixed2Dot14(value); + } + + /// + /// Creates a new from . + /// + /// A floating-point value. + /// A fixed 2.14 value. + public static Fixed2Dot14 FromDouble(double value) + { + return new Fixed2Dot14(value); + } + + /// + /// Creates a new from . + /// + /// A floating-point value. + /// A fixed 2.14 value. + public static Fixed2Dot14 FromDecimal(decimal value) + { + return new Fixed2Dot14(value); + } + + /// + /// Adds two 2.14 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed2Dot14 Add(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Fixed2Dot14.FromRawValue((short)(left.value + right.value)); + } + + /// + /// Subtacts one 2.14 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed2Dot14 Subtract(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Fixed2Dot14.FromRawValue((short)(left.value - right.value)); + } + + /// + /// Multiplies two 2.14 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed2Dot14 Multiply(Fixed2Dot14 left, Fixed2Dot14 right) + { + int mul = (int)left.value * (int)right.value; + Fixed2Dot14 ans; + ans.value = (short)(mul >> 14); + return ans; + } + + /// + /// Divides one 2.14 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed2Dot14 Divide(Fixed2Dot14 left, Fixed2Dot14 right) + { + int div = ((int)left.Value << 6) / right.value; + Fixed2Dot14 ans; + ans.value = (short)div; + return ans; + } + + #endregion + + #region Operators + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed2Dot14(float value) + { + return new Fixed2Dot14(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed2Dot14(double value) + { + return new Fixed2Dot14(value); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static explicit operator Fixed2Dot14(decimal value) + { + return new Fixed2Dot14(value); + } + + /// + /// Casts a to a . + /// + /// + /// This operation can result in a loss of data. + /// + /// A value. + /// The equivalent value. + public static explicit operator float(Fixed2Dot14 value) + { + return value.ToSingle(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator double(Fixed2Dot14 value) + { + return value.ToDouble(); + } + + /// + /// Casts a to a . + /// + /// A value. + /// The equivalent value. + public static implicit operator decimal(Fixed2Dot14 value) + { + return value.ToDecimal(); + } + + /// + /// Adds two 2.14 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the addition. + public static Fixed2Dot14 operator +(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Add(left, right); + } + + /// + /// Subtacts one 2.14 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the subtraction. + public static Fixed2Dot14 operator -(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Subtract(left, right); + } + + /// + /// Multiplies two 2.14 values together. + /// + /// The left operand. + /// The right operand. + /// The result of the multiplication. + public static Fixed2Dot14 operator *(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Multiply(left, right); + } + + /// + /// Divides one 2.14 values from another. + /// + /// The left operand. + /// The right operand. + /// The result of the division. + public static Fixed2Dot14 operator /(Fixed2Dot14 left, Fixed2Dot14 right) + { + return Divide(left, right); + } + + /// + /// Compares two instances of for equality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are equal. + public static bool operator ==(Fixed2Dot14 left, Fixed2Dot14 right) + { + return left.Equals(right); + } + + /// + /// Compares two instances of for inequality. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether the two instances are not equal. + public static bool operator !=(Fixed2Dot14 left, Fixed2Dot14 right) + { + return !(left == right); + } + + /// + /// Checks if the left operand is less than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than right. + public static bool operator <(Fixed2Dot14 left, Fixed2Dot14 right) + { + return left.CompareTo(right) < 0; + } + + /// + /// Checks if the left operand is less than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is less than or equal to right. + public static bool operator <=(Fixed2Dot14 left, Fixed2Dot14 right) + { + return left.CompareTo(right) <= 0; + } + + /// + /// Checks if the left operand is greater than the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than right. + public static bool operator >(Fixed2Dot14 left, Fixed2Dot14 right) + { + return left.CompareTo(right) > 0; + } + + /// + /// Checks if the left operand is greater than or equal to the right operand. + /// + /// The left operand. + /// The right operand. + /// A value indicating whether left is greater than or equal to right. + public static bool operator >=(Fixed2Dot14 left, Fixed2Dot14 right) + { + return left.CompareTo(right) >= 0; + } + + #endregion + + #region Instance + + /// + /// Removes the decimal part of the value. + /// + /// The truncated number. + public short Floor() + { + return (short)(value >> 14); + } + + /// + /// Rounds to the nearest whole number. + /// + /// The nearest whole number. + public short Round() + { + //add 2^13, rounds the integer part up if the decimal value is >= 0.5 + return (short)((value + 8192) >> 14); + } + + /// + /// Rounds up to the next whole number. + /// + /// The next whole number. + public short Ceiling() + { + //add 2^14 - 1, rounds the integer part up if there's any decimal value + return (short)((value + 16383) >> 14); + } + + /// + /// Converts the value to a . The value is floored. + /// + /// An integer value. + public short ToInt16() + { + return Floor(); + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public float ToSingle() + { + return value / 16384f; + } + + /// + /// Converts the value to a . + /// + /// A floating-point value. + public double ToDouble() + { + return value / 16384d; + } + + /// + /// Converts the value to a . + /// + /// A decimal value. + public decimal ToDecimal() + { + return value / 16384m; + } + + /// + /// Compares this instance to another for equality. + /// + /// A . + /// A value indicating whether the two instances are equal. + public bool Equals(Fixed2Dot14 other) + { + return value == other.value; + } + + /// + /// Compares this instnace with another and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other . + /// + /// A . + /// A value indicating the relative order of the instances. + public int CompareTo(Fixed2Dot14 other) + { + return value.CompareTo(other.value); + } + + #endregion + + #region Overrides + + /// + /// Returns a string that represents the current object. + /// + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(IFormatProvider provider) + { + return ToDecimal().ToString(provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// A string that represents the current object. + public string ToString(string format) + { + return ToDecimal().ToString(format); + } + + /// + /// Returns a string that represents the current object. + /// + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// A string that represents the current object. + public string ToString(string format, IFormatProvider provider) + { + return ToDecimal().ToString(format, provider); + } + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + public override string ToString() + { + return ToDecimal().ToString(); + } + + /// + /// Calculates a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return value.GetHashCode(); + } + + /// + /// Determines whether the specified object isequal to the current object. + /// + /// The object to compare with the current object. + /// A value indicating equality between the two objects. + public override bool Equals(object obj) + { + if (obj is Fixed2Dot14) + return this.Equals((Fixed2Dot14)obj); + else if (obj is int) + return value == ((Fixed2Dot14)obj).value; + else + return false; + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Fnt/Header.cs b/SharpFont/Source/SharpFontShared/Fnt/Header.cs new file mode 100644 index 000000000..2f6f67a41 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fnt/Header.cs @@ -0,0 +1,594 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Linq; + +using SharpFont.Fnt.Internal; + +namespace SharpFont.Fnt +{ + /// + /// Describes the general appearance of the font. + /// + public enum Family + { + /// + /// Don't care or don't know which family. + /// + DontCare = 0, + + /// + /// The font has a Roman appearance. + /// + Roman = 1, + + /// + /// The font has a Swiss appearance. + /// + Swiss = 2, + + /// + /// The font has a Modern appearance. + /// + Modern = 3, + + /// + /// The font has a script-like appearance. + /// + Script = 4, + + /// + /// The font is decorative. + /// + Decorative = 5 + } + + /// + /// Provides flags for font proportions and color. + /// + [Flags] + [CLSCompliant(false)] + public enum Flags : ushort + { + /// + /// Font is fixed. + /// + Fixed = 1 << 0, + + /// + /// Font is proportional. + /// + Proportional = 1 << 1, + + /// + /// Font is ABC fixed. + /// + AbcFixed = 1 << 2, + + /// + /// Font is ABC proportional. + /// + AbcProportional = 1 << 3, + + /// + /// Font is 2-bit color. + /// + Color1 = 1 << 4, + + /// + /// Font is 4-bit color. + /// + Color16 = 1 << 5, + + /// + /// Font is 8-bit color. + /// + Color256 = 1 << 6, + + /// + /// Font is RGB color. + /// + RgbColor = 1 << 7 + } + + /// + /// Windows FNT Header info. + /// + public class Header + { + #region Fields + + private IntPtr reference; + private HeaderRec rec; + + #endregion + + #region Constructors + + internal Header(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the version format of the file (e.g. 0x0200). + /// + [CLSCompliant(false)] + public ushort Version + { + get + { + return rec.version; + } + } + + /// + /// Gets the size of the file in bytes. + /// + [CLSCompliant(false)] + public uint FileSize + { + get + { + return (uint)rec.file_size; + } + } + + /// + /// Gets the copyright text. + /// Limited to 60 bytes. + /// + public byte[] Copyright + { + get + { + return rec.copyright; + } + } + + /// + /// Gets the filetype (vector or bitmap). This is exclusively for GDI use. + /// + [CLSCompliant(false)] + public ushort FileType + { + get + { + return rec.file_type; + } + } + + /// + /// Gets the nominal point size determined by the designer at which the font looks + /// best. + /// + [CLSCompliant(false)] + public ushort NominalPointSize + { + get + { + return rec.nominal_point_size; + } + } + + /// + /// Gets the nominal vertical resolution in dots per inch. + /// + [CLSCompliant(false)] + public ushort VerticalResolution + { + get + { + return rec.vertical_resolution; + } + } + + /// + /// Gets the nominal horizontal resolution in dots per inch. + /// + [CLSCompliant(false)] + public ushort HorizontalResolution + { + get + { + return rec.horizontal_resolution; + } + } + + /// + /// Gets the height of the font's ascent from the baseline. + /// + [CLSCompliant(false)] + public ushort Ascent + { + get + { + return rec.ascent; + } + } + + /// + /// Gets the amount of leading inside the bounds of . + /// + [CLSCompliant(false)] + public ushort InternalLeading + { + get + { + return rec.internal_leading; + } + } + + /// + /// Gets the amount of leading the designer recommends to be added between + /// rows. + /// + [CLSCompliant(false)] + public ushort ExternalLeading + { + get + { + return rec.external_leading; + } + } + + /// + /// Gets whether the font is italic. + /// + public bool Italic + { + get + { + return (0x01 & rec.italic) == 0x01; + } + } + + /// + /// Ges whether the font includes underlining. + /// + public bool Underline + { + get + { + return (0x01 & rec.underline) == 0x01; + } + } + + /// + /// Ges whether the font includes strikeout. + /// + public bool Strikeout + { + get + { + return (0x01 & rec.strike_out) == 0x01; + } + } + + /// + /// Gets the weight of characters on a scale of 1 to 1000, with + /// 400 being regular weight. + /// + [CLSCompliant(false)] + public ushort Weight + { + get + { + return rec.weight; + } + } + + /// + /// Gets the character set specified by the font. + /// + public byte Charset + { + get + { + return rec.charset; + } + } + + /// + /// Gets the width of the vector grid (vector fonts). For raster fonts, + /// a zero value indicates that characters have variables widths, + /// otherwise, the value is the width of the bitmap for all characters. + /// + [CLSCompliant(false)] + public ushort PixelWidth + { + get + { + return rec.pixel_width; + } + } + + /// + /// Gets the height of the vector grid (vector fonts) or the height + /// of the bitmap for all characters (raster fonts). + /// + [CLSCompliant(false)] + public ushort PixelHeight + { + get + { + return rec.pixel_height; + } + } + + /// + /// Gets whether the font is variable pitch. + /// + public byte PitchAndFamily + { + get + { + return rec.pitch_and_family; + } + } + + /// + /// Gets the width of characters in the font, based on the width of 'X'. + /// + [CLSCompliant(false)] + public ushort AverageWidth + { + get + { + return rec.avg_width; + } + } + + /// + /// Gets the maximum width of all characters in the font. + /// + [CLSCompliant(false)] + public ushort MaximumWidth + { + get + { + return rec.max_width; + } + } + + /// + /// Gets the first character code specified in the font. + /// + public byte FirstChar + { + get + { + return rec.first_char; + } + } + + /// + /// Gets the last character code specified in the font. + /// + public byte LastChar + { + get + { + return rec.last_char; + } + } + + /// + /// Gets the character to substitute when a character is needed that + /// isn't defined in the font. + /// + public byte DefaultChar + { + get + { + return rec.default_char; + } + } + + /// + /// Gets the character that defines word breaks, for purposes of word + /// wrapping and word spacing justification. This value is relative to + /// the , so the character code is this value + /// minus . + /// + public byte BreakChar + { + get + { + return rec.break_char; + } + } + + /// + /// Gets the number of bytes in each row of the bitmap (raster fonts). + /// + [CLSCompliant(false)] + public ushort BytesPerRow + { + get + { + return rec.bytes_per_row; + } + } + + /// + /// Gets the offset in the file, in bytes, to the string that gives the device name. + /// The value is 0 for generic fonts. + /// + [CLSCompliant(false)] + public uint DeviceOffset + { + get + { + return (uint)rec.device_offset; + } + } + + /// + /// Gets the offset in the file, in bytes, to the string that gives the face name + /// (null-terminated). + /// + [CLSCompliant(false)] + public uint FaceNameOffset + { + get + { + return (uint)rec.face_name_offset; + } + } + + /// + /// Gets the absolute machine address of the bitmap, + /// which is set by GDI at load time. + /// + [CLSCompliant(false)] + public uint BitsPointer + { + get + { + return (uint)rec.bits_pointer; + } + } + + /// + /// Gets the offset in the file, in bytes, to the beginning of the character data + /// (raster or vector). + /// + [CLSCompliant(false)] + public uint BitsOffset + { + get + { + return (uint)rec.bits_offset; + } + } + + /// + /// Reservied. + /// + public byte Reserved + { + get + { + return rec.reserved; + } + } + + /// + /// Gets that describe font proportion and color. + /// + [CLSCompliant(false)] + public Flags Flags + { + get + { + return (Flags)rec.flags; + } + } + + /// + /// ASpace has not been used since before Windows 3.0. + /// Set it to 0 for compatibility. + /// + [CLSCompliant(false)] + public ushort ASpace + { + get + { + return rec.A_space; + } + } + + /// + /// BSpace has not been used since before Windows 3.0. + /// Set it to 0 for compatibility. + /// + [CLSCompliant(false)] + public ushort BSpace + { + get + { + return rec.B_space; + } + } + + /// + /// CSpace has not been used since before Windows 3.0. + /// Set it to 0 for compatibility. + /// + [CLSCompliant(false)] + public ushort CSpace + { + get + { + return rec.C_space; + } + } + + /// + /// Gets the offset of the color table. + /// + [CLSCompliant(false)] + public ushort ColorTableOffset + { + get + { + return rec.color_table_offset; + } + } + + /// + /// This field is reserved. + /// + [CLSCompliant(false)] + public uint[] Reserved1 + { + get + { + return rec.reserved1.Select(x => (uint) x).ToArray(); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Fnt/Internal/HeaderRec.cs b/SharpFont/Source/SharpFontShared/Fnt/Internal/HeaderRec.cs new file mode 100644 index 000000000..7ea86c587 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fnt/Internal/HeaderRec.cs @@ -0,0 +1,77 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Fnt.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct HeaderRec + { + internal ushort version; + internal FT_ULong file_size; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 60)] + internal byte[] copyright; + internal ushort file_type; + internal ushort nominal_point_size; + internal ushort vertical_resolution; + internal ushort horizontal_resolution; + internal ushort ascent; + internal ushort internal_leading; + internal ushort external_leading; + internal byte italic; + internal byte underline; + internal byte strike_out; + internal ushort weight; + internal byte charset; + internal ushort pixel_width; + internal ushort pixel_height; + internal byte pitch_and_family; + internal ushort avg_width; + internal ushort max_width; + internal byte first_char; + internal byte last_char; + internal byte default_char; + internal byte break_char; + internal ushort bytes_per_row; + internal FT_ULong device_offset; + internal FT_ULong face_name_offset; + internal FT_ULong bits_pointer; + internal FT_ULong bits_offset; + internal byte reserved; + internal FT_ULong flags; + internal ushort A_space; + internal ushort B_space; + internal ushort C_space; + internal ushort color_table_offset; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + internal FT_ULong[] reserved1; + } +} diff --git a/SharpFont/Source/SharpFontShared/Fnt/WinFntID.cs b/SharpFont/Source/SharpFontShared/Fnt/WinFntID.cs new file mode 100644 index 000000000..c26c6693f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Fnt/WinFntID.cs @@ -0,0 +1,148 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.Fnt +{ + /// + /// A list of valid values for the ‘charset’ byte in . Exact mapping tables for the various + /// cpXXXX encodings (except for cp1361) can be found at in the + /// MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is roughly a superset of + /// MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT. + /// + public enum WinFntId : byte + { + /// + /// ANSI encoding. A superset of ISO 8859-1. + /// + CP1252 = 0, + + /// + /// This is used for font enumeration and font creation as a ‘don't care’ value. Valid font files don't contain + /// this value. When querying for information about the character set of the font that is currently selected + /// into a specified device context, this return value (of the related Windows API) simply denotes failure. + /// + Default = 1, + + /// + /// There is no known mapping table available. + /// + Symbol = 2, + + /// + /// Mac Roman encoding. + /// + Mac = 77, + + /// + /// A superset of Japanese Shift-JIS (with minor deviations). + /// + CP932 = 128, + + /// + /// A superset of Korean Hangul KS C 5601-1987 (with different ordering and minor deviations). + /// + CP949 = 129, + + /// + /// Korean (Johab). + /// + CP1361 = 130, + + /// + /// A superset of simplified Chinese GB 2312-1980 (with different ordering and minor deviations). + /// + CP936 = 134, + + /// + /// A superset of traditional Chinese Big 5 ETen (with different ordering and minor deviations). + /// + CP950 = 136, + + /// + /// A superset of Greek ISO 8859-7 (with minor modifications). + /// + CP1253 = 161, + + /// + /// A superset of Turkish ISO 8859-9. + /// + CP1254 = 162, + + /// + /// For Vietnamese. This encoding doesn't cover all necessary characters. + /// + CP1258 = 163, + + /// + /// A superset of Hebrew ISO 8859-8 (with some modifications). + /// + CP1255 = 177, + + /// + /// A superset of Arabic ISO 8859-6 (with different ordering). + /// + CP1256 = 178, + + /// + /// A superset of Baltic ISO 8859-13 (with some deviations). + /// + CP1257 = 186, + + /// + /// A superset of Russian ISO 8859-5 (with different ordering). + /// + CP1251 = 204, + + /// + /// A superset of Thai TIS 620 and ISO 8859-11. + /// + CP874 = 222, + + /// + /// A superset of East European ISO 8859-2 (with slightly different ordering). + /// + CP1250 = 238, + + /// + /// From Michael Pöttgen <michael@poettgen.de>: + /// The ‘Windows Font Mapping’ article says that is used for the charset of vector + /// fonts, like ‘modern.fon’, ‘roman.fon’, and ‘script.fon’ on Windows. + /// + /// The ‘CreateFont’ documentation says: The value specifies a character set that is + /// operating-system dependent. + /// + /// The ‘IFIMETRICS’ documentation from the ‘Windows Driver Development Kit’ says: This font supports an + /// OEM-specific character set. The OEM character set is system dependent. + /// + /// In general OEM, as opposed to ANSI (i.e., cp1252), denotes the second default codepage that most + /// international versions of Windows have. It is one of the OEM codepages from + /// , and is used for the ‘DOS boxes’, to + /// support legacy applications. A German Windows version for example usually uses ANSI codepage 1252 and OEM + /// codepage 850. + /// + Oem = 255 + } +} diff --git a/SharpFont/Source/SharpFontShared/FreeTypeException.cs b/SharpFont/Source/SharpFontShared/FreeTypeException.cs new file mode 100644 index 000000000..ea10a4a93 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/FreeTypeException.cs @@ -0,0 +1,153 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An exception that gets thrown when FreeType returns an error code. + /// + public class FreeTypeException : Exception + { + private Error error; + + /// + /// Initializes a new instance of the class. + /// + /// The error returned by FreeType. + public FreeTypeException(Error error) + : base("FreeType error: " + GetErrorMessage(error)) + { + this.error = error; + } + + /// + /// Gets the FreeType error code that caused the exception. + /// + public Error Error + { + get + { + return this.error; + } + } + + private static string GetErrorMessage(Error err) + { + switch (err) + { + case Error.Ok: return "No error."; + case Error.CannotOpenResource: return "Cannot open resource."; + case Error.UnknownFileFormat: return "Unknown file format."; + case Error.InvalidFileFormat: return "Broken file."; + case Error.InvalidVersion: return "Invalid FreeType version."; + case Error.LowerModuleVersion: return "Module version is too low."; + case Error.InvalidArgument: return "Invalid argument."; + case Error.UnimplementedFeature: return "Unimplemented feature."; + case Error.InvalidTable: return "Broken table."; + case Error.InvalidOffset: return "Broken offset within table."; + case Error.ArrayTooLarge: return "Array allocation size too large."; + case Error.InvalidGlyphIndex: return "Invalid glyph index."; + case Error.InvalidCharacterCode: return "Invalid character code."; + case Error.InvalidGlyphFormat: return "Unsupported glyph image format."; + case Error.CannotRenderGlyph: return "Cannot render this glyph format."; + case Error.InvalidOutline: return "Invalid outline."; + case Error.InvalidComposite: return "Invalid composite glyph."; + case Error.TooManyHints: return "Too many hints."; + case Error.InvalidPixelSize: return "Invalid pixel size."; + case Error.InvalidHandle: return "Invalid object handle."; + case Error.InvalidLibraryHandle: return "Invalid library handle."; + case Error.InvalidDriverHandle: return "Invalid module handle."; + case Error.InvalidFaceHandle: return "Invalid face handle."; + case Error.InvalidSizeHandle: return "Invalid size handle."; + case Error.InvalidSlotHandle: return "Invalid glyph slot handle."; + case Error.InvalidCharMapHandle: return "Invalid charmap handle."; + case Error.InvalidCacheHandle: return "Invalid cache manager handle."; + case Error.InvalidStreamHandle: return "Invalid stream handle."; + case Error.TooManyDrivers: return "Too many modules."; + case Error.TooManyExtensions: return "Too many extensions."; + case Error.OutOfMemory: return "Out of memory."; + case Error.UnlistedObject: return "Unlisted object."; + case Error.CannotOpenStream: return "Cannot open stream."; + case Error.InvalidStreamSeek: return "Invalid stream seek."; + case Error.InvalidStreamSkip: return "Invalid stream skip."; + case Error.InvalidStreamRead: return "Invalid stream read."; + case Error.InvalidStreamOperation: return "Invalid stream operation."; + case Error.InvalidFrameOperation: return "Invalid frame operation."; + case Error.NestedFrameAccess: return "Nested frame access."; + case Error.InvalidFrameRead: return "Invalid frame read."; + case Error.RasterUninitialized: return "Raster uninitialized."; + case Error.RasterCorrupted: return "Raster corrupted."; + case Error.RasterOverflow: return "Raster overflow."; + case Error.RasterNegativeHeight: return "Negative height while rastering."; + case Error.TooManyCaches: return "Too many registered caches."; + case Error.InvalidOpCode: return "Invalid opcode."; + case Error.TooFewArguments: return "Too few arguments."; + case Error.StackOverflow: return "Stack overflow."; + case Error.CodeOverflow: return "Code overflow."; + case Error.BadArgument: return "Bad argument."; + case Error.DivideByZero: return "Division by zero."; + case Error.InvalidReference: return "Invalid reference."; + case Error.DebugOpCode: return "Found debug opcode."; + case Error.EndfInExecStream: return "Found ENDF opcode in execution stream."; + case Error.NestedDefs: return "Nested DEFS."; + case Error.InvalidCodeRange: return "Invalid code range."; + case Error.ExecutionTooLong: return "Execution context too long."; + case Error.TooManyFunctionDefs: return "Too many function definitions."; + case Error.TooManyInstructionDefs: return "Too many instruction definitions."; + case Error.TableMissing: return "SFNT font table missing."; + case Error.HorizHeaderMissing: return "Horizontal header (hhea) table missing."; + case Error.LocationsMissing: return "Locations (loca) table missing."; + case Error.NameTableMissing: return "Name table missing."; + case Error.CMapTableMissing: return "Character map (cmap) table missing."; + case Error.HmtxTableMissing: return "Horizontal metrics (hmtx) table missing."; + case Error.PostTableMissing: return "PostScript (post) table missing."; + case Error.InvalidHorizMetrics: return "Invalid horizontal metrics."; + case Error.InvalidCharMapFormat: return "Invalid character map (cmap) format."; + case Error.InvalidPPem: return "Invalid ppem value."; + case Error.InvalidVertMetrics: return "Invalid vertical metrics."; + case Error.CouldNotFindContext: return "Could not find context."; + case Error.InvalidPostTableFormat: return "Invalid PostScript (post) table format."; + case Error.InvalidPostTable: return "Invalid PostScript (post) table."; + case Error.SyntaxError: return "Opcode syntax error."; + case Error.StackUnderflow: return "Argument stack underflow."; + case Error.Ignore: return "Ignore this error."; + case Error.NoUnicodeGlyphName: return "No Unicode glyph name found."; + case Error.MissingStartfontField: return "`STARTFONT' field missing."; + case Error.MissingFontField: return "`FONT' field missing."; + case Error.MissingSizeField: return "`SIZE' field missing."; + case Error.MissingFontboudingboxField: return "`FONTBOUNDINGBOX' field missing."; + case Error.MissingCharsField: return "`CHARS' field missing."; + case Error.MissingStartcharField: return "`STARTCHAR' field missing."; + case Error.MissingEncodingField: return "`ENCODING' field missing."; + case Error.MissingBbxField: return "`BBX' field missing."; + case Error.BbxTooBig: return "`BBX' too big."; + case Error.CorruptedFontHeader: return "Font header corrupted or missing fields."; + case Error.CorruptedFontGlyphs: return "Font glyphs corrupted or missing fields."; + default: return "Encountered an unknown error. Most likely this is a new error that hasn't been included in SharpFont yet. Error:" + (int)err; + } + } + } +} diff --git a/SharpFont/Source/SharpFontShared/Gasp.cs b/SharpFont/Source/SharpFontShared/Gasp.cs new file mode 100644 index 000000000..4f1be20dc --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Gasp.cs @@ -0,0 +1,70 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of values and/or bit-flags returned by the FT_Get_Gasp function. + /// + /// + /// The bit-flags and are to be used for standard font + /// rasterization only. Independently of that, and + /// are to be used if ClearType is enabled (and + /// and are consequently ignored). + /// + /// ‘ClearType’ is Microsoft's implementation of LCD rendering, partly protected by patents. + /// + [Flags] + public enum Gasp + { + /// + /// This special value means that there is no GASP table in this face. It is up to the client to decide what to + /// do. + /// + NoTable = -1, + + /// + /// Grid-fitting and hinting should be performed at the specified ppem. This really means TrueType bytecode + /// interpretation. If this bit is not set, no hinting gets applied. + /// + DoGridfit = 0x01, + + /// + /// Anti-aliased rendering should be performed at the specified ppem. If not set, do monochrome rendering. + /// + DoGray = 0x02, + + /// + /// If set, smoothing along multiple axes must be used with ClearType. + /// + SymmetricSmoothing = 0x08, + + /// + /// Grid-fitting must be used with ClearType's symmetric smoothing. + /// + SymmetricGridfit = 0x10 + } +} diff --git a/SharpFont/Source/SharpFontShared/Generic.cs b/SharpFont/Source/SharpFontShared/Generic.cs new file mode 100644 index 000000000..20b7f8973 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Generic.cs @@ -0,0 +1,156 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// Describe a function used to destroy the ‘client’ data of any FreeType object. See the description of the + /// type for details of usage. + /// + /// + /// The address of the FreeType object which is under finalization. Its client data is accessed through its + /// ‘generic’ field. + /// + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void GenericFinalizer(IntPtr @object); + + /// + /// Client applications often need to associate their own data to a variety of FreeType core objects. For example, + /// a text layout API might want to associate a glyph cache to a given size object. + /// + /// Most FreeType object contains a ‘generic’ field, of type , which usage is left to client + /// applications and font servers. + /// + /// It can be used to store a pointer to client-specific data, as well as the address of a ‘finalizer’ function, + /// which will be called by FreeType when the object is destroyed (for example, the previous client example would + /// put the address of the glyph cache destructor in the ‘finalizer’ field). + /// + [Obsolete("Use the Tag property and Disposed event.")] + public class Generic + { + #region Fields + + private GenericRec rec; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// A typeless pointer to some client data. The data it cointains must stay fixed until finalizer is called. + /// + /// A delegate that gets called when the contained object gets finalized. + public Generic(IntPtr data, GenericFinalizer finalizer) + { + rec.data = data; + //rec.finalizer = finalizer; + } + + internal Generic(GenericRec genInternal) + { + rec = genInternal; + } + + internal Generic(IntPtr reference) + { + rec = PInvokeHelper.PtrToStructure(reference); + } + + internal Generic(IntPtr reference, int offset) + : this(new IntPtr(reference.ToInt64() + offset)) + { + } + + #endregion + + #region Properties + + /// + /// Gets the size of a , in bytes. + /// + public static int SizeInBytes + { + get + { + return Marshal.SizeOf(typeof(GenericRec)); + } + } + + /// + /// Gets or sets a typeless pointer to any client-specified data. This field is completely ignored by the + /// FreeType library. + /// + public IntPtr Data + { + get + { + return rec.data; + } + + set + { + rec.data = value; + } + } + + /// + /// Gets or sets a pointer to a function, which will be called when the object + /// is destroyed. If this field is set to NULL, no code will be called. + /// + /*public GenericFinalizer Finalizer + { + get + { + return rec.finalizer; + } + + set + { + rec.finalizer = value; + } + }*/ + + #endregion + + #region Methods + + //TODO make this private and build it into the setters if the reference isn't IntPtr.Zero. + internal void WriteToUnmanagedMemory(IntPtr location) + { + Marshal.WriteIntPtr(location, rec.data); + //Marshal.WriteIntPtr(location, IntPtr.Size, Marshal.GetFunctionPointerForDelegate(rec.finalizer)); + Marshal.WriteIntPtr(location, IntPtr.Size, rec.finalizer); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Glyph.cs b/SharpFont/Source/SharpFontShared/Glyph.cs new file mode 100644 index 000000000..c024d8393 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Glyph.cs @@ -0,0 +1,444 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// The root glyph structure contains a given glyph image plus its advance width in 16.16 fixed float format. + /// + public sealed class Glyph : IDisposable + { + #region Fields + + private bool disposed; + + private IntPtr reference; + private GlyphRec rec; + + private Library parentLibrary; + + #endregion + + #region Constructors + + internal Glyph(IntPtr reference, Library parentLibrary) + { + Reference = reference; + + this.parentLibrary = parentLibrary; + parentLibrary.AddChildGlyph(this); + } + + /// + /// Finalizes an instance of the Glyph class. + /// + ~Glyph() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets a handle to the FreeType library object. + /// + public Library Library + { + get + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + return parentLibrary; + } + } + + /// + /// Gets the format of the glyph's image. + /// + [CLSCompliant(false)] + public GlyphFormat Format + { + get + { + if (disposed) + throw new ObjectDisposedException("Format", "Cannot access a disposed object."); + + return rec.format; + } + } + + /// + /// Gets a 16.16 vector that gives the glyph's advance width. + /// + public FTVector Advance + { + get + { + if (disposed) + throw new ObjectDisposedException("Advance", "Cannot access a disposed object."); + + return rec.advance; + } + } + + 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; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Operators + + /// + /// Downcasts a to a + /// + /// A . + /// A . + /// + /// If the 's format is not . + /// + public static explicit operator BitmapGlyph(Glyph g) + { + if (g.Format == GlyphFormat.Bitmap) + return new BitmapGlyph(g); + else + throw new InvalidCastException("The glyph's format is not GlyphFormat.Bitmap."); + } + + /// + /// Downcasts a to a + /// + /// A . + /// A . + /// + /// If the 's format is not . + /// + public static explicit operator OutlineGlyph(Glyph g) + { + if (g.Format == GlyphFormat.Outline) + return new OutlineGlyph(g); + else + throw new InvalidCastException("The glyph's format is not GlyphFormat.Outline."); + } + + #endregion + + #region Methods + + /// + /// CLS-compliant equivalent of an explicit cast to . + /// + /// A . + public BitmapGlyph ToBitmapGlyph() + { + return (BitmapGlyph)this; + } + + /// + /// CLS-compliant equivalent of an explicit cast to . + /// + /// A . + public OutlineGlyph ToOutlineGlyph() + { + return (OutlineGlyph)this; + } + + /// + /// A function used to copy a glyph image. Note that the created object must be released + /// with . + /// + /// A handle to the target glyph object. 0 in case of error. + public Glyph Copy() + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + IntPtr glyphRef; + + Error err = FT.FT_Glyph_Copy(Reference, out glyphRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new Glyph(glyphRef, Library); + } + + /// + /// Transform a glyph image if its format is scalable. + /// + /// A pointer to a 2x2 matrix to apply. + /// + /// A pointer to a 2d vector to apply. Coordinates are expressed in 1/64th of a pixel. + /// + public void Transform(FTMatrix matrix, FTVector delta) + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + Error err = FT.FT_Glyph_Transform(Reference, ref matrix, ref delta); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Return a glyph's ‘control box’. The control box encloses all the outline's points, including Bézier control + /// points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger in some + /// situations (like when rotating an outline which contains Bézier outside arcs). + /// + /// Computing the control box is very fast, while getting the bounding box can take much more time as it needs + /// to walk over all segments and arcs in the outline. To get the latter, you can use the ‘ftbbox’ component + /// which is dedicated to this single task. + /// + /// + /// Coordinates are relative to the glyph origin, using the y upwards convention. + /// + /// If the glyph has been loaded with , ‘bbox_mode’ must be set to + /// to get unscaled font units in 26.6 pixel format. The value + /// is another name for this constant. + /// + /// If the font is tricky and the glyph has been loaded with , the resulting + /// CBox is meaningless. To get reasonable values for the CBox it is necessary to load the glyph at a large + /// ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting + /// the CBox which can be eventually converted back to font units. + /// + /// Note that the maximum coordinates are exclusive, which means that one can compute the width and height of + /// the glyph image (be it in integer or 26.6 pixels) as: + /// + /// + /// width = bbox.xMax - bbox.xMin; + /// height = bbox.yMax - bbox.yMin; + /// + /// + /// Note also that for 26.6 coordinates, if ‘bbox_mode’ is set to , the + /// coordinates will also be grid-fitted, which corresponds to: + /// + /// + /// bbox.xMin = FLOOR(bbox.xMin); + /// bbox.yMin = FLOOR(bbox.yMin); + /// bbox.xMax = CEILING(bbox.xMax); + /// bbox.yMax = CEILING(bbox.yMax); + /// + /// + /// To get the bbox in pixel coordinates, set ‘bbox_mode’ to . + /// + /// To get the bbox in grid-fitted pixel coordinates, set ‘bbox_mode’ to . + /// + /// The mode which indicates how to interpret the returned bounding box values. + /// + /// The glyph coordinate bounding box. Coordinates are expressed in 1/64th of pixels if it is grid-fitted. + /// + [CLSCompliant(false)] + public BBox GetCBox(GlyphBBoxMode mode) + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + BBox box; + FT.FT_Glyph_Get_CBox(Reference, mode, out box); + + return box; + } + + /// + /// Convert a given glyph object to a bitmap glyph object. + /// + /// + /// This function does nothing if the glyph format isn't scalable. + /// + /// The glyph image is translated with the ‘origin’ vector before rendering. + /// + /// The first parameter is a pointer to an handle, that will be replaced by this function + /// (with newly allocated data). Typically, you would use (omitting error handling): + /// + /// --sample code ommitted-- + /// + /// An enumeration that describes how the data is rendered. + /// + /// A pointer to a vector used to translate the glyph image before rendering. Can be 0 (if no translation). The + /// origin is expressed in 26.6 pixels. + /// + /// + /// A boolean that indicates that the original glyph image should be destroyed by this function. It is never + /// destroyed in case of error. + /// + public void ToBitmap(RenderMode renderMode, FTVector26Dot6 origin, bool destroy) + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + IntPtr glyphRef = Reference; + Error err = FT.FT_Glyph_To_Bitmap(ref glyphRef, renderMode, ref origin, destroy); + + Reference = glyphRef; + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #region Glyph Stroker + + /// + /// Stroke a given outline glyph object with a given stroker. + /// + /// + /// The source glyph is untouched in case of error. + /// + /// A stroker handle. + /// A Boolean. If 1, the source glyph object is destroyed on success. + /// New glyph handle. + public Glyph Stroke(Stroker stroker, bool destroy) + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + if (stroker == null) + throw new ArgumentNullException("stroker"); + + IntPtr sourceRef = Reference; + Error err = FT.FT_Glyph_Stroke(ref sourceRef, stroker.Reference, destroy); + + if (destroy && err == Error.Ok) + { + //if FT_Glyph_Stroke destroys the glyph, keep the C# side synchronized. + disposed = true; + reference = IntPtr.Zero; + } + + if (err != Error.Ok) + throw new FreeTypeException(err); + + //check if the pointer didn't change. + if (sourceRef == Reference) + return this; + else + return new Glyph(sourceRef, Library); + } + + /// + /// Stroke a given outline glyph object with a given stroker, but only return either its inside or outside + /// border. + /// + /// + /// The source glyph is untouched in case of error. + /// + /// A stroker handle. + /// A Boolean. If 1, return the inside border, otherwise the outside border. + /// A Boolean. If 1, the source glyph object is destroyed on success. + /// New glyph handle. + public Glyph StrokeBorder(Stroker stroker, bool inside, bool destroy) + { + if (disposed) + throw new ObjectDisposedException("Glyph", "Cannot access a disposed object."); + + if (stroker == null) + throw new ArgumentNullException("stroker"); + + IntPtr sourceRef = Reference; + Error err = FT.FT_Glyph_StrokeBorder(ref sourceRef, stroker.Reference, inside, destroy); + + if (destroy && err == Error.Ok) + { + //if FT_Glyph_Stroke destroys the glyph, keep the C# side synchronized. + disposed = true; + reference = IntPtr.Zero; + } + + if (err != Error.Ok) + throw new FreeTypeException(err); + + //check if the pointer didn't change. + if (sourceRef == Reference) + return this; + else + return new Glyph(sourceRef, Library); + } + + #endregion + + /// + /// Disposes the Glyph. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + FT.FT_Done_Glyph(reference); + + // removes itself from the parent Library, with a check to prevent this from happening when Library is + // being disposed (Library disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (!parentLibrary.IsDisposed) + parentLibrary.RemoveChildGlyph(this); + + reference = IntPtr.Zero; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/GlyphBBoxMode.cs b/SharpFont/Source/SharpFontShared/GlyphBBoxMode.cs new file mode 100644 index 000000000..f0e889c7d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/GlyphBBoxMode.cs @@ -0,0 +1,50 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// The mode how the values of are returned. + /// + [CLSCompliant(false)] + public enum GlyphBBoxMode : uint + { + /// Return unscaled font units. + Unscaled = 0, + + /// Return unfitted 26.6 coordinates. + Subpixels = 0, + + /// Return grid-fitted 26.6 coordinates. + Gridfit = 1, + + /// Return coordinates in integer pixels. + Truncate = 2, + + /// Return grid-fitted pixel coordinates. + Pixels = 3 + } +} diff --git a/SharpFont/Source/SharpFontShared/GlyphFormat.cs b/SharpFont/Source/SharpFontShared/GlyphFormat.cs new file mode 100644 index 000000000..761a5547b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/GlyphFormat.cs @@ -0,0 +1,67 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration type used to describe the format of a given glyph image. Note that this version of FreeType only + /// supports two image formats, even though future font drivers will be able to register their own format. + /// + [CLSCompliant(false)] + public enum GlyphFormat : uint + { + /// + /// The value 0 is reserved. + /// + None = 0, + + /// + /// The glyph image is a composite of several other images. This format is only used with + /// , and is used to report compound glyphs (like accented characters). + /// + Composite = ('c' << 24 | 'o' << 16 | 'm' << 8 | 'p'), + + /// + /// The glyph image is a bitmap, and can be described as an . You generally need to + /// access the ‘bitmap’ field of the structure to read it. + /// + Bitmap = ('b' << 24 | 'i' << 16 | 't' << 8 | 's'), + + /// + /// The glyph image is a vectorial outline made of line segments and Bézier arcs; it can be described as an + /// ; you generally want to access the ‘outline’ field of the + /// structure to read it. + /// + Outline = ('o' << 24 | 'u' << 16 | 't' << 8 | 'l'), + + /// + /// The glyph image is a vectorial path with no inside and outside contours. Some Type 1 fonts, like those in + /// the Hershey family, contain glyphs in this format. These are described as , but + /// FreeType isn't currently capable of rendering them correctly. + /// + Plotter = ('p' << 24 | 'l' << 16 | 'o' << 8 | 't') + } +} diff --git a/SharpFont/Source/SharpFontShared/GlyphMetrics.cs b/SharpFont/Source/SharpFontShared/GlyphMetrics.cs new file mode 100644 index 000000000..93cc1615f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/GlyphMetrics.cs @@ -0,0 +1,180 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used to model the metrics of a single glyph. The values are expressed in 26.6 fractional pixel + /// format; if the flag has been used while loading the glyph, values are expressed + /// in font units instead. + /// + /// + /// If not disabled with , the values represent dimensions of the hinted glyph (in + /// case hinting is applicable). + /// + public sealed class GlyphMetrics + { + #region Fields + + private IntPtr reference; + private GlyphMetricsRec rec; + + #endregion + + #region Constructors + + internal GlyphMetrics(IntPtr reference) + { + Reference = reference; + } + + internal GlyphMetrics(GlyphMetricsRec glyphMetInt) + { + this.rec = glyphMetInt; + } + + #endregion + + #region Properties + + /// + /// Gets the glyph's width. If getting metrics from a face loaded with , call + /// to get the unscaled value. + /// + public Fixed26Dot6 Width + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.width); + } + } + + /// + /// Gets the glyph's height. If getting metrics from a face loaded with , call + /// to get the unscaled value. + /// + public Fixed26Dot6 Height + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.height); + } + } + + /// + /// Gets the left side bearing for horizontal layout. If getting metrics from a face loaded with + /// , call to get the unscaled value. + /// + public Fixed26Dot6 HorizontalBearingX + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.horiBearingX); + } + } + + /// + /// Gets the top side bearing for horizontal layout. If getting metrics from a face loaded with + /// , call to get the unscaled value. + /// + public Fixed26Dot6 HorizontalBearingY + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.horiBearingY); + } + } + + /// + /// Gets the advance width for horizontal layout. If getting metrics from a face loaded with + /// , call to get the unscaled value. + /// + public Fixed26Dot6 HorizontalAdvance + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.horiAdvance); + } + } + + /// + /// Gets the left side bearing for vertical layout. If getting metrics from a face loaded with + /// , call to get the unscaled value. + /// + public Fixed26Dot6 VerticalBearingX + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.vertBearingX); + } + } + + /// + /// Gets the top side bearing for vertical layout. Larger positive values mean further below the vertical glyph + /// origin. If getting metrics from a face loaded with , call + /// to get the unscaled value. + /// + public Fixed26Dot6 VerticalBearingY + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.vertBearingY); + } + } + + /// + /// Gets the advance height for vertical layout. Positive values mean the glyph has a positive advance + /// downward. If getting metrics from a face loaded with , call + /// to get the unscaled value. + /// + public Fixed26Dot6 VerticalAdvance + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.vertAdvance); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/GlyphSlot.cs b/SharpFont/Source/SharpFontShared/GlyphSlot.cs new file mode 100644 index 000000000..ed5818dea --- /dev/null +++ b/SharpFont/Source/SharpFontShared/GlyphSlot.cs @@ -0,0 +1,475 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015-2016 Robert Rouhani + +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.Runtime.InteropServices; +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// FreeType root glyph slot class structure. A glyph slot is a container where individual glyphs can be loaded, be + /// they in outline or bitmap format. + /// + /// + /// If is called with default flags (see ) + /// the glyph image is loaded in the glyph slot in its native format (e.g., an outline glyph for TrueType and Type + /// 1 formats). + /// + /// This image can later be converted into a bitmap by calling . This function finds the + /// current renderer for the native image's format, then invokes it. + /// + /// The renderer is in charge of transforming the native image through the slot's face transformation fields, then + /// converting it into a bitmap that is returned in ‘slot->bitmap’. + /// + /// Note that ‘slot->bitmap_left’ and ‘slot->bitmap_top’ are also used to specify the position of the bitmap + /// relative to the current pen position (e.g., coordinates (0,0) on the baseline). Of course, ‘slot->format’ is + /// also changed to . + /// + /// + /// + /// FT_Pos origin_x = 0; + /// FT_Pos prev_rsb_delta = 0; + /// + /// + /// for all glyphs do + /// <compute kern between current and previous glyph and add it to + /// `origin_x'> + /// + /// <load glyph with `FT_Load_Glyph'> + /// + /// if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) + /// origin_x -= 64; + /// else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) + /// origin_x += 64; + /// + /// prev_rsb_delta = face->glyph->rsb_delta; + /// + /// <save glyph image, or render glyph, or ...> + /// + /// origin_x += face->glyph->advance.x; + /// endfor + /// + /// + public sealed class GlyphSlot + { + #region Fields + + private IntPtr reference; + private GlyphSlotRec rec; + + private Face parentFace; + private Library parentLibrary; + + #endregion + + #region Constructors + + internal GlyphSlot(IntPtr reference, Face parentFace, Library parentLibrary) + { + Reference = reference; + this.parentFace = parentFace; + this.parentLibrary = parentLibrary; + } + + #endregion + + #region Properties + + /// + /// Gets a handle to the FreeType library instance this slot belongs to. + /// + public Library Library + { + get + { + return parentLibrary; + } + } + + /// + /// Gets a handle to the parent face object. + /// + public Face Face + { + get + { + return parentFace; + } + } + + /// + /// Gets the next . In some cases (like some font tools), several glyph slots per face + /// object can be a good thing. As this is rare, the glyph slots are listed through a direct, single-linked + /// list using its ‘next’ field. + /// + public GlyphSlot Next + { + get + { + return new GlyphSlot(rec.next, parentFace, parentLibrary); + } + } + + /// + /// Gets a typeless pointer which is unused by the FreeType library or any of its drivers. It can be used by + /// client applications to link their own data to each glyph slot object. + /// + [Obsolete("Use the Tag property, Dispose callback not handled currently.")] + public Generic Generic + { + get + { + return new Generic(rec.generic); + } + } + + /// + /// Gets the metrics of the last loaded glyph in the slot. The returned values depend on the last load flags + /// (see the API function) and can be expressed either in 26.6 + /// fractional pixels or font units. + /// + /// Note that even when the glyph image is transformed, the metrics are not. + /// + public GlyphMetrics Metrics + { + get + { + return new GlyphMetrics(rec.metrics); + } + } + + /// + /// Gets the advance width of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless + /// is set when loading the glyph. This field can be important to perform + /// correct WYSIWYG layout. Only relevant for outline glyphs. + /// + public Fixed16Dot16 LinearHorizontalAdvance + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.linearHoriAdvance); + } + } + + /// + /// Gets the advance height of the unhinted glyph. Its value is expressed in 16.16 fractional pixels, unless + /// is set when loading the glyph. This field can be important to perform + /// correct WYSIWYG layout. Only relevant for outline glyphs. + /// + public Fixed16Dot16 LinearVerticalAdvance + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.linearVertAdvance); + } + } + + /// + /// Gets the advance. This shorthand is, depending on , the transformed + /// advance width for the glyph (in 26.6 fractional pixel format). As specified with + /// , it uses either the ‘horiAdvance’ or the ‘vertAdvance’ value of + /// ‘metrics’ field. + /// + public FTVector26Dot6 Advance + { + get + { + return rec.advance; + } + } + + /// + /// Gets the glyph format. This field indicates the format of the image contained in the glyph slot. Typically + /// , , or + /// , but others are possible. + /// + [CLSCompliant(false)] + public GlyphFormat Format + { + get + { + return rec.format; + } + } + + /// + /// Gets the bitmap. This field is used as a bitmap descriptor when the slot format is + /// . Note that the address and content of the bitmap buffer can change between + /// calls of and a few other functions. + /// + public FTBitmap Bitmap + { + get + { + return new FTBitmap(PInvokeHelper.AbsoluteOffsetOf(Reference, "bitmap"), rec.bitmap, parentLibrary); + } + } + + /// + /// Gets the bitmap's left bearing expressed in integer pixels. Of course, this is only valid if the format is + /// . + /// + public int BitmapLeft + { + get + { + return rec.bitmap_left; + } + } + + /// + /// Gets the bitmap's top bearing expressed in integer pixels. Remember that this is the distance from the + /// baseline to the top-most glyph scanline, upwards y coordinates being positive. + /// + public int BitmapTop + { + get + { + return rec.bitmap_top; + } + } + + /// + /// Gets the outline descriptor for the current glyph image if its format is . + /// Once a glyph is loaded, ‘outline’ can be transformed, distorted, embolded, etc. However, it must not be + /// freed. + /// + public Outline Outline + { + get + { + return new Outline(PInvokeHelper.AbsoluteOffsetOf(Reference, "outline"), rec.outline); + } + } + + /// + /// Gets the number of subglyphs in a composite glyph. This field is only valid for the composite glyph format + /// that should normally only be loaded with the flag. For now this is + /// internal to FreeType. + /// + [CLSCompliant(false)] + public uint SubglyphsCount + { + get + { + return rec.num_subglyphs; + } + } + + /// + /// Gets an array of subglyph descriptors for composite glyphs. There are ‘num_subglyphs’ elements in there. + /// Currently internal to FreeType. + /// + public SubGlyph[] Subglyphs + { + get + { + int count = (int)SubglyphsCount; + + if (count == 0) + return null; + + SubGlyph[] subglyphs = new SubGlyph[count]; + IntPtr array = rec.subglyphs; + + for (int i = 0; i < count; i++) + { + subglyphs[i] = new SubGlyph((IntPtr)(array.ToInt64() + IntPtr.Size * i)); + } + + return subglyphs; + } + } + + /// + /// Gets the control data. Certain font drivers can also return the control data for a given glyph image (e.g. + /// TrueType bytecode, Type 1 charstrings, etc.). This field is a pointer to such data. + /// + public IntPtr ControlData + { + get + { + return rec.control_data; + } + } + + /// + /// Gets the length in bytes of the control data. + /// + public int ControlLength + { + get + { + return (int)rec.control_len; + } + } + + /// + /// Gets the difference between hinted and unhinted left side bearing while autohinting is active. Zero + /// otherwise. + /// + public int DeltaLsb + { + get + { + return (int)rec.lsb_delta; + } + } + + /// + /// Gets the difference between hinted and unhinted right side bearing while autohinting is active. Zero + /// otherwise. + /// + public int DeltaRsb + { + get + { + return (int)rec.rsb_delta; + } + } + + /// + /// Gets or sets an object used to identify this instance of . This object will not be + /// modified or accessed internally. + /// + /// + /// This is a replacement for FT_Generic in FreeType. If you are retrieving the same object multiple times + /// from functions, this object will not appear in new copies. + /// + public object Tag { get; set; } + + /// + /// Gets other data. Really wicked formats can use this pointer to present their own glyph image to client + /// applications. Note that the application needs to know about the image format. + /// + public IntPtr Other + { + get + { + return rec.other; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Public Methods + + #region Base Interface + + /// + /// Convert a given glyph image to a bitmap. It does so by inspecting the glyph image format, finding the + /// relevant renderer, and invoking it. + /// + /// This is the render mode used to render the glyph image into a bitmap. + public void RenderGlyph(RenderMode mode) + { + Error err = FT.FT_Render_Glyph(Reference, mode); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Retrieve a description of a given subglyph. Only use it if is + /// ; an error is returned otherwise. + /// + /// + /// The values of ‘*p_arg1’, ‘*p_arg2’, and ‘*p_transform’ must be interpreted depending on the flags returned + /// in ‘*p_flags’. See the TrueType specification for details. + /// + /// + /// The index of the subglyph. Must be less than . + /// + /// The glyph index of the subglyph. + /// The subglyph flags, see . + /// The subglyph's first argument (if any). + /// The subglyph's second argument (if any). + /// The subglyph transformation (if any). + [CLSCompliant(false)] + public void GetSubGlyphInfo(uint subIndex, out int index, out SubGlyphFlags flags, out int arg1, out int arg2, out FTMatrix transform) + { + Error err = FT.FT_Get_SubGlyph_Info(Reference, subIndex, out index, out flags, out arg1, out arg2, out transform); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #endregion + + #region Glyph Management + + /// + /// A function used to extract a glyph image from a slot. Note that the created object must + /// be released with . + /// + /// A handle to the glyph object. + public Glyph GetGlyph() + { + IntPtr glyphRef; + Error err = FT.FT_Get_Glyph(Reference, out glyphRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return new Glyph(glyphRef, Library); + } + + #endregion + + #region Bitmap Handling + + /// + /// Make sure that a glyph slot owns ‘slot->bitmap’. + /// + /// + /// This function is to be used in combination with . + /// + public void OwnBitmap() + { + Error err = FT.FT_GlyphSlot_Own_Bitmap(Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + #endregion + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/GlyphToScriptMapProperty.cs b/SharpFont/Source/SharpFontShared/GlyphToScriptMapProperty.cs new file mode 100644 index 000000000..4159b57cf --- /dev/null +++ b/SharpFont/Source/SharpFontShared/GlyphToScriptMapProperty.cs @@ -0,0 +1,96 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// The data exchange structure for the glyph-to-script-map property. + /// + public class GlyphToScriptMapProperty + { + private GlyphToScriptMapPropertyRec rec; + private Face face; + + /// + /// Initializes a new instance of the class. + /// + /// The face to apply the property to. + public GlyphToScriptMapProperty(Face face) + { + Face = face; + } + + internal GlyphToScriptMapProperty(GlyphToScriptMapPropertyRec rec, Face face) + { + this.rec = rec; + this.face = face; + } + + /// + /// Gets or sets the associated face. + /// + public Face Face + { + get + { + return face; + } + + set + { + face = value; + rec.face = face.Reference; + } + } + + /// + /// Gets or sets the associated map. + /// + public IntPtr Map + { + get + { + return rec.map; + } + + set + { + rec.map = value; + } + } + + internal GlyphToScriptMapPropertyRec Rec + { + get + { + return rec; + } + } + } +} diff --git a/SharpFont/Source/SharpFontShared/IncreaseXHeightProperty.cs b/SharpFont/Source/SharpFontShared/IncreaseXHeightProperty.cs new file mode 100644 index 000000000..162ea3d49 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/IncreaseXHeightProperty.cs @@ -0,0 +1,97 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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 SharpFont.Internal; + +namespace SharpFont +{ + /// + /// The data exchange structure for the increase-x-height property. + /// + public class IncreaseXHeightProperty + { + private IncreaseXHeightPropertyRec rec; + private Face face; + + /// + /// Initializes a new instance of the class. + /// + /// The face to increase the X height of. + public IncreaseXHeightProperty(Face face) + { + this.rec.face = face.Reference; + this.face = face; + } + + internal IncreaseXHeightProperty(IncreaseXHeightPropertyRec rec, Face face) + { + this.rec = rec; + this.face = face; + } + + /// + /// Gets or sets the associated face. + /// + public Face Face + { + get + { + return face; + } + + set + { + face = value; + rec.face = face.Reference; + } + } + + /// + /// Gets or sets the limit property. + /// + [CLSCompliant(false)] + public uint Limit + { + get + { + return rec.limit; + } + + set + { + rec.limit = value; + } + } + + internal IncreaseXHeightPropertyRec Rec + { + get + { + return rec; + } + } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/BitmapGlyphRec.cs b/SharpFont/Source/SharpFontShared/Internal/BitmapGlyphRec.cs new file mode 100644 index 000000000..394b8a218 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/BitmapGlyphRec.cs @@ -0,0 +1,38 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct BitmapGlyphRec + { + internal GlyphRec root; + internal int left; + internal int top; + internal BitmapRec bitmap; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/BitmapRec.cs b/SharpFont/Source/SharpFontShared/Internal/BitmapRec.cs new file mode 100644 index 000000000..77fdea325 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/BitmapRec.cs @@ -0,0 +1,48 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a Bitmap. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct BitmapRec + { + internal int rows; + internal int width; + internal int pitch; + internal IntPtr buffer; + internal short num_grays; + internal PixelMode pixel_mode; + internal byte palette_mode; + internal IntPtr palette; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/BitmapSizeRec.cs b/SharpFont/Source/SharpFontShared/Internal/BitmapSizeRec.cs new file mode 100644 index 000000000..158cc3131 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/BitmapSizeRec.cs @@ -0,0 +1,52 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a BitmapSize. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct BitmapSizeRec + { + internal short height; + internal short width; + + internal FT_Long size; + + internal FT_Long x_ppem; + internal FT_Long y_ppem; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(BitmapSizeRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/CharMapRec.cs b/SharpFont/Source/SharpFontShared/Internal/CharMapRec.cs new file mode 100644 index 000000000..b36cb6412 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/CharMapRec.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a CharMap. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct CharMapRec + { + internal IntPtr face; + internal Encoding encoding; + internal PlatformId platform_id; + internal ushort encoding_id; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/FaceRec.cs b/SharpFont/Source/SharpFontShared/Internal/FaceRec.cs new file mode 100644 index 000000000..6c248b9af --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/FaceRec.cs @@ -0,0 +1,90 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a Face. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct FaceRec + { + internal FT_Long num_faces; + internal FT_Long face_index; + + internal FT_Long face_flags; + internal FT_Long style_flags; + + internal FT_Long num_glyphs; + + internal IntPtr family_name; + internal IntPtr style_name; + + internal int num_fixed_sizes; + internal IntPtr available_sizes; + + internal int num_charmaps; + internal IntPtr charmaps; + + internal GenericRec generic; + + internal BBox bbox; + + internal ushort units_per_EM; + internal short ascender; + internal short descender; + internal short height; + + internal short max_advance_width; + internal short max_advance_height; + + internal short underline_position; + internal short underline_thickness; + + internal IntPtr glyph; + internal IntPtr size; + internal IntPtr charmap; + + private IntPtr driver; + private IntPtr memory; + private IntPtr stream; + + private IntPtr sizes_list; + private GenericRec autohint; + private IntPtr extensions; + + private IntPtr @internal; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(FaceRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/GenericRec.cs b/SharpFont/Source/SharpFontShared/Internal/GenericRec.cs new file mode 100644 index 000000000..9cc80070e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/GenericRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct GenericRec + { + internal IntPtr data; + internal IntPtr finalizer; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/GlyphMetricsRec.cs b/SharpFont/Source/SharpFontShared/Internal/GlyphMetricsRec.cs new file mode 100644 index 000000000..df7496a5a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/GlyphMetricsRec.cs @@ -0,0 +1,53 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a GlyphMetrics. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphMetricsRec + { + internal FT_Long width; + internal FT_Long height; + + internal FT_Long horiBearingX; + internal FT_Long horiBearingY; + internal FT_Long horiAdvance; + + internal FT_Long vertBearingX; + internal FT_Long vertBearingY; + internal FT_Long vertAdvance; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/GlyphRec.cs b/SharpFont/Source/SharpFontShared/Internal/GlyphRec.cs new file mode 100644 index 000000000..d4c2f64a2 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/GlyphRec.cs @@ -0,0 +1,38 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphRec + { + internal IntPtr library; + private IntPtr clazz; + internal GlyphFormat format; + internal FTVector advance; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/GlyphSlotRec.cs b/SharpFont/Source/SharpFontShared/Internal/GlyphSlotRec.cs new file mode 100644 index 000000000..d971b7f25 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/GlyphSlotRec.cs @@ -0,0 +1,74 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a GlyphSlot. + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphSlotRec + { + internal IntPtr library; + internal IntPtr face; + internal IntPtr next; + internal uint reserved; + internal GenericRec generic; + + internal GlyphMetricsRec metrics; + internal FT_Long linearHoriAdvance; + internal FT_Long linearVertAdvance; + internal FTVector26Dot6 advance; + + internal GlyphFormat format; + + internal BitmapRec bitmap; + internal int bitmap_left; + internal int bitmap_top; + + internal OutlineRec outline; + + internal uint num_subglyphs; + internal IntPtr subglyphs; + + internal IntPtr control_data; + internal FT_Long control_len; + + internal FT_Long lsb_delta; + internal FT_Long rsb_delta; + + internal IntPtr other; + + private IntPtr @internal; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/GlyphToScriptMapPropertyRec.cs b/SharpFont/Source/SharpFontShared/Internal/GlyphToScriptMapPropertyRec.cs new file mode 100644 index 000000000..bfa7098b8 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/GlyphToScriptMapPropertyRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphToScriptMapPropertyRec + { + internal IntPtr face; + internal IntPtr map; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/IncreaseXHeightPropertyRec.cs b/SharpFont/Source/SharpFontShared/Internal/IncreaseXHeightPropertyRec.cs new file mode 100644 index 000000000..7527a3e1a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/IncreaseXHeightPropertyRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct IncreaseXHeightPropertyRec + { + internal IntPtr face; + internal uint limit; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/ListNodeRec.cs b/SharpFont/Source/SharpFontShared/Internal/ListNodeRec.cs new file mode 100644 index 000000000..46984ede3 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/ListNodeRec.cs @@ -0,0 +1,39 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ListNodeRec + { + internal IntPtr prev; + internal IntPtr next; + internal IntPtr data; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(ListNodeRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/ListRec.cs b/SharpFont/Source/SharpFontShared/Internal/ListRec.cs new file mode 100644 index 000000000..e09d2f602 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/ListRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ListRec + { + internal IntPtr head; + internal IntPtr tail; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/MemoryRec.cs b/SharpFont/Source/SharpFontShared/Internal/MemoryRec.cs new file mode 100644 index 000000000..8b3d1e157 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/MemoryRec.cs @@ -0,0 +1,40 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct MemoryRec + { + internal IntPtr user; + internal AllocFunc alloc; + internal FreeFunc free; + internal ReallocFunc realloc; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(MemoryRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/ModuleClassRec.cs b/SharpFont/Source/SharpFontShared/Internal/ModuleClassRec.cs new file mode 100644 index 000000000..b25622339 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/ModuleClassRec.cs @@ -0,0 +1,50 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ModuleClassRec + { + internal uint module_flags; + internal FT_Long module_size; + + [MarshalAs(UnmanagedType.LPStr)] + internal string module_name; + internal FT_Long module_version; + internal FT_Long module_requires; + + internal IntPtr module_interface; + + internal ModuleConstructor module_init; + internal ModuleDestructor module_done; + internal ModuleRequester get_interface; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/NativeObject.cs b/SharpFont/Source/SharpFontShared/Internal/NativeObject.cs new file mode 100644 index 000000000..55d58601e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/NativeObject.cs @@ -0,0 +1,33 @@ +using System; + +namespace SharpFont +{ + /// + /// Provide a consistent means for using pointers as references. + /// + public abstract class NativeObject + { + private IntPtr reference; + + /// + /// Construct a new NativeObject and assign the reference. + /// + /// + protected NativeObject(IntPtr reference) + { + this.reference = reference; + } + + internal virtual IntPtr Reference + { + get + { + return reference; + } + set + { + reference = value; + } + } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/NativeReference.cs b/SharpFont/Source/SharpFontShared/Internal/NativeReference.cs new file mode 100644 index 000000000..272c23f3a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/NativeReference.cs @@ -0,0 +1,58 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + /// + /// Struct NativeReference + /// + /// + [StructLayout(LayoutKind.Sequential)] + public struct NativeReference where T : NativeObject + { + private readonly IntPtr memoryPtr; + + /// + /// Initializes a new instance of the struct. + /// + /// The memory PTR. + public NativeReference(IntPtr memoryPtr) + { + this.memoryPtr = memoryPtr; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The memory. + /// The result of the conversion. + public static implicit operator NativeReference(T memory) + { + return new NativeReference(memory.Reference); + } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/OpenArgsRec.cs b/SharpFont/Source/SharpFontShared/Internal/OpenArgsRec.cs new file mode 100644 index 000000000..58740832b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/OpenArgsRec.cs @@ -0,0 +1,48 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct OpenArgsRec + { + internal OpenFlags flags; + internal IntPtr memory_base; + internal FT_Long memory_size; + + [MarshalAs(UnmanagedType.LPStr)] + internal string pathname; + + internal IntPtr stream; + internal IntPtr driver; + internal int num_params; + internal IntPtr @params; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/OutlineFuncsRec.cs b/SharpFont/Source/SharpFontShared/Internal/OutlineFuncsRec.cs new file mode 100644 index 000000000..e67258c3d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/OutlineFuncsRec.cs @@ -0,0 +1,43 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct OutlineFuncsRec + { + internal IntPtr moveTo; + internal IntPtr lineTo; + internal IntPtr conicTo; + internal IntPtr cubicTo; + internal int shift; + internal FT_Long delta; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/OutlineGlyphRec.cs b/SharpFont/Source/SharpFontShared/Internal/OutlineGlyphRec.cs new file mode 100644 index 000000000..d0b0d8681 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/OutlineGlyphRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct OutlineGlyphRec + { + internal GlyphRec root; + internal OutlineRec outline; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/OutlineRec.cs b/SharpFont/Source/SharpFontShared/Internal/OutlineRec.cs new file mode 100644 index 000000000..a6713120a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/OutlineRec.cs @@ -0,0 +1,42 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct OutlineRec + { + internal short n_contours; + internal short n_points; + + internal IntPtr points; + internal IntPtr tags; + internal IntPtr contours; + + internal OutlineFlags flags; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/ParameterRec.cs b/SharpFont/Source/SharpFontShared/Internal/ParameterRec.cs new file mode 100644 index 000000000..14cae95b4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/ParameterRec.cs @@ -0,0 +1,41 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct ParameterRec + { + internal FT_ULong tag; + internal IntPtr data; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(ParameterRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/RasterFuncsRec.cs b/SharpFont/Source/SharpFontShared/Internal/RasterFuncsRec.cs new file mode 100644 index 000000000..a3dbc2d6b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/RasterFuncsRec.cs @@ -0,0 +1,40 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct RasterFuncsRec + { + internal GlyphFormat glyph_format; + internal RasterNewFunc raster_new; + internal RasterResetFunc raster_reset; + internal RasterSetModeFunc raster_set_mode; + internal RasterRenderFunc raster_render; + internal RasterDoneFunc raster_done; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/RasterParamsRec.cs b/SharpFont/Source/SharpFontShared/Internal/RasterParamsRec.cs new file mode 100644 index 000000000..f8fc3e4ee --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/RasterParamsRec.cs @@ -0,0 +1,50 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct RasterParamsRec + { + internal IntPtr target; + internal IntPtr source; + internal RasterFlags flags; + internal RasterSpanFunc gray_spans; + internal RasterSpanFunc black_spans; + + [Obsolete("Unused")] + internal RasterBitTestFunc bit_test; + + [Obsolete("Unused")] + internal RasterBitSetFunc bit_set; + + internal IntPtr user; + internal BBox clip_box; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(RasterParamsRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/RendererClassRec.cs b/SharpFont/Source/SharpFontShared/Internal/RendererClassRec.cs new file mode 100644 index 000000000..8e764f8fe --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/RendererClassRec.cs @@ -0,0 +1,44 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct RendererClassRec + { + internal ModuleClassRec root; + + internal GlyphFormat glyph_format; + + internal IntPtr render_glyph; + internal IntPtr transform_glyph; + internal IntPtr get_glyph_cbox; + internal IntPtr set_mode; + + internal IntPtr raster_class; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/SizeMetricsRec.cs b/SharpFont/Source/SharpFontShared/Internal/SizeMetricsRec.cs new file mode 100644 index 000000000..149c9f581 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/SizeMetricsRec.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SizeMetricsRec + { + internal ushort x_ppem; + internal ushort y_ppem; + + internal FT_Long x_scale; + internal FT_Long y_scale; + internal FT_Long ascender; + internal FT_Long descender; + internal FT_Long height; + internal FT_Long max_advance; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/SizeRec.cs b/SharpFont/Source/SharpFontShared/Internal/SizeRec.cs new file mode 100644 index 000000000..05cbf061b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/SizeRec.cs @@ -0,0 +1,39 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SizeRec + { + internal IntPtr face; + internal GenericRec generic; + internal SizeMetricsRec metrics; + private IntPtr @internal; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/SizeRequestRec.cs b/SharpFont/Source/SharpFontShared/Internal/SizeRequestRec.cs new file mode 100644 index 000000000..ddc8fde87 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/SizeRequestRec.cs @@ -0,0 +1,48 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + /// + /// Internally represents a . + /// + /// + /// Refer to for FreeType documentation. + /// + [StructLayout(LayoutKind.Sequential)] + internal struct SizeRequestRec + { + internal SizeRequestType type; + internal FT_Long width; + internal FT_Long height; + internal uint horiResolution; + internal uint vertResolution; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/SpanRec.cs b/SharpFont/Source/SharpFontShared/Internal/SpanRec.cs new file mode 100644 index 000000000..742411f35 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/SpanRec.cs @@ -0,0 +1,39 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SpanRec + { + internal short x; + internal ushort len; + internal byte coverage; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(SpanRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/StreamDescRec.cs b/SharpFont/Source/SharpFontShared/Internal/StreamDescRec.cs new file mode 100644 index 000000000..75d2b8ba5 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/StreamDescRec.cs @@ -0,0 +1,42 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Explicit)] + internal struct StreamDescRec + { + [FieldOffset(0)] + internal FT_Long value; + + [FieldOffset(0)] + internal IntPtr pointer; + } +} diff --git a/SharpFont/Source/SharpFontShared/Internal/StreamRec.cs b/SharpFont/Source/SharpFontShared/Internal/StreamRec.cs new file mode 100644 index 000000000..45486b4c0 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Internal/StreamRec.cs @@ -0,0 +1,51 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct StreamRec + { + internal IntPtr @base; + internal FT_ULong size; + internal FT_ULong pos; + + internal StreamDescRec descriptor; + internal StreamDescRec pathname; + internal StreamIOFunc read; + internal StreamCloseFunc close; + + internal IntPtr memory; + internal IntPtr cursor; + internal IntPtr limit; + + internal static int SizeInBytes { get { return Marshal.SizeOf(typeof(StreamRec)); } } + } +} diff --git a/SharpFont/Source/SharpFontShared/KerningMode.cs b/SharpFont/Source/SharpFontShared/KerningMode.cs new file mode 100644 index 000000000..0cf3db41f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/KerningMode.cs @@ -0,0 +1,49 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration used to specify which kerning values to return in . + /// + public enum KerningMode + { + /// + /// Return scaled and grid-fitted kerning distances. + /// + Default = 0, + + /// + /// Return scaled but un-grid-fitted kerning distances. + /// + Unfitted, + + /// + /// Return the kerning vector in original font units. + /// + Unscaled + } +} diff --git a/SharpFont/Source/SharpFontShared/LcdFilter.cs b/SharpFont/Source/SharpFontShared/LcdFilter.cs new file mode 100644 index 000000000..075773dd4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/LcdFilter.cs @@ -0,0 +1,61 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of values to identify various types of LCD filters. + /// + public enum LcdFilter + { + /// + /// Do not perform filtering. When used with subpixel rendering, this results in sometimes severe color + /// fringes. + /// + None = 0, + + /// + /// The default filter reduces color fringes considerably, at the cost of a slight blurriness in the output. + /// + Default = 1, + + /// + /// The light filter is a variant that produces less blurriness at the cost of slightly more color fringes than + /// the default one. It might be better, depending on taste, your monitor, or your personal vision. + /// + Light = 2, + + /// + /// This filter corresponds to the original libXft color filter. It provides high contrast output but can + /// exhibit really bad color fringes if glyphs are not extremely well hinted to the pixel grid. In other words, + /// it only works well if the TrueType bytecode interpreter is enabled and high-quality hinted fonts are used. + /// + /// This filter is only provided for comparison purposes, and might be disabled or stay unsupported in the + /// future. + /// + Legacy = 16 + } +} diff --git a/SharpFont/Source/SharpFontShared/Library.cs b/SharpFont/Source/SharpFontShared/Library.cs new file mode 100644 index 000000000..5d4fc205e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Library.cs @@ -0,0 +1,897 @@ +#region MIT License +/*Copyright (c) 2012-2014, 2016 Robert Rouhani + +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.Linq; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using SharpFont.Cache; +using SharpFont.Internal; +using SharpFont.TrueType; + +namespace SharpFont +{ + /// + /// 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. + /// + /// It also embeds a memory manager (see ), as well as a scan-line converter object (see + /// ). + /// + /// For multi-threading applications each thread should have its own object. + /// + public sealed class Library : IDisposable + { + #region Fields + + private IntPtr reference; + + private bool customMemory; + private bool disposed; + + private List childFaces; + private List childGlyphs; + private List childOutlines; + private List childStrokers; + private List childManagers; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// + /// SharpFont assumes that you have the correct version of FreeType for your operating system and processor + /// architecture. If you get a here on Windows, there's a good chance + /// that you're trying to run your program as a 64-bit process and have a 32-bit version of FreeType or vice + /// versa. See the SharpFont.Examples project for how to handle this situation. + /// + public Library() + : this(false) + { + IntPtr libraryRef; + Error err = FT.FT_Init_FreeType(out libraryRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = libraryRef; + } + + /// + /// Initializes a new instance of the class. + /// + /// A custom FreeType memory manager. + 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(); + childGlyphs = new List(); + childOutlines = new List(); + childStrokers = new List(); + childManagers = new List(); + } + + /// + /// Finalizes an instance of the class. + /// + ~Library() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets the version of the FreeType library being used. + /// + 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 + + /// + /// This function calls to open a font by its pathname. + /// + /// A path to the font file. + /// The index of the face within the font. The first face has index 0. + /// + /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL. + /// + /// + public Face NewFace(string path, int faceIndex) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + return new Face(this, path, faceIndex); + } + + /// + /// This function calls to open a font which has been loaded into memory. + /// + /// + /// You must not deallocate the memory before calling . + /// + /// A pointer to the beginning of the font data. + /// The index of the face within the font. The first face has index 0. + /// + /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL. + /// + /// + public Face NewMemoryFace(byte[] file, int faceIndex) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + return new Face(this, file, faceIndex); + } + + /// + /// This function calls to open a font which has been loaded into memory. + /// + /// A pointer to the beginning of the font data. + /// Length of the buffer + /// The index of the face within the font. The first face has index 0. + /// + /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL. + /// + public Face NewMemoryFace(IntPtr bufferPtr, int length, int faceIndex) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + return new Face(this, bufferPtr, length, faceIndex); + } + + /// + /// Create a object from a given resource described by . + /// + /// + /// Unlike FreeType 1.x, this function automatically creates a glyph slot for the face object which can be + /// accessed directly through . + /// + /// 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 which gives + /// the number of faces within the font file. After examination, the returned structure + /// should be deallocated with a call to . + /// + /// Each new face object created with this function also owns a default object, accessible + /// as . + /// + /// See the discussion of reference counters in the description of FT_Reference_Face. + /// + /// + /// A pointer to an structure which must be filled by the caller. + /// + /// The index of the face within the font. The first face has index 0. + /// + /// A handle to a new face object. If ‘faceIndex’ is greater than or equal to zero, it must be non-NULL. + /// + 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 + +#if !SHARPFONT_PLATFORM_IOS + #region Mac Specific Interface + + /// + /// Create a new face object from a FOND resource. + /// + /// + /// This function can be used to create objects from fonts that are installed in the system + /// as follows. + /// + /// fond = GetResource( 'FOND', fontName ); + /// error = FT_New_Face_From_FOND( library, fond, 0, &face ); + /// + /// + /// A FOND resource. + /// Only supported for the -1 ‘sanity check’ special case. + /// A handle to a new face object. + 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); + } + + /// + /// Create a new face object from a given resource and typeface index using an FSSpec to the font file. + /// + /// + /// is identical to except it accepts an FSSpec instead + /// of a path. + /// + /// FSSpec to the font file. + /// The index of the face within the resource. The first face has index 0. + /// A handle to a new face object. + 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); + } + + /// + /// Create a new face object from a given resource and typeface index using an FSRef to the font file. + /// + /// + /// is identical to except it accepts an FSRef instead of + /// a path. + /// + /// FSRef to the font file. + /// The index of the face within the resource. The first face has index 0. + /// A handle to a new face object. + 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 +#endif + + #region Module Management + + /// + /// Add a new module to a given library instance. + /// + /// + /// 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. + /// + /// A pointer to class descriptor for the module. + 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); + } + + /// + /// Find a module by its name. + /// + /// + /// FreeType's internal modules aren't documented very well, and you should look up the source code for + /// details. + /// + /// The module's name (as an ASCII string). + /// A module handle. 0 if none was found. + 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)); + } + + /// + /// Remove a given module from a library instance. + /// + /// + /// The module object is destroyed by the function in case of success. + /// + /// A handle to a module object. + 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); + } + + /// + /// Set a property for a given module. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection + /// of the module's documentation. + /// + /// Note that only a few modules have properties. + /// A generic pointer to a variable or structure which gives the new value of the property. + /// The exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertySet(string moduleName, string propertyName, IntPtr value) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + Error err = FT.FT_Property_Set(Reference, moduleName, propertyName, value); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Set a property for a given module. + /// + /// The type of property to set. + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection + /// of the module's documentation. + /// + /// Note that only a few modules have properties. + /// A generic pointer to a variable or structure which gives the new value of the property. + /// The exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertySet(string moduleName, string propertyName, ref T value) + where T : struct + { + GCHandle gch = GCHandle.Alloc(value, GCHandleType.Pinned); + PropertySet(moduleName, propertyName, gch.AddrOfPinnedObject()); + gch.Free(); + } + + /// + /// Set a property for a given module. + /// + /// The type of property to set. + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection + /// of the module's documentation. + /// + /// Note that only a few modules have properties. + /// A generic pointer to a variable or structure which gives the new value of the property. + /// The exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertySet(string moduleName, string propertyName, T value) + where T : struct + { + PropertySet(moduleName, propertyName, ref value); + } + + /// + /// Set a property for a given module. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection + /// of the module's documentation. + /// + /// Note that only a few modules have properties. + /// A generic pointer to a variable or structure which gives the new value of the property. + /// The exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertySet(string moduleName, string propertyName, GlyphToScriptMapProperty value) + { + var rec = value.Rec; + PropertySet(moduleName, propertyName, ref rec); + } + + /// + /// Set a property for a given module. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection + /// of the module's documentation. + /// + /// Note that only a few modules have properties. + /// A generic pointer to a variable or structure which gives the new value of the property. + /// The exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertySet(string moduleName, string propertyName, IncreaseXHeightProperty value) + { + var rec = value.Rec; + PropertySet(moduleName, propertyName, ref rec); + } + + /// + /// Get a module's property value. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// A generic pointer to a variable or structure which gives the value of the property. The + /// exact definition of ‘value’ is dependent on the property; see the ‘Synopsis’ subsection of the module's + /// documentation. + public void PropertyGet(string moduleName, string propertyName, IntPtr value) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + Error err = FT.FT_Property_Get(Reference, moduleName, propertyName, value); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Get a module's property value. + /// + /// The type of property to get. + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// The value read from the module. + public void PropertyGet(string moduleName, string propertyName, out T value) + where T : struct + { + value = default(T); + + GCHandle gch = GCHandle.Alloc(value, GCHandleType.Pinned); + PropertyGet(moduleName, propertyName, gch.AddrOfPinnedObject()); + value = PInvokeHelper.PtrToStructure(gch.AddrOfPinnedObject()); + gch.Free(); + } + + /// + /// Get a module's property value. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// The value read from the module. + [Obsolete("Use PropertyGetGlyphToScriptMap instead")] + public void PropertyGet(string moduleName, string propertyName, out GlyphToScriptMapProperty value) + { + value = PropertyGetGlyphToScriptMap(moduleName, propertyName); + } + + /// + /// Get a module's property value. + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// The value read from the module. + [Obsolete("Use PropertyGetIncreaseXHeight instead")] + public void PropertyGet(string moduleName, string propertyName, out IncreaseXHeightProperty value) + { + value = PropertyGetIncreaseXHeight(moduleName, propertyName); + } + + /// + /// Gets a module's property value of the type . + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// The value read from the module. + public GlyphToScriptMapProperty PropertyGetGlyphToScriptMap(string moduleName, string propertyName) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + GlyphToScriptMapPropertyRec rec; + PropertyGet(moduleName, propertyName, out rec); + + Face face = childFaces.Find(f => f.Reference == rec.face); + return new GlyphToScriptMapProperty(rec, face); + } + + /// + /// Gets a module's property value of the type . + /// + /// The module name. + /// The property name. Properties are described in the ‘Synopsis’ subsection of the + /// module's documentation. + /// The value read from the module. + public IncreaseXHeightProperty PropertyGetIncreaseXHeight(string moduleName, string propertyName) + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + IncreaseXHeightPropertyRec rec; + PropertyGet(moduleName, propertyName, out rec); + + Face face = childFaces.Find(f => f.Reference == rec.face); + return new IncreaseXHeightProperty(rec, face); + } + + /// + /// Set a debug hook function for debugging the interpreter of a font format. + /// + /// + /// Currently, four debug hook slots are available, but only two (for the TrueType and the Type 1 interpreter) + /// are defined. + /// + /// 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. + /// + /// The index of the debug hook. You should use the values defined in ‘ftobjs.h’, e.g., + /// ‘FT_DEBUG_HOOK_TRUETYPE’. + /// The function used to debug the interpreter. + [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); + } + + /// + /// Add the set of default drivers to a given library object. This is only useful when you create a library + /// object with (usually to plug a custom memory manager). + /// + public void AddDefaultModules() + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + FT.FT_Add_Default_Modules(Reference); + } + + /// + /// Retrieve the current renderer for a given glyph format. + /// + /// + /// 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. + /// + /// To add a new renderer, simply use . To retrieve a renderer by its name, use + /// . + /// + /// The glyph format. + /// A renderer handle. 0 if none found. + [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)); + } + + /// + /// Set the current renderer to use, and set additional mode. + /// + /// + /// In case of success, the renderer will be used to convert glyph images in the renderer's known format into + /// bitmaps. + /// + /// This doesn't change the current renderer for other formats. + /// + /// 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. + /// + /// A handle to the renderer object. + /// The number of additional parameters. + /// Additional parameters. + [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 = parameters.Select(x => x.Record).ToArray(); + 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 + + /// + /// This function is used to apply color filtering to LCD decimated bitmaps, like the ones used when calling + /// with or + /// . + /// + /// + /// This feature is always disabled by default. Clients must make an explicit call to this function with a + /// ‘filter’ value other than in order to enable it. + /// + /// Due to PATENTS covering subpixel rendering, this function doesn't do anything except returning + /// 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. + /// + /// The filter affects glyph bitmaps rendered through , + /// , , and . + /// + /// It does not affect the output of and + /// . + /// + /// 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 + /// , the filter adds up to 3 pixels to the left, and up to 3 pixels to the right. + /// + /// The bitmap offset values are adjusted correctly, so clients shouldn't need to modify their layout and glyph + /// positioning code when enabling the filter. + /// + /// + /// The filter type. + /// + /// You can use here to disable this feature, or + /// to use a default filter that should work well on most LCD screens. + /// + 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); + } + + /// + /// Use this function to override the filter weights selected by . By default, + /// FreeType uses the quintuple (0x00, 0x55, 0x56, 0x55, 0x00) for , and (0x10, + /// 0x40, 0x70, 0x40, 0x10) for and . + /// + /// + /// Due to PATENTS covering subpixel rendering, this function doesn't do anything except returning + /// 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. + /// + /// This function must be called after to have any effect. + /// + /// + /// A pointer to an array; the function copies the first five bytes and uses them to specify the filter + /// weights. + /// + 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 + + /// + /// Return an value to indicate which level of the TrueType virtual machine a given + /// library instance supports. + /// + /// A value indicating which level is supported. + public EngineType GetTrueTypeEngineType() + { + if (disposed) + throw new ObjectDisposedException("Library", "Cannot access a disposed object."); + + return FT.FT_Get_TrueType_Engine_Type(Reference); + } + + #endregion + + /// + /// Disposes the Library. + /// + 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); + reference = IntPtr.Zero; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/ListNode.cs b/SharpFont/Source/SharpFontShared/ListNode.cs new file mode 100644 index 000000000..dd094d3b4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/ListNode.cs @@ -0,0 +1,108 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used to hold a single list element. + /// + public class ListNode: NativeObject + { + #region Fields + + private ListNodeRec rec; + + #endregion + + #region Constructors + + internal ListNode(IntPtr reference): base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets the previous element in the list. NULL if first. + /// + public ListNode Previous + { + get + { + if (rec.prev == IntPtr.Zero) + return null; + + return new ListNode(rec.prev); + } + } + + /// + /// Gets the next element in the list. NULL if last. + /// + public ListNode Next + { + get + { + if (rec.next == IntPtr.Zero) + return null; + + return new ListNode(rec.next); + } + } + + /// + /// Gets a typeless pointer to the listed object. + /// + public IntPtr Data + { + get + { + return rec.data; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/LoadFlags.cs b/SharpFont/Source/SharpFontShared/LoadFlags.cs new file mode 100644 index 000000000..54cc15c1a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/LoadFlags.cs @@ -0,0 +1,196 @@ +#region MIT License +/*Copyright (c) 2012-2016 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants used with to indicate what kind of operations to + /// perform during glyph loading. + /// + /// + /// By default, hinting is enabled and the font's native hinter (see ) is preferred + /// over the auto-hinter. You can disable hinting by setting or change the + /// precedence by setting . You can also set + /// in case you don't want the auto-hinter to be used at all. + /// + /// See the description of for a special exception (affecting only a handful of + /// Asian fonts). + /// + /// Besides deciding which hinter to use, you can also decide which hinting algorithm to use. See + /// for details. + /// + [Flags] + [CLSCompliant(false)] + public enum LoadFlags : uint + { + /// + /// Corresponding to 0, this value is used as the default glyph load operation. In this case, the following + /// happens: + /// + /// + /// FreeType looks for a bitmap for the glyph corresponding to the face's current size. If one is found, the + /// function returns. The bitmap data can be accessed from the glyph slot (see note below). + /// + /// + /// If no embedded bitmap is searched or found, FreeType looks for a scalable outline. If one is found, it is + /// loaded from the font file, scaled to device pixels, then ‘hinted’ to the pixel grid in order to optimize + /// it. The outline data can be accessed from the glyph slot (see note below). + /// + /// + /// Note that by default, the glyph loader doesn't render outlines into bitmaps. The following flags are used + /// to modify this default behaviour to more specific and useful cases. + /// + Default = 0x000000, + + /// + /// Don't scale the outline glyph loaded, but keep it in font units. + /// + /// This flag implies and , and unsets + /// . + /// + NoScale = 0x000001, + + /// + /// Disable hinting. This generally generates ‘blurrier’ bitmap glyph when the glyph is rendered in any of the + /// anti-aliased modes. See also the note below. + /// + /// This flag is implied by . + /// + NoHinting = 0x000002, + + /// + /// Call after the glyph is loaded. By default, the glyph is rendered in + /// mode. This can be overridden by or + /// . + /// + /// This flag is unset by . + /// + Render = 0x000004, + + /// + /// Ignore bitmap strikes when loading. Bitmap-only fonts ignore this flag. + /// + /// always sets this flag. + /// + NoBitmap = 0x000008, + + /// + /// Load the glyph for vertical text layout. Don't use it as it is problematic currently. + /// + VerticalLayout = 0x000010, + + /// + /// Indicates that the auto-hinter is preferred over the font's native hinter. See also the note below. + /// + ForceAutohint = 0x000020, + + /// + /// Indicates that the font driver should crop the loaded bitmap glyph (i.e., remove all space around its black + /// bits). Not all drivers implement this. + /// + CropBitmap = 0x000040, + + /// + /// Indicates that the font driver should perform pedantic verifications during glyph loading. This is mostly + /// used to detect broken glyphs in fonts. By default, FreeType tries to handle broken fonts also. + /// + Pedantic = 0x000080, + + /// + /// Ignored. Deprecated. + /// + [Obsolete("Ignored. Deprecated.")] + IgnoreGlobalAdvanceWidth = 0x000200, + + /// + /// This flag is only used internally. It merely indicates that the font driver should not load composite + /// glyphs recursively. Instead, it should set the ‘num_subglyph’ and ‘subglyphs’ values of the glyph slot + /// accordingly, and set ‘glyph->format’ to . + /// + /// The description of sub-glyphs is not available to client applications for now. + /// + /// This flag implies and . + /// + NoRecurse = 0x000400, + + /// + /// Indicates that the transform matrix set by should be ignored. + /// + IgnoreTransform = 0x000800, + + /// + /// This flag is used with to indicate that you want to render an outline glyph + /// to a 1-bit monochrome bitmap glyph, with 8 pixels packed into each byte of the bitmap data. + /// + /// Note that this has no effect on the hinting algorithm used. You should rather use + /// so that the monochrome-optimized hinting algorithm is used. + /// + Monochrome = 0x001000, + + /// + /// Indicates that the ‘linearHoriAdvance’ and ‘linearVertAdvance’ fields of should be + /// kept in font units. See for details. + /// + LinearDesign = 0x002000, + + /// + /// Disable auto-hinter. See also the note below. + /// + NoAutohint = 0x008000, + + /// + /// This flag is used to request loading of color embedded-bitmap images. The resulting color bitmaps, if + /// available, will have the format. When the flag is not used and color bitmaps + /// are found, they will be converted to 256-level gray bitmaps transparently. Those bitmaps will be in the + /// format. + /// + Color = 0x100000, + + /// + /// This flag sets computing glyph metrics without the use of bundled + /// metrics tables. Well-behaving fonts have optimized bundled metrics + /// and these should be used. This flag is mainly used by font + /// validating or font editing applications which need to ignore, verify + /// or edit those tables. + /// + ComputeMetrics = 0x200000, + + /// + /// A bit-flag to be OR-ed with the ‘flags’ parameter of the and + /// functions. + /// + /// If set, it indicates that you want these functions to fail if the corresponding hinting mode or font driver + /// doesn't allow for very quick advance computation. + /// + /// Typically, glyphs which are either unscaled, unhinted, bitmapped, or light-hinted can have their advance + /// width computed very quickly. + /// + /// Normal and bytecode hinted modes, which require loading, scaling, and hinting of the glyph outline, are + /// extremely slow by comparison. + /// + AdvanceFlagFastOnly = 0x20000000 + } +} diff --git a/SharpFont/Source/SharpFontShared/LoadTarget.cs b/SharpFont/Source/SharpFontShared/LoadTarget.cs new file mode 100644 index 000000000..c41aad440 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/LoadTarget.cs @@ -0,0 +1,88 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of values that are used to select a specific hinting algorithm to use by the hinter. You should OR one + /// of these values to your ‘load_flags’ when calling . + /// + /// Note that font's native hinters may ignore the hinting algorithm you have specified (e.g., the TrueType + /// bytecode interpreter). You can set to ensure that the auto-hinter is + /// used. + /// + /// Also note that is an exception, in that it always implies + /// . + /// + /// + /// You should use only one of the values in your ‘load_flags’. They can't be ORed. + /// + /// If is also set, the glyph is rendered in the corresponding mode (i.e., the mode + /// which matches the used algorithm best) unless is set. + /// + /// You can use a hinting algorithm that doesn't correspond to the same rendering mode. As an example, it is + /// possible to use the ‘light’ hinting algorithm and have the results rendered in horizontal LCD pixel mode, with + /// code like: + /// + /// FT_Load_Glyph( face, glyph_index, + /// load_flags | FT_LOAD_TARGET_LIGHT ); + /// + /// FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD ); + /// + /// + public enum LoadTarget + { + /// + /// This corresponds to the default hinting algorithm, optimized for standard gray-level rendering. For + /// monochrome output, use instead. + /// + Normal = (RenderMode.Normal & 15) << 16, + + /// + /// A lighter hinting algorithm for non-monochrome modes. Many generated glyphs are more fuzzy but better + /// resemble its original shape. A bit like rendering on Mac OS X. + /// + /// As a special exception, this target implies . + /// + Light = (RenderMode.Light & 15) << 16, + + /// + /// Strong hinting algorithm that should only be used for monochrome output. The result is probably unpleasant + /// if the glyph is rendered in non-monochrome modes. + /// + Mono = (RenderMode.Mono & 15) << 16, + + /// + /// A variant of optimized for horizontally decimated LCD displays. + /// + Lcd = (RenderMode.Lcd & 15) << 16, + + /// + /// A variant of optimized for vertically decimated LCD displays. + /// + VerticalLcd = (RenderMode.VerticalLcd & 15) << 16 + } +} diff --git a/SharpFont/Source/SharpFontShared/Memory.cs b/SharpFont/Source/SharpFontShared/Memory.cs new file mode 100644 index 000000000..9deb8a4a7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Memory.cs @@ -0,0 +1,174 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function used to allocate ‘size’ bytes from ‘memory’. + /// + /// A handle to the source memory manager. + /// The size in bytes to allocate. + /// Address of new memory block. 0 in case of failure. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr AllocFunc(NativeReference memory, IntPtr size); + + /// + /// A function used to release a given block of memory. + /// + /// A handle to the source memory manager. + /// The address of the target memory block. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void FreeFunc(NativeReference memory, IntPtr block); + + /// + /// A function used to re-allocate a given block of memory. + /// + /// + /// In case of error, the old block must still be available. + /// + /// A handle to the source memory manager. + /// The block's current size in bytes. + /// The block's requested new size. + /// The block's current address. + /// New block address. 0 in case of memory shortage. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr ReallocFunc(NativeReference memory, IntPtr currentSize, IntPtr newSize, IntPtr block); + + /// + /// A structure used to describe a given memory manager to FreeType 2. + /// + public class Memory: NativeObject + { + #region Fields + + private MemoryRec rec; + + #endregion + + #region Constructors + + internal Memory(IntPtr reference): base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets a generic typeless pointer for user data. + /// + public IntPtr User + { + get + { + return rec.user; + } + } + + /// + /// Gets a pointer type to an allocation function. + /// + public AllocFunc Allocate + { + get + { + return rec.alloc; + } + } + + /// + /// Gets a pointer type to an memory freeing function. + /// + public FreeFunc Free + { + get + { + return rec.free; + } + } + + /// + /// Gets a pointer type to a reallocation function. + /// + public ReallocFunc Reallocate + { + get + { + return rec.realloc; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + + #region Methods + + /// + /// Decompress a zipped input buffer into an output buffer. This function is modeled after zlib's ‘uncompress’ + /// function. + /// + /// + /// This function may return if your build of FreeType was not + /// compiled with zlib support. + /// + /// The input buffer. + /// The output buffer. + /// The length of the used data in output. + public unsafe int GzipUncompress(byte[] input, byte[] output) + { + IntPtr len = (IntPtr)output.Length; + + fixed (byte* inPtr = input, outPtr = output) + { + Error err = FT.FT_Gzip_Uncompress(Reference, (IntPtr)outPtr, ref len, (IntPtr)inPtr, (IntPtr)input.Length); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + return (int)len; + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Module.cs b/SharpFont/Source/SharpFontShared/Module.cs new file mode 100644 index 000000000..cd59ec699 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Module.cs @@ -0,0 +1,43 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A handle to a given FreeType module object. Each module can be a font driver, a renderer, or anything else that + /// provides services to the formers. + /// + public sealed class Module : NativeObject + { + #region Constructors + + internal Module(IntPtr reference): base(reference) + { + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/ModuleClass.cs b/SharpFont/Source/SharpFontShared/ModuleClass.cs new file mode 100644 index 000000000..d6a80db57 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/ModuleClass.cs @@ -0,0 +1,194 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function used to initialize (not create) a new module object. + /// + /// The module to initialize. + /// FreeType error code. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Error ModuleConstructor(NativeReference module); + + /// + /// A function used to finalize (not destroy) a given module object. + /// + /// The module to finalize. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ModuleDestructor(NativeReference module); + + /// + /// A function used to query a given module for a specific interface. + /// + /// The module that contains the interface. + /// The name of the interface in the module. + /// The interface. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr ModuleRequester(NativeReference module, [MarshalAs(UnmanagedType.LPStr)] string name); + + /// + /// The module class descriptor. + /// + public class ModuleClass : NativeObject + { + #region Fields + + private ModuleClassRec rec; + + #endregion + + #region Constructors + + internal ModuleClass(IntPtr reference) : base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets bit flags describing the module. + /// + [CLSCompliant(false)] + public uint Flags + { + get + { + return rec.module_flags; + } + } + + /// + /// Gets the size of one module object/instance in bytes. + /// + public int Size + { + get + { + return (int)rec.module_size; + } + } + + /// + /// Gets the name of the module. + /// + public string Name + { + get + { + return rec.module_name; + } + } + + /// + /// Gets the version, as a 16.16 fixed number (major.minor). + /// + public Fixed16Dot16 Version + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.module_version); + } + } + + /// + /// Gets the version of FreeType this module requires, as a 16.16 fixed number (major.minor). Starts at version + /// 2.0, i.e., 0x20000. + /// + public Fixed16Dot16 Requires + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.module_requires); + } + } + + /// + /// Get the module interface. + /// + public IntPtr Interface + { + get + { + return rec.module_interface; + } + } + + /// + /// Gets the initializing function. + /// + public ModuleConstructor Init + { + get + { + return rec.module_init; + } + } + + /// + /// Gets the finalizing function. + /// + public ModuleDestructor Done + { + get + { + return rec.module_done; + } + } + + /// + /// Gets the interface requesting function. + /// + public ModuleRequester GetInterface + { + get + { + return rec.get_interface; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMAxisRec.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMAxisRec.cs new file mode 100644 index 000000000..75188cff1 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMAxisRec.cs @@ -0,0 +1,42 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.MultipleMasters.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct MMAxisRec + { + [MarshalAs(UnmanagedType.LPStr)] + internal string name; + + internal FT_Long minimum; + internal FT_Long maximum; + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMVarRec.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMVarRec.cs new file mode 100644 index 000000000..12ce4b690 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MMVarRec.cs @@ -0,0 +1,39 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.MultipleMasters.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct MMVarRec + { + internal uint num_axis; + internal uint num_designs; + internal uint num_namedstyles; + internal IntPtr axis; + internal IntPtr namedstyle; + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MultiMasterRec.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MultiMasterRec.cs new file mode 100644 index 000000000..8c1d66d25 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/MultiMasterRec.cs @@ -0,0 +1,39 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.MultipleMasters.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct MultiMasterRec + { + internal uint num_axis; + internal uint num_designs; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + internal MMAxisRec[] axis; + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarAxisRec.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarAxisRec.cs new file mode 100644 index 000000000..9524436d2 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarAxisRec.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.MultipleMasters.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct VarAxisRec + { + [MarshalAs(UnmanagedType.LPStr)] + internal string name; + + internal FT_Long minimum; + internal FT_Long def; + internal FT_Long maximum; + + internal FT_ULong tag; + internal uint strid; + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarNamedStyleRec.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarNamedStyleRec.cs new file mode 100644 index 000000000..c0ee4fcf0 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/Internal/VarNamedStyleRec.cs @@ -0,0 +1,36 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.MultipleMasters.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct VarNamedStyleRec + { + internal IntPtr coords; + internal uint strid; + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/MMAxis.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/MMAxis.cs new file mode 100644 index 000000000..9cbed9a5a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/MMAxis.cs @@ -0,0 +1,111 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.MultipleMasters.Internal; + +namespace SharpFont.MultipleMasters +{ + /// + /// A simple structure used to model a given axis in design space for Multiple Masters fonts. + /// + /// This structure can't be used for GX var fonts. + /// + public class MMAxis + { + #region Fields + + private IntPtr reference; + private MMAxisRec rec; + + #endregion + + #region Constructors + + internal MMAxis(IntPtr reference) + { + Reference = reference; + } + + internal MMAxis(MMAxisRec axisInternal) + { + this.rec = axisInternal; + } + + #endregion + + #region Properties + + /// + /// Gets the axis's name. + /// + public string Name + { + get + { + return rec.name; + } + } + + /// + /// Gets the axis's minimum design coordinate. + /// + public int Minimum + { + get + { + return (int)rec.minimum; + } + } + + /// + /// Gets the axis's maximum design coordinate. + /// + public int Maximum + { + get + { + return (int)rec.maximum; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/MMVar.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/MMVar.cs new file mode 100644 index 000000000..3969583ab --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/MMVar.cs @@ -0,0 +1,134 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.MultipleMasters.Internal; + +namespace SharpFont.MultipleMasters +{ + /// + /// A structure used to model the axes and space of a Multiple Masters or GX var distortable font. + /// + /// Some fields are specific to one format and not to the other. + /// + public class MMVar + { + #region Fields + + private IntPtr reference; + private MMVarRec rec; + + #endregion + + #region Constructors + + internal MMVar(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the number of axes. The maximum value is 4 for MM; no limit in GX. + /// + [CLSCompliant(false)] + public uint AxisCount + { + get + { + return rec.num_axis; + } + } + + /// + /// Gets the number of designs; should be normally 2^num_axis for MM fonts. Not meaningful for GX (where every + /// glyph could have a different number of designs). + /// + [CLSCompliant(false)] + public uint DesignsCount + { + get + { + return rec.num_designs; + } + } + + /// + /// Gets the number of named styles; only meaningful for GX which allows certain design coordinates to have a + /// string ID (in the ‘name’ table) associated with them. The font can tell the user that, for example, + /// Weight=1.5 is ‘Bold’. + /// + [CLSCompliant(false)] + public uint NamedStylesCount + { + get + { + return rec.num_namedstyles; + } + } + + /// + /// Gets a table of axis descriptors. GX fonts contain slightly more data than MM. + /// + public VarAxis Axis + { + get + { + return new VarAxis(rec.axis); + } + } + + /// + /// Gets a table of named styles. Only meaningful with GX. + /// + public VarNamedStyle NamedStyle + { + get + { + return new VarNamedStyle(rec.namedstyle); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/MultiMaster.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/MultiMaster.cs new file mode 100644 index 000000000..aa0c53200 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/MultiMaster.cs @@ -0,0 +1,114 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.MultipleMasters.Internal; + +namespace SharpFont.MultipleMasters +{ + /// + /// A structure used to model the axes and space of a Multiple Masters font. + /// + /// This structure can't be used for GX var fonts. + /// + public class MultiMaster + { + #region Fields + + private IntPtr reference; + private MultiMasterRec rec; + + #endregion + + #region Constructors + + internal MultiMaster(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the number of axes. Cannot exceed 4. + /// + [CLSCompliant(false)] + public uint AxisCount + { + get + { + return rec.num_axis; + } + } + + /// + /// Gets the number of designs; should be normally 2^num_axis even though the Type 1 specification strangely + /// allows for intermediate designs to be present. This number cannot exceed 16. + /// + [CLSCompliant(false)] + public uint DesignsCount + { + get + { + return rec.num_designs; + } + } + + /// + /// Gets a table of axis descriptors. + /// + public MMAxis[] Axis + { + get + { + MMAxis[] axis = new MMAxis[rec.num_axis]; + + for (int i = 0; i < rec.num_axis; i++) + axis[i] = new MMAxis(rec.axis[i]); + + return axis; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/VarAxis.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/VarAxis.cs new file mode 100644 index 000000000..8c9b75241 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/VarAxis.cs @@ -0,0 +1,140 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.MultipleMasters.Internal; + +namespace SharpFont.MultipleMasters +{ + /// + /// A simple structure used to model a given axis in design space for Multiple Masters and GX var fonts. + /// + public class VarAxis + { + #region Fields + + private IntPtr reference; + private VarAxisRec rec; + + #endregion + + #region Constructors + + internal VarAxis(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the axis's name. Not always meaningful for GX. + /// + public string Name + { + get + { + return rec.name; + } + } + + /// + /// Gets the axis's minimum design coordinate. + /// + public int Minimum + { + get + { + return (int)rec.minimum; + } + } + + /// + /// Gets the axis's default design coordinate. FreeType computes meaningful default values for MM; it is then + /// an integer value, not in 16.16 format. + /// + public int Default + { + get + { + return (int)rec.def; + } + } + + /// + /// Gets the axis's maximum design coordinate. + /// + public int Maximum + { + get + { + return (int)rec.maximum; + } + } + + /// + /// Gets the axis's tag (the GX equivalent to ‘name’). FreeType provides default values for MM if possible. + /// + [CLSCompliant(false)] + public uint Tag + { + get + { + return (uint)rec.tag; + } + } + + /// + /// Gets the entry in ‘name’ table (another GX version of ‘name’). Not meaningful for MM. + /// + [CLSCompliant(false)] + public uint StrId + { + get + { + return rec.strid; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/MultipleMasters/VarNamedStyle.cs b/SharpFont/Source/SharpFontShared/MultipleMasters/VarNamedStyle.cs new file mode 100644 index 000000000..c6a5c2234 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/MultipleMasters/VarNamedStyle.cs @@ -0,0 +1,96 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.MultipleMasters.Internal; + +namespace SharpFont.MultipleMasters +{ + /// + /// A simple structure used to model a named style in a GX var font. + /// + /// This structure can't be used for MM fonts. + /// + public class VarNamedStyle + { + #region Fields + + private IntPtr reference; + private VarNamedStyleRec rec; + + #endregion + + #region Constructors + + internal VarNamedStyle(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the design coordinates for this style. This is an array with one entry for each axis. + /// + public IntPtr Coordinates + { + get + { + return rec.coords; + } + } + + /// + /// Gets the entry in ‘name’ table identifying this style. + /// + [CLSCompliant(false)] + public uint StrId + { + get + { + return rec.strid; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/OpenArgs.cs b/SharpFont/Source/SharpFontShared/OpenArgs.cs new file mode 100644 index 000000000..d32ac6d2b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OpenArgs.cs @@ -0,0 +1,204 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used to indicate how to open a new font file or stream. A pointer to such a structure can be used + /// as a parameter for the functions and . + /// + /// + /// The stream type is determined by the contents of which are tested in the following order by + /// : + /// + /// + /// If the bit is set, assume that this is a memory file of + /// bytes, located at . The data are are not copied, and the client is responsible for + /// releasing and destroying them after the corresponding call to . + /// + /// + /// Otherwise, if the bit is set, assume that a custom input stream + /// is used. + /// + /// + /// Otherwise, if the bit is set, assume that this is a normal file and use + /// to open it. + /// + /// + /// If the bit is set, only tries to open the file + /// with the driver whose handler is in . + /// + /// + /// If the bit is set, the parameters given by and + /// is used. They are ignored otherwise. + /// + /// + /// Ideally, both the and fields should be tagged as ‘const’; this is + /// missing for API backwards compatibility. In other words, applications should treat them as read-only. + /// + public sealed class OpenArgs + { + #region Fields + + private IntPtr reference; + private OpenArgsRec rec; + + #endregion + + #region Constructors + + internal OpenArgs(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets a set of bit flags indicating how to use the structure. + /// + public OpenFlags Flags + { + get + { + return rec.flags; + } + } + + /// + /// Gets the first byte of the file in memory. + /// + public IntPtr MemoryBase + { + get + { + return rec.memory_base; + } + } + + /// + /// Gets the size in bytes of the file in memory. + /// + public int MemorySize + { + get + { + return (int)rec.memory_size; + } + } + + /// + /// Gets a pointer to an 8-bit file pathname. + /// + public string PathName + { + get + { + return rec.pathname; + } + } + + /// + /// Gets a handle to a source stream object. + /// + public FTStream Stream + { + get + { + return new FTStream(rec.stream); + } + } + + /// + /// Gets the font driver to use to open the face. If set to 0, FreeType tries to load the face with each one of + /// the drivers in its list. + /// + /// This field is exclusively used by . + public Module Driver + { + get + { + return new Module(rec.driver); + } + } + + /// + /// Gets the number of extra parameters. + /// + public int ParamsCount + { + get + { + return rec.num_params; + } + } + + /// + /// Gets the extra parameters passed to the font driver when opening a new face. + /// + public Parameter[] Params + { + get + { + int count = ParamsCount; + + if (count == 0) + return null; + + Parameter[] parameters = new Parameter[count]; + IntPtr array = rec.@params; + + for (int i = 0; i < count; i++) + { + parameters[i] = new Parameter(new IntPtr(array.ToInt64() + ParameterRec.SizeInBytes * i)); + } + + return parameters; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/OpenFlags.cs b/SharpFont/Source/SharpFontShared/OpenFlags.cs new file mode 100644 index 000000000..84af4fdd7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OpenFlags.cs @@ -0,0 +1,54 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants used within the ‘flags’ field of the structure. + /// + /// + /// The , , and flags + /// are mutually exclusive. + /// + [Flags] + public enum OpenFlags + { + /// This is a memory-based stream. + Memory = 0x01, + + /// Copy the stream from the ‘stream’ field. + Stream = 0x02, + + /// Create a new input stream from a C path name. + PathName = 0x04, + + /// Use the ‘driver’ field. + Driver = 0x08, + + /// Use the ‘num_params’ and ‘params’ fields. + Params = 0x10 + } +} diff --git a/SharpFont/Source/SharpFontShared/OpenTypeValidationFlags.cs b/SharpFont/Source/SharpFontShared/OpenTypeValidationFlags.cs new file mode 100644 index 000000000..559f4d810 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OpenTypeValidationFlags.cs @@ -0,0 +1,58 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants used with to indicate which OpenType tables + /// should be validated. + /// + [Flags] + [CLSCompliant(false)] + public enum OpenTypeValidationFlags : uint + { + /// Validate BASE table. + Base = 0x0100, + + /// Validate GDEF table. + Gdef = 0x0200, + + /// Validate GPOS table. + Gpos = 0x0400, + + /// Validate GSUB table. + Gsub = 0x0800, + + /// Validate JSTF table. + Jstf = 0x1000, + + /// Validate MATH table. + Math = 0x2000, + + /// Validate all OpenType tables. + All = Base | Gdef | Gpos | Gsub | Jstf | Math + } +} diff --git a/SharpFont/Source/SharpFontShared/Orientation.cs b/SharpFont/Source/SharpFontShared/Orientation.cs new file mode 100644 index 000000000..c609c2749 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Orientation.cs @@ -0,0 +1,66 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of values used to describe an outline's contour orientation. + /// + /// The TrueType and PostScript specifications use different conventions to determine whether outline contours + /// should be filled or unfilled. + /// + public enum Orientation + { + /// + /// According to the TrueType specification, clockwise contours must be filled, and counter-clockwise ones must + /// be unfilled. + /// + TrueType = 0, + + /// + /// According to the PostScript specification, counter-clockwise contours must be filled, and clockwise ones + /// must be unfilled. + /// + PostScript = 1, + + /// + /// This is identical to , but is used to remember that in TrueType, everything that is + /// to the right of the drawing direction of a contour must be filled. + /// + FillRight = TrueType, + + /// + /// This is identical to , but is used to remember that in PostScript, everything that + /// is to the left of the drawing direction of a contour must be filled. + /// + FillLeft = PostScript, + + /// + /// The orientation cannot be determined. That is, different parts of the glyph have different orientation. + /// + None + } +} diff --git a/SharpFont/Source/SharpFontShared/Outline.cs b/SharpFont/Source/SharpFontShared/Outline.cs new file mode 100644 index 000000000..6e6dc8463 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Outline.cs @@ -0,0 +1,698 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// This structure is used to describe an outline to the scan-line converter. + /// + /// + /// The B/W rasterizer only checks bit 2 in the ‘tags’ array for the first point of each contour. The drop-out mode + /// as given with , , and + /// in ‘flags’ is then overridden. + /// + public sealed class Outline : IDisposable + { + #region Fields + + private bool disposed; + private bool duplicate; + + private IntPtr reference; + private OutlineRec rec; + + private Library parentLibrary; + private Memory parentMemory; + + #endregion + + #region Constructor + + /// + /// Initializes a new instance of the class. + /// + /// + /// The reason why this function takes a ‘library’ parameter is simply to use the library's memory allocator. + /// + /// + /// A handle to the library object from where the outline is allocated. Note however that the new outline will + /// not necessarily be freed, when destroying the library, by . + /// + /// The maximum number of points within the outline. + /// The maximum number of contours within the outline. + [CLSCompliant(false)] + public Outline(Library library, uint pointsCount, int contoursCount) + { + IntPtr reference; + Error err = FT.FT_Outline_New(library.Reference, pointsCount, contoursCount, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + parentLibrary = library; + parentLibrary.AddChildOutline(this); + } + + /// + /// Initializes a new instance of the class. + /// + /// A handle to the memory object from where the outline is allocated. + /// The maximum number of points within the outline. + /// The maximum number of contours within the outline. + [CLSCompliant(false)] + public Outline(Memory memory, uint pointsCount, int contoursCount) + { + IntPtr reference; + Error err = FT.FT_Outline_New_Internal(memory.Reference, pointsCount, contoursCount, out reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + parentMemory = memory; //TODO Should Memory be disposable as well? + } + + internal Outline(IntPtr reference, OutlineRec outlineInt) + { + this.rec = outlineInt; + this.reference = reference; + + duplicate = true; + } + + /// + /// Finalizes an instance of the class. + /// + ~Outline() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + /// + /// Gets the number of contours in the outline. + /// + public short ContoursCount + { + get + { + if (disposed) + throw new ObjectDisposedException("ContoursCount", "Cannot access a disposed object."); + + return rec.n_contours; + } + } + + /// + /// Gets the number of points in the outline. + /// + public short PointsCount + { + get + { + if (disposed) + throw new ObjectDisposedException("PointsCount", "Cannot access a disposed object."); + + return rec.n_points; + } + } + + /// + /// Gets a pointer to an array of ‘PointsCount’ elements, giving the outline's point + /// coordinates. + /// + public FTVector[] Points + { + get + { + if (disposed) + throw new ObjectDisposedException("Points", "Cannot access a disposed object."); + + int count = PointsCount; + + if (count == 0) + return null; + + FTVector[] points = new FTVector[count]; + IntPtr array = rec.points; + + for (int i = 0; i < count; i++) + { + points[i] = new FTVector(new IntPtr(array.ToInt64() + (IntPtr.Size * i * 2))); + } + + return points; + } + } + + /// + /// Gets a pointer to an array of ‘PointsCount’ chars, giving each outline point's type. + /// + /// If bit 0 is unset, the point is ‘off’ the curve, i.e., a Bézier control point, while it is ‘on’ if set. + /// + /// Bit 1 is meaningful for ‘off’ points only. If set, it indicates a third-order Bézier arc control point; and + /// a second-order control point if unset. + /// + /// If bit 2 is set, bits 5-7 contain the drop-out mode (as defined in the OpenType specification; the value is + /// the same as the argument to the SCANMODE instruction). + /// + /// Bits 3 and 4 are reserved for internal purposes. + /// + public byte[] Tags + { + get + { + if (disposed) + throw new ObjectDisposedException("Tags", "Cannot access a disposed object."); + + int count = PointsCount; + + if (count == 0) + return null; + + byte[] tags = new byte[count]; + IntPtr array = rec.tags; + + for (int i = 0; i < count; i++) + { + tags[i] = Marshal.ReadByte(array, sizeof(byte) * i); + } + + return tags; + } + } + + /// + /// Gets an array of ‘ContoursCount’ shorts, giving the end point of each contour within the outline. For + /// example, the first contour is defined by the points ‘0’ to ‘Contours[0]’, the second one is defined by the + /// points ‘Contours[0]+1’ to ‘Contours[1]’, etc. + /// + public short[] Contours + { + get + { + if (disposed) + throw new ObjectDisposedException("Contours", "Cannot access a disposed object."); + + int count = ContoursCount; + + if (count == 0) + return null; + + short[] contours = new short[count]; + IntPtr array = rec.contours; + + for (int i = 0; i < count; i++) + { + contours[i] = Marshal.ReadInt16(array, sizeof(short) * i); + } + + return contours; + } + } + + /// + /// Gets a set of bit flags used to characterize the outline and give hints to the scan-converter and hinter on + /// how to convert/grid-fit it. + /// + /// + public OutlineFlags Flags + { + get + { + if (disposed) + throw new ObjectDisposedException("Flags", "Cannot access a disposed object."); + + return rec.flags; + } + } + + 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; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + + #region Methods + + #region Outline Processing + + /// + /// Copy an outline into another one. Both objects must have the same sizes (number of points & number of + /// contours) when this function is called. + /// + /// A handle to the target outline. + public void Copy(Outline target) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + if (target == null) + throw new ArgumentNullException("target"); + + IntPtr targetRef = target.Reference; + Error err = FT.FT_Outline_Copy(reference, ref targetRef); + target.Reference = reference; + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Apply a simple translation to the points of an outline. + /// + /// The horizontal offset. + /// The vertical offset. + public void Translate(int offsetX, int offsetY) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + FT.FT_Outline_Translate(reference, offsetX, offsetY); + } + + /// + /// Apply a simple 2x2 matrix to all of an outline's points. Useful for applying rotations, slanting, flipping, + /// etc. + /// + /// + /// You can use if you need to translate the outline's points. + /// + /// A pointer to the transformation matrix. + public void Transform(FTMatrix matrix) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + FT.FT_Outline_Transform(reference, ref matrix); + } + + /// + /// Embolden an outline. The new outline will be at most 4 times ‘strength’ pixels wider and higher. You may + /// think of the left and bottom borders as unchanged. + /// + /// Negative ‘strength’ values to reduce the outline thickness are possible also. + /// + /// + /// The used algorithm to increase or decrease the thickness of the glyph doesn't change the number of points; + /// this means that certain situations like acute angles or intersections are sometimes handled incorrectly. + /// + /// If you need ‘better’ metrics values you should call or . + /// + /// + /// FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); + /// if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) + /// FT_Outline_Embolden( &face->slot->outline, strength ); + /// + /// How strong the glyph is emboldened. Expressed in 26.6 pixel format. + public void Embolden(Fixed26Dot6 strength) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + Error err = FT.FT_Outline_Embolden(reference, (IntPtr)strength.Value); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Embolden an outline. The new outline will be ‘xstrength’ pixels wider and ‘ystrength’ pixels higher. + /// Otherwise, it is similar to , which uses the same strength in both directions. + /// + /// + /// How strong the glyph is emboldened in the X direction. Expressed in 26.6 pixel format. + /// + /// + /// How strong the glyph is emboldened in the Y direction. Expressed in 26.6 pixel format. + /// + public void EmboldenXY(int strengthX, int strengthY) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + Error err = FT.FT_Outline_EmboldenXY(reference, strengthX, strengthY); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Reverse the drawing direction of an outline. This is used to ensure consistent fill conventions for + /// mirrored glyphs. + /// + /// + /// This function toggles the bit flag in the outline's ‘flags’ field. + /// + /// It shouldn't be used by a normal client application, unless it knows what it is doing. + /// + public void Reverse() + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + FT.FT_Outline_Reverse(reference); + } + + /// + /// Check the contents of an outline descriptor. + /// + public void Check() + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + Error err = FT.FT_Outline_Check(reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Compute the exact bounding box of an outline. This is slower than computing the control box. However, it + /// uses an advanced algorithm which returns very quickly when the two boxes coincide. Otherwise, the outline + /// Bézier arcs are traversed to extract their extrema. + /// + /// + /// If the font is tricky and the glyph has been loaded with , the resulting + /// BBox is meaningless. To get reasonable values for the BBox it is necessary to load the glyph at a large + /// ppem value (so that the hinting instructions can properly shift and scale the subglyphs), then extracting + /// the BBox which can be eventually converted back to font units. + /// + /// The outline's exact bounding box. + public BBox GetBBox() + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + BBox bbox; + Error err = FT.FT_Outline_Get_BBox(reference, out bbox); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + return bbox; + } + + /// + /// Walk over an outline's structure to decompose it into individual segments and Bézier arcs. This function + /// also emits ‘move to’ operations to indicate the start of new contours in the outline. + /// + /// + /// A table of ‘emitters’, i.e., function pointers called during decomposition to indicate path operations. + /// + /// + /// A typeless pointer which is passed to each emitter during the decomposition. It can be used to store the + /// state during the decomposition. + /// + public void Decompose(OutlineFuncs funcInterface, IntPtr user) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + if (funcInterface == null) + throw new ArgumentNullException("funcInterface"); + + OutlineFuncsRec ofRec = funcInterface.Record; + Error err = FT.FT_Outline_Decompose(reference, ref ofRec, user); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Return an outline's ‘control box’. The control box encloses all the outline's points, including Bézier + /// control points. Though it coincides with the exact bounding box for most glyphs, it can be slightly larger + /// in some situations (like when rotating an outline which contains Bézier outside arcs). + /// + /// Computing the control box is very fast, while getting the bounding box can take much more time as it needs + /// to walk over all segments and arcs in the outline. To get the latter, you can use the ‘ftbbox’ component + /// which is dedicated to this single task. + /// + /// See for a discussion of tricky fonts. + /// The outline's control box. + public BBox GetCBox() + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + BBox cbox; + FT.FT_Outline_Get_CBox(reference, out cbox); + + return cbox; + } + + /// + /// Render an outline within a bitmap. The outline's image is simply OR-ed to the target bitmap. + /// + /// + /// This function does NOT CREATE the bitmap, it only renders an outline image within the one you pass to it! + /// Consequently, the various fields in ‘abitmap’ should be set accordingly. + /// + /// It will use the raster corresponding to the default glyph format. + /// + /// The value of the ‘num_grays’ field in ‘abitmap’ is ignored. If you select the gray-level rasterizer, and + /// you want less than 256 gray levels, you have to use directly. + /// + /// A pointer to the target bitmap descriptor. + public void GetBitmap(FTBitmap bitmap) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + Error err = FT.FT_Outline_Get_Bitmap(parentLibrary.Reference, reference, bitmap.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Render an outline within a bitmap. The outline's image is simply OR-ed to the target bitmap. + /// + /// + /// This function does NOT CREATE the bitmap, it only renders an outline image within the one you pass to it! + /// Consequently, the various fields in ‘abitmap’ should be set accordingly. + /// + /// It will use the raster corresponding to the default glyph format. + /// + /// The value of the ‘num_grays’ field in ‘abitmap’ is ignored. If you select the gray-level rasterizer, and + /// you want less than 256 gray levels, you have to use directly. + /// + /// A handle to a FreeType library object. + /// A pointer to the target bitmap descriptor. + public void GetBitmap(Library library, FTBitmap bitmap) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + if (library == null) + throw new ArgumentNullException("library"); + + if (bitmap == null) + throw new ArgumentNullException("bitmap"); + + Error err = FT.FT_Outline_Get_Bitmap(library.Reference, reference, bitmap.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Render an outline within a bitmap using the current scan-convert. This function uses an + /// structure as an argument, allowing advanced features like direct composition, + /// translucency, etc. + /// + /// + /// You should know what you are doing and how works to use this function. + /// + /// The field ‘params.source’ will be set to ‘outline’ before the scan converter is called, which means that + /// the value you give to it is actually ignored. + /// + /// The gray-level rasterizer always uses 256 gray levels. If you want less gray levels, you have to provide + /// your own span callback. See the value of the ‘flags’ field in the + /// structure for more details. + /// + /// + /// A pointer to an structure used to describe the rendering operation. + /// + public void Render(RasterParams parameters) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + if (parameters == null) + throw new ArgumentNullException("parameters"); + + Error err = FT.FT_Outline_Render(parentLibrary.Reference, reference, parameters.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Render an outline within a bitmap using the current scan-convert. This function uses an + /// structure as an argument, allowing advanced features like direct composition, + /// translucency, etc. + /// + /// + /// You should know what you are doing and how works to use this function. + /// + /// The field ‘params.source’ will be set to ‘outline’ before the scan converter is called, which means that + /// the value you give to it is actually ignored. + /// + /// The gray-level rasterizer always uses 256 gray levels. If you want less gray levels, you have to provide + /// your own span callback. See the value of the ‘flags’ field in the + /// structure for more details. + /// + /// A handle to a FreeType library object. + /// + /// A pointer to an structure used to describe the rendering operation. + /// + public void Render(Library library, RasterParams parameters) + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + if (library == null) + throw new ArgumentNullException("library"); + + if (parameters == null) + throw new ArgumentNullException("parameters"); + + Error err = FT.FT_Outline_Render(library.Reference, reference, parameters.Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// This function analyzes a glyph outline and tries to compute its fill orientation (see + /// ). This is done by computing the direction of each global horizontal and/or + /// vertical extrema within the outline. + /// + /// Note that this will return for empty outlines. + /// + /// The orientation. + public Orientation GetOrientation() + { + if (disposed) + throw new ObjectDisposedException("Outline", "Cannot access a disposed object."); + + return FT.FT_Outline_Get_Orientation(reference); + } + + #endregion + + #region Glyph Stroker + + /// + /// Retrieve the value corresponding to the ‘inside’ borders of a given outline. + /// + /// The border index. for empty or invalid outlines. + public StrokerBorder GetInsideBorder() + { + return FT.FT_Outline_GetInsideBorder(Reference); + } + + /// + /// Retrieve the value corresponding to the ‘outside’ borders of a given outline. + /// + /// The border index. for empty or invalid outlines. + public StrokerBorder GetOutsideBorder() + { + return FT.FT_Outline_GetOutsideBorder(Reference); + } + + #endregion + + /// + /// Disposes an instance of the class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + if (!duplicate) + { + if (parentLibrary != null) + FT.FT_Outline_Done(parentLibrary.Reference, reference); + else + FT.FT_Outline_Done_Internal(parentMemory.Reference, reference); + + // removes itself from the parent Library, with a check to prevent this from happening when Library is + // being disposed (Library disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (!parentLibrary.IsDisposed) + parentLibrary.RemoveChildOutline(this); + } + + reference = IntPtr.Zero; + rec = default(OutlineRec); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/OutlineFlags.cs b/SharpFont/Source/SharpFontShared/OutlineFlags.cs new file mode 100644 index 000000000..aad16f2f5 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OutlineFlags.cs @@ -0,0 +1,102 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants use for the flags in an outline's ‘flags’ field. + /// + /// + /// The flags , , and + /// are ignored by the smooth rasterizer. + /// + /// There exists a second mechanism to pass the drop-out mode to the B/W rasterizer; see the ‘tags’ field in + /// . + /// + /// Please refer to the description of the ‘SCANTYPE’ instruction in the OpenType specification (in file + /// ‘ttinst1.doc’) how simple drop-outs, smart drop-outs, and stubs are defined. + /// + [Flags] + public enum OutlineFlags + { + /// + /// Value 0 is reserved. + /// + None = 0x0000, + + /// + /// If set, this flag indicates that the outline's field arrays (i.e., ‘points’, ‘flags’, and ‘contours’) are + /// ‘owned’ by the outline object, and should thus be freed when it is destroyed. + /// + Owner = 0x0001, + + /// + /// By default, outlines are filled using the non-zero winding rule. If set to 1, the outline will be filled + /// using the even-odd fill rule (only works with the smooth rasterizer). + /// + EvenOddFill = 0x0002, + + /// + /// By default, outside contours of an outline are oriented in clock-wise direction, as defined in the TrueType + /// specification. This flag is set if the outline uses the opposite direction (typically for Type 1 fonts). + /// This flag is ignored by the scan converter. + /// + ReverseFill = 0x0004, + + /// + /// By default, the scan converter will try to detect drop-outs in an outline and correct the glyph bitmap to + /// ensure consistent shape continuity. If set, this flag hints the scan-line converter to ignore such cases. + /// See below for more information. + /// + IgnoreDropouts = 0x0008, + + /// + /// Select smart dropout control. If unset, use simple dropout control. Ignored if + /// is set. See below for more information. + /// + SmartDropouts = 0x0010, + + /// + /// If set, turn pixels on for ‘stubs’, otherwise exclude them. Ignored if + /// is set. See below for more information. + /// + IncludeStubs = 0x0020, + + /// + /// This flag indicates that the scan-line converter should try to convert this outline to bitmaps with the + /// highest possible quality. It is typically set for small character sizes. Note that this is only a hint that + /// might be completely ignored by a given scan-converter. + /// + HighPrecision = 0x0100, + + /// + /// This flag is set to force a given scan-converter to only use a single pass over the outline to render a + /// bitmap glyph image. Normally, it is set for very large character sizes. It is only a hint that might be + /// completely ignored by a given scan-converter. + /// + SinglePass = 0x0200 + } +} diff --git a/SharpFont/Source/SharpFontShared/OutlineFuncs.cs b/SharpFont/Source/SharpFontShared/OutlineFuncs.cs new file mode 100644 index 000000000..cedfa99c8 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OutlineFuncs.cs @@ -0,0 +1,404 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function pointer type used to describe the signature of a ‘move to’ function during outline + /// walking/decomposition. + /// + /// A ‘move to’ is emitted to start a new contour in an outline. + /// + /// A pointer to the target point of the ‘move to’. + /// A typeless pointer which is passed from the caller of the decomposition function. + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int MoveToFunc(ref FTVector to, IntPtr user); + + /// + /// A function pointer type used to describe the signature of a ‘line to’ function during outline + /// walking/decomposition. + /// + /// A ‘line to’ is emitted to indicate a segment in the outline. + /// + /// A pointer to the target point of the ‘line to’. + /// A typeless pointer which is passed from the caller of the decomposition function. + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int LineToFunc(ref FTVector to, IntPtr user); + + /// + /// A function pointer type used to describe the signature of a ‘conic to’ function during outline walking or + /// decomposition. + /// + /// A ‘conic to’ is emitted to indicate a second-order Bézier arc in the outline. + /// + /// + /// An intermediate control point between the last position and the new target in ‘to’. + /// + /// A pointer to the target end point of the conic arc. + /// A typeless pointer which is passed from the caller of the decomposition function. + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int ConicToFunc(ref FTVector control, ref FTVector to, IntPtr user); + + /// + /// A function pointer type used to describe the signature of a ‘cubic to’ function during outline walking or + /// decomposition. + /// + /// A ‘cubic to’ is emitted to indicate a third-order Bézier arc. + /// + /// A pointer to the first Bézier control point. + /// A pointer to the second Bézier control point. + /// A pointer to the target end point. + /// A typeless pointer which is passed from the caller of the decomposition function. + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int CubicToFunc(ref FTVector control1, ref FTVector control2, ref FTVector to, IntPtr user); + + /// + /// A structure to hold various function pointers used during outline decomposition in order to emit segments, + /// conic, and cubic Béziers. + /// + /// + /// The point coordinates sent to the emitters are the transformed version of the original coordinates (this is + /// important for high accuracy during scan-conversion). The transformation is simple: + /// + /// x' = (x << shift) - delta + /// y' = (x << shift) - delta + /// + /// Set the values of ‘shift’ and ‘delta’ to 0 to get the original point coordinates. + /// + public class OutlineFuncs : IDisposable + { + #region Fields + + private bool isDisposed; + + private MoveToFunc moveToFunc; + private LineToFunc lineToFunc; + private ConicToFunc conicToFunc; + private CubicToFunc cubicToFunc; + + private GCHandle moveToPin; + private GCHandle lineToPin; + private GCHandle conicToPin; + private GCHandle cubicToPin; + + private IntPtr moveToPtr; + private IntPtr lineToPtr; + private IntPtr conicToPtr; + private IntPtr cubicToPtr; + + private int shift; + private IntPtr delta; + + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the OutlineFuncs class. + /// + public OutlineFuncs() + { + } + + /// + /// Initializes a new instance of the OutlineFuncs class. + /// + /// The move to delegate. + /// The line to delegate. + /// The conic to delegate. + /// The cubic to delegate. + /// A value to shift by. + /// A delta to transform by. + /// , , + /// , or is . + public OutlineFuncs(MoveToFunc moveTo, LineToFunc lineTo, ConicToFunc conicTo, CubicToFunc cubicTo, int shift, int delta) + { + if (moveTo == null) + { + throw new ArgumentNullException(nameof(moveTo)); + } + if (lineTo == null) + { + throw new ArgumentNullException(nameof(lineTo)); + } + if (conicTo == null) + { + throw new ArgumentNullException(nameof(conicTo)); + } + if (cubicTo == null) + { + throw new ArgumentNullException(nameof(cubicTo)); + } + + moveToFunc = moveTo; + lineToFunc = lineTo; + conicToFunc = conicTo; + cubicToFunc = cubicTo; + + moveToPtr = Marshal.GetFunctionPointerForDelegate(moveToFunc); + lineToPtr = Marshal.GetFunctionPointerForDelegate(lineToFunc); + conicToPtr = Marshal.GetFunctionPointerForDelegate(conicToFunc); + cubicToPtr = Marshal.GetFunctionPointerForDelegate(cubicToFunc); + + this.shift = shift; + this.delta = (IntPtr) delta; + } + + #endregion + + #region Properties + + /// + /// Gets or sets the ‘move to’ emitter. + /// + public MoveToFunc MoveFunction + { + get + { + ThrowIfDisposed(); + return moveToFunc; + } + set + { + ThrowIfDisposed(); + if (moveToPin.IsAllocated) + { + moveToPin.Free(); + } + moveToFunc = value; + moveToPin = GCHandle.Alloc(moveToFunc); + moveToPtr = Marshal.GetFunctionPointerForDelegate(moveToFunc); + } + } + + /// + /// Gets or sets the segment emitter. + /// + public LineToFunc LineFunction + { + + get + { + ThrowIfDisposed(); + return lineToFunc; + } + set + { + ThrowIfDisposed(); + if (lineToPin.IsAllocated) + { + lineToPin.Free(); + } + lineToFunc = value; + lineToPin = GCHandle.Alloc(lineToFunc); + lineToPtr = Marshal.GetFunctionPointerForDelegate(lineToFunc); + } + } + + /// + /// Gets or sets the second-order Bézier arc emitter. + /// + public ConicToFunc ConicFunction + { + + get + { + ThrowIfDisposed(); + return conicToFunc; + } + set + { + ThrowIfDisposed(); + if (conicToPin.IsAllocated) + { + conicToPin.Free(); + } + conicToFunc = value; + conicToPin = GCHandle.Alloc(conicToFunc); + conicToPtr = Marshal.GetFunctionPointerForDelegate(conicToFunc); + } + } + + /// + /// Gets or sets the third-order Bézier arc emitter. + /// + public CubicToFunc CubicFunction + { + + get + { + ThrowIfDisposed(); + return cubicToFunc; + } + set + { + ThrowIfDisposed(); + if (cubicToPin.IsAllocated) + { + cubicToPin.Free(); + } + cubicToFunc = value; + cubicToPin = GCHandle.Alloc(cubicToFunc); + cubicToPtr = Marshal.GetFunctionPointerForDelegate(cubicToFunc); + } + } + + /// + /// Gets or sets the shift that is applied to coordinates before they are sent to the emitter. + /// + public int Shift + { + get + { + ThrowIfDisposed(); + return shift; + } + + set + { + ThrowIfDisposed(); + shift = value; + } + } + + /// + /// Gets the delta that is applied to coordinates before they are sent to the emitter, but after the + /// shift. + /// + public int Delta + { + get + { + ThrowIfDisposed(); + return (int) delta; + } + + /*set + { + funcsInt.delta = (IntPtr)value; + }*/ + } + + //TODO make a reference parameter instead? + //HACK this copies the struct + internal OutlineFuncsRec Record + { + get + { + ThrowIfDisposed(); + var r = new OutlineFuncsRec(); + r.moveTo = moveToPtr; + r.lineTo = lineToPtr; + r.conicTo = conicToPtr; + r.cubicTo = cubicToPtr; + return r; + } + } + + #endregion + + + #region IDisposable + + /// + /// Helper method to throw an exception if the object is disposed. + /// + /// If the object is already disposed + private void ThrowIfDisposed() + { + if (isDisposed) + { + throw new ObjectDisposedException("OutlineFuncs", "The outline funcs has already been disposed."); + } + } + + /// + /// Finalizer which ensures that the pinned delegates are released. + /// + ~OutlineFuncs() + { + Dispose(false); + } + + /// + /// Disposes this outline funcs, releasing any of the resources held by it. + /// + /// + protected virtual void Dispose(bool disposing) + { + if (isDisposed) + { + return; + } + + if (disposing) + { + // If this class later needs any managed resources, they should be included here. + } + if (moveToPin.IsAllocated) + { + moveToPin.Free(); + } + if (lineToPin.IsAllocated) + { + lineToPin.Free(); + } + if (cubicToPin.IsAllocated) + { + cubicToPin.Free(); + } + if (conicToPin.IsAllocated) + { + conicToPin.Free(); + } + isDisposed = true; + + } + + /// + /// Releases the pinned memory on this object. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + + #endregion + + + + } +} diff --git a/SharpFont/Source/SharpFontShared/OutlineGlyph.cs b/SharpFont/Source/SharpFontShared/OutlineGlyph.cs new file mode 100644 index 000000000..c16978d68 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/OutlineGlyph.cs @@ -0,0 +1,177 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used for outline (vectorial) glyph images. This really is a ‘sub-class’ of . + /// + /// + /// You can typecast an to if you have ‘ + /// == ’. This lets you access the outline's content easily. + /// + /// As the outline is extracted from a glyph slot, its coordinates are expressed normally in 26.6 pixels, unless + /// the flag was used in or + /// . + /// + /// The outline's tables are always owned by the object and are destroyed with it. + /// + public class OutlineGlyph : IDisposable + { + #region Fields + + private Glyph original; + private OutlineGlyphRec rec; + + #endregion + + #region Constructors + + internal OutlineGlyph(Glyph original) + { + this.original = original; + Reference = original.Reference; //sets the rec + } + + /// + /// Finalizes an instance of the class. + /// + ~OutlineGlyph() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the object has been disposed. + /// + public bool IsDisposed + { + get + { + return original.IsDisposed; + } + } + + /// + /// Gets the root fields. + /// + public Glyph Root + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Bitmap", "Cannot access a disposed object."); + + return original; + } + } + + /// + /// Gets a descriptor for the outline. + /// + public Outline Outline + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Bitmap", "Cannot access a disposed object."); + + return new Outline(PInvokeHelper.AbsoluteOffsetOf(Reference, "outline"), rec.outline); + } + } + + internal IntPtr Reference + { + get + { + if (IsDisposed) + throw new ObjectDisposedException("Bitmap", "Cannot access a disposed object."); + + return original.Reference; + } + + set + { + if (IsDisposed) + throw new ObjectDisposedException("Bitmap", "Cannot access a disposed object."); + + rec = PInvokeHelper.PtrToStructure(original.Reference); + } + } + + #endregion + + #region Operators + + /// + /// Casts a back up to a . The eqivalent of + /// . + /// + /// A . + /// A . + public static implicit operator Glyph(OutlineGlyph g) + { + return g.original; + } + + #endregion + + #region Methods + + /// + /// A CLS-compliant version of the implicit cast to . + /// + /// A . + public Glyph ToGlyph() + { + return (Glyph)this; + } + + /// + /// Disposes an instance of the class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposing) + original.Dispose(); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/PInvokeHelper.cs b/SharpFont/Source/SharpFontShared/PInvokeHelper.cs new file mode 100644 index 000000000..37255140a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PInvokeHelper.cs @@ -0,0 +1,78 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// Helpful methods to make marshalling simpler. + /// + internal static class PInvokeHelper + { + /// + /// A generic wrapper for . + /// + /// The type to cast to. + /// The pointer that holds the struct. + /// A marshalled struct. + internal static T PtrToStructure(IntPtr reference) + { + return (T)Marshal.PtrToStructure(reference, typeof(T)); + } + + /// + /// A method to copy data from one pointer to another, byte by byte. + /// + /// The source pointer. + /// An offset into the source buffer. + /// The destination pointer. + /// An offset into the destination buffer. + /// The number of bytes to copy. + internal static unsafe void Copy(IntPtr source, int sourceOffset, IntPtr destination, int destinationOffset, int count) + { + byte* src = (byte*)source + sourceOffset; + byte* dst = (byte*)destination + destinationOffset; + byte* end = dst + count; + + while (dst != end) + *dst++ = *src++; + } + + /// + /// A common pattern in SharpFont is to pass a pointer to a memory address inside of a struct. This method + /// works for all cases and provides a generic API. + /// + /// + /// The type of the struct to take an offset from. + /// A pointer to the start of a struct. + /// The name of the field to get an offset to. + /// start + the offset of the fieldName field in T. + internal static IntPtr AbsoluteOffsetOf(IntPtr start, string fieldName) + { + return new IntPtr(start.ToInt64() + Marshal.OffsetOf(typeof(T), fieldName).ToInt64()); + } + } +} diff --git a/SharpFont/Source/SharpFontShared/ParamTag.cs b/SharpFont/Source/SharpFontShared/ParamTag.cs new file mode 100644 index 000000000..01570ed8d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/ParamTag.cs @@ -0,0 +1,62 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// Constants used as the tag of structures. + /// + [CLSCompliant(false)] + public enum ParamTag : uint + { + /// + /// A constant used as the tag of structures to make + /// ignore preferred family subfamily names in ‘name’ table since OpenType version 1.4. For backwards + /// compatibility with legacy systems which has 4-face-per-family restriction. + /// + IgnorePreferredFamily = ('i' << 24 | 'g' << 16 | 'p' << 8 | 'f'), + + /// + /// A constant used as the tag of structures to make + /// ignore preferred subfamily names in ‘name’ table since OpenType version 1.4. For backwards compatibility + /// with legacy systems which has 4-face-per-family restriction. + /// + IgnorePreferredSubfamily = ('i' << 24 | 'g' << 16 | 'p' << 8 | 's'), + + /// + /// A constant used as the tag of structures to indicate an incremental loading object + /// to be used by FreeType. + /// + Incremental = ('i' << 24 | 'n' << 16 | 'c' << 8 | 'r'), + + /// + /// A constant used as the tag of an structure to indicate that unpatented methods only + /// should be used by the TrueType bytecode interpreter for a typeface opened by + /// . + /// + UnpatentedHinting = ('u' << 24 | 'n' << 16 | 'p' << 8 | 'a') + } +} diff --git a/SharpFont/Source/SharpFontShared/Parameter.cs b/SharpFont/Source/SharpFontShared/Parameter.cs new file mode 100644 index 000000000..d6d1b2b11 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Parameter.cs @@ -0,0 +1,106 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A simple structure used to pass more or less generic parameters to . + /// + /// + /// The ID and function of parameters are driver-specific. See the various flags for more + /// information. + /// + public sealed class Parameter + { + #region Fields + + private IntPtr reference; + private ParameterRec rec; + + #endregion + + #region Constructors + + internal Parameter(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets a four-byte identification tag. + /// + [CLSCompliant(false)] + public ParamTag Tag + { + get + { + return (ParamTag)rec.tag; + } + } + + /// + /// Gets a pointer to the parameter data. + /// + public IntPtr Data + { + get + { + return rec.data; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + internal ParameterRec Record + { + get + { + return rec; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/PixelMode.cs b/SharpFont/Source/SharpFontShared/PixelMode.cs new file mode 100644 index 000000000..c53d6c0bd --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PixelMode.cs @@ -0,0 +1,87 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration type used to describe the format of pixels in a given bitmap. Note that additional formats may + /// be added in the future. + /// + public enum PixelMode : byte + { + /// + /// Value 0 is reserved. + /// + None = 0, + + /// + /// A monochrome bitmap, using 1 bit per pixel. Note that pixels are stored in most-significant order (MSB), + /// which means that the left-most pixel in a byte has value 128. + /// + Mono, + + /// + /// An 8-bit bitmap, generally used to represent anti-aliased glyph images. Each pixel is stored in one byte. + /// Note that the number of ‘gray’ levels is stored in the ‘num_grays’ field of the + /// structure (it generally is 256). + /// + Gray, + + /// + /// A 2-bit per pixel bitmap, used to represent embedded anti-aliased bitmaps in font files according to the + /// OpenType specification. We haven't found a single font using this format, however. + /// + Gray2, + + /// + /// A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in font files according to the + /// OpenType specification. We haven't found a single font using this format, however. + /// + Gray4, + + /// + /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on LCD displays; the + /// bitmap is three times wider than the original glyph image. See also . + /// + Lcd, + + /// + /// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for display on rotated LCD displays; + /// the bitmap is three times taller than the original glyph image. See also + /// . + /// + VerticalLcd, + + /// + /// An image with four 8-bit channels per pixel, representing a color image (such as emoticons) with alpha + /// channel. For each pixel, the format is BGRA, which means, the blue channel comes first in memory. The color + /// channels are pre-multiplied and in the sRGB colorspace. For example, full red at half-translucent opacity + /// will be represented as ‘00,00,80,80’, not ‘00,00,FF,80’. + /// + /// + Bgra + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/BlendFlags.cs b/SharpFont/Source/SharpFontShared/PostScript/BlendFlags.cs new file mode 100644 index 000000000..dd7c8b5e7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/BlendFlags.cs @@ -0,0 +1,105 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.PostScript +{ + /// + /// A set of flags used to indicate which fields are present in a given blend dictionary (font info or private). + /// Used to support Multiple Masters fonts. + /// + public enum BlendFlags + { + /// + /// The position of the underline stroke. + /// + UnderlinePosition = 0, + + /// + /// The thickness of the underline stroke. + /// + UnderlineThickness, + + /// + /// The angle of italics. + /// + ItalicAngle, + + /// + /// Set if the font contains BlueValues. + /// + BlueValues, + + /// + /// Set if the font contains OtherBlues. + /// + OtherBlues, + + /// + /// Set if the font contains StandardWidth values. + /// + StandardWidth, + + /// + /// Set if the font contains StandardHeight values. + /// + StandardHeight, + + /// + /// Set if the font contains StemSnapWidths. + /// + StemSnapWidths, + + /// + /// Set if the font contains StemSnapHeights. + /// + StemSnapHeights, + + /// + /// Set if the font contains BlueScale values. + /// + BlueScale, + + /// + /// Set if the font contains BlueShift values. + /// + BlueShift, + + /// + /// Set if the font contains FamilyBlues values. + /// + FamilyBlues, + + /// + /// Set if the font contains FamilyOtherBlues values. + /// + FamilyOtherBlues, + + /// + /// Force bold blending. + /// + ForceBold + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/DictionaryKeys.cs b/SharpFont/Source/SharpFontShared/PostScript/DictionaryKeys.cs new file mode 100644 index 000000000..06b49675f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/DictionaryKeys.cs @@ -0,0 +1,271 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.PostScript +{ + /// + /// An enumeration used in calls to to identify the Type 1 dictionary entry to + /// retrieve. + /// + /// + public enum DictionaryKeys + { + /// + /// The font's type. Type 1 fonts must have a value of 1. + /// + FontType, + + /// + /// The font's matrix. Typically scaled 1000:1. + /// + FontMatrix, + + /// + /// The font's general bounding box. + /// + FontBBox, + + /// + /// The font's method of painting characters. Type 1 only supports fill (0) and outline (2). + /// + PaintType, + + /// + /// The font's name. + /// + FontName, + + /// + /// A unique identifier for popular fonts assigned by Adobe. + /// + UniqueId, + + /// + /// The number of characters the font can draw. + /// + NumCharStrings, + + /// + /// The char string key. + /// + CharStringKey, + + /// + /// The char string entry. + /// + CharString, + + /// + /// The font's encoding type. + /// + EncodingType, + + /// + /// The font's encoding entry. + /// + EncodingEntry, + + /// + /// The number of charstring subroutines in the font. + /// + NumSubrs, + + /// + /// The font's subroutines. + /// + Subr, + + /// + /// An array with only one real number entry expressing the dominant width of horizontal stems (measured + /// vertically in character space units). + /// + StdHW, + + /// + /// An array with only one real number entry expressing the dominant width of vertical stems (measured + /// horizontally in character space units). + /// + StdVW, + + /// + /// The number of BlueValues the font defines. The value must be at least 0 and at most 14. (7 integer pairs). + /// + NumBlueValues, + + /// + /// An array of integer pairs. The first pair must be the base overshoot position and the base-line. + /// + BlueValue, + + /// + /// An optional entry that speciï¬es the number of character space units to extend (in both directions) the + /// effect of an alignment zone on a horizontal stem. The default value is 1. + /// + BlueFuzz, + + /// + /// The number of OtherBlue values. The value must be at least 0 and at most 10 (5 integer pairs). + /// + NumOtherBlues, + + /// + /// An optional array of integer pairs very similar to those in . + /// + OtherBlue, + + /// + /// The number of FamilyBlue values. + /// + NumFamilyBlues, + + /// + /// An array of integer pairs very similar to those in . + /// + FamilyBlue, + + /// + /// The number of FamilyOtherBlue values. + /// + NumFamilyOtherBlues, + + /// + /// An array of integer pairs very similar to those in . + /// + FamilyOtherBlue, + + /// + /// An optional entry that controls the point size at which overshoot suppression ceases. The default value is + /// 0.039625. + /// + BlueScale, + + /// + /// An optional entry that indicates a character space distance beyond the flat position of alignment zones at + /// which overshoot enforcement for character features occurs. The default value is 7. + /// + BlueShift, + + /// + /// The number of StemSnapH values. Cannot exceed 12. + /// + NumStemSnapH, + + /// + /// An array of up to 12 real numbers of the most common widths (including the dominant width given in the + /// StdHW array) for horizontal stems (measured vertically). These widths must be sorted in increasing order. + /// + StemSnapH, + + /// + /// The number of StemSnapV values. Cannot exceed 12. + /// + NumStemSnapV, + + /// + /// An array of up to 12 real numbers of the most common widths (including the dominant width given in the + /// StdVW array) for vertical stems (measured horizontally). These widths must be sorted in increasing order. + /// + StemSnapV, + + /// + /// A boolean value indicating whether to force bold characters when a regular character is drawn 1-pixel wide. + /// + ForceBold, + + /// + /// Compatibility entry. Use only for font programs in language group 1. + /// + RndStemUp, + + /// + /// Obsolete. Set to {16 16}. Required. + /// + MinFeature, + + /// + /// An integer specifying the number of random bytes at the beginning of charstrings for encryption. By default + /// this value is 4. + /// + LenIV, + + /// + /// Compatibility entry. Set to 5839. + /// + Password, + + /// + /// Identifies the language group of the font. A value of 0 indicates a language that uses Latin, Greek, + /// Cyrillic, etc. characters. A value of 1 indicates a language that consists of Chinese ideographs, Jpaanese + /// Kanji, and Korean Hangul. The default value is 0. + /// + LanguageGroup, + + /// + /// The version identifier for this font. + /// + Version, + + /// + /// The copyright notice of the font. + /// + Notice, + + /// + /// The fullname of the font. + /// + FullName, + + /// + /// The family name of the font. + /// + FamilyName, + + /// + /// The name of the weight of the font. + /// + Weight, + + /// + /// Whether the font is fixed pitch. + /// + IsFixedPitch, + + /// + /// The position of the underline stroke. + /// + UnderlinePosition, + + /// + /// What types of embedding and usages are allowed. + /// + FSType, + + /// + /// The italic angle. + /// + ItalicAngle + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/EncodingType.cs b/SharpFont/Source/SharpFontShared/PostScript/EncodingType.cs new file mode 100644 index 000000000..900e72f37 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/EncodingType.cs @@ -0,0 +1,55 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.PostScript +{ + /// + /// An enumeration describing the ‘Encoding’ entry in a Type 1 dictionary. + /// + public enum EncodingType + { + /// + /// Not encoded. + /// + None = 0, + /// + /// Array encoding. + /// + Array, + /// + /// Standard encoding. + /// + Standard, + /// + /// ISO Latin 1 encoding. + /// + IsoLatin1, + /// + /// Expert encoding. + /// + Expert + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/FaceDict.cs b/SharpFont/Source/SharpFontShared/PostScript/FaceDict.cs new file mode 100644 index 000000000..4f965b663 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/FaceDict.cs @@ -0,0 +1,209 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.PostScript.Internal; + +namespace SharpFont.PostScript +{ + /// + /// A structure used to represent data in a CID top-level dictionary. + /// + public class FaceDict + { + #region Fields + + private IntPtr reference; + private FaceDictRec rec; + + #endregion + + #region Constructors + + internal FaceDict(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the Private structure containing more information. + /// + public Private PrivateDictionary + { + get + { + return new Private(rec.private_dict); + } + } + + /// + /// Gets the length of the BuildChar entry. + /// + [CLSCompliant(false)] + public uint BuildCharLength + { + get + { + return rec.len_buildchar; + } + } + + /// + /// Gets whether to force bold characters when a regular character has + /// strokes drawn 1-pixel wide. + /// + public int ForceBoldThreshold + { + get + { + return (int)rec.forcebold_threshold; + } + } + + /// + /// Gets the width of stroke. + /// + public int StrokeWidth + { + get + { + return (int)rec.stroke_width; + } + } + + /// + /// Gets hinting useful for rendering glyphs such as barcodes and logos that + /// have many counters. + /// + public int ExpansionFactor + { + get + { + return (int)rec.expansion_factor; + } + } + + /// + /// Gets the method for painting strokes (fill or outline). + /// + public byte PaintType + { + get + { + return rec.paint_type; + } + } + + /// + /// Gets the type of font. Must be set to 1 for all Type 1 fonts. + /// + public byte FontType + { + get + { + return rec.font_type; + } + } + + /// + /// Gets the matrix that indicates scaling of space units. + /// + public FTMatrix FontMatrix + { + get + { + return rec.font_matrix; + } + } + + /// + /// Gets the offset of the font. + /// + public FTVector FontOffset + { + get + { + return rec.font_offset; + } + } + + /// + /// Gets the number of subroutines. + /// + [CLSCompliant(false)] + public uint SubrsCount + { + get + { + return rec.num_subrs; + } + } + + /// + /// Gets the offset in bytes, from the start of the + /// data section of the CIDFont to the beginning of the SubrMap. + /// + [CLSCompliant(false)] + public uint SubrmapOffset + { + get + { + return (uint)rec.subrmap_offset; + } + } + + /// + /// Gets the number of bytes needed to store the SD value. + /// + public int SDBytes + { + get + { + return rec.sd_bytes; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/FaceInfo.cs b/SharpFont/Source/SharpFontShared/PostScript/FaceInfo.cs new file mode 100644 index 000000000..731a4b775 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/FaceInfo.cs @@ -0,0 +1,267 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Linq; +using System.Runtime.InteropServices; + +using SharpFont.PostScript.Internal; + +namespace SharpFont.PostScript +{ + /// + /// A structure used to represent CID Face information. + /// + public class FaceInfo + { + #region Fields + + private IntPtr reference; + private FaceInfoRec rec; + + #endregion + + #region Constructors + + internal FaceInfo(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// The name of the font, usually condensed from FullName. + /// + public string CidFontName + { + get + { + return rec.cid_font_name; + } + } + + /// + /// The version number of the font. + /// + public int CidVersion + { + get + { + return (int)rec.cid_version; + } + } + + /// + /// Gets the string identifying the font's manufacturer. + /// + public string Registry + { + get + { + return rec.registry; + } + } + + /// + /// Gets the unique identifier for the character collection. + /// + public string Ordering + { + get + { + return rec.ordering; + } + } + + /// + /// Gets the identifier (supplement number) of the character collection. + /// + public int Supplement + { + get + { + return rec.supplement; + } + } + + /// + /// Gets the dictionary of font info that is not used by the PostScript interpreter. + /// + public FontInfo FontInfo + { + get + { + return new FontInfo(rec.font_info); + } + } + + /// + /// Gets the coordinates of the corners of the bounding box. + /// + public BBox FontBBox + { + get + { + return rec.font_bbox; + } + } + + /// + /// Gets the value to form UniqueID entries for base fonts within a composite font. + /// + [CLSCompliant(false)] + public uint UidBase + { + get + { + return (uint)rec.uid_base; + } + } + + /// + /// Gets the number of entries in the XUID array. + /// + public int XuidCount + { + get + { + return rec.num_xuid; + } + } + + /// + /// Gets the extended unique IDS that identify the form, which allows + /// the PostScript interpreter to cache the output for reuse. + /// + [CLSCompliant(false)] + public uint[] Xuid + { + get + { + return rec.xuid.Select(x => (uint)x).ToArray(); + } + } + + /// + /// Gets the offset in bytes to the charstring offset table. + /// + [CLSCompliant(false)] + public uint CidMapOffset + { + get + { + return (uint)rec.cidmap_offset; + } + } + + /// + /// Gets the length in bytes of the FDArray index. + /// A value of 0 indicates that the charstring offset table doesn't contain + /// any FDArray indexes. + /// + public int FDBytes + { + get + { + return rec.fd_bytes; + } + } + + /// + /// Gets the length of the offset to the charstring for each CID in the CID font. + /// + public int GDBytes + { + get + { + return rec.gd_bytes; + } + } + + /// + /// Gets the number of valid CIDs in the CIDFont. + /// + [CLSCompliant(false)] + public uint CidCount + { + get + { + return (uint)rec.cid_count; + } + } + + /// + /// Gets the number of entries in the FontDicts array. + /// + public int DictsCount + { + get + { + return rec.num_dicts; + } + } + + /// + /// Gets the set of font dictionaries for this font. + /// + public FaceDict FontDicts + { + get + { + return new FaceDict(PInvokeHelper.AbsoluteOffsetOf(Reference, "font_dicts")); + } + } + + /// + /// The offset of the data. + /// + [CLSCompliant(false)] + public uint DataOffset + { + get + { + return (uint)rec.data_offset; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/FontInfo.cs b/SharpFont/Source/SharpFontShared/PostScript/FontInfo.cs new file mode 100644 index 000000000..7fd879281 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/FontInfo.cs @@ -0,0 +1,157 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.PostScript.Internal; + +namespace SharpFont.PostScript +{ + /// + /// A structure used to model a Type 1 or Type 2 FontInfo dictionary. Note that for Multiple Master fonts, each + /// instance has its own FontInfo dictionary. + /// + public class FontInfo + { + #region Fields + + private FontInfoRec rec; + + #endregion + + #region Constructors + + internal FontInfo(FontInfoRec rec) + { + this.rec = rec; + } + + #endregion + + #region Properties + + /// + /// The version of the font. + /// + public string Version + { + get + { + return rec.version; + } + } + + /// + /// The copyright notice for the font. + /// + public string Notice + { + get + { + return rec.notice; + } + } + + /// + /// Gets the font's full name. + /// + public string FullName + { + get + { + return rec.full_name; + } + } + + /// + /// Gets the font's family name. + /// + public string FamilyName + { + get + { + return rec.family_name; + } + } + + /// + /// Gets the weight description of the font + /// + public string Weight + { + get + { + return rec.weight; + } + } + + /// + /// Gets italic angle of the font. + /// + public int ItalicAngle + { + get + { + return (int)rec.italic_angle; + } + } + + /// + /// Gets whether the font is fixed pitch. + /// + public bool IsFixedPitch + { + get + { + return rec.is_fixed_pitch == 1; + } + } + + /// + /// Gets the position of the underline. + /// + public short UnderlinePosition + { + get + { + return rec.underline_position; + } + } + + /// + /// Gets the thickness of the underline stroke. + /// + [CLSCompliant(false)] + public ushort UnderlineThickness + { + get + { + return rec.underline_thickness; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceDictRec.cs b/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceDictRec.cs new file mode 100644 index 000000000..482083cb4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceDictRec.cs @@ -0,0 +1,54 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.PostScript.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct FaceDictRec + { + internal PrivateRec private_dict; + + internal uint len_buildchar; + internal FT_Long forcebold_threshold; + internal FT_Long stroke_width; + internal FT_Long expansion_factor; + + internal byte paint_type; + internal byte font_type; + internal FTMatrix font_matrix; + internal FTVector font_offset; + + internal uint num_subrs; + internal FT_ULong subrmap_offset; + internal int sd_bytes; + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceInfoRec.cs b/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceInfoRec.cs new file mode 100644 index 000000000..c55d0ca76 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/Internal/FaceInfoRec.cs @@ -0,0 +1,69 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.PostScript.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct FaceInfoRec + { + [MarshalAs(UnmanagedType.LPStr)] + internal string cid_font_name; + internal FT_Long cid_version; + internal int cid_font_type; + + [MarshalAs(UnmanagedType.LPStr)] + internal string registry; + + [MarshalAs(UnmanagedType.LPStr)] + internal string ordering; + internal int supplement; + + internal FontInfoRec font_info; + internal BBox font_bbox; + internal FT_ULong uid_base; + + internal int num_xuid; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + internal FT_ULong[] xuid; + + internal FT_ULong cidmap_offset; + internal int fd_bytes; + internal int gd_bytes; + internal FT_ULong cid_count; + + internal int num_dicts; + internal IntPtr font_dicts; + + internal FT_ULong data_offset; + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/Internal/FontInfoRec.cs b/SharpFont/Source/SharpFontShared/PostScript/Internal/FontInfoRec.cs new file mode 100644 index 000000000..cd06fb2d7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/Internal/FontInfoRec.cs @@ -0,0 +1,56 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.PostScript.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct FontInfoRec + { + [MarshalAs(UnmanagedType.LPStr)] + internal string version; + + [MarshalAs(UnmanagedType.LPStr)] + internal string notice; + + [MarshalAs(UnmanagedType.LPStr)] + internal string full_name; + + [MarshalAs(UnmanagedType.LPStr)] + internal string family_name; + + [MarshalAs(UnmanagedType.LPStr)] + internal string weight; + + internal FT_Long italic_angle; + internal byte is_fixed_pitch; + internal short underline_position; + internal ushort underline_thickness; + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/Internal/PrivateRec.cs b/SharpFont/Source/SharpFontShared/PostScript/Internal/PrivateRec.cs new file mode 100644 index 000000000..52067e914 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/Internal/PrivateRec.cs @@ -0,0 +1,82 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.PostScript.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct PrivateRec + { + internal int unique_id; + internal int lenIV; + + internal byte num_blue_values; + internal byte num_other_blues; + internal byte num_family_blues; + internal byte num_family_other_blues; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + internal short[] blue_values; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + internal short[] other_blues; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + internal short[] family_blues; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + internal short[] family_other_blues; + + internal FT_Long blue_scale; + internal int blue_shift; + internal int blue_fuzz; + + internal ushort standard_width; + internal ushort standard_height; + + internal byte num_snap_widths; + internal byte num_snap_heights; + internal byte force_bold; + internal byte round_stem_up; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] + internal short[] snap_widths; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] + internal short[] snap_heights; + + internal FT_Long expansion_factor; + + internal FT_Long language_group; + internal FT_Long password; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + internal short[] min_feature; + } +} diff --git a/SharpFont/Source/SharpFontShared/PostScript/Private.cs b/SharpFont/Source/SharpFontShared/PostScript/Private.cs new file mode 100644 index 000000000..a846d5831 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/PostScript/Private.cs @@ -0,0 +1,346 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.PostScript.Internal; + +namespace SharpFont.PostScript +{ + /// + /// A structure used to model a Type 1 or Type 2 private dictionary. Note that for Multiple Master fonts, each + /// instance has its own Private dictionary. + /// + public class Private + { + #region Fields + + private PrivateRec rec; + + #endregion + + #region Constructors + + internal Private(PrivateRec rec) + { + this.rec = rec; + } + + #endregion + + #region Properties + + /// + /// Gets the ID unique to the Type 1 font. + /// + public int UniqueId + { + get + { + return rec.unique_id; + } + } + + /// + /// Gets the number of random bytes at the beginning of charstrings (for encryption). + /// + public int LenIV + { + get + { + return rec.lenIV; + } + } + + /// + /// Gets the number of values (pairs) in the Blues array. + /// + public byte BlueValuesCount + { + get + { + return rec.num_blue_values; + } + } + + /// + /// Gets the number of values (pairs) in the OtherBlues array. + /// + public byte OtherBluesCount + { + get + { + return rec.num_other_blues; + } + } + + /// + /// Gets the number of values (pairs) in the FamilyBlues array. + /// + public byte FamilyBluesCount + { + get + { + return rec.num_family_blues; + } + } + + /// + /// Gets the number of values (pairs) in the FamilyOtherBlues array. + /// + public byte FamilyOtherBluesCount + { + get + { + return rec.num_family_other_blues; + } + } + + /// + /// Gets the pairs of blue values. + /// + public short[] BlueValues + { + get + { + return rec.blue_values; + } + } + + /// + /// Gets the pairs of blue values. + /// + public short[] OtherBlues + { + get + { + return rec.other_blues; + } + } + + /// + /// Gets the pairs of blue values. + /// + public short[] FamilyBlues + { + get + { + return rec.family_blues; + } + } + + /// + /// Gets the pairs of blue values. + /// + public short[] FamilyOtherBlues + { + get + { + return rec.family_other_blues; + } + } + + /// + /// Gets the point size at which overshoot suppression ceases. + /// + public int BlueScale + { + get + { + return (int)rec.blue_scale; + } + } + + /// + /// Gets whether characters smaller than the size given by BlueScale + /// should have overshoots suppressed. + /// + public int BlueShift + { + get + { + return rec.blue_shift; + } + } + + /// + /// Gets the number of character space units to extend the effect of an + /// alignment zone on a horizontal stem. Setting this to 0 is recommended + /// because it is unreliable. + /// + public int BlueFuzz + { + get + { + return rec.blue_fuzz; + } + } + + /// + /// Indicates the standard stroke width of vertical stems. + /// + [CLSCompliant(false)] + public ushort StandardWidth + { + get + { + return rec.standard_width; + } + } + + /// + /// Indicates the standard stroke width of horizontal stems. + /// + [CLSCompliant(false)] + public ushort StandardHeight + { + get + { + return rec.standard_height; + } + } + + /// + /// Indicates the number of values in the SnapWidths array. + /// + public byte SnapWidthsCount + { + get + { + return rec.num_snap_widths; + } + } + + /// + /// Indicates the number of values in the SnapHeights array. + /// + public byte SnapHeightsCount + { + get + { + return rec.num_snap_heights; + } + } + + /// + /// Gets whether bold characters should appear thicker than non-bold characters + /// at very small point sizes, where otherwise bold characters might appear the + /// same as non-bold characters. + /// + public bool ForceBold + { + get + { + return rec.force_bold == 1; + } + } + + /// + /// Superseded by the LanguageGroup entry. + /// + public bool RoundStemUp + { + get + { + return rec.round_stem_up == 1; + } + } + + /// + /// StemSnapH is an array of up to 12 values of the most common stroke widths for horizontal stems + /// (measured vertically). + /// + public short[] SnapWidths + { + get + { + return rec.snap_widths; + } + } + + /// + /// StemSnapV is an array of up to 12 values of the most common stroke widths for vertical stems + /// (measured horizontally). + /// + public short[] SnapHeights + { + get + { + return rec.snap_heights; + } + } + + /// + /// The Expansion Factor provides a limit for changing character bounding boxes during + /// processing that adjusts the size of fonts of Language Group 1. + /// + public int ExpansionFactor + { + get + { + return (int)rec.expansion_factor; + } + } + + /// + /// Indicates the aesthetic characteristics of the font. Currently, only LanguageGroup 0 + /// (e.g. Latin, Greek, Cyrillic, etc.) and LanguageGroup 1 (e.g. Chinese ideographs, Japanese + /// Kanji, etc) are recognized. + /// + public int LanguageGroup + { + get + { + return (int)rec.language_group; + } + } + + /// + /// The Password value is required for the Type 1 BuildChar to operate. + /// It must be set to 5839. + /// + public int Password + { + get + { + return (int)rec.password; + } + } + + /// + /// The MinFeature value is required for the Type 1 BuildChar to operate, but is obsolete. + /// It must be set to {16,16}. + /// + public short[] MinFeature + { + get + { + return rec.min_feature; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Properties/AssemblyInfo.cs b/SharpFont/Source/SharpFontShared/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..05fe76079 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Properties/AssemblyInfo.cs @@ -0,0 +1,67 @@ +#region MIT License +/*Copyright (c) 2012-2016, Robert Rouhani + +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.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: CLSCompliant(true)] +[assembly: InternalsVisibleTo("SharpFont.HarfBuzz, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bfa6d85b0d27c914bc0fe0b18b7f05e0b2ac082c9e154b1739325f4e5537a3dc24712151df168ff0b28699c42cfc39f5f604c6321615d0dc1cd295422d2d244a172d24de1b01d1ced6854ed8d0cc82dd20409a1555f355160612869002de0bc9a9e50eaaa762ec4ebb46943adc18e829a0eb2ee45f47a2d9d46e808c736c77e9")] + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SharpFont")] +[assembly: AssemblyDescription("Cross-platform FreeType bindings for C#")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Robmaister")] +[assembly: AssemblyProduct("SharpFont")] +[assembly: AssemblyCopyright("Copyright (c) Robert Rouhani 2012-2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("baf287e3-cfcc-4183-ba83-f23a7ecb8373")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("4.0.1.200")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +//The SemVer version +[assembly: AssemblyInformationalVersion("4.0.1")] diff --git a/SharpFont/Source/SharpFontShared/Raster.cs b/SharpFont/Source/SharpFontShared/Raster.cs new file mode 100644 index 000000000..9bb2824c2 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Raster.cs @@ -0,0 +1,44 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// A handle (pointer) to a raster object. Each object can be used independently to convert an outline into a + /// bitmap or pixmap. + /// + public class Raster : NativeObject + { + #region Constructors + + internal Raster(IntPtr reference) : base(reference) + { + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/RasterFlags.cs b/SharpFont/Source/SharpFontShared/RasterFlags.cs new file mode 100644 index 000000000..5b5ef8f2a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/RasterFlags.cs @@ -0,0 +1,64 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit flag constants as used in the ‘flags’ field of a structure. + /// + [Flags] + public enum RasterFlags + { + /// + /// This value is 0. + /// + Default = 0x0, + + /// + /// This flag is set to indicate that an anti-aliased glyph image should be generated. Otherwise, it will be + /// monochrome (1-bit). + /// + AntiAlias = 0x1, + + /// + /// This flag is set to indicate direct rendering. In this mode, client applications must provide their own + /// span callback. This lets them directly draw or compose over an existing bitmap. If this bit is not set, the + /// target pixmap's buffer must be zeroed before rendering. + /// + /// Note that for now, direct rendering is only possible with anti-aliased glyphs. + /// + Direct = 0x2, + + /// + /// This flag is only used in direct rendering mode. If set, the output will be clipped to a box specified in + /// the ‘clip_box’ field of the structure. + /// + /// Note that by default, the glyph bitmap is clipped to the target pixmap, except in direct rendering mode + /// where all spans are generated if no clipping box is set. + /// + Clip = 0x4 + } +} diff --git a/SharpFont/Source/SharpFontShared/RasterFuncs.cs b/SharpFont/Source/SharpFontShared/RasterFuncs.cs new file mode 100644 index 000000000..58fd14098 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/RasterFuncs.cs @@ -0,0 +1,210 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function used to create a new raster object. + /// + /// + /// The ‘memory’ parameter is a typeless pointer in order to avoid un-wanted dependencies on the rest of the + /// FreeType code. In practice, it is an object, i.e., a handle to the standard FreeType + /// memory allocator. However, this field can be completely ignored by a given raster implementation. + /// + /// A handle to the memory allocator. + /// A handle to the new raster object. + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Error RasterNewFunc(IntPtr memory, NativeReference raster); + + /// + /// A function used to destroy a given raster object. + /// + /// A handle to the raster object. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RasterDoneFunc(NativeReference raster); + + /// + /// FreeType provides an area of memory called the ‘render pool’, available to all registered rasters. This pool + /// can be freely used during a given scan-conversion but is shared by all rasters. Its content is thus transient. + /// + /// This function is called each time the render pool changes, or just after a new raster object is created. + /// + /// + /// Rasters can ignore the render pool and rely on dynamic memory allocation if they want to (a handle to the + /// memory allocator is passed to the raster constructor). However, this is not recommended for efficiency + /// purposes. + /// + /// A handle to the new raster object. + /// The address in memory of the render pool. + /// The size in bytes of the render pool. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RasterResetFunc(NativeReference raster, IntPtr pool_base, int pool_size); + + /// + /// This function is a generic facility to change modes or attributes in a given raster. This can be used for + /// debugging purposes, or simply to allow implementation-specific ‘features’ in a given raster module. + /// + /// A handle to the new raster object. + /// A 4-byte tag used to name the mode or property. + /// A pointer to the new mode/property to use. + [CLSCompliant(false)] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RasterSetModeFunc(NativeReference raster, uint mode, IntPtr args); + + /// + /// Invoke a given raster to scan-convert a given glyph image into a target + /// bitmap. + /// + /// + /// The exact format of the source image depends on the raster's glyph format defined in its + /// structure. It can be an or anything else in order to support a + /// large array of glyph formats. + /// + /// Note also that the render function can fail and return a error code if + /// the raster used does not support direct composition. + /// + /// XXX: For now, the standard raster doesn't support direct composition but this should change for the final + /// release (see the files ‘demos/src/ftgrays.c’ and ‘demos/src/ftgrays2.c’ for examples of distinct + /// implementations which support direct composition). + /// + /// A handle to the raster object. + /// + /// A pointer to an structure used to store the rendering parameters. + /// + /// Error code. 0 means success. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Error RasterRenderFunc(NativeReference raster, NativeReference @params); + + /// + /// A structure used to describe a given raster class to the library. + /// + public class RasterFuncs: NativeObject + { + #region Fields + + private RasterFuncsRec rec; + + #endregion + + #region Constructors + + internal RasterFuncs(IntPtr reference) : base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets the supported glyph format for this raster. + /// + [CLSCompliant(false)] + public GlyphFormat Format + { + get + { + return rec.glyph_format; + } + } + + /// + /// Gets the raster constructor. + /// + public RasterNewFunc New + { + get + { + return rec.raster_new; + } + } + + /// + /// Gets a function used to reset the render pool within the raster. + /// + public RasterResetFunc Reset + { + get + { + return rec.raster_reset; + } + } + + /// + /// Gets a function to set or change modes. + /// + [CLSCompliant(false)] + public RasterSetModeFunc SetMode + { + get + { + return rec.raster_set_mode; + } + } + + /// + /// Gets a function to render a glyph into a given bitmap. + /// + public RasterRenderFunc Render + { + get + { + return rec.raster_render; + } + } + + /// + /// Gets the raster destructor. + /// + public RasterDoneFunc Done + { + get + { + return rec.raster_done; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/RasterParams.cs b/SharpFont/Source/SharpFontShared/RasterParams.cs new file mode 100644 index 000000000..2673bea92 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/RasterParams.cs @@ -0,0 +1,237 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A function used as a call-back by the anti-aliased renderer in order to let client applications draw themselves + /// the gray pixel spans on each scan line. + /// + /// + /// This callback allows client applications to directly render the gray spans of the anti-aliased bitmap to any + /// kind of surfaces. + /// + /// This can be used to write anti-aliased outlines directly to a given background bitmap, and even perform + /// translucency. + /// + /// Note that the ‘count’ field cannot be greater than a fixed value defined by the ‘FT_MAX_GRAY_SPANS’ + /// configuration macro in ‘ftoption.h’. By default, this value is set to 32, which means that if there are more + /// than 32 spans on a given scanline, the callback is called several times with the same ‘y’ parameter in order to + /// draw all callbacks. + /// + /// Otherwise, the callback is only called once per scan-line, and only for those scanlines that do have ‘gray’ + /// pixels on them. + /// + /// The scanline's y coordinate. + /// The number of spans to draw on this scanline. + /// A table of ‘count’ spans to draw on the scanline. + /// User-supplied data that is passed to the callback. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RasterSpanFunc(int y, int count, NativeReference spans, IntPtr user); + + /// + /// THIS TYPE IS DEPRECATED. DO NOT USE IT. + /// + /// A function used as a call-back by the monochrome scan-converter to test whether a given target pixel is already + /// set to the drawing ‘color’. These tests are crucial to implement drop-out control per-se the TrueType spec. + /// + /// The pixel's y coordinate. + /// The pixel's x coordinate. + /// User-supplied data that is passed to the callback. + /// 1 if the pixel is ‘set’, 0 otherwise. + [Obsolete("This type is deprecated. Do not use it. See FreeType docuementation.")] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int RasterBitTestFunc(int y, int x, IntPtr user); + + /// + /// THIS TYPE IS DEPRECATED. DO NOT USE IT. + /// + /// A function used as a call-back by the monochrome scan-converter to set an individual target pixel. This is + /// crucial to implement drop-out control according to the TrueType specification. + /// + /// The pixel's y coordinate. + /// The pixel's x coordinate. + /// User-supplied data that is passed to the callback. + [Obsolete("This type is deprecated. Do not use it. See FreeType docuementation.")] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RasterBitSetFunc(int y, int x, IntPtr user); + + /// + /// A structure to hold the arguments used by a raster's render function. + /// + /// + /// An anti-aliased glyph bitmap is drawn if the bit flag is set in the ‘flags’ + /// field, otherwise a monochrome bitmap is generated. + /// + /// If the bit flag is set in ‘flags’, the raster will call the ‘gray_spans’ + /// callback to draw gray pixel spans, in the case of an aa glyph bitmap, it will call ‘black_spans’, and + /// ‘bit_test’ and ‘bit_set’ in the case of a monochrome bitmap. This allows direct composition over a pre-existing + /// bitmap through user-provided callbacks to perform the span drawing/composition. + /// + /// Note that the ‘bit_test’ and ‘bit_set’ callbacks are required when rendering a monochrome bitmap, as they are + /// crucial to implement correct drop-out control as defined in the TrueType specification. + /// + public class RasterParams : NativeObject + { + #region Fields + + private RasterParamsRec rec; + + #endregion + + #region Constructors + + internal RasterParams(IntPtr reference) : base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets the target bitmap. + /// + public FTBitmap Target + { + get + { + return new FTBitmap(rec.target, null); + } + } + + /// + /// Gets a pointer to the source glyph image (e.g., an ). + /// + public IntPtr Source + { + get + { + return rec.source; + } + } + + /// + /// Gets the rendering flags. + /// + public RasterFlags Flags + { + get + { + return rec.flags; + } + } + + /// + /// Gets the gray span drawing callback. + /// + public RasterSpanFunc GraySpans + { + get + { + return rec.gray_spans; + } + } + + /// + /// Gets the black span drawing callback. UNIMPLEMENTED! + /// + [Obsolete] + public RasterSpanFunc BlackSpans + { + get + { + return rec.black_spans; + } + } + + /// + /// Gets the bit test callback. UNIMPLEMENTED! + /// + [Obsolete] + public RasterBitTestFunc BitTest + { + get + { + return rec.bit_test; + } + } + + /// + /// Gets the bit set callback. UNIMPLEMENTED! + /// + [Obsolete] + public RasterBitSetFunc BitSet + { + get + { + return rec.bit_set; + } + } + + /// + /// Gets the user-supplied data that is passed to each drawing callback. + /// + public IntPtr User + { + get + { + return rec.user; + } + } + + /// + /// Gets an optional clipping box. It is only used in direct rendering mode. Note that coordinates here should + /// be expressed in integer pixels (and not in 26.6 fixed-point units). + /// + public BBox ClipBox + { + get + { + return rec.clip_box; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/RenderMode.cs b/SharpFont/Source/SharpFontShared/RenderMode.cs new file mode 100644 index 000000000..046c9de22 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/RenderMode.cs @@ -0,0 +1,80 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration type that lists the render modes supported by FreeType 2. Each mode corresponds to a specific + /// type of scanline conversion performed on the outline. + /// + /// For bitmap fonts and embedded bitmaps the field in the + /// structure gives the format of the returned bitmap. + /// + /// All modes except use 256 levels of opacity. + /// + /// + /// The LCD-optimized glyph bitmaps produced by can be filtered to reduce + /// color-fringes by using (not active in the default builds). It is up to the + /// caller to either call (if available) or do the filtering itself. + /// + /// The selected render mode only affects vector glyphs of a font. Embedded bitmaps often have a different pixel + /// mode like . You can use to transform them into 8-bit + /// pixmaps. + /// + public enum RenderMode + { + /// + /// This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps. + /// + Normal = 0, + + /// + /// This is equivalent to . It is only defined as a separate value because + /// render modes are also used indirectly to define hinting algorithm selectors. + /// + /// + Light, + + /// + /// This mode corresponds to 1-bit bitmaps (with 2 levels of opacity). + /// + Mono, + + /// + /// This mode corresponds to horizontal RGB and BGR sub-pixel displays like LCD screens. It produces 8-bit + /// bitmaps that are 3 times the width of the original glyph outline in pixels, and which use the + /// mode. + /// + Lcd, + + /// + /// This mode corresponds to vertical RGB and BGR sub-pixel displays (like PDA screens, rotated LCD displays, + /// etc.). It produces 8-bit bitmaps that are 3 times the height of the original glyph outline in pixels and + /// use the mode. + /// + VerticalLcd, + } +} diff --git a/SharpFont/Source/SharpFontShared/Renderer.cs b/SharpFont/Source/SharpFontShared/Renderer.cs new file mode 100644 index 000000000..fc93a1a6a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Renderer.cs @@ -0,0 +1,69 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// A handle to a given FreeType renderer. A renderer is a special module in charge of converting a glyph image to + /// a bitmap, when necessary. Each renderer supports a given glyph image format, and one or more target surface + /// depths. + /// + public class Renderer + { + #region Fields + + private IntPtr reference; + + #endregion + + #region Constructors + + internal Renderer(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/RendererClass.cs b/SharpFont/Source/SharpFontShared/RendererClass.cs new file mode 100644 index 000000000..4f36342d7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/RendererClass.cs @@ -0,0 +1,150 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// The renderer module class descriptor. + /// + public class RendererClass + { + #region Fields + + private IntPtr reference; + private RendererClassRec rec; + + #endregion + + #region Constructors + + internal RendererClass(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the root fields. + /// + public ModuleClass Root + { + get + { + return new ModuleClass(reference); + } + } + + /// + /// Gets the glyph image format this renderer handles. + /// + [CLSCompliant(false)] + public GlyphFormat Format + { + get + { + return rec.glyph_format; + } + } + + /// + /// Gets a method used to render the image that is in a given glyph slot into a bitmap. + /// + public IntPtr RenderGlyph + { + get + { + return rec.render_glyph; + } + } + + /// + /// Gets a method used to transform the image that is in a given glyph slot. + /// + public IntPtr TransformGlyph + { + get + { + return rec.transform_glyph; + } + } + + /// + /// Gets a method used to access the glyph's cbox. + /// + public IntPtr GetGlyphCBox + { + get + { + return rec.get_glyph_cbox; + } + } + + /// + /// Gets a method used to pass additional parameters. + /// + public IntPtr SetMode + { + get + { + return rec.set_mode; + } + } + + /// + /// Gets a pointer to its raster's class. + /// + /// For renderers only. + public RasterFuncs RasterClass + { + get + { + return new RasterFuncs(PInvokeHelper.AbsoluteOffsetOf(Reference, "raster_class")); + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Settings.StyleCop b/SharpFont/Source/SharpFontShared/Settings.StyleCop new file mode 100644 index 000000000..2c2aa1c55 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Settings.StyleCop @@ -0,0 +1,97 @@ + + + + + + Rec\.cs$ + Marhsaler\.cs$ + + + + + + + + + + False + + + + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + + + + + + False + + + + + + + + + + False + + + + + False + + + + + True + True + + + + + + + False + + + + + + + + + + False + + + + + + + \ No newline at end of file diff --git a/SharpFont/Source/SharpFontShared/SharpFontShared.projitems b/SharpFont/Source/SharpFontShared/SharpFontShared.projitems new file mode 100644 index 000000000..545a9af4b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SharpFontShared.projitems @@ -0,0 +1,187 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 2e4773b7-961a-4328-9d77-9749f9071ca2 + + + SharpFont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharpFont/Source/SharpFontShared/SharpFontShared.shproj b/SharpFont/Source/SharpFontShared/SharpFontShared.shproj new file mode 100644 index 000000000..3aa2efe8c --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SharpFontShared.shproj @@ -0,0 +1,12 @@ + + + + 2e4773b7-961a-4328-9d77-9749f9071ca2 + + + + + + + + diff --git a/SharpFont/Source/SharpFontShared/SizeMetrics.cs b/SharpFont/Source/SharpFontShared/SizeMetrics.cs new file mode 100644 index 000000000..43de64525 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SizeMetrics.cs @@ -0,0 +1,167 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// The size metrics structure gives the metrics of a size object. + /// + /// + /// The scaling values, if relevant, are determined first during a size changing operation. The remaining fields + /// are then set by the driver. For scalable formats, they are usually set to scaled values of the corresponding + /// fields in . + /// + /// Note that due to glyph hinting, these values might not be exact for certain fonts. Thus they must be treated as + /// unreliable with an error margin of at least one pixel! + /// + /// Indeed, the only way to get the exact metrics is to render all glyphs. As this would be a definite performance + /// hit, it is up to client applications to perform such computations. + /// + /// The structure is valid for bitmap fonts also. + /// + public sealed class SizeMetrics + { + #region Fields + + private SizeMetricsRec rec; + + #endregion + + #region Constructors + + internal SizeMetrics(SizeMetricsRec metricsInternal) + { + rec = metricsInternal; + } + + #endregion + + #region Properties + + /// + /// Gets the width of the scaled EM square in pixels, hence the term ‘ppem’ (pixels per EM). It is also referred to + /// as ‘nominal width’. + /// + [CLSCompliant(false)] + public ushort NominalWidth + { + get + { + return rec.x_ppem; + } + } + + /// + /// Gets the height of the scaled EM square in pixels, hence the term ‘ppem’ (pixels per EM). It is also referred to + /// as ‘nominal height’. + /// + [CLSCompliant(false)] + public ushort NominalHeight + { + get + { + return rec.y_ppem; + } + } + + /// + /// Gets a 16.16 fractional scaling value used to convert horizontal metrics from font units to 26.6 fractional + /// pixels. Only relevant for scalable font formats. + /// + public Fixed16Dot16 ScaleX + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.x_scale); + } + } + + /// + /// Gets a 16.16 fractional scaling value used to convert vertical metrics from font units to 26.6 fractional + /// pixels. Only relevant for scalable font formats. + /// + public Fixed16Dot16 ScaleY + { + get + { + return Fixed16Dot16.FromRawValue((int)rec.y_scale); + } + } + + /// + /// Gets the ascender in 26.6 fractional pixels. + /// + /// + public Fixed26Dot6 Ascender + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.ascender); + } + } + + /// + /// Gets the descender in 26.6 fractional pixels. + /// + /// + public Fixed26Dot6 Descender + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.descender); + } + } + + /// + /// Gets the height in 26.6 fractional pixels. + /// + /// + public Fixed26Dot6 Height + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.height); + } + } + + /// + /// Gets the maximal advance width in 26.6 fractional pixels. + /// + /// + public Fixed26Dot6 MaxAdvance + { + get + { + return Fixed26Dot6.FromRawValue((int)rec.max_advance); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/SizeRequest.cs b/SharpFont/Source/SharpFontShared/SizeRequest.cs new file mode 100644 index 000000000..c2b14ee5a --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SizeRequest.cs @@ -0,0 +1,205 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont +{ + /// + /// A structure used to model a size request. + /// + /// + /// If is zero, then the horizontal scaling value is set equal to the vertical scaling value, + /// and vice versa. + /// + [StructLayout(LayoutKind.Sequential)] + public struct SizeRequest : IEquatable + { + #region Fields + + private SizeRequestType requestType; + private FT_Long width; + private FT_Long height; + private uint horiResolution; + private uint vertResolution; + + #endregion + + #region Properties + + /// + /// Gets the type of request. See . + /// + public SizeRequestType RequestType + { + get + { + return requestType; + } + + set + { + requestType = value; + } + } + + /// + /// Gets or sets the desired width. + /// + public int Width + { + get + { + return (int)width; + } + + set + { + width = (FT_Long)value; + } + } + + /// + /// Gets or sets the desired height. + /// + public int Height + { + get + { + return (int)height; + } + + set + { + height = (FT_Long)value; + } + } + + /// + /// Gets or sets the horizontal resolution. If set to zero, is treated as a 26.6 fractional pixel + /// value. + /// + [CLSCompliant(false)] + public uint HorizontalResolution + { + get + { + return horiResolution; + } + + set + { + horiResolution = value; + } + } + + /// + /// Gets or sets the horizontal resolution. If set to zero, is treated as a 26.6 fractional pixel + /// value. + /// + [CLSCompliant(false)] + public uint VerticalResolution + { + get + { + return vertResolution; + } + + set + { + vertResolution = value; + } + } + + #endregion + + #region Methods + + /// + /// Compares two s for equality. + /// + /// A . + /// Another . + /// A value indicating equality. + public static bool operator ==(SizeRequest left, SizeRequest right) + { + return left.Equals(right); + } + + /// + /// Compares two s for inequality. + /// + /// A . + /// Another . + /// A value indicating inequality. + public static bool operator !=(SizeRequest left, SizeRequest right) + { + return !left.Equals(right); + } + + /// + /// Compares this instance of to another for equality. + /// + /// A . + /// A value indicating equality. + public bool Equals(SizeRequest other) + { + return requestType == other.requestType && + width == other.width && + height == other.height && + horiResolution == other.horiResolution && + vertResolution == other.vertResolution; + } + + /// + /// Compares this instance of to another object for equality. + /// + /// An object. + /// A value indicating equality. + public override bool Equals(object obj) + { + if (obj is SizeRequest) + return this.Equals((SizeRequest)obj); + else + return false; + } + + /// + /// Gets a unique hash code for this instance. + /// + /// A unique hash code. + public override int GetHashCode() + { + return requestType.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ horiResolution.GetHashCode() ^ vertResolution.GetHashCode(); + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/SizeRequestType.cs b/SharpFont/Source/SharpFontShared/SizeRequestType.cs new file mode 100644 index 000000000..76e90d671 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SizeRequestType.cs @@ -0,0 +1,70 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// An enumeration type that lists the supported size request types. + /// + /// + /// The above descriptions only apply to scalable formats. For bitmap formats, the behaviour is up to the driver. + /// + /// See the note section of if you wonder how size + /// requesting relates to scaling values. + /// + public enum SizeRequestType + { + /// + /// The nominal size. The ‘units_per_EM’ field of is used to determine both scaling values. + /// + Normal, + + /// + /// The real dimension. The sum of the the ‘ascender’ and (minus of) the ‘descender’ fields of + /// are used to determine both scaling values. + /// + RealDimensions, + + /// + /// The font bounding box. The width and height of the ‘bbox’ field of are used to determine + /// the horizontal and vertical scaling value, respectively. + /// + BoundingBox, + + /// + /// The ‘max_advance_width’ field of is used to determine the horizontal scaling value; the + /// vertical scaling value is determined the same way as does. + /// Finally, both scaling values are set to the smaller one. This type is useful if you want to specify the + /// font size for, say, a window of a given dimension and 80x24 cells. + /// + Cell, + + /// + /// Specify the scaling values directly. + /// + Scales + } +} diff --git a/SharpFont/Source/SharpFontShared/Span.cs b/SharpFont/Source/SharpFontShared/Span.cs new file mode 100644 index 000000000..f154955c5 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Span.cs @@ -0,0 +1,112 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A structure used to model a single span of gray (or black) pixels when rendering a monochrome or anti-aliased + /// bitmap. + /// + /// + /// This structure is used by the span drawing callback type named which takes the y + /// coordinate of the span as a a parameter. + /// + /// The coverage value is always between 0 and 255. If you want less gray values, the callback function has to + /// reduce them. + /// + public class Span : NativeObject + { + #region Fields + + private SpanRec rec; + + #endregion + + #region Constructors + + internal Span(IntPtr reference) : base(reference) + { + } + + #endregion + + #region Properties + + /// + /// Gets the span's horizontal start position. + /// + public short X + { + get + { + return rec.x; + } + } + + /// + /// Gets the span's length in pixels. + /// + [CLSCompliant(false)] + public ushort Length + { + get + { + return rec.len; + } + } + + /// + /// Gets the span color/coverage, ranging from 0 (background) to 255 (foreground). Only used for anti-aliased + /// rendering. + /// + public byte Coverage + { + get + { + return rec.coverage; + } + } + + internal override IntPtr Reference + { + get + { + return base.Reference; + } + + set + { + base.Reference = value; + rec = PInvokeHelper.PtrToStructure(value); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/StreamDesc.cs b/SharpFont/Source/SharpFontShared/StreamDesc.cs new file mode 100644 index 000000000..0962ad697 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/StreamDesc.cs @@ -0,0 +1,94 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.Internal; + +namespace SharpFont +{ + /// + /// A union type used to store either a long or a pointer. This is used to store a file descriptor or a ‘FILE*’ in + /// an input stream. + /// + public class StreamDesc + { + #region Fields + + private IntPtr reference; + private StreamDescRec rec; + + #endregion + + #region Constructors + + internal StreamDesc(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the as a file descriptor. + /// + public int Value + { + get + { + return (int)rec.value; + } + } + + /// + /// Gets the as an input stream (FILE*). + /// + public IntPtr Pointer + { + get + { + return rec.pointer; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/Stroker.cs b/SharpFont/Source/SharpFontShared/Stroker.cs new file mode 100644 index 000000000..9ae79b4ea --- /dev/null +++ b/SharpFont/Source/SharpFontShared/Stroker.cs @@ -0,0 +1,392 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2015 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// Opaque handler to a path stroker object. + /// + public class Stroker : IDisposable + { + #region Fields + + private IntPtr reference; + private bool disposed; + + private Library parentLibrary; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// FreeType library handle. + public Stroker(Library library) + { + IntPtr strokerRef; + Error err = FT.FT_Stroker_New(library.Reference, out strokerRef); + + if (err != Error.Ok) + throw new FreeTypeException(err); + + Reference = strokerRef; + library.AddChildStroker(this); + parentLibrary = library; + } + + /// + /// Finalizes an instance of the class. + /// + ~Stroker() + { + Dispose(false); + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating whether the has been disposed. + /// + public bool IsDisposed + { + get + { + return disposed; + } + } + + internal IntPtr Reference + { + get + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + return reference; + } + + set + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + reference = value; + } + } + + #endregion + + #region Methods + + /// + /// Reset a stroker object's attributes. + /// + /// + /// The radius is expressed in the same units as the outline coordinates. + /// + /// The border radius. + /// The line cap style. + /// The line join style. + /// + /// The miter limit for the and + /// line join styles, expressed as 16.16 fixed point value. + /// + public void Set(int radius, StrokerLineCap lineCap, StrokerLineJoin lineJoin, Fixed16Dot16 miterLimit) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + FT.FT_Stroker_Set(Reference, radius, lineCap, lineJoin, (IntPtr)miterLimit.Value); + } + + /// + /// Reset a stroker object without changing its attributes. You should call this function before beginning a + /// new series of calls to or . + /// + public void Rewind() + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + FT.FT_Stroker_Rewind(Reference); + } + + /// + /// A convenience function used to parse a whole outline with the stroker. The resulting outline(s) can be + /// retrieved later by functions like and . + /// + /// + /// If ‘opened’ is 0 (the default), the outline is treated as a closed path, and the stroker generates two + /// distinct ‘border’ outlines. + /// + /// If ‘opened’ is 1, the outline is processed as an open path, and the stroker generates a single ‘stroke’ + /// outline. + /// + /// This function calls automatically. + /// + /// The source outline. + /// + /// A boolean. If 1, the outline is treated as an open path instead of a closed one. + /// + public void ParseOutline(Outline outline, bool opened) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + if (outline == null) + throw new ArgumentNullException("outline"); + + Error err = FT.FT_Stroker_ParseOutline(Reference, outline.Reference, opened); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Start a new sub-path in the stroker. + /// + /// + /// This function is useful when you need to stroke a path that is not stored as an + /// object. + /// + /// A pointer to the start vector. + /// A boolean. If 1, the sub-path is treated as an open one. + public void BeginSubPath(FTVector to, bool open) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_BeginSubPath(Reference, ref to, open); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Close the current sub-path in the stroker. + /// + /// + /// You should call this function after . If the subpath was not ‘opened’, this + /// function ‘draws’ a single line segment to the start position when needed. + /// + public void EndSubPath() + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_EndSubPath(Reference); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// ‘Draw’ a single line segment in the stroker's current sub-path, from the last position. + /// + /// + /// You should call this function between and . + /// + /// A pointer to the destination point. + public void LineTo(FTVector to) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_LineTo(Reference, ref to); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// ‘Draw’ a single quadratic Bézier in the stroker's current sub-path, from the last position. + /// + /// + /// You should call this function between and . + /// + /// A pointer to a Bézier control point. + /// A pointer to the destination point. + public void ConicTo(FTVector control, FTVector to) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_ConicTo(Reference, ref control, ref to); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// ‘Draw’ a single cubic Bézier in the stroker's current sub-path, from the last position. + /// + /// + /// You should call this function between and . + /// + /// A pointer to the first Bézier control point. + /// A pointer to second Bézier control point. + /// A pointer to the destination point. + public void CubicTo(FTVector control1, FTVector control2, FTVector to) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_CubicTo(Reference, ref control1, ref control2, ref to); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Call this function once you have finished parsing your paths with the stroker. It returns the number of + /// points and contours necessary to export one of the ‘border’ or ‘stroke’ outlines generated by the stroker. + /// + /// + /// When an outline, or a sub-path, is ‘closed’, the stroker generates two independent ‘border’ outlines, named + /// ‘left’ and ‘right’. + /// + /// When the outline, or a sub-path, is ‘opened’, the stroker merges the ‘border’ outlines with caps. The + /// ‘left’ border receives all points, while the ‘right’ border becomes empty. + /// + /// Use the function instead if you want to retrieve the counts associated to both + /// borders. + /// + /// The border index. + /// The number of points. + /// The number of contours. + [CLSCompliant(false)] + public void GetBorderCounts(StrokerBorder border, out uint pointsCount, out uint contoursCount) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_GetBorderCounts(Reference, border, out pointsCount, out contoursCount); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Call this function after to export the corresponding border to your own + /// structure. + /// + /// Note that this function appends the border points and contours to your outline, but does not try to resize + /// its arrays. + /// + /// + /// Always call this function after to get sure that there is enough room in your + /// object to receive all new data. + /// + /// When an outline, or a sub-path, is ‘closed’, the stroker generates two independent ‘border’ outlines, named + /// ‘left’ and ‘right’. + /// + /// When the outline, or a sub-path, is ‘opened’, the stroker merges the ‘border’ outlines with caps. The + /// ‘left’ border receives all points, while the ‘right’ border becomes empty. + /// + /// Use the function instead if you want to retrieve all borders at once. + /// + /// The border index. + /// The target outline handle. + public void ExportBorder(StrokerBorder border, Outline outline) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + if (outline == null) + throw new ArgumentNullException("outline"); + + FT.FT_Stroker_ExportBorder(Reference, border, outline.Reference); + } + + /// + /// Call this function once you have finished parsing your paths with the stroker. It returns the number of + /// points and contours necessary to export all points/borders from the stroked outline/path. + /// + /// The number of points. + /// The number of contours. + [CLSCompliant(false)] + public void GetCounts(out uint pointsCount, out uint contoursCount) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + Error err = FT.FT_Stroker_GetCounts(Reference, out pointsCount, out contoursCount); + + if (err != Error.Ok) + throw new FreeTypeException(err); + } + + /// + /// Call this function after to export all borders to your own + /// structure. + /// + /// Note that this function appends the border points and contours to your outline, but does not try to resize + /// its arrays. + /// + /// The target outline handle. + public void Export(Outline outline) + { + if (disposed) + throw new ObjectDisposedException("Stroker", "Cannot access a disposed object."); + + if (outline == null) + throw new ArgumentNullException("outline"); + + FT.FT_Stroker_Export(Reference, outline.Reference); + } + + /// + /// Disposes an instance of the class. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed) + { + disposed = true; + + FT.FT_Stroker_Done(reference); + + // removes itself from the parent Library, with a check to prevent this from happening when Library is + // being disposed (Library disposes all it's children with a foreach loop, this causes an + // InvalidOperationException for modifying a collection during enumeration) + if (!parentLibrary.IsDisposed) + parentLibrary.RemoveChildStroker(this); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/StrokerBorder.cs b/SharpFont/Source/SharpFontShared/StrokerBorder.cs new file mode 100644 index 000000000..2a08bb3b3 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/StrokerBorder.cs @@ -0,0 +1,53 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// These values are used to select a given stroke border in and + /// . + /// + /// + /// Applications are generally interested in the ‘inside’ and ‘outside’ borders. However, there is no direct + /// mapping between these and the ‘left’ and ‘right’ ones, since this really depends on the glyph's drawing + /// orientation, which varies between font formats. + /// + /// You can however use and to get + /// these. + /// + public enum StrokerBorder + { + /// + /// Select the left border, relative to the drawing direction. + /// + Left = 0, + + /// + /// Select the right border, relative to the drawing direction. + /// + Right + } +} diff --git a/SharpFont/Source/SharpFontShared/StrokerLineCap.cs b/SharpFont/Source/SharpFontShared/StrokerLineCap.cs new file mode 100644 index 000000000..7f43084e2 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/StrokerLineCap.cs @@ -0,0 +1,49 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// These values determine how the end of opened sub-paths are rendered in a stroke. + /// + public enum StrokerLineCap + { + /// + /// The end of lines is rendered as a full stop on the last point itself. + /// + Butt = 0, + + /// + /// The end of lines is rendered as a half-circle around the last point. + /// + Round, + + /// + /// The end of lines is rendered as a square around the last point. + /// + Square + } +} diff --git a/SharpFont/Source/SharpFontShared/StrokerLineJoin.cs b/SharpFont/Source/SharpFontShared/StrokerLineJoin.cs new file mode 100644 index 000000000..770cb2a24 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/StrokerLineJoin.cs @@ -0,0 +1,69 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// These values determine how two joining lines are rendered in a stroker. + /// + public enum StrokerLineJoin + { + /// + /// Used to render rounded line joins. Circular arcs are used to join two lines smoothly. + /// + Round = 0, + + /// + /// Used to render beveled line joins. The outer corner of the joined lines is filled by enclosing the + /// triangular region of the corner with a straight line between the outer corners of each stroke. + /// + Bevel = 1, + + /// + /// Used to render mitered line joins, with fixed bevels if the miter limit is exceeded. The outer edges of the + /// strokes for the two segments are extended until they meet at an angle. If the segments meet at too sharp an + /// angle (such that the miter would extend from the intersection of the segments a distance greater than the + /// product of the miter limit value and the border radius), then a bevel join (see above) is used instead. + /// This prevents long spikes being created. generates a miter line join as used in + /// PostScript and PDF. + /// + MiterVariable = 2, + + /// + /// An alias for , retained for backwards compatibility. + /// + Miter = MiterVariable, + + /// + /// Used to render mitered line joins, with variable bevels if the miter limit is exceeded. The intersection of + /// the strokes is clipped at a line perpendicular to the bisector of the angle between the strokes, at the + /// distance from the intersection of the segments equal to the product of the miter limit value and the border + /// radius. This prevents long spikes being created. generates a mitered line join + /// as used in XPS. + /// + MiterFixed = 3 + } +} diff --git a/SharpFont/Source/SharpFontShared/StyleFlags.cs b/SharpFont/Source/SharpFontShared/StyleFlags.cs new file mode 100644 index 000000000..1951520e3 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/StyleFlags.cs @@ -0,0 +1,49 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-flags used to indicate the style of a given face. These are used in the ‘style_flags’ field of + /// . + /// + /// + /// The style information as provided by FreeType is very basic. More details are beyond the scope and should be + /// done on a higher level (for example, by analyzing various fields of the ‘OS/2’ table in SFNT based fonts). + /// + [Flags] + public enum StyleFlags + { + /// No style flags. + None = 0x00, + + /// Indicates that a given face style is italic or oblique. + Italic = 0x01, + + /// Indicates that a given face is bold. + Bold = 0x02 + } +} diff --git a/SharpFont/Source/SharpFontShared/SubGlyph.cs b/SharpFont/Source/SharpFontShared/SubGlyph.cs new file mode 100644 index 000000000..0db46f1ca --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SubGlyph.cs @@ -0,0 +1,73 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont +{ + /// + /// The subglyph structure is an internal object used to describe subglyphs (for example, in the case of + /// composites). + /// + /// + /// The subglyph implementation is not part of the high-level API, hence the forward structure declaration. + /// + /// You can however retrieve subglyph information with . + /// + public sealed class SubGlyph + { + #region Fields + + private IntPtr reference; + + #endregion + + #region Constructors + + internal SubGlyph(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/SubGlyphFlags.cs b/SharpFont/Source/SharpFontShared/SubGlyphFlags.cs new file mode 100644 index 000000000..8cc64027f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/SubGlyphFlags.cs @@ -0,0 +1,71 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of constants used to describe subglyphs. Please refer to the TrueType specification for the meaning of + /// the various flags. + /// + [Flags] + public enum SubGlyphFlags + { + /// + /// Set this to indicate arguments are word size; otherwise, they are byte size. + /// + ArgsAreWords = 0x0001, + + /// + /// Set this to indicate arguments are X and Y values; otherwise, X and Y indicate point coordinates. + /// + ArgsAreXYValues = 0x0002, + + /// + /// Set this to round XY values to the grid. + /// + RoundXYToGrid = 0x0004, + + /// + /// Set this to indicate the component has a simple scale; otherwise, the scale is 1.0. + /// + Scale = 0x0008, + + /// + /// Set this to indicate that X and Y are scaled independently. + /// + XYScale = 0x0040, + + /// + /// Set this to indicate there is a 2 by 2 transformation used to scale the component. + /// + TwoByTwo = 0x0080, + + /// + /// Set this to forse aw, lsb and rsb for the composite to be equal to those from the original glyph. + /// + UseMyMetrics = 0x0200 + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/EncodingId.cs b/SharpFont/Source/SharpFontShared/TrueType/EncodingId.cs new file mode 100644 index 000000000..ba850c7bc --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/EncodingId.cs @@ -0,0 +1,230 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.TrueType +{ + /// + /// A list of valid values for the ‘encoding_id’ for TT_PLATFORM_APPLE_UNICODE charmaps and name entries. + /// + [CLSCompliant(false)] + public enum AppleEncodingId : ushort + { + /// Unicode version 1.0. + Default = 0, + + /// Unicode 1.1; specifies Hangul characters starting at U+34xx. + Unicode11, + + /// Deprecated (identical to preceding). + Iso10646, + + /// Unicode 2.0 and beyond (UTF-16 BMP only). + Unicode20, + + /// Unicode 3.1 and beyond, using UTF-32. + Unicode32, + + /// From Adobe, not Apple. Not a normal cmap. Specifies variations on a real cmap. + VariantSelector, + } + + /// + /// A list of valid values for the ‘encoding_id’ for TT_PLATFORM_MACINTOSH charmaps and name entries. + /// + [CLSCompliant(false)] + public enum MacEncodingId : ushort + { + /// Roman encoding. + Roman = 0, + + /// Japanese encoding. + Japanese = 1, + + /// Traditional Chinese encoding. + TraditionalChinese = 2, + + /// Korean encoding. + Korean = 3, + + /// Arabic encoding. + Arabic = 4, + + /// Hebrew encoding. + Hebrew = 5, + + /// Greek encoding. + Greek = 6, + + /// Russian encoding. + Russian = 7, + + /// RSymbol encoding. + RSymbol = 8, + + /// Devanagari encoding. + Devanagari = 9, + + /// Gurmukhi encoding. + Gurmukhi = 10, + + /// Gujarati encoding. + Gujarati = 11, + + /// Oriya encoding. + Oriya = 12, + + /// Bengali encoding. + Bengali = 13, + + /// Tamil encoding. + Tamil = 14, + + /// Telugu encoding. + Telugu = 15, + + /// Kannada encoding. + Kannada = 16, + + /// Malayalam encoding. + Malayalam = 17, + + /// Sinhalese encoding. + Sinhalese = 18, + + /// Burmese encoding. + Burmese = 19, + + /// Khmer encoding. + Khmer = 20, + + /// Thai encoding. + Thai = 21, + + /// Laotian encoding. + Laotian = 22, + + /// Georgian encoding. + Georgian = 23, + + /// Amernian encoding. + Armenian = 24, + + /// Maldivian encoding. + Maldivian = 25, + + /// Simplified Chinese encoding. + SimplifiedChinese = 25, + + /// Tibetan encoding. + Tibetan = 26, + + /// Mongolian encoding. + Mongolian = 27, + + /// Geez encoding. + Geez = 28, + + /// Slavic encoding. + Slavic = 29, + + /// Vietnamese encoding. + Vietnamese = 30, + + /// Sindhi encoding. + Sindhi = 31, + + /// No encoding specified. + Uninterpreted = 32, + } + + /// + /// A list of valid values for the ‘encoding_id’ for TT_PLATFORM_MICROSOFT charmaps and name entries. + /// + [CLSCompliant(false)] + public enum MicrosoftEncodingId : ushort + { + /// + /// Corresponds to Microsoft symbol encoding. See FT_ENCODING_MS_SYMBOL. + /// + Symbol = 0, + + /// + /// Corresponds to a Microsoft WGL4 charmap, matching Unicode. See FT_ENCODING_UNICODE. + /// + Unicode = 1, + + /// + /// Corresponds to SJIS Japanese encoding. See FT_ENCODING_SJIS. + /// + Sjis = 2, + + /// + /// Corresponds to Simplified Chinese as used in Mainland China. See FT_ENCODING_GB2312. + /// + GB2312 = 3, + + /// + /// Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. See FT_ENCODING_BIG5. + /// + Big5 = 4, + + /// + /// Corresponds to Korean Wansung encoding. See FT_ENCODING_WANSUNG. + /// + Wansung = 5, + + /// + /// Corresponds to Johab encoding. See FT_ENCODING_JOHAB. + /// + Johab = 6, + + /// + /// Corresponds to UCS-4 or UTF-32 charmaps. This has been added to the OpenType specification version 1.4 + /// (mid-2001.) + /// + Ucs4 = 10, + } + + /// + /// A list of valid values for the ‘encoding_id’ for TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific + /// extension! + /// + [CLSCompliant(false)] + public enum AdobeEncodingId : ushort + { + /// Adobe standard encoding. + Standard = 0, + + /// Adobe expert encoding. + Expert = 1, + + /// Adobe custom encoding. + Custom = 2, + + /// Adobe Latin 1 encoding. + Latin1 = 3 + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/EngineType.cs b/SharpFont/Source/SharpFontShared/TrueType/EngineType.cs new file mode 100644 index 000000000..8b4c88d9e --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/EngineType.cs @@ -0,0 +1,55 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.TrueType +{ + /// + /// A list of values describing which kind of TrueType bytecode engine is implemented in a given + /// instance. It is used by the function. + /// + public enum EngineType + { + /// + /// The library doesn't implement any kind of bytecode interpreter. + /// + None = 0, + + /// + /// The library implements a bytecode interpreter that doesn't support the patented operations of the TrueType + /// virtual machine. + /// + /// Its main use is to load certain Asian fonts which position and scale glyph components with bytecode + /// instructions. It produces bad output for most other fonts. + /// + Unpatented, + + /// + /// The library implements a bytecode interpreter that covers the full instruction set of the TrueType virtual + /// machine (this was governed by patents until May 2010, hence the name). + /// + Patented + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Header.cs b/SharpFont/Source/SharpFontShared/TrueType/Header.cs new file mode 100644 index 000000000..664ab3c2d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Header.cs @@ -0,0 +1,396 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Linq; +using System.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// Provides Mac style flags for the header table. + /// + [Flags] + [CLSCompliant(false)] + public enum HeaderMacStyles : ushort + { + /// + /// Bold style. + /// + Bold = 1 << 0, + + /// + /// Italic style. + /// + Italic = 1 << 2, + + /// + /// Underline style. + /// + Underline = 1 << 3, + + /// + /// Outline style. + /// + Outline = 1 << 4, + + /// + /// Shadow style. + /// + Shadow = 1 << 5, + + /// + /// Condensed style. + /// + Condensed = 1 << 6, + + /// + /// Extended style. + /// + Extended = 1 << 7, + + // bits 7-15 are reserved + } + + /// + /// Provides flags for the header table. + /// + [Flags] + [CLSCompliant(false)] + public enum HeaderFLags : ushort + { + /// + /// The baseline for this font is at the y-origin. + /// + BaselineAtOrigin = 1 << 0, + + /// + /// The left side bearing is at the x-origin. + /// + LeftSidebearingAtOrigin = 1 << 1, + + /// + /// The instructions in this font depend on the point size. + /// + InstructionsDependOnPointSize = 1 << 2, + + /// + /// Use integer values only (no fractional ppem sizes) for internal scaler math. + /// + ForcePpemToIntegers = 1 << 3, + + /// + /// Instructions may alter the advance width and therefore, advance widths might not scale linearly. + /// + InstructionsMayAlterAdvance = 1 << 4, + + // Bits 5-10 are not implemented in TrueType, but should be set according to Apple's specification + + /// + /// The font is designed to be laid out vertically, using the x-origin as the vertical baseline. + /// + FontIsVertical = 1 << 5, + + /// + /// This bit is reserved and must be set to zero. + /// + Reserved6 = 1 << 6, + + /// + /// The font requires layout for linguistic rendering, such as in Arabic fonts. + /// + RequiresLayout = 1 << 7, + + /// + /// The font is an AAT font having metamorphosis effects. + /// + HasMetamorphosisEffects = 1 << 8, + + /// + /// The font contains strong right-to-left glyphs. + /// + RightToLeft = 1 << 9, + + /// + /// The font contains Indic effects. + /// + IsIndic = 1 << 10, + + /// + /// The font data has been compressed and decompressed, making the data lossless. + /// + FontDataIsLossless = 1 << 11, + + /// + /// The font has been converted. + /// + FontIsConverted = 1 << 12, + + /// + /// The font is optimized for ClearType display. + /// + FontIsClearTypeOptimized = 1 << 13, + + /// + /// The glyphs in the cmap subtables are generic representations of code points. + /// If unset, those glyphs represent proper support for those code points. + /// + FontIsLastResort = 1 << 14, + + // Bit 15: reserved + } + + /// + /// A structure used to model a TrueType font header table. All fields follow the TrueType specification. + /// + public class Header + { + #region Fields + + private IntPtr reference; + private HeaderRec rec; + + #endregion + + #region Constructors + + internal Header(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// The version number of this table definition. + /// + public int TableVersion + { + get + { + return (int)rec.Table_Version; + } + } + + /// + /// The version number of the font, provided by the font manufacturer. + /// + public int FontRevision + { + get + { + return (int)rec.Font_Revision; + } + } + + /// + /// Provides a checksum of the font. + /// + public int ChecksumAdjust + { + get + { + return (int)rec.Checksum_Adjust; + } + } + + /// + /// Gets the constant 0x5F0F3CF5. + /// + public int MagicNumber + { + get + { + return (int)rec.Magic_Number; + } + } + + /// + /// Gets font flags for miscellaneous information. + /// + [CLSCompliant(false)] + public HeaderFLags Flags + { + get + { + return (HeaderFLags)rec.Flags; + } + } + + /// + /// Gets the designed number of units per em, also referred to as FUnits. + /// + [CLSCompliant(false)] + public ushort UnitsPerEM + { + get + { + return rec.Units_Per_EM; + } + } + + /// + /// Gets the date and time created. + /// + public int[] Created + { + get + { + return rec.Created.Select(x => (int)x).ToArray(); + } + } + + /// + /// Gets the last time modified. + /// + public int[] Modified + { + get + { + return rec.Modified.Select(x => (int)x).ToArray(); + } + } + + /// + /// Get the minimum X value of all glyph bounding boxes. + /// + public short MinimumX + { + get + { + return rec.xMin; + } + } + + /// + /// Get the minimum Y value of all glyph bounding boxes. + /// + public short MinimumY + { + get + { + return rec.yMin; + } + } + + /// + /// Get the maximum X value of all glyph bounding boxes. + /// + public short MaximumX + { + get + { + return rec.xMax; + } + } + + /// + /// Get the maximum Y value of all glyph bounding boxes. + /// + public short MaximumY + { + get + { + return rec.yMax; + } + } + + /// + /// Gets the basic style of the font (bold, etc.). + /// + [CLSCompliant(false)] + public HeaderMacStyles MacStyle + { + get + { + return (HeaderMacStyles)rec.Mac_Style; + } + } + + /// + /// Gets the smallest readable size, in pixels. + /// + [CLSCompliant(false)] + public ushort LowestRecPpem + { + get + { + return rec.Lowest_Rec_PPEM; + } + } + + /// + /// Gets the direction of glyhps (deprecated). + /// + public short FontDirection + { + get + { + return rec.Font_Direction; + } + } + + /// + /// Gets the length of index: 0 for short, 1 for long. + /// + public short IndexToLocFormat + { + get + { + return rec.Index_To_Loc_Format; + } + } + + /// + /// Gets the format of glyph data. + /// + public short GlyphDataFormat + { + get + { + return rec.Glyph_Data_Format; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/HoriHeader.cs b/SharpFont/Source/SharpFontShared/TrueType/HoriHeader.cs new file mode 100644 index 000000000..621db055c --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/HoriHeader.cs @@ -0,0 +1,274 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model a TrueType horizontal header, the ‘hhea’ table, as well as the corresponding + /// horizontal metrics table, i.e., the ‘hmtx’ table. + /// + /// + /// IMPORTANT: The and structures should be identical except for + /// the names of their fields which are different. + /// + /// This ensures that a single function in the ‘ttload’ module is able to read both the horizontal and vertical + /// headers. + /// + public class HoriHeader + { + #region Fields + + private IntPtr reference; + private HoriHeaderRec rec; + + #endregion + + #region Constructors + + internal HoriHeader(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the table version. + /// + public int Version + { + get + { + return (int)rec.Version; + } + } + + /// + /// Gets the font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in + /// the font. + /// + /// This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a + /// portion of the glyphs found in the font (maybe ASCII). + /// + /// You should use the ‘sTypoAscender’ field of the OS/2 table instead if you want the correct one. + /// + public short Ascender + { + get + { + return rec.Ascender; + } + } + + /// + /// Gets the font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points + /// found in the font. It is negative. + /// + /// This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a + /// portion of the glyphs found in the font (maybe ASCII). + /// + /// You should use the ‘sTypoDescender’ field of the OS/2 table instead if you want the correct one. + /// + public short Descender + { + get + { + return rec.Descender; + } + } + + /// + /// Gets the font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the + /// baseline-to-baseline distance for the font. + /// + public short LineGap + { + get + { + return rec.Line_Gap; + } + } + + /// + /// Gets the maximum of all advance widths found in the font. It can be used to compute the maximum width of an + /// arbitrary string of text. + /// + [CLSCompliant(false)] + public ushort AdvanceWidthMax + { + get + { + return rec.advance_Width_Max; + } + } + + /// + /// Gets the minimum left side bearing of all glyphs within the font. + /// + public short MinimumLeftSideBearing + { + get + { + return rec.min_Left_Side_Bearing; + } + } + + /// + /// Gets the minimum right side bearing of all glyphs within the font. + /// + public short MinimumRightSideBearing + { + get + { + return rec.min_Right_Side_Bearing; + } + } + + /// + /// Gets the maximum horizontal extent (i.e., the ‘width’ of a glyph's bounding box) for all glyphs in the + /// font. + /// + public short MaximumExtentX + { + get + { + return rec.xMax_Extent; + } + } + + /// + /// Gets the rise coefficient of the cursor's slope of the cursor (slope=rise/run). + /// + public short CaretSlopeRise + { + get + { + return rec.caret_Slope_Rise; + } + } + + /// + /// Gets the run coefficient of the cursor's slope. + /// + public short CaretSlopeRun + { + get + { + return rec.caret_Slope_Run; + } + } + + /// + /// Gets the amount of offset needed to provide best appearance with slanted fonts. + /// Set to 0 for non-slanted fonts. + /// + public short CaretOffset + { + get + { + return rec.caret_Offset; + } + } + + /// + /// Gets the 8 reserved bytes. + /// + public short[] Reserved + { + get + { + return rec.Reserved; + } + } + + /// + /// Gets 0, always. + /// + public short MetricDataFormat + { + get + { + return rec.metric_Data_Format; + } + } + + /// + /// Gets the number of HMetrics entries in the ‘hmtx’ table -- this value can be smaller than the total number + /// of glyphs in the font. + /// + [CLSCompliant(false)] + public ushort HMetricsCount + { + get + { + return rec.number_Of_HMetrics; + } + } + + /// + /// Gets a pointer into the ‘hmtx’ table. + /// + public IntPtr LongMetrics + { + get + { + return rec.long_metrics; + } + } + + /// + /// Gets a pointer into the ‘hmtx’ table. + /// + public IntPtr ShortMetrics + { + get + { + return rec.short_metrics; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/HeaderRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/HeaderRec.cs new file mode 100644 index 000000000..c216ac539 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/HeaderRec.cs @@ -0,0 +1,65 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct HeaderRec + { + internal FT_Long Table_Version; + internal FT_Long Font_Revision; + + internal FT_Long Checksum_Adjust; + internal FT_Long Magic_Number; + + internal ushort Flags; + internal ushort Units_Per_EM; + + private FT_Long created1; + private FT_Long created2; + internal FT_Long[] Created { get { return new[] {created1, created2}; } } + + private FT_Long modified1; + private FT_Long modified2; + internal FT_Long[] Modified { get { return new[] { modified1, modified2 }; } } + + internal short xMin; + internal short yMin; + internal short xMax; + internal short yMax; + + internal ushort Mac_Style; + internal ushort Lowest_Rec_PPEM; + + internal short Font_Direction; + internal short Index_To_Loc_Format; + internal short Glyph_Data_Format; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/HoriHeaderRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/HoriHeaderRec.cs new file mode 100644 index 000000000..19bffee0b --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/HoriHeaderRec.cs @@ -0,0 +1,73 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct HoriHeaderRec + { + internal FT_Long Version; + internal short Ascender; + internal short Descender; + internal short Line_Gap; + + internal ushort advance_Width_Max; + + internal short min_Left_Side_Bearing; + internal short min_Right_Side_Bearing; + internal short xMax_Extent; + internal short caret_Slope_Rise; + internal short caret_Slope_Run; + internal short caret_Offset; + + private fixed short reserved[4]; + internal short[] Reserved + { + get + { + var array = new short[4]; + + fixed (short* p = reserved) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + + return array; + } + } + + internal short metric_Data_Format; + internal ushort number_Of_HMetrics; + + internal IntPtr long_metrics; + internal IntPtr short_metrics; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/MaxProfileRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/MaxProfileRec.cs new file mode 100644 index 000000000..504f48bd4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/MaxProfileRec.cs @@ -0,0 +1,52 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct MaxProfileRec + { + internal FT_Long version; + internal ushort numGlyphs; + internal ushort maxPoints; + internal ushort maxContours; + internal ushort maxCompositePoints; + internal ushort maxCompositeContours; + internal ushort maxZones; + internal ushort maxTwilightPoints; + internal ushort maxStorage; + internal ushort maxFunctionDefs; + internal ushort maxInstructionDefs; + internal ushort maxStackElements; + internal ushort maxSizeOfInstructions; + internal ushort maxComponentElements; + internal ushort maxComponentDepth; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/OS2Rec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/OS2Rec.cs new file mode 100644 index 000000000..d54c52a05 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/OS2Rec.cs @@ -0,0 +1,113 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct OS2Rec + { + internal ushort version; + internal short xAvgCharWidth; + internal ushort usWeightClass; + internal ushort usWidthClass; + internal EmbeddingTypes fsType; + internal short ySubscriptXSize; + internal short ySubscriptYSize; + internal short ySubscriptXOffset; + internal short ySubscriptYOffset; + internal short ySuperscriptXSize; + internal short ySuperscriptYSize; + internal short ySuperscriptXOffset; + internal short ySuperscriptYOffset; + internal short yStrikeoutSize; + internal short yStrikeoutPosition; + internal short sFamilyClass; + + private fixed byte _panose[10]; + internal byte[] panose + { + get + { + var array = new byte[10]; + + fixed (byte* p = _panose) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + + return array; + } + } + + internal FT_ULong ulUnicodeRange1; + internal FT_ULong ulUnicodeRange2; + internal FT_ULong ulUnicodeRange3; + internal FT_ULong ulUnicodeRange4; + + private fixed byte _achVendID[4]; + internal byte[] achVendID + { + get + { + var array = new byte[4]; + + fixed (byte* p = _achVendID) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + + return array; + } + } + + internal ushort fsSelection; + internal ushort usFirstCharIndex; + internal ushort usLastCharIndex; + internal short sTypoAscender; + internal short sTypoDescender; + internal short sTypoLineGap; + internal ushort usWinAscent; + internal ushort usWinDescent; + + internal FT_ULong ulCodePageRange1; + internal FT_ULong ulCodePageRange2; + + internal short sxHeight; + internal short sCapHeight; + internal ushort usDefaultChar; + internal ushort usBreakChar; + internal ushort usMaxContext; + + internal ushort usLowerOpticalPointSize; + internal ushort usUpperOpticalPointSize; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/PCLTRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/PCLTRec.cs new file mode 100644 index 000000000..8638bb49f --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/PCLTRec.cs @@ -0,0 +1,85 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + internal unsafe struct PCLTRec + { + internal FT_Long Version; + internal FT_ULong FontNumber; + internal ushort Pitch; + internal ushort xHeight; + internal ushort Style; + internal ushort TypeFamily; + internal ushort CapHeight; + internal ushort SymbolSet; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + internal string TypeFace; + + private fixed byte characterComplement[8]; + internal byte[] CharacterComplement + { + get + { + var array = new byte[8]; + fixed (byte* p = characterComplement) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + return array; + } + } + + private fixed byte fileName[6]; + internal byte[] FileName + { + get + { + var array = new byte[6]; + + fixed (byte* p = fileName) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + + return array; + } + } + + internal byte StrokeWeight; + internal byte WidthType; + internal byte SerifStyle; + internal byte Reserved; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/PostscriptRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/PostscriptRec.cs new file mode 100644 index 000000000..c20668ed4 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/PostscriptRec.cs @@ -0,0 +1,46 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct PostscriptRec + { + internal FT_Long FormatType; + internal FT_Long italicAngle; + internal short underlinePosition; + internal short underlineThickness; + internal FT_ULong isFixedPitch; + internal FT_ULong minMemType42; + internal FT_ULong maxMemType42; + internal FT_ULong minMemType1; + internal FT_ULong maxMemType1; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/SfntNameRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/SfntNameRec.cs new file mode 100644 index 000000000..6f21c4977 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/SfntNameRec.cs @@ -0,0 +1,41 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal struct SfntNameRec + { + internal PlatformId platform_id; + internal ushort encoding_id; + internal ushort language_id; + internal ushort name_id; + + internal IntPtr @string; + internal uint string_len; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Internal/VertHeaderRec.cs b/SharpFont/Source/SharpFontShared/TrueType/Internal/VertHeaderRec.cs new file mode 100644 index 000000000..332e8ad01 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Internal/VertHeaderRec.cs @@ -0,0 +1,73 @@ +#region MIT License +/*Copyright (c) 2012-2015 Robert Rouhani + +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.Runtime.InteropServices; + +using FT_Long = System.IntPtr; +using FT_ULong = System.UIntPtr; + +namespace SharpFont.TrueType.Internal +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct VertHeaderRec + { + internal FT_Long Version; + internal short Ascender; + internal short Descender; + internal short Line_Gap; + + internal ushort advance_Height_Max; + + internal short min_Top_Side_Bearing; + internal short min_Bottom_Side_Bearing; + internal short yMax_Extent; + internal short caret_Slope_Rise; + internal short caret_Slope_Run; + internal short caret_Offset; + + private fixed short reserved[4]; + internal short[] Reserved + { + get + { + var array = new short[4]; + + fixed (short* p = reserved) + { + for (int i = 0; i < array.Length; i++) + array[i] = p[i]; + } + + return array; + } + } + + internal short metric_Data_Format; + internal ushort number_Of_VMetrics; + + internal IntPtr long_metrics; + internal IntPtr short_metrics; + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/MaxProfile.cs b/SharpFont/Source/SharpFontShared/TrueType/MaxProfile.cs new file mode 100644 index 000000000..8162c824c --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/MaxProfile.cs @@ -0,0 +1,258 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// The maximum profile is a table containing many max values which can be used to pre-allocate arrays. This + /// ensures that no memory allocation occurs during a glyph load. + /// + /// + /// This structure is only used during font loading. + /// + public class MaxProfile + { + #region Fields + + private IntPtr reference; + private MaxProfileRec rec; + + #endregion + + #region Constructors + + internal MaxProfile(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the version number. + /// + public int Version + { + get + { + return (int)rec.version; + } + } + + /// + /// Gets the number of glyphs in this TrueType font. + /// + [CLSCompliant(false)] + public ushort GlyphCount + { + get + { + return rec.numGlyphs; + } + } + + /// + /// Gets the maximum number of points in a non-composite TrueType glyph. See also the structure element + /// ‘maxCompositePoints’. + /// + [CLSCompliant(false)] + public ushort MaxPoints + { + get + { + return rec.maxPoints; + } + } + + /// + /// Gets the maximum number of contours in a non-composite TrueType glyph. See also the structure element + /// ‘maxCompositeContours’. + /// + [CLSCompliant(false)] + public ushort MaxContours + { + get + { + return rec.maxContours; + } + } + + /// + /// Gets the maximum number of points in a composite TrueType glyph. See also the structure element + /// ‘maxPoints’. + /// + [CLSCompliant(false)] + public ushort MaxCompositePoints + { + get + { + return rec.maxCompositePoints; + } + } + + /// + /// Gets the maximum number of contours in a composite TrueType glyph. See also the structure element + /// ‘maxContours’. + /// + [CLSCompliant(false)] + public ushort MaxCompositeContours + { + get + { + return rec.maxCompositeContours; + } + } + + /// + /// Gets the maximum number of zones used for glyph hinting. + /// + [CLSCompliant(false)] + public ushort MaxZones + { + get + { + return rec.maxZones; + } + } + + /// + /// Gets the maximum number of points in the twilight zone used for glyph hinting. + /// + [CLSCompliant(false)] + public ushort MaxTwilightPoints + { + get + { + return rec.maxTwilightPoints; + } + } + + /// + /// Gets the maximum number of elements in the storage area used for glyph hinting. + /// + [CLSCompliant(false)] + public ushort MaxStorage + { + get + { + return rec.maxStorage; + } + } + + /// + /// Gets the maximum number of function definitions in the TrueType bytecode for this font. + /// + [CLSCompliant(false)] + public ushort MaxFunctionDefs + { + get + { + return rec.maxFunctionDefs; + } + } + + /// + /// Gets the maximum number of instruction definitions in the TrueType bytecode for this font. + /// + [CLSCompliant(false)] + public ushort MaxInstructionDefs + { + get + { + return rec.maxInstructionDefs; + } + } + + /// + /// Gets the maximum number of stack elements used during bytecode interpretation. + /// + [CLSCompliant(false)] + public ushort MaxStackElements + { + get + { + return rec.maxStackElements; + } + } + + /// + /// Gets the maximum number of TrueType opcodes used for glyph hinting. + /// + [CLSCompliant(false)] + public ushort MaxSizeOfInstructions + { + get + { + return rec.maxSizeOfInstructions; + } + } + + /// + /// Gets the maximum number of simple (i.e., non- composite) glyphs in a composite glyph. + /// + [CLSCompliant(false)] + public ushort MaxComponentElements + { + get + { + return rec.maxComponentElements; + } + } + + /// + /// Gets the maximum nesting depth of composite glyphs. + /// + [CLSCompliant(false)] + public ushort MaxComponentDepth + { + get + { + return rec.maxComponentDepth; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/OS2.cs b/SharpFont/Source/SharpFontShared/TrueType/OS2.cs new file mode 100644 index 000000000..cf40219b2 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/OS2.cs @@ -0,0 +1,532 @@ +#region MIT License +/*Copyright (c) 2012-2014 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model a TrueType OS/2 table. This is the long table version. All fields comply to the + /// TrueType specification. + /// + /// Note that we now support old Mac fonts which do not include an OS/2 table. In this case, the ‘version’ field is + /// always set to 0xFFFF. + /// + public class OS2 + { + #region Fields + + private IntPtr reference; + private OS2Rec rec; + + #endregion + + #region Constructors + + internal OS2(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// The version of this table. + /// + [CLSCompliant(false)] + public ushort Version + { + get + { + return rec.version; + } + } + + /// + /// The average glyph width, computed by averaging ALL non-zero width glyphs in the font, in pels/em. + /// + public short AverageCharWidth + { + get + { + return rec.xAvgCharWidth; + } + } + + /// + /// The visual weight of the font. + /// + [CLSCompliant(false)] + public ushort WeightClass + { + get + { + return rec.usWeightClass; + } + } + + /// + /// The relative change in width from the normal aspect ratio. + /// + [CLSCompliant(false)] + public ushort WidthClass + { + get + { + return rec.usWidthClass; + } + } + + /// + /// Font embedding and subsetting licensing rights as determined by the font author. + /// + [CLSCompliant(false)] + public EmbeddingTypes EmbeddingType + { + get + { + return rec.fsType; + } + } + + /// + /// The font author's recommendation for sizing glyphs (em square) to create subscripts when a glyph doesn't exist for a subscript. + /// + public short SubscriptSizeX + { + get + { + return rec.ySubscriptXSize; + } + } + + /// + /// The font author's recommendation for sizing glyphs (em height) to create subscripts when a glyph doesn't exist for a subscript. + /// + public short SubscriptSizeY + { + get + { + return rec.ySubscriptYSize; + } + } + + /// + /// The font author's recommendation for vertically positioning subscripts that are created when a glyph doesn't exist for a subscript. + /// + public short SubscriptOffsetX + { + get + { + return rec.ySubscriptXOffset; + } + } + + /// + /// The font author's recommendation for horizontally positioning subscripts that are created when a glyph doesn't exist for a subscript. + /// + public short SubscriptOffsetY + { + get + { + return rec.ySubscriptYOffset; + } + } + + /// + /// The font author's recommendation for sizing glyphs (em square) to create superscripts when a glyph doesn't exist for a subscript. + /// + public short SuperscriptSizeX + { + get + { + return rec.ySuperscriptXSize; + } + } + + /// + /// The font author's recommendation for sizing glyphs (em height) to create superscripts when a glyph doesn't exist for a subscript. + /// + public short SuperscriptSizeY + { + get + { + return rec.ySuperscriptYSize; + } + } + + /// + /// The font author's recommendation for vertically positioning superscripts that are created when a glyph doesn't exist for a subscript. + /// + public short SuperscriptOffsetX + { + get + { + return rec.ySuperscriptXOffset; + } + } + + /// + /// The font author's recommendation for horizontally positioning superscripts that are created when a glyph doesn't exist for a subscript. + /// + public short SuperscriptOffsetY + { + get + { + return rec.ySuperscriptYOffset; + } + } + + /// + /// The thickness of the strikeout stroke. + /// + public short StrikeoutSize + { + get + { + return rec.yStrikeoutSize; + } + } + + /// + /// The position of the top of the strikeout line relative to the baseline. + /// + public short StrikeoutPosition + { + get + { + return rec.yStrikeoutPosition; + } + } + + /// + /// The IBM font family class and subclass, useful for choosing visually similar fonts. + /// + /// Refer to https://www.microsoft.com/typography/otspec160/ibmfc.htm. + public short FamilyClass + { + get + { + return rec.sFamilyClass; + } + } + + //TODO write a PANOSE class from TrueType spec? + /// + /// The Panose values describe visual characteristics of the font. + /// Similar fonts can then be selected based on their Panose values. + /// + public byte[] Panose + { + get + { + return rec.panose; + } + } + + /// + /// Unicode character range, bits 0-31. + /// + [CLSCompliant(false)] + public uint UnicodeRange1 + { + get + { + return (uint)rec.ulUnicodeRange1; + } + } + + /// + /// Unicode character range, bits 32-63. + /// + [CLSCompliant(false)] + public uint UnicodeRange2 + { + get + { + return (uint)rec.ulUnicodeRange2; + } + } + + /// + /// Unicode character range, bits 64-95. + /// + [CLSCompliant(false)] + public uint UnicodeRange3 + { + get + { + return (uint)rec.ulUnicodeRange3; + } + } + + /// + /// Unicode character range, bits 96-127. + /// + [CLSCompliant(false)] + public uint UnicodeRange4 + { + get + { + return (uint)rec.ulUnicodeRange4; + } + } + + /// + /// The vendor's identifier. + /// + public byte[] VendorId + { + get + { + return rec.achVendID; + } + } + + /// + /// Describes variations in the font. + /// + [CLSCompliant(false)] + public ushort SelectionFlags + { + get + { + return rec.fsSelection; + } + } + + /// + /// The minimum Unicode index (character code) in this font. + /// Since this value is limited to 0xFFFF, applications should not use this field. + /// + [CLSCompliant(false)] + public ushort FirstCharIndex + { + get + { + return rec.usFirstCharIndex; + } + } + + /// + /// The maximum Unicode index (character code) in this font. + /// Since this value is limited to 0xFFFF, applications should not use this field. + /// + [CLSCompliant(false)] + public ushort LastCharIndex + { + get + { + return rec.usLastCharIndex; + } + } + + /// + /// The ascender value, useful for computing a default line spacing in conjunction with unitsPerEm. + /// + public short TypographicAscender + { + get + { + return rec.sTypoAscender; + } + } + + /// + /// The descender value, useful for computing a default line spacing in conjunction with unitsPerEm. + /// + public short TypographicDescender + { + get + { + return rec.sTypoDescender; + } + } + + /// + /// The line gap value, useful for computing a default line spacing in conjunction with unitsPerEm. + /// + public short TypographicLineGap + { + get + { + return rec.sTypoLineGap; + } + } + + /// + /// The ascender metric for Windows, usually set to yMax. Windows will clip glyphs that go above this value. + /// + [CLSCompliant(false)] + public ushort WindowsAscent + { + get + { + return rec.usWinAscent; + } + } + + /// + /// The descender metric for Windows, usually set to yMin. Windows will clip glyphs that go below this value. + /// + [CLSCompliant(false)] + public ushort WindowsDescent + { + get + { + return rec.usWinDescent; + } + } + + /// + /// Specifies the code pages encompassed by this font. + /// + [CLSCompliant(false)] + public uint CodePageRange1 + { + get + { + return (uint)rec.ulCodePageRange1; + } + } + + /// + /// Specifies the code pages encompassed by this font. + /// + [CLSCompliant(false)] + public uint CodePageRange2 + { + get + { + return (uint)rec.ulUnicodeRange1; + } + } + + /// + /// The approximate height of non-ascending lowercase letters relative to the baseline. + /// + public short Height + { + get + { + return rec.sxHeight; + } + } + + /// + /// The approximate height of uppercase letters relative to the baseline. + /// + public short CapHeight + { + get + { + return rec.sCapHeight; + } + } + + /// + /// The Unicode index (character code) of the glyph to use when a glyph doesn't exist for the requested character. + /// Since this value is limited to 0xFFFF, applications should not use this field. + /// + [CLSCompliant(false)] + public ushort DefaultChar + { + get + { + return rec.usDefaultChar; + } + } + + /// + /// The Unicode index (character code) of the glyph to use as the break character. + /// The 'space' character is normally the break character. + /// Since this value is limited to 0xFFFF, applications should not use this field. + /// + [CLSCompliant(false)] + public ushort BreakChar + { + get + { + return rec.usBreakChar; + } + } + + /// + /// The maximum number of characters needed to determine glyph context when applying features such as ligatures. + /// + [CLSCompliant(false)] + public ushort MaxContext + { + get + { + return rec.usMaxContext; + } + } + + /// + /// The lowest point size at which the font starts to be used, in twips. + /// + [CLSCompliant(false)] + public ushort LowerOpticalPointSize + { + get + { + return rec.usLowerOpticalPointSize; + } + } + + /// + /// The highest point size at which the font is no longer used, in twips. + /// + [CLSCompliant(false)] + public ushort UpperOpticalPointSize + { + get + { + return rec.usUpperOpticalPointSize; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Pclt.cs b/SharpFont/Source/SharpFontShared/TrueType/Pclt.cs new file mode 100644 index 000000000..6f9bdd1d7 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Pclt.cs @@ -0,0 +1,251 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model a TrueType PCLT table. All fields comply to the TrueType specification. + /// + public class Pclt + { + #region Fields + + private IntPtr reference; + private PCLTRec rec; + + #endregion + + #region Constructors + + internal Pclt(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// The version number of this table. Version 1.0 is represented as 0x00010000. + /// + public int Version + { + get + { + return (int)rec.Version; + } + } + + /// + /// A unique identifier for the font. Refer to the specification for the meaning of various bits. + /// + [CLSCompliant(false)] + public uint FontNumber + { + get + { + return (uint)rec.FontNumber; + } + } + + /// + /// The width of the space character, in FUnits (see UnitsPerEm in the head table). + /// + [CLSCompliant(false)] + public ushort Pitch + { + get + { + return rec.Pitch; + } + } + + /// + /// The height of the optical height of the lowercase 'x' in FUnits. + /// This is a separate value from its height measurement. + /// + [CLSCompliant(false)] + public ushort Height + { + get + { + return rec.xHeight; + } + } + + /// + /// Describes structural appearance and effects of letterforms. + /// + [CLSCompliant(false)] + public ushort Style + { + get + { + return rec.Style; + } + } + + /// + /// Encodes the font vendor code and font family code into 16 bits. + /// Refer to the spec for details. + /// + [CLSCompliant(false)] + public ushort TypeFamily + { + get + { + return rec.TypeFamily; + } + } + + /// + /// The height of the optical height of the uppercase 'H' in FUnits. + /// This is a separate value from its height measurement. + /// + [CLSCompliant(false)] + public ushort CapHeight + { + get + { + return rec.CapHeight; + } + } + + /// + /// Encodes the symbol set's number field and ID field. + /// Refer to the spec for details. + /// + [CLSCompliant(false)] + public ushort SymbolSet + { + get + { + return rec.SymbolSet; + } + } + + /// + /// The name and style of the font. The names of fonts within a family should be identical and the + /// style identifiers should be standardized: e.g., Bd, It, BdIt. Length is 16 bytes. + /// + public string Typeface + { + get + { + return rec.TypeFace; + } + } + + /// + /// Identifies the symbol collections provided by the font. Length is 8 bytes. + /// Refer to the spec for details. + /// + public byte[] CharacterComplement + { + get + { + return rec.CharacterComplement; + } + } + + /// + /// A standardized filename of the font. Length is 6 bytes. + /// Refer to the spec for details. + /// + public byte[] FileName + { + get + { + return rec.FileName; + } + } + + /// + /// Indicates the stroke weight. Valid values are in the range -7 to 7. Length is 1 byte. + /// + public byte StrokeWeight + { + get + { + return rec.StrokeWeight; + } + } + + /// + /// Indicates the stroke weight. Valid values are in the range -5 to 5. Length is 1 byte. + /// + public byte WidthType + { + get + { + return rec.WidthType; + } + } + + /// + /// Encodes the serif style. The top two bits indicate sans serif/monoline or serif/contrasting. + /// Valid values for the lower 6 bits are in the range 0 to 12. Length is 1 byte. + /// + public byte SerifStyle + { + get + { + return rec.SerifStyle; + } + } + + /// + /// Reserved. Set to 0. + /// + public byte Reserved + { + get + { + return rec.Reserved; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/PlatformId.cs b/SharpFont/Source/SharpFontShared/TrueType/PlatformId.cs new file mode 100644 index 000000000..cb0b52845 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/PlatformId.cs @@ -0,0 +1,74 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.TrueType +{ + /// + /// A list of valid values for the ‘platform_id’ identifier code in and + /// structures. + /// + [CLSCompliant(false)] + public enum PlatformId : ushort + { + /// + /// Used by Apple to indicate a Unicode character map and/or name entry. See TT_APPLE_ID_XXX for corresponding + /// ‘encoding_id’ values. Note that name entries in this format are coded as big-endian UCS-2 character codes + /// only. + /// + AppleUnicode = 0, + + /// + /// Used by Apple to indicate a MacOS-specific charmap and/or name entry. See TT_MAC_ID_XXX for corresponding + /// ‘encoding_id’ values. Note that most TrueType fonts contain an Apple roman charmap to be usable on MacOS + /// systems (even if they contain a Microsoft charmap as well). + /// + Macintosh = 1, + + /// + /// This value was used to specify ISO/IEC 10646 charmaps. It is however now deprecated. See TT_ISO_ID_XXX for + /// a list of corresponding ‘encoding_id’ values. + /// + Iso = 2, + + /// + /// Used by Microsoft to indicate Windows-specific charmaps. See TT_MS_ID_XXX for a list of corresponding + /// ‘encoding_id’ values. Note that most fonts contain a Unicode charmap using (TT_PLATFORM_MICROSOFT, + /// TT_MS_ID_UNICODE_CS). + /// + Microsoft = 3, + + /// + /// Used to indicate application-specific charmaps. + /// + Custom = 4, + + /// + /// This value isn't part of any font format specification, but is used by FreeType to report Adobe-specific + /// charmaps in an structure. See TT_ADOBE_ID_XXX. + /// + Adobe = 7 + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/Postscript.cs b/SharpFont/Source/SharpFontShared/TrueType/Postscript.cs new file mode 100644 index 000000000..da95afe4d --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/Postscript.cs @@ -0,0 +1,179 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model a TrueType PostScript table. All fields comply to the TrueType specification. This + /// structure does not reference the PostScript glyph names, which can be nevertheless accessed with the ‘ttpost’ + /// module. + /// + public class Postscript + { + #region Fields + + private IntPtr reference; + private PostscriptRec rec; + + #endregion + + #region Constructors + + internal Postscript(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the version of the table information. + /// + public int FormatType + { + get + { + return (int)rec.FormatType; + } + } + + /// + /// Gets the angle of italics, in degrees, counter-clockwise from vertical. + /// + public int ItalicAngle + { + get + { + return (int)rec.italicAngle; + } + } + + /// + /// Gets the recommended position of the underline. + /// + public short UnderlinePosition + { + get + { + return rec.underlinePosition; + } + } + + /// + /// Gets the recommended thickness of the underline. + /// + public short UnderlineThickness + { + get + { + return rec.underlineThickness; + } + } + + /// + /// + /// + [CLSCompliant(false)] + public uint IsFixedPitch + { + get + { + return (uint)rec.isFixedPitch; + } + } + + /// + /// Gets the minimum amount of memory used by the font when an OpenType font is loaded. + /// + [CLSCompliant(false)] + public uint MinimumMemoryType42 + { + get + { + return (uint)rec.minMemType42; + } + } + + /// + /// Gets the maximum amount of memory used by the font when an OpenType font is loaded. + /// + [CLSCompliant(false)] + public uint MaximumMemoryType42 + { + get + { + return (uint)rec.maxMemType42; + } + } + + /// + /// Gets the minimum amount of memory used by the font when an OpenType font is loaded as + /// a Type 1 font. + /// + [CLSCompliant(false)] + public uint MinimumMemoryType1 + { + get + { + return (uint)rec.minMemType1; + } + } + + /// + /// Gets the maximum amount of memory used by the font when an OpenType font is loaded as + /// a Type 1 font. + /// + [CLSCompliant(false)] + public uint MaximumMemoryType1 + { + get + { + return (uint)rec.maxMemType1; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/SfntName.cs b/SharpFont/Source/SharpFontShared/TrueType/SfntName.cs new file mode 100644 index 000000000..1f4b10c14 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/SfntName.cs @@ -0,0 +1,152 @@ +#region MIT License +/*Copyright (c) 2012-2013, 2016 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model an SFNT ‘name’ table entry. + /// + /// + /// Possible values for ‘platform_id’, ‘encoding_id’, ‘language_id’, and ‘name_id’ are given in the file + /// ‘ttnameid.h’. For details please refer to the TrueType or OpenType specification. + /// + /// + /// + /// + /// + public class SfntName + { + #region Fields + + private SfntNameRec rec; + + #endregion + + #region Constructors + + internal SfntName(SfntNameRec rec) + { + this.rec = rec; + } + + #endregion + + #region Properties + + /// + /// Gets the platform ID for ‘string’. + /// + [CLSCompliant(false)] + public PlatformId PlatformId + { + get + { + return rec.platform_id; + } + } + + /// + /// Gets the encoding ID for ‘string’. + /// + [CLSCompliant(false)] + public ushort EncodingId + { + get + { + return rec.encoding_id; + } + } + + /// + /// Gets the language ID for ‘string’. + /// + [CLSCompliant(false)] + public ushort LanguageId + { + get + { + return rec.language_id; + } + } + + /// + /// Gets an identifier for ‘string’. + /// + [CLSCompliant(false)] + public ushort NameId + { + get + { + return rec.name_id; + } + } + + /// + /// This property returns interpreted as UTF-16. + /// + public string String + { + get + { + //TODO it may be possible to consolidate all of these properties + //if the strings follow some sane structure. Otherwise, leave + //them or add more overloads for common encodings like UTF-8. + return Marshal.PtrToStringUni(rec.@string, (int)rec.string_len); + } + } + + /// + /// This property returns interpreted as ANSI. + /// + public string StringAnsi + { + get + { + return Marshal.PtrToStringAnsi(rec.@string, (int)rec.string_len); + } + } + + /// + /// Gets the ‘name’ string. Note that its format differs depending on the (platform,encoding) pair. It can be a + /// Pascal String, a UTF-16 one, etc. + /// + /// Generally speaking, the string is not zero-terminated. Please refer to the TrueType specification for + /// details. + /// + public IntPtr StringPtr + { + get + { + return rec.@string; + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/SfntTag.cs b/SharpFont/Source/SharpFontShared/TrueType/SfntTag.cs new file mode 100644 index 000000000..c13a69726 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/SfntTag.cs @@ -0,0 +1,70 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont.TrueType +{ + /// + /// An enumeration used to specify the index of an SFNT table. Used in the API + /// function. + /// + public enum SfntTag + { + /// + /// The 'head' (header) table. + /// + Header = 0, + + /// + /// The 'maxp' (maximum profile) table. + /// + MaxProfile = 1, + + /// + /// The 'os/2' (OS/2 and Windows) table. + /// + OS2 = 2, + + /// + /// The 'hhea' (horizontal metrics header) table. + /// + HorizontalHeader = 3, + + /// + /// The 'vhea' (vertical metrics header) table. + /// + VertHeader = 4, + + /// + /// The 'post' (PostScript) table. + /// + Postscript = 5, + + /// + /// The 'pclt' (PCL5 data) table. + /// + Pclt = 6 + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueType/VertHeader.cs b/SharpFont/Source/SharpFontShared/TrueType/VertHeader.cs new file mode 100644 index 000000000..238ff98fd --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueType/VertHeader.cs @@ -0,0 +1,273 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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.Runtime.InteropServices; + +using SharpFont.TrueType.Internal; + +namespace SharpFont.TrueType +{ + /// + /// A structure used to model a TrueType vertical header, the ‘vhea’ table, as well as the corresponding vertical + /// metrics table, i.e., the ‘vmtx’ table. + /// + /// + /// IMPORTANT: The and structures should be identical except for + /// the names of their fields which are different. + /// + /// This ensures that a single function in the ‘ttload’ module is able to read both the horizontal and vertical + /// headers. + /// + public class VertHeader + { + #region Fields + + private IntPtr reference; + private VertHeaderRec rec; + + #endregion + + #region Constructors + + internal VertHeader(IntPtr reference) + { + Reference = reference; + } + + #endregion + + #region Properties + + /// + /// Gets the table version. + /// + public int Version + { + get + { + return (int)rec.Version; + } + } + + /// + /// Gets the font's ascender, i.e., the distance from the baseline to the top-most of all glyph points found in + /// the font. + /// + /// This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a + /// portion of the glyphs found in the font (maybe ASCII). + /// + /// You should use the ‘sTypoAscender’ field of the OS/2 table instead if you want the correct one. + /// + public short Ascender + { + get + { + return rec.Ascender; + } + } + + /// + /// Gets the font's descender, i.e., the distance from the baseline to the bottom-most of all glyph points + /// found in the font. It is negative. + /// + /// This value is invalid in many fonts, as it is usually set by the font designer, and often reflects only a + /// portion of the glyphs found in the font (maybe ASCII). + /// + /// You should use the ‘sTypoDescender’ field of the OS/2 table instead if you want the correct one. + /// + public short Descender + { + get + { + return rec.Descender; + } + } + + /// + /// Gets the font's line gap, i.e., the distance to add to the ascender and descender to get the BTB, i.e., the + /// baseline-to-baseline distance for the font. + /// + public short LineGap + { + get + { + return rec.Line_Gap; + } + } + + /// + /// Gets the maximum of all advance heights found in the font. It can be used to compute the maximum height of + /// an arbitrary string of text. + /// + [CLSCompliant(false)] + public ushort AdvanceHeightMax + { + get + { + return rec.advance_Height_Max; + } + } + + /// + /// Gets the minimum top side bearing of all glyphs within the font. + /// + public short MinimumTopSideBearing + { + get + { + return rec.min_Top_Side_Bearing; + } + } + + /// + /// Gets the minimum bottom side bearing of all glyphs within the font. + /// + public short MinimumBottomSideBearing + { + get + { + return rec.min_Bottom_Side_Bearing; + } + } + + /// + /// Gets the maximum vertical extent (i.e., the ‘height’ of a glyph's bounding box) for all glyphs in the font. + /// + public short MaximumExtentY + { + get + { + return rec.yMax_Extent; + } + } + + /// + /// Gets the rise coefficient of the cursor's slope of the cursor (slope=rise/run). + /// + public short CaretSlopeRise + { + get + { + return rec.caret_Slope_Rise; + } + } + + /// + /// Gets the run coefficient of the cursor's slope. + /// + public short CaretSlopeRun + { + get + { + return rec.caret_Slope_Run; + } + } + + /// + /// Gets the amount of space needed to offset the caret for best appearance. Applies to slanted fonts. + /// For non-slanted fonts, set this to 0. + /// + public short CaretOffset + { + get + { + return rec.caret_Offset; + } + } + + /// + /// Gets the 8 reserved bytes. + /// + public short[] Reserved + { + get + { + return rec.Reserved; + } + } + + /// + /// Gets 0, always. + /// + public short MetricDataFormat + { + get + { + return rec.metric_Data_Format; + } + } + + /// + /// Gets the number of VMetrics entries in the ‘vmtx’ table -- this value can be smaller than the total number + /// of glyphs in the font. + /// + [CLSCompliant(false)] + public ushort VMetricsCount + { + get + { + return rec.number_Of_VMetrics; + } + } + + /// + /// Gets a pointer into the ‘vmtx’ table. + /// + public IntPtr LongMetrics + { + get + { + return rec.long_metrics; + } + } + + /// + /// Gets a pointer into the ‘vmtx’ table. + /// + public IntPtr ShortMetrics + { + get + { + return rec.short_metrics; + } + } + + internal IntPtr Reference + { + get + { + return reference; + } + + set + { + reference = value; + rec = PInvokeHelper.PtrToStructure(reference); + } + } + + #endregion + } +} diff --git a/SharpFont/Source/SharpFontShared/TrueTypeValidationFlags.cs b/SharpFont/Source/SharpFontShared/TrueTypeValidationFlags.cs new file mode 100644 index 000000000..6a74ea2b8 --- /dev/null +++ b/SharpFont/Source/SharpFontShared/TrueTypeValidationFlags.cs @@ -0,0 +1,70 @@ +#region MIT License +/*Copyright (c) 2012-2013 Robert Rouhani + +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; + +namespace SharpFont +{ + /// + /// A list of bit-field constants used with to indicate which TrueTypeGX/AAT + /// Type tables should be validated. + /// + [Flags] + [CLSCompliant(false)] + public enum TrueTypeValidationFlags : uint + { + /// Validate ‘feat’ table. + Feat = 0x4000 << 0, + + /// Validate ‘mort’ table. + Mort = 0x4000 << 1, + + /// Validate ‘morx’ table. + Morx = 0x4000 << 2, + + /// Validate ‘bsln’ table. + Bsln = 0x4000 << 3, + + /// Validate ‘just’ table. + Just = 0x4000 << 4, + + /// Validate ‘kern’ table. + Kern = 0x4000 << 5, + + /// Validate ‘opbd’ table. + Opbd = 0x4000 << 6, + + /// Validate ‘trak’ table. + Trak = 0x4000 << 7, + + /// Validate ‘prop’ table. + Prop = 0x4000 << 8, + + /// Validate ‘lcar’ table. + Lcar = 0x4000 << 9, + + /// Validate all TrueTypeGX tables. + All = Feat | Mort | Morx | Bsln | Just | Kern | Opbd | Trak | Prop | Lcar + } +} diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index c6c62a760..2f49a034a 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -110,6 +110,7 @@ + @@ -1042,6 +1043,9 @@ PreserveNewest Designer + + PreserveNewest + PreserveNewest @@ -1217,6 +1221,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1226,6 +1233,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1676,6 +1689,10 @@ {49ba1c69-6104-41ac-a5d8-b54fa9f696e8} Lidgren.Network + + {c293db32-fa42-486d-b128-5a12522fae4e} + SharpFont + npy2H)vULjbrwUoT<$C#_&n%sa?W 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 O2iYb1YeCKTiu?tAv~H0A literal 0 HcmV?d00001 diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index 21ad55bf9..73b0bee77 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -524,7 +524,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, ConvertUnits.ToDisplayUnits(new Vector2(wallAttackPos.X, -wallAttackPos.Y)) - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false); } - spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY*20.0f, Color.Red); + GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY*20.0f, Color.Red); } if (selectedAiTarget != null) @@ -534,10 +534,10 @@ namespace Barotrauma new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red); } - spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red); + GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red); - spriteBatch.DrawString(GUI.Font, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red); - spriteBatch.DrawString(GUI.Font, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red); + GUI.Font.DrawString(spriteBatch, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red); + GUI.Font.DrawString(spriteBatch, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red); IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager; @@ -556,7 +556,7 @@ namespace Barotrauma new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y), Color.LightGreen); - spriteBatch.DrawString(GUI.SmallFont, + GUI.SmallFont.DrawString(spriteBatch, pathSteering.CurrentPath.Nodes[i].ID.ToString(), new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10), Color.LightGreen); diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index fe25a7bb6..ed63eb9eb 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -186,7 +186,7 @@ namespace Barotrauma new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y), Color.LightGreen); - spriteBatch.DrawString(GUI.SmallFont, + GUI.SmallFont.DrawString(spriteBatch, pathSteering.CurrentPath.Nodes[i].ID.ToString(), new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10), Color.LightGreen); diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 47de2f7bb..f00df91bd 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -1387,12 +1387,12 @@ namespace Barotrauma { nameColor = Color.Red; } - spriteBatch.DrawString(GUI.Font, Info.Name, namePos + new Vector2(1.0f/cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f,Vector2.Zero, 1.0f / cam.Zoom,SpriteEffects.None,0.001f); - spriteBatch.DrawString(GUI.Font, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f/cam.Zoom, SpriteEffects.None, 0.0f); + GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f/cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f,Vector2.Zero, 1.0f / cam.Zoom,SpriteEffects.None,0.001f); + GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f/cam.Zoom, SpriteEffects.None, 0.0f); if (GameMain.DebugDraw) { - spriteBatch.DrawString(GUI.Font, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White); + GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White); } } diff --git a/Subsurface/Source/Characters/CharacterInfo.cs b/Subsurface/Source/Characters/CharacterInfo.cs index 4eada1df1..b29e93b75 100644 --- a/Subsurface/Source/Characters/CharacterInfo.cs +++ b/Subsurface/Source/Characters/CharacterInfo.cs @@ -223,7 +223,7 @@ namespace Barotrauma { new GUIImage(new Rectangle(0,0,30,30), HeadSprite, Alignment.TopLeft, frame); - SpriteFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font; + ScalableFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font; int x = 0, y = 0; new GUITextBlock(new Rectangle(x+60, y, 200, 20), Name, GUI.Style, frame, font); diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index ba9a80569..de8316b29 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -54,14 +54,14 @@ namespace Barotrauma { int x = 20, y = 20; int width = 800, height = 500; - + frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.5f)); frame.Color = Color.White * 0.4f; frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, GUI.Style, frame); listBox.Color = Color.Black * 0.7f; - + textBox = new GUITextBox(new Rectangle(0,0,0,20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, GUI.Style, frame); textBox.Color = Color.Black * 0.7f; diff --git a/Subsurface/Source/Fonts/ScalableFont.cs b/Subsurface/Source/Fonts/ScalableFont.cs new file mode 100644 index 000000000..526394ec9 --- /dev/null +++ b/Subsurface/Source/Fonts/ScalableFont.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpFont; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Barotrauma +{ + public class ScalableFont + { + private static List FontList = new List(); + private static Library Lib = null; + + private string filename; + private Face face; + private uint size; + private int baseHeight; + //private int lineHeight; + private Dictionary texCoords; + private List textures; + private GraphicsDevice graphicsDevice; + + public uint Size + { + get + { + return size; + } + set + { + size = value; + if (graphicsDevice!=null) RenderAtlas(graphicsDevice, charRanges, texDims, baseChar); + } + } + + private uint[] charRanges; + private int texDims; + private uint baseChar; + + private struct GlyphData + { + public int texIndex; + public Vector2 drawOffset; + public float advance; + public Rectangle texCoords; + } + + public ScalableFont(string filename, uint size, GraphicsDevice gd=null) + { + if (Lib == null) Lib = new Library(); + this.filename = filename; + this.face = null; + foreach (ScalableFont font in FontList) + { + if (font.filename == filename) + { + this.face = font.face; + break; + } + } + if (this.face == null) + { + this.face = new Face(Lib, filename); + } + this.size = size; + + this.textures = new List(); + + this.texCoords = new Dictionary(); + + if (gd != null) RenderAtlas(gd); + + FontList.Add(this); + } + + /// + /// Renders the font into at least one texture atlas, which is simply a collection of all glyphs in the ranges defined by charRanges. + /// Don't call this too often or with very large sizes. + /// + /// Graphics device, required to create textures. + /// Character ranges between each even element with their corresponding odd element. Default is 0x20 to 0xFFFF. + /// Texture dimensions. Default is 512x512. + /// Base character used to shift all other characters downwards when rendering. Defaults to T. + public void RenderAtlas(GraphicsDevice gd, uint[] charRanges = null, int texDims = 512, uint baseChar = 0x54) + { + if (charRanges == null) + { + charRanges = new uint[] { 0x20, 0xFFFF }; + } + this.charRanges = charRanges; + this.texDims = texDims; + this.baseChar = baseChar; + + face.SetPixelSizes(0, size); + textures.ForEach(t => t.Dispose()); + textures.Clear(); + texCoords.Clear(); + + uint[] pixelBuffer = new uint[texDims * texDims]; + for (int i = 0; i < texDims * texDims; i++) + { + pixelBuffer[i] = 0; + } + + textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color)); + int texIndex = 0; + + Vector2 currentCoords = Vector2.Zero; + int nextY = 0; + + face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal); + baseHeight = face.Glyph.Metrics.Height.ToInt32(); + //lineHeight = baseHeight; + for (int i = 0; i < charRanges.Count(); i += 2) + { + uint start = charRanges[i]; + uint end = charRanges[i + 1]; + for (uint j = start; j <= end; j++) + { + uint glyphIndex = face.GetCharIndex(j); + if (glyphIndex == 0) continue; + face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); + if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0) + { + if (face.Glyph.Metrics.HorizontalAdvance > 0) + { + //glyph is empty, but char still applies advance + GlyphData blankData = new GlyphData(); + blankData.advance = (float)face.Glyph.Metrics.HorizontalAdvance; + blankData.texIndex = -1; //indicates no texture because the glyph is empty + texCoords.Add(j, blankData); + } + continue; + } + //stacktrace doesn't really work that well when RenderGlyph throws an exception + face.Glyph.RenderGlyph(RenderMode.Normal); + byte[] bitmap = face.Glyph.Bitmap.BufferData; + int glyphWidth = face.Glyph.Bitmap.Width; + int glyphHeight = bitmap.Count() / glyphWidth; + + //if (glyphHeight>lineHeight) lineHeight=glyphHeight; + + if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1) + { + throw new Exception(filename + ", " + size.ToString() + ", "+ (char)j + "; Glyph dimensions exceed texture atlas dimensions"); + } + + nextY = Math.Max(nextY, glyphHeight + 2); + + if (currentCoords.X + glyphWidth + 2 > texDims - 1) + { + currentCoords.X = 0; + currentCoords.Y += nextY; + nextY = 0; + } + if (currentCoords.Y + glyphHeight + 2 > texDims - 1) + { + currentCoords.X = 0; + currentCoords.Y = 0; + textures[texIndex].SetData(pixelBuffer); + textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color)); + texIndex++; + for (int k = 0; k < texDims * texDims; k++) + { + pixelBuffer[k] = 0; + } + } + + GlyphData newData = new GlyphData(); + newData.advance = (float)face.Glyph.Metrics.HorizontalAdvance; + newData.texIndex = texIndex; + newData.texCoords = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight); + newData.drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight*14/10 - face.Glyph.BitmapTop); + texCoords.Add(j, newData); + + for (int y = 0; y < glyphHeight; y++) + { + for (int x = 0; x < glyphWidth; x++) + { + byte byteColor = bitmap[x + y * glyphWidth]; + pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor); + } + } + + currentCoords.X += glyphWidth + 2; + } + textures[texIndex].SetData(pixelBuffer); + } + + graphicsDevice = gd; + } + + public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects se, float layerDepth) + { + if (textures.Count == 0) return; + + int lineNum = 0; + Vector2 currentPos = position; + Vector2 advanceUnit = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)); + for (int i = 0; i < text.Length; i++) + { + if (text[i]=='\n') + { + lineNum++; + currentPos = position; + currentPos.X += baseHeight * 18 / 10 * lineNum * advanceUnit.Y; + currentPos.Y += baseHeight * 18 / 10 * lineNum * advanceUnit.X; + continue; + } + uint charIndex = text[i]; + GlyphData gd; + if (texCoords.TryGetValue(charIndex, out gd)) + { + if (gd.texIndex >= 0) + { + Texture2D tex = textures[gd.texIndex]; + Vector2 drawOffset; + drawOffset.X = gd.drawOffset.X * advanceUnit.X - gd.drawOffset.Y * advanceUnit.Y; + drawOffset.Y = gd.drawOffset.X * advanceUnit.Y + gd.drawOffset.Y * advanceUnit.X; + + sb.Draw(tex, currentPos + drawOffset, null, gd.texCoords, origin, rotation, scale, color, se, layerDepth); + } + currentPos += gd.advance * advanceUnit * scale.X; + } + } + } + + public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects se, float layerDepth) + { + DrawString(sb, text, position, color, rotation, origin, new Vector2(scale), se, layerDepth); + } + + public void DrawString(SpriteBatch sb, string text, Vector2 position, Color color) + { + if (textures.Count == 0) return; + + Vector2 currentPos = position; + for (int i = 0; i < text.Length; i++) + { + if (text[i] == '\n') + { + currentPos.X = position.X; + currentPos.Y += baseHeight * 18 / 10; + continue; + } + uint charIndex = text[i]; + GlyphData gd; + if (texCoords.TryGetValue(charIndex, out gd)) + { + if (gd.texIndex >= 0) + { + Texture2D tex = textures[gd.texIndex]; + sb.Draw(tex, currentPos + gd.drawOffset, gd.texCoords, color); + } + currentPos.X += gd.advance; + } + } + } + + public Vector2 MeasureString(string text) + { + float currentLineX = 0.0f; + Vector2 retVal = Vector2.Zero; + retVal.Y = baseHeight*18/10; + for (int i = 0; i < text.Length; i++) + { + if (text[i] == '\n') + { + currentLineX = 0.0f; + retVal.Y += baseHeight*18/10; + continue; + } + uint charIndex = text[i]; + GlyphData gd; + if (texCoords.TryGetValue(charIndex, out gd)) + { + currentLineX += gd.advance; + } + retVal.X = Math.Max(retVal.X,currentLineX); + } + return retVal; + } + } +} diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index 862994141..4e325fa86 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -31,11 +31,22 @@ namespace Barotrauma public static GUIStyle Style; private static Texture2D t; - public static SpriteFont Font, SmallFont, LargeFont; + public static ScalableFont Font, SmallFont, LargeFont; private static Sprite cursor; private static GraphicsDevice graphicsDevice; + public static GraphicsDevice GraphicsDevice + { + get + { + return graphicsDevice; + } + set + { + graphicsDevice = value; + } + } private static List messages = new List(); @@ -68,9 +79,9 @@ namespace Barotrauma public static void Init(ContentManager content) { - Font = ToolBox.TryLoadFont("SpriteFont1", content); - SmallFont = ToolBox.TryLoadFont("SmallFont", content); - LargeFont = ToolBox.TryLoadFont("LargeFont", content); + Font = new ScalableFont("Content/Exo2-Medium.otf", 14, graphicsDevice); + SmallFont = new ScalableFont("Content/Exo2-Light.otf", 12, graphicsDevice); + LargeFont = new ScalableFont("Content/CODE Bold.otf", 22, graphicsDevice); cursor = new Sprite("Content/UI/cursor.png", Vector2.Zero); @@ -87,10 +98,8 @@ namespace Barotrauma get { return settingsMenuOpen; } } - public static void LoadContent(GraphicsDevice graphics, bool loadSounds = true) + public static void LoadContent(bool loadSounds = true) { - graphicsDevice = graphics; - if (loadSounds) { sounds = new Sound[Enum.GetValues(typeof(GUISoundType)).Length]; @@ -232,7 +241,7 @@ namespace Barotrauma depth); } - public static void DrawString(SpriteBatch sb, Vector2 pos, string text, Color color, Color? backgroundColor=null, int backgroundPadding=0, SpriteFont font = null) + public static void DrawString(SpriteBatch sb, Vector2 pos, string text, Color color, Color? backgroundColor=null, int backgroundPadding=0, ScalableFont font = null) { if (font == null) font = Font; @@ -242,7 +251,7 @@ namespace Barotrauma DrawRectangle(sb, pos - Vector2.One * backgroundPadding, textSize + Vector2.One * 2.0f * backgroundPadding, (Color)backgroundColor, true); } - sb.DrawString(font, text, pos, color); + font.DrawString(sb, text, pos, color); } public static void DrawRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, bool isFilled = false, float depth = 0.0f, int thickness = 1) @@ -405,7 +414,7 @@ namespace Barotrauma origin = Vector2.Zero; } - sb.DrawString(Font, text, new Vector2(rect.Center.X, rect.Center.Y) , Color.White, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f); + Font.DrawString(sb, text, new Vector2(rect.Center.X, rect.Center.Y) , Color.White, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f); return clicked; } @@ -591,12 +600,12 @@ namespace Barotrauma msg.Pos = MathUtils.SmoothStep(msg.Pos, currPos, deltaTime*20.0f); - spriteBatch.DrawString(Font, msg.Text, + Font.DrawString(spriteBatch, msg.Text, new Vector2((int)msg.Pos.X - 1, (int)msg.Pos.Y - 1), Color.Black * alpha*0.5f, 0.0f, new Vector2((int)(0.5f * msg.Size.X), (int)(0.5f * msg.Size.Y)), 1.0f, SpriteEffects.None, 0.0f); - spriteBatch.DrawString(Font, msg.Text, + Font.DrawString(spriteBatch, msg.Text, new Vector2((int)msg.Pos.X, (int)msg.Pos.Y), msg.Color * alpha, 0.0f, new Vector2((int)(0.5f * msg.Size.X), (int)(0.5f * msg.Size.Y)), 1.0f, SpriteEffects.None, 0.0f); diff --git a/Subsurface/Source/GUI/GUIButton.cs b/Subsurface/Source/GUI/GUIButton.cs index c96f149bd..d55676f2a 100644 --- a/Subsurface/Source/GUI/GUIButton.cs +++ b/Subsurface/Source/GUI/GUIButton.cs @@ -84,7 +84,7 @@ namespace Barotrauma set { textBlock.TextColor = value; } } - public override SpriteFont Font + public override ScalableFont Font { get { diff --git a/Subsurface/Source/GUI/GUIComponent.cs b/Subsurface/Source/GUI/GUIComponent.cs index 8af57bd6c..94e4b3d54 100644 --- a/Subsurface/Source/GUI/GUIComponent.cs +++ b/Subsurface/Source/GUI/GUIComponent.cs @@ -99,7 +99,7 @@ namespace Barotrauma protected Color flashColor; protected float flashTimer; - public virtual SpriteFont Font + public virtual ScalableFont Font { get; set; diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs index 5e3ef7697..493461e04 100644 --- a/Subsurface/Source/GUI/GUITextBlock.cs +++ b/Subsurface/Source/GUI/GUITextBlock.cs @@ -14,6 +14,7 @@ namespace Barotrauma protected Vector2 origin; protected Vector2 caretPos; + protected int caretAt; protected Color textColor; @@ -103,8 +104,8 @@ namespace Barotrauma { get { return caretPos; } } - - public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent, SpriteFont font) + + public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent, ScalableFont font) : this(rect, text, style, Alignment.TopLeft, Alignment.TopLeft, parent, false, font) { } @@ -142,7 +143,7 @@ namespace Barotrauma if (textColor != null) this.textColor = (Color)textColor; } - public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false, SpriteFont font = null) + public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false, ScalableFont font = null) :base (style) { this.Font = font == null ? GUI.Font : font; @@ -174,7 +175,7 @@ namespace Barotrauma wrappedText = text; - Vector2 size = MeasureText(text); + Vector2 size = MeasureText(text); if (Wrap && rect.Width>0) { @@ -184,7 +185,7 @@ namespace Barotrauma size = newSize; } - + if (LimitText && text.Length>1 && size.Y > rect.Height) { string[] lines = text.Split('\n'); @@ -205,7 +206,7 @@ namespace Barotrauma if (textAlignment.HasFlag(Alignment.Bottom)) origin.Y -= (rect.Height / 2.0f - padding.W) - size.Y / 2; - + origin.X = (int)origin.X; origin.Y = (int)origin.Y; @@ -263,7 +264,7 @@ namespace Barotrauma if (!string.IsNullOrEmpty(text)) { - spriteBatch.DrawString(Font, + Font.DrawString(spriteBatch, Wrap ? wrappedText : text, new Vector2(rect.X, rect.Y) + textPos + offset, textColor * (textColor.A / 255.0f), diff --git a/Subsurface/Source/GUI/GUITextBox.cs b/Subsurface/Source/GUI/GUITextBox.cs index 30bdd6c6a..aa0fe900f 100644 --- a/Subsurface/Source/GUI/GUITextBox.cs +++ b/Subsurface/Source/GUI/GUITextBox.cs @@ -15,7 +15,7 @@ namespace Barotrauma bool caretVisible; float caretTimer; - + GUITextBlock textBlock; public delegate bool OnEnterHandler(GUITextBox textBox, string text); @@ -65,7 +65,7 @@ namespace Barotrauma } } - public override SpriteFont Font + public override ScalableFont Font { set { @@ -131,7 +131,7 @@ namespace Barotrauma if (textBlock.Text != "") { - //if you attempt to display a Character that is not in your font + /*//if you attempt to display a Character that is not in your font //you will get an exception, so we filter the characters //remove the filtering if you're using a default Character in your spritefont String filtered = ""; @@ -140,7 +140,7 @@ namespace Barotrauma if (Font.Characters.Contains(c)) filtered += c; } - textBlock.Text = filtered; + textBlock.Text = filtered;*/ if (!Wrap && Font.MeasureString(textBlock.Text).X > rect.Width) { @@ -182,6 +182,8 @@ namespace Barotrauma textBlock = new GUITextBlock(new Rectangle(0,0,0,0), "", color, textColor, textAlignment, style, this); + Font = GUI.Font; + if (style != null) style.Apply(textBlock, this); textBlock.Padding = new Vector4(3.0f, 0.0f, 3.0f, 0.0f); diff --git a/Subsurface/Source/GUI/GUITickBox.cs b/Subsurface/Source/GUI/GUITickBox.cs index 8ed501baa..c54a620dc 100644 --- a/Subsurface/Source/GUI/GUITickBox.cs +++ b/Subsurface/Source/GUI/GUITickBox.cs @@ -65,7 +65,7 @@ namespace Barotrauma { } - public GUITickBox(Rectangle rect, string label, Alignment alignment, SpriteFont font, GUIComponent parent) + public GUITickBox(Rectangle rect, string label, Alignment alignment, ScalableFont font, GUIComponent parent) : base(null) { if (parent != null) diff --git a/Subsurface/Source/GUI/LoadingScreen.cs b/Subsurface/Source/GUI/LoadingScreen.cs index bbf194600..4d0a8863b 100644 --- a/Subsurface/Source/GUI/LoadingScreen.cs +++ b/Subsurface/Source/GUI/LoadingScreen.cs @@ -167,7 +167,7 @@ namespace Barotrauma if (GUI.LargeFont!=null) { - spriteBatch.DrawString(GUI.LargeFont, loadText, + GUI.LargeFont.DrawString(spriteBatch, loadText, new Vector2(GameMain.GraphicsWidth/2.0f - GUI.LargeFont.MeasureString(loadText).X/2.0f, GameMain.GraphicsHeight*0.8f), Color.White); } diff --git a/Subsurface/Source/GameMain.cs b/Subsurface/Source/GameMain.cs index e8c171971..42b657b14 100644 --- a/Subsurface/Source/GameMain.cs +++ b/Subsurface/Source/GameMain.cs @@ -116,7 +116,7 @@ namespace Barotrauma public GameMain() { Graphics = new GraphicsDeviceManager(this); - + Window.Title = "Barotrauma"; Instance = this; @@ -208,6 +208,7 @@ namespace Barotrauma public IEnumerable Load() { + GUI.GraphicsDevice = GraphicsDevice; GUI.Init(Content); GUIComponent.Init(Window); @@ -221,7 +222,7 @@ namespace Barotrauma TitleScreen.LoadState = 1.0f; yield return CoroutineStatus.Running; - GUI.LoadContent(GraphicsDevice); + GUI.LoadContent(); TitleScreen.LoadState = 2.0f; yield return CoroutineStatus.Running; @@ -380,8 +381,7 @@ namespace Barotrauma if (!paused) Timing.Alpha = Timing.Accumulator / Timing.Step; } - - + /// /// This is called when the game should draw itself. /// @@ -399,7 +399,7 @@ namespace Barotrauma { Screen.Selected.Draw(deltaTime, GraphicsDevice, spriteBatch); } - + if (!DebugDraw) return; if (GUIComponent.MouseOn!=null) { diff --git a/Subsurface/Source/Items/Components/Machines/Engine.cs b/Subsurface/Source/Items/Components/Machines/Engine.cs index 3ecec7d7c..97b5ae165 100644 --- a/Subsurface/Source/Items/Components/Machines/Engine.cs +++ b/Subsurface/Source/Items/Components/Machines/Engine.cs @@ -115,7 +115,7 @@ namespace Barotrauma.Items.Components //GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); - spriteBatch.DrawString(GUI.Font, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White); + GUI.Font.DrawString(spriteBatch, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White); } public override void AddToGUIUpdateList() diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index c388ff63a..7c96528a4 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -158,7 +158,7 @@ namespace Barotrauma.Items.Components GuiFrame.Draw(spriteBatch); - spriteBatch.DrawString(GUI.Font, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White); + GUI.Font.DrawString(spriteBatch, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White); } diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 02849c33a..c7a3fad4a 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -443,9 +443,9 @@ namespace Barotrauma.Items.Components //GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); - spriteBatch.DrawString(GUI.Font, "Output: " + (int)temperature + " kW", + GUI.Font.DrawString(spriteBatch, "Output: " + (int)temperature + " kW", new Vector2(x + 450, y + 30), Color.Red); - spriteBatch.DrawString(GUI.Font, "Grid load: " + (int)load + " kW", + GUI.Font.DrawString(spriteBatch, "Grid load: " + (int)load + " kW", new Vector2(x + 600, y + 30), Color.Yellow); float maxLoad = 0.0f; @@ -460,18 +460,18 @@ namespace Barotrauma.Items.Components DrawGraph(loadGraph, spriteBatch, new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Yellow); - spriteBatch.DrawString(GUI.Font, "Shutdown Temperature: " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White); + GUI.Font.DrawString(spriteBatch, "Shutdown Temperature: " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White); - //spriteBatch.DrawString(GUI.Font, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 450, y + 180), Color.White); + //GUI.Font.DrawString(spriteBatch, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 450, y + 180), Color.White); y += 300; - spriteBatch.DrawString(GUI.Font, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White); + GUI.Font.DrawString(spriteBatch, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White); DrawGraph(fissionRateGraph, spriteBatch, new Rectangle(x + 30, y + 30, 200, 100), 100.0f, xOffset, Color.Orange); - spriteBatch.DrawString(GUI.Font, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White); + GUI.Font.DrawString(spriteBatch, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White); DrawGraph(coolingRateGraph, spriteBatch, new Rectangle(x + 320, y + 30, 200, 100), 100.0f, xOffset, Color.LightBlue); diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index b5377d5b8..f58edf092 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -232,11 +232,11 @@ namespace Barotrauma.Items.Components int y = GuiFrame.Rect.Y; //GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); - spriteBatch.DrawString(GUI.Font, + GUI.Font.DrawString(spriteBatch, "Charge: " + (int)charge + "/" + (int)capacity + " kWm (" + (int)((charge / capacity) * 100.0f) + " %)", new Vector2(x + 30, y + 30), Color.White); - spriteBatch.DrawString(GUI.Font, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White); + GUI.Font.DrawString(spriteBatch, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White); } public override void AddToGUIUpdateList() diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index 9fa4d9b2c..2542019bc 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -179,8 +179,8 @@ namespace Barotrauma.Items.Components GuiFrame.Draw(spriteBatch); - spriteBatch.DrawString(GUI.Font, "Power: " + (int)(-currPowerConsumption) + " kW", new Vector2(x + 30, y + 30), Color.White); - spriteBatch.DrawString(GUI.Font, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White); + GUI.Font.DrawString(spriteBatch, "Power: " + (int)(-currPowerConsumption) + " kW", new Vector2(x + 30, y + 30), Color.White); + GUI.Font.DrawString(spriteBatch, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White); } public override void AddToGUIUpdateList() diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index 6e84a083d..1d4fbab66 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -316,7 +316,7 @@ namespace Barotrauma.Items.Components private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval) { - //spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White); + //GUI.SmallFont.DrawString(spriteBatch, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White); GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black,0, GUI.SmallFont); GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X-10, (int)position.Y-10, 20, 20), Color.White); diff --git a/Subsurface/Source/Items/Inventory.cs b/Subsurface/Source/Items/Inventory.cs index 6ef1e3640..f4532972b 100644 --- a/Subsurface/Source/Items/Inventory.cs +++ b/Subsurface/Source/Items/Inventory.cs @@ -361,7 +361,7 @@ namespace Barotrauma pos.Y = (int)pos.Y; GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true); - spriteBatch.DrawString(GUI.Font, toolTip, + GUI.Font.DrawString(spriteBatch, toolTip, new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)), Color.White, 0.0f, new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)), diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index ec2ae613c..ee3a51c69 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -603,9 +603,9 @@ namespace Barotrauma if (GameMain.DebugDraw) { - spriteBatch.DrawString(GUI.SmallFont, "Pressure: " + ((int)pressure - rect.Y).ToString() + + GUI.SmallFont.DrawString(spriteBatch, "Pressure: " + ((int)pressure - rect.Y).ToString() + " - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White); - spriteBatch.DrawString(GUI.SmallFont, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White); + GUI.SmallFont.DrawString(spriteBatch, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White); } if ((IsSelected || isHighlighted) && editing) diff --git a/Subsurface/Source/Map/MapEntityPrefab.cs b/Subsurface/Source/Map/MapEntityPrefab.cs index 7f6dacd67..24139401d 100644 --- a/Subsurface/Source/Map/MapEntityPrefab.cs +++ b/Subsurface/Source/Map/MapEntityPrefab.cs @@ -232,7 +232,7 @@ namespace Barotrauma public void DrawListLine(SpriteBatch spriteBatch, Vector2 pos, Color color) { - spriteBatch.DrawString(GUI.Font, name, pos, color); + GUI.Font.DrawString(spriteBatch, name, pos, color); } } diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index 6575a5ff0..05626dfd8 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -158,7 +158,7 @@ namespace Barotrauma //GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true); - //spriteBatch.DrawString(GUI.SmallFont, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); + //GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White); foreach (MapEntity e in linkedTo) { @@ -314,7 +314,7 @@ namespace Barotrauma - //spriteBatch.DrawString(GUI.font, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black); + //GUI.Font.DrawString(spriteBatch, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black); y = y + 30; diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index bc2617c79..2cbafde69 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -876,23 +876,23 @@ namespace Barotrauma.Networking int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f); GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true); - spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); + GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); if (client.ServerConnection != null) { - spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White); + GUI.Font.DrawString(spriteBatch, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White); y += 15; - spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); } else { - spriteBatch.DrawString(GUI.Font, "Disconnected", new Vector2(x + 10, y + 25), Color.White); + GUI.Font.DrawString(spriteBatch, "Disconnected", new Vector2(x + 10, y + 25), Color.White); } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 2531e252e..5dd1a1f15 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -1433,14 +1433,14 @@ namespace Barotrauma.Networking GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true); - spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); + GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White); + GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); int resentMessages = 0; @@ -1460,10 +1460,10 @@ namespace Barotrauma.Networking if (y >= startY && y < startY + height - 120) { - spriteBatch.DrawString(GUI.SmallFont, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor); - spriteBatch.DrawString(GUI.SmallFont, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor); + GUI.SmallFont.DrawString(spriteBatch, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor); + GUI.SmallFont.DrawString(spriteBatch, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor); } - if (y + 25 >= startY && y < startY + height - 130) spriteBatch.DrawString(GUI.SmallFont, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor); + if (y + 25 >= startY && y < startY + height - 130) GUI.SmallFont.DrawString(spriteBatch, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor); resentMessages += (int)c.Connection.Statistics.ResentMessages; diff --git a/Subsurface/Source/Networking/NetStats.cs b/Subsurface/Source/Networking/NetStats.cs index 8ef1a651a..bdc19a3e6 100644 --- a/Subsurface/Source/Networking/NetStats.cs +++ b/Subsurface/Source/Networking/NetStats.cs @@ -71,24 +71,24 @@ namespace Barotrauma.Networking graphs[(int)NetStatType.ResentMessages].Draw(spriteBatch, rect, null, 0.0f, Color.Red); - spriteBatch.DrawString(GUI.SmallFont, + GUI.SmallFont.DrawString(spriteBatch, "Peak received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].LargestValue()) + "/s " + "Avg received: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.ReceivedBytes].Average()) + "/s", new Vector2(rect.X + 10, rect.Y + 10), Color.Cyan); - spriteBatch.DrawString(GUI.SmallFont, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " + + GUI.SmallFont.DrawString(spriteBatch, "Peak sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].LargestValue()) + "/s " + "Avg sent: " + MathUtils.GetBytesReadable((int)graphs[(int)NetStatType.SentBytes].Average()) + "/s", new Vector2(rect.X + 10, rect.Y + 30), Color.Orange); - spriteBatch.DrawString(GUI.SmallFont, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s", + GUI.SmallFont.DrawString(spriteBatch, "Peak resent: " + graphs[(int)NetStatType.ResentMessages].LargestValue() + " messages/s", new Vector2(rect.X + 10, rect.Y + 50), Color.Red); #if DEBUG int y = 10; foreach (KeyValuePair msgBytesSent in server.messageCount.OrderBy(key => -key.Value)) { - spriteBatch.DrawString(GUI.SmallFont, msgBytesSent.Key + ": " + MathUtils.GetBytesReadable(msgBytesSent.Value), + GUI.SmallFont.DrawString(spriteBatch, msgBytesSent.Key + ": " + MathUtils.GetBytesReadable(msgBytesSent.Value), new Vector2(rect.Right - 200, rect.Y + y), Color.Red); y += 15; diff --git a/Subsurface/Source/Program.cs b/Subsurface/Source/Program.cs index f678a1114..eaf57c560 100644 --- a/Subsurface/Source/Program.cs +++ b/Subsurface/Source/Program.cs @@ -139,11 +139,11 @@ namespace Barotrauma if (GameMain.Server != null) { - sb.AppendLine("Server (" + (GameMain.Server.GameStarted ? "Round had started)" : "Round hand't been started)")); + sb.AppendLine("Server (" + (GameMain.Server.GameStarted ? "Round had started)" : "Round hadn't been started)")); } else if (GameMain.Client != null) { - sb.AppendLine("Client (" + (GameMain.Client.GameStarted ? "Round had started)" : "Round hand't been started)")); + sb.AppendLine("Client (" + (GameMain.Client.GameStarted ? "Round had started)" : "Round hadn't been started)")); } sb.AppendLine("\n"); diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs index 50fb6747f..76ac9323f 100644 --- a/Subsurface/Source/Screens/LobbyScreen.cs +++ b/Subsurface/Source/Screens/LobbyScreen.cs @@ -267,7 +267,7 @@ namespace Barotrauma frame.ToolTip = ep.Description; - SpriteFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; + ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; GUITextBlock textBlock = new GUITextBlock( new Rectangle(50, 0, 0, 25), diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index 293e15cbd..f172d3daa 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -511,7 +511,7 @@ namespace Barotrauma GUI.Draw((float)deltaTime, spriteBatch, null); - spriteBatch.DrawString(GUI.Font, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White); + GUI.Font.DrawString(spriteBatch, "Barotrauma v"+GameMain.Version, new Vector2(10, GameMain.GraphicsHeight-20), Color.White); spriteBatch.End(); } diff --git a/Subsurface/Source/Screens/ServerListScreen.cs b/Subsurface/Source/Screens/ServerListScreen.cs index 44ccd93d0..69f2f08b4 100644 --- a/Subsurface/Source/Screens/ServerListScreen.cs +++ b/Subsurface/Source/Screens/ServerListScreen.cs @@ -60,7 +60,7 @@ namespace Barotrauma if (n > 0) columnX[n] += columnX[n - 1]; } - SpriteFont font = GUI.SmallFont; // serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font; + ScalableFont font = GUI.SmallFont; // serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font; new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.Style, menu).Font = font; diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index decd88e39..eb11099ec 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -89,7 +89,7 @@ namespace Barotrauma return doc; } - public static SpriteFont TryLoadFont(string file, Microsoft.Xna.Framework.Content.ContentManager contentManager) + /*public static SpriteFont TryLoadFont(string file, Microsoft.Xna.Framework.Content.ContentManager contentManager) { SpriteFont font = null; try @@ -102,7 +102,7 @@ namespace Barotrauma } return font; - } + }*/ public static object GetAttributeObject(XElement element, string name) { @@ -383,7 +383,7 @@ namespace Barotrauma return str.Substring(0, maxCharacters-3) + "..."; } - public static string LimitString(string str, SpriteFont font, int maxWidth) + public static string LimitString(string str, ScalableFont font, int maxWidth) { if (maxWidth <= 0 || string.IsNullOrWhiteSpace(str)) return ""; @@ -465,7 +465,7 @@ namespace Barotrauma return d[n, m]; } - public static string WrapText(string text, float lineLength, SpriteFont font) + public static string WrapText(string text, float lineLength, ScalableFont font) //TODO: could integrate this into the ScalableFont class directly { if (font.MeasureString(text).X < lineLength) return text; diff --git a/Subsurface/freetype6.dll b/Subsurface/freetype6.dll new file mode 100644 index 0000000000000000000000000000000000000000..3a94b26fee34aab9afab4780019d9aa2c226d75f GIT binary patch literal 452096 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