├── .gitignore ├── FW1FontWrapper ├── CFW1ColorRGBA.cpp ├── CFW1ColorRGBA.h ├── CFW1ColorRGBAInterface.cpp ├── CFW1DWriteRenderTarget.cpp ├── CFW1DWriteRenderTarget.h ├── CFW1DWriteRenderTargetInterface.cpp ├── CFW1Factory.cpp ├── CFW1Factory.h ├── CFW1FactoryInterface.cpp ├── CFW1FontWrapper.cpp ├── CFW1FontWrapper.h ├── CFW1FontWrapperInterface.cpp ├── CFW1GlyphAtlas.cpp ├── CFW1GlyphAtlas.h ├── CFW1GlyphAtlasInterface.cpp ├── CFW1GlyphProvider.cpp ├── CFW1GlyphProvider.h ├── CFW1GlyphProviderInterface.cpp ├── CFW1GlyphRenderStates.cpp ├── CFW1GlyphRenderStates.h ├── CFW1GlyphRenderStatesInterface.cpp ├── CFW1GlyphSheet.cpp ├── CFW1GlyphSheet.h ├── CFW1GlyphSheetInterface.cpp ├── CFW1GlyphVertexDrawer.cpp ├── CFW1GlyphVertexDrawer.h ├── CFW1GlyphVertexDrawerInterface.cpp ├── CFW1Object.h ├── CFW1StateSaver.cpp ├── CFW1StateSaver.h ├── CFW1TextGeometry.cpp ├── CFW1TextGeometry.h ├── CFW1TextGeometryInterface.cpp ├── CFW1TextRenderer.cpp ├── CFW1TextRenderer.h ├── CFW1TextRendererInterface.cpp ├── FW1CompileSettings.h ├── FW1FontWrapper.cpp ├── FW1FontWrapper.h ├── FW1Precompiled.cpp └── FW1Precompiled.h ├── LICENSE ├── Minhook ├── include │ └── MinHook.h └── src │ ├── HDE │ ├── hde32.c │ ├── hde32.h │ ├── hde64.c │ ├── hde64.h │ ├── pstdint.h │ ├── table32.h │ └── table64.h │ ├── buffer.c │ ├── buffer.h │ ├── hook.c │ ├── trampoline.c │ └── trampoline.h ├── README.md ├── SDK.hpp ├── SDK.rar ├── UE4-SDK-InternalHack-Zanzo.sln ├── bones.h ├── d3d11hook.vcxproj ├── d3d11hook.vcxproj.filters ├── d3d11hook.vcxproj.user ├── global.h ├── hooks.h ├── main.cpp ├── main.h ├── renderer.cpp ├── renderer.h ├── shader.h └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1ColorRGBA.cpp: -------------------------------------------------------------------------------- 1 | // CFW1ColorRGBA.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1ColorRGBA.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Construct 12 | CFW1ColorRGBA::CFW1ColorRGBA() : 13 | m_color32(0xffffffff) 14 | { 15 | } 16 | 17 | 18 | // Destruct 19 | CFW1ColorRGBA::~CFW1ColorRGBA() { 20 | } 21 | 22 | 23 | // Init 24 | HRESULT CFW1ColorRGBA::initColor(IFW1Factory *pFW1Factory, UINT32 initialColor32) { 25 | HRESULT hResult = initBaseObject(pFW1Factory); 26 | if(FAILED(hResult)) 27 | return hResult; 28 | 29 | m_color32 = initialColor32; 30 | 31 | return S_OK; 32 | } 33 | 34 | 35 | }// namespace FW1FontWrapper 36 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1ColorRGBA.h: -------------------------------------------------------------------------------- 1 | // CFW1ColorRGBA.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1ColorRGBA 4 | #define IncludeGuard__FW1_CFW1ColorRGBA 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // A color 13 | class CFW1ColorRGBA : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1Color32 19 | virtual void STDMETHODCALLTYPE SetColor(UINT32 Color); 20 | virtual void STDMETHODCALLTYPE SetColor(FLOAT Red, FLOAT Green, FLOAT Blue, FLOAT Alpha); 21 | virtual void STDMETHODCALLTYPE SetColor(const FLOAT *pColor); 22 | virtual void STDMETHODCALLTYPE SetColor(const BYTE *pColor); 23 | 24 | virtual UINT32 STDMETHODCALLTYPE GetColor32(); 25 | 26 | // Public functions 27 | public: 28 | CFW1ColorRGBA(); 29 | 30 | HRESULT initColor(IFW1Factory *pFW1Factory, UINT32 initialColor32); 31 | 32 | // Internal functions 33 | private: 34 | virtual ~CFW1ColorRGBA(); 35 | 36 | // Internal data 37 | private: 38 | UINT32 m_color32; 39 | }; 40 | 41 | 42 | }// namespace FW1FontWrapper 43 | 44 | 45 | #endif// IncludeGuard__FW1_CFW1ColorRGBA 46 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1ColorRGBAInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1ColorRGBAInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1ColorRGBA.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1ColorRGBA::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1ColorRGBA))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Set the color 27 | void STDMETHODCALLTYPE CFW1ColorRGBA::SetColor(UINT32 Color) { 28 | m_color32 = Color; 29 | } 30 | 31 | 32 | // Set the color 33 | void STDMETHODCALLTYPE CFW1ColorRGBA::SetColor(FLOAT Red, FLOAT Green, FLOAT Blue, FLOAT Alpha) { 34 | UINT32 color32; 35 | BYTE *colorBytes = reinterpret_cast(&color32); 36 | colorBytes[0] = static_cast(Red * 255.0f + 0.5f); 37 | colorBytes[1] = static_cast(Green * 255.0f + 0.5f); 38 | colorBytes[2] = static_cast(Blue * 255.0f + 0.5f); 39 | colorBytes[3] = static_cast(Alpha * 255.0f + 0.5f); 40 | 41 | m_color32 = color32; 42 | } 43 | 44 | 45 | // Set the color 46 | void STDMETHODCALLTYPE CFW1ColorRGBA::SetColor(const FLOAT *pColor) { 47 | SetColor(pColor[0], pColor[1], pColor[2], pColor[3]); 48 | } 49 | 50 | 51 | // Set the color 52 | void STDMETHODCALLTYPE CFW1ColorRGBA::SetColor(const BYTE *pColor) { 53 | UINT32 color32; 54 | BYTE *colorBytes = reinterpret_cast(&color32); 55 | for(int i=0; i < 4; ++i) 56 | colorBytes[i] = pColor[i]; 57 | 58 | m_color32 = color32; 59 | } 60 | 61 | 62 | // Get the color 63 | UINT32 STDMETHODCALLTYPE CFW1ColorRGBA::GetColor32() { 64 | return m_color32; 65 | } 66 | 67 | 68 | }// namespace FW1FontWrapper 69 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1DWriteRenderTarget.cpp: -------------------------------------------------------------------------------- 1 | // CFW1DWriteRenderTarget.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1DWriteRenderTarget.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1DWriteRenderTarget::CFW1DWriteRenderTarget() : 15 | m_pRenderTarget(NULL), 16 | m_hDC(NULL), 17 | m_hBlackBrush(NULL), 18 | m_bmWidthBytes(0), 19 | m_bmBytesPixel(0), 20 | m_renderTargetWidth(0), 21 | m_renderTargetHeight(0) 22 | { 23 | } 24 | 25 | 26 | // Destruct 27 | CFW1DWriteRenderTarget::~CFW1DWriteRenderTarget() { 28 | if(m_hBlackBrush != NULL) 29 | DeleteObject(m_hBlackBrush); 30 | 31 | SAFE_RELEASE(m_pRenderTarget); 32 | 33 | for(RenderingParamsMap::iterator it = m_renderingParams.begin(); it != m_renderingParams.end(); ++it) 34 | it->second->Release(); 35 | } 36 | 37 | 38 | // Init 39 | HRESULT CFW1DWriteRenderTarget::initRenderTarget( 40 | IFW1Factory *pFW1Factory, 41 | IDWriteFactory *pDWriteFactory, 42 | UINT renderTargetWidth, 43 | UINT renderTargetHeight 44 | ) { 45 | HRESULT hResult = initBaseObject(pFW1Factory); 46 | if(FAILED(hResult)) 47 | return hResult; 48 | 49 | if(pDWriteFactory == NULL) 50 | return E_INVALIDARG; 51 | 52 | m_renderTargetWidth = 384; 53 | if(renderTargetWidth > 0) 54 | m_renderTargetWidth = renderTargetWidth; 55 | 56 | m_renderTargetHeight = 384; 57 | if(renderTargetHeight > 0) 58 | m_renderTargetHeight = renderTargetHeight; 59 | 60 | // Create render target 61 | hResult = createRenderTarget(pDWriteFactory); 62 | 63 | if(SUCCEEDED(hResult)) 64 | hResult = S_OK; 65 | 66 | return hResult; 67 | } 68 | 69 | 70 | // Create render target 71 | HRESULT CFW1DWriteRenderTarget::createRenderTarget(IDWriteFactory *pDWriteFactory) { 72 | IDWriteGdiInterop *pGDIInterop; 73 | HRESULT hResult = pDWriteFactory->GetGdiInterop(&pGDIInterop); 74 | if(FAILED(hResult)) { 75 | m_lastError = L"Failed to get GDI interop"; 76 | } 77 | else { 78 | IDWriteBitmapRenderTarget *pRenderTarget; 79 | hResult = pGDIInterop->CreateBitmapRenderTarget( 80 | NULL, 81 | m_renderTargetWidth, 82 | m_renderTargetHeight, 83 | &pRenderTarget 84 | ); 85 | if(FAILED(hResult)) { 86 | m_lastError = L"Failed to create bitmap render target"; 87 | } 88 | else { 89 | hResult = pRenderTarget->SetPixelsPerDip(1.0f); 90 | hResult = S_OK; 91 | 92 | HDC hDC = pRenderTarget->GetMemoryDC(); 93 | if(hDC == NULL) { 94 | m_lastError = L"Failed to get render target DC"; 95 | hResult = E_FAIL; 96 | } 97 | else { 98 | HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0)); 99 | if(hBrush == NULL) { 100 | m_lastError = L"Failed to create brush"; 101 | hResult = E_FAIL; 102 | } 103 | else { 104 | HBITMAP hBitmap = static_cast(GetCurrentObject(hDC, OBJ_BITMAP)); 105 | if(hBitmap == NULL) { 106 | m_lastError = L"GetCurrentObject failed"; 107 | hResult = E_FAIL; 108 | } 109 | else { 110 | DIBSECTION dib; 111 | int iResult = GetObject(hBitmap, sizeof(dib), &dib); 112 | if(iResult < sizeof(dib)) { 113 | m_lastError = L"GetObject failed"; 114 | hResult = E_FAIL; 115 | } 116 | else { 117 | // Store render target resources and info 118 | m_pRenderTarget = pRenderTarget; 119 | 120 | m_hDC = hDC; 121 | m_hBlackBrush = hBrush; 122 | 123 | m_bmBits = dib.dsBm.bmBits; 124 | m_bmWidthBytes = static_cast(dib.dsBm.bmWidthBytes); 125 | m_bmBytesPixel = static_cast(dib.dsBm.bmBitsPixel) / 8; 126 | 127 | hResult = S_OK; 128 | } 129 | } 130 | 131 | if(FAILED(hResult)) 132 | DeleteObject(hBrush); 133 | } 134 | } 135 | 136 | if(FAILED(hResult)) 137 | pRenderTarget->Release(); 138 | } 139 | 140 | pGDIInterop->Release(); 141 | } 142 | 143 | // Create rendering params for all accepted rendering modes 144 | if(SUCCEEDED(hResult)) { 145 | const UINT renderingModeCount = 2; 146 | DWRITE_RENDERING_MODE renderingModes[renderingModeCount] = { 147 | DWRITE_RENDERING_MODE_DEFAULT, 148 | DWRITE_RENDERING_MODE_ALIASED 149 | }; 150 | 151 | for(UINT i=0; i < renderingModeCount; ++i) { 152 | DWRITE_RENDERING_MODE renderingMode = renderingModes[i]; 153 | IDWriteRenderingParams *pRenderingParams; 154 | 155 | hResult = pDWriteFactory->CreateCustomRenderingParams( 156 | 1.0f, 157 | 0.0f, 158 | 0.0f, 159 | DWRITE_PIXEL_GEOMETRY_FLAT, 160 | renderingMode, 161 | &pRenderingParams 162 | ); 163 | if(SUCCEEDED(hResult)) 164 | m_renderingParams.insert(std::make_pair(renderingMode, pRenderingParams)); 165 | } 166 | 167 | if(m_renderingParams.empty()) { 168 | m_lastError = L"Failed to create rendering params"; 169 | hResult = E_FAIL; 170 | } 171 | else 172 | hResult = S_OK; 173 | } 174 | 175 | return hResult; 176 | } 177 | 178 | 179 | // Init glyph data 180 | void CFW1DWriteRenderTarget::initGlyphData( 181 | const DWRITE_FONT_METRICS *fontMetrics, 182 | const DWRITE_GLYPH_METRICS *glyphMetrics, 183 | FLOAT fontSize, 184 | DWGlyphData *outGlyphData 185 | ) { 186 | // Calculate pixel-space coordinates 187 | FLOAT fscale = fontSize / static_cast(fontMetrics->designUnitsPerEm); 188 | 189 | FLOAT l = static_cast(glyphMetrics->leftSideBearing) * fscale; 190 | FLOAT t = static_cast(glyphMetrics->topSideBearing) * fscale; 191 | 192 | FLOAT r = static_cast(glyphMetrics->rightSideBearing) * fscale; 193 | FLOAT b = static_cast(glyphMetrics->bottomSideBearing) * fscale; 194 | 195 | FLOAT v = static_cast(glyphMetrics->verticalOriginY) * fscale; 196 | 197 | FLOAT aw = static_cast(glyphMetrics->advanceWidth) * fscale; 198 | FLOAT ah = static_cast(glyphMetrics->advanceHeight) * fscale; 199 | 200 | // Set up glyph data 201 | outGlyphData->offsetX = floor(l); 202 | outGlyphData->offsetY = floor(t) - floor(v); 203 | outGlyphData->maxWidth = static_cast(aw - r - l + 2.0f); 204 | outGlyphData->maxHeight = static_cast(ah - b - t + 2.0f); 205 | } 206 | 207 | 208 | }// namespace FW1FontWrapper 209 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1DWriteRenderTarget.h: -------------------------------------------------------------------------------- 1 | // CFW1DWriteRenderTarget.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1DWriteRenderTarget 4 | #define IncludeGuard__FW1_CFW1DWriteRenderTarget 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Render target that provides pixels of one glyph-image at a time 13 | class CFW1DWriteRenderTarget : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1DWriteRenderTarget 19 | virtual HRESULT STDMETHODCALLTYPE DrawGlyphTemp( 20 | IDWriteFontFace *pFontFace, 21 | UINT16 GlyphIndex, 22 | FLOAT FontSize, 23 | DWRITE_RENDERING_MODE RenderingMode, 24 | DWRITE_MEASURING_MODE MeasuringMode, 25 | FW1_GLYPHIMAGEDATA *pOutData 26 | ); 27 | 28 | // Public functions 29 | public: 30 | CFW1DWriteRenderTarget(); 31 | 32 | HRESULT initRenderTarget( 33 | IFW1Factory *pFW1Factory, 34 | IDWriteFactory *pDWriteFactory, 35 | UINT renderTargetWidth, 36 | UINT renderTargetHeight 37 | ); 38 | 39 | // Internal types 40 | private: 41 | struct DWGlyphData { 42 | FLOAT offsetX; 43 | FLOAT offsetY; 44 | LONG maxWidth; 45 | LONG maxHeight; 46 | }; 47 | 48 | typedef std::map RenderingParamsMap; 49 | 50 | // Internal functions 51 | private: 52 | virtual ~CFW1DWriteRenderTarget(); 53 | 54 | HRESULT createRenderTarget(IDWriteFactory *pDWriteFactory); 55 | 56 | void initGlyphData( 57 | const DWRITE_FONT_METRICS *fontMetrics, 58 | const DWRITE_GLYPH_METRICS *glyphMetrics, 59 | FLOAT fontSize, 60 | DWGlyphData *outGlyphData 61 | ); 62 | 63 | // Internal data 64 | private: 65 | std::wstring m_lastError; 66 | 67 | IDWriteBitmapRenderTarget *m_pRenderTarget; 68 | HDC m_hDC; 69 | HBRUSH m_hBlackBrush; 70 | LPVOID m_bmBits; 71 | UINT m_bmWidthBytes; 72 | UINT m_bmBytesPixel; 73 | UINT m_renderTargetWidth; 74 | UINT m_renderTargetHeight; 75 | RenderingParamsMap m_renderingParams; 76 | }; 77 | 78 | 79 | }// namespace FW1FontWrapper 80 | 81 | 82 | #endif// IncludeGuard__FW1_CFW1DWriteRenderTarget 83 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1DWriteRenderTargetInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1DWriteRenderTargetInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1DWriteRenderTarget.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1DWriteRenderTarget::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1DWriteRenderTarget))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Draw glyph to temporary storage 27 | HRESULT STDMETHODCALLTYPE CFW1DWriteRenderTarget::DrawGlyphTemp( 28 | IDWriteFontFace *pFontFace, 29 | UINT16 GlyphIndex, 30 | FLOAT FontSize, 31 | DWRITE_RENDERING_MODE RenderingMode, 32 | DWRITE_MEASURING_MODE MeasuringMode, 33 | FW1_GLYPHIMAGEDATA *pOutData 34 | ) { 35 | // Font metrics 36 | DWRITE_FONT_METRICS fontMetrics; 37 | pFontFace->GetMetrics(&fontMetrics); 38 | 39 | // Glyph metrics 40 | DWRITE_GLYPH_METRICS glyphMetrics; 41 | HRESULT hResult = pFontFace->GetDesignGlyphMetrics(&GlyphIndex, 1, &glyphMetrics, FALSE); 42 | if(FAILED(hResult)) 43 | return hResult; 44 | 45 | // Calculate pixel measurements 46 | DWGlyphData dwGlyphData; 47 | initGlyphData(&fontMetrics, &glyphMetrics, FontSize, &dwGlyphData); 48 | 49 | // Set up drawing 50 | FLOAT glyphAdvance = 0.0f; 51 | DWRITE_GLYPH_OFFSET glyphOffset = {0.0f, 0.0f}; 52 | 53 | DWRITE_GLYPH_RUN glyphRun; 54 | ZeroMemory(&glyphRun, sizeof(glyphRun)); 55 | glyphRun.fontFace = pFontFace; 56 | glyphRun.fontEmSize = FontSize; 57 | glyphRun.glyphCount = 1; 58 | glyphRun.glyphIndices = &GlyphIndex; 59 | glyphRun.glyphAdvances = &glyphAdvance; 60 | glyphRun.glyphOffsets = &glyphOffset; 61 | 62 | // Clear background 63 | RECT rect; 64 | SetRect(&rect, 0, 0, 2+dwGlyphData.maxWidth+5, 2+dwGlyphData.maxHeight+5); 65 | int iRet = FillRect(m_hDC, &rect, m_hBlackBrush); 66 | if(iRet == 0) { 67 | } 68 | 69 | // Rendering mode 70 | IDWriteRenderingParams *pRenderingParams; 71 | 72 | RenderingParamsMap::iterator it = m_renderingParams.find(RenderingMode); 73 | if(it != m_renderingParams.end()) 74 | pRenderingParams = it->second; 75 | else 76 | pRenderingParams = m_renderingParams.begin()->second; 77 | 78 | // Draw 79 | hResult = m_pRenderTarget->DrawGlyphRun( 80 | 2.0f - dwGlyphData.offsetX, 81 | 2.0f - dwGlyphData.offsetY, 82 | MeasuringMode, 83 | &glyphRun, 84 | pRenderingParams, 85 | RGB(255, 255, 255), 86 | &rect 87 | ); 88 | if(FAILED(hResult)) 89 | return hResult; 90 | 91 | // Clip to valid render target to avoid buffer overruns in case the glyph was too large 92 | rect.left = std::max(rect.left, 0L); 93 | rect.top = std::max(rect.top, 0L); 94 | rect.right = std::min(static_cast(m_renderTargetWidth), rect.right); 95 | rect.bottom = std::min(static_cast(m_renderTargetHeight), rect.bottom); 96 | 97 | // Return glyph data 98 | pOutData->Metrics.OffsetX = dwGlyphData.offsetX + static_cast(rect.left) - 2.0f; 99 | pOutData->Metrics.OffsetY = dwGlyphData.offsetY + static_cast(rect.top) - 2.0f; 100 | pOutData->Metrics.Width = static_cast(rect.right - rect.left); 101 | pOutData->Metrics.Height = static_cast(rect.bottom - rect.top); 102 | pOutData->pGlyphPixels = 103 | static_cast(m_bmBits) 104 | + rect.top * m_bmWidthBytes 105 | + rect.left * m_bmBytesPixel; 106 | pOutData->RowPitch = m_bmWidthBytes; 107 | pOutData->PixelStride = m_bmBytesPixel; 108 | 109 | return S_OK; 110 | } 111 | 112 | 113 | }// namespace FW1FontWrapper 114 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1Factory.cpp: -------------------------------------------------------------------------------- 1 | // CFW1Factory.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1Factory.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Construct 12 | CFW1Factory::CFW1Factory() : 13 | m_cRefCount(1) 14 | { 15 | InitializeCriticalSection(&m_errorStringCriticalSection); 16 | } 17 | 18 | 19 | // Destruct 20 | CFW1Factory::~CFW1Factory() { 21 | DeleteCriticalSection(&m_errorStringCriticalSection); 22 | } 23 | 24 | 25 | // Init 26 | HRESULT CFW1Factory::initFactory() { 27 | return S_OK; 28 | } 29 | 30 | 31 | // Create a DWrite factory 32 | HRESULT CFW1Factory::createDWriteFactory(IDWriteFactory **ppDWriteFactory) { 33 | HRESULT hResult = E_FAIL; 34 | 35 | typedef HRESULT (WINAPI * PFN_DWRITECREATEFACTORY)(__in DWRITE_FACTORY_TYPE factoryType, __in REFIID iid, __out IUnknown **factory); 36 | PFN_DWRITECREATEFACTORY pfnDWriteCreateFactory = NULL; 37 | 38 | #ifdef FW1_DELAYLOAD_DWRITE_DLL 39 | HMODULE hDWriteLib = LoadLibrary(TEXT("DWrite.dll")); 40 | if(hDWriteLib == NULL) { 41 | DWORD dwErr = GetLastError(); 42 | dwErr; 43 | setErrorString(L"Failed to load DWrite.dll"); 44 | } 45 | else { 46 | pfnDWriteCreateFactory = 47 | reinterpret_cast(GetProcAddress(hDWriteLib, "DWriteCreateFactory")); 48 | if(pfnDWriteCreateFactory == NULL) { 49 | DWORD dwErr = GetLastError(); 50 | dwErr; 51 | setErrorString(L"Failed to load DWriteCreateFactory"); 52 | } 53 | } 54 | #else 55 | pfnDWriteCreateFactory = DWriteCreateFactory; 56 | #endif 57 | 58 | if(pfnDWriteCreateFactory != NULL) { 59 | IDWriteFactory *pDWriteFactory; 60 | 61 | hResult = pfnDWriteCreateFactory( 62 | DWRITE_FACTORY_TYPE_SHARED, 63 | __uuidof(IDWriteFactory), 64 | reinterpret_cast(&pDWriteFactory) 65 | ); 66 | if(FAILED(hResult)) { 67 | setErrorString(L"DWriteCreateFactory failed"); 68 | } 69 | else { 70 | *ppDWriteFactory = pDWriteFactory; 71 | 72 | hResult = S_OK; 73 | } 74 | } 75 | 76 | return hResult; 77 | } 78 | 79 | 80 | // Set error string 81 | void CFW1Factory::setErrorString(const wchar_t *str) { 82 | EnterCriticalSection(&m_errorStringCriticalSection); 83 | m_lastError = str; 84 | LeaveCriticalSection(&m_errorStringCriticalSection); 85 | } 86 | 87 | 88 | }// namespace FW1FontWrapper 89 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1Factory.h: -------------------------------------------------------------------------------- 1 | // CFW1Factory.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1Factory 4 | #define IncludeGuard__FW1_CFW1Factory 5 | 6 | 7 | namespace FW1FontWrapper { 8 | 9 | 10 | // Factory that creates FW1 objects 11 | class CFW1Factory : public IFW1Factory { 12 | public: 13 | // IUnknown 14 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 15 | virtual ULONG STDMETHODCALLTYPE AddRef(); 16 | virtual ULONG STDMETHODCALLTYPE Release(); 17 | 18 | // IFW1Factory 19 | virtual HRESULT STDMETHODCALLTYPE CreateFontWrapper( 20 | ID3D11Device *pDevice, 21 | LPCWSTR pszFontFamily, 22 | IFW1FontWrapper **ppFontWrapper 23 | ); 24 | virtual HRESULT STDMETHODCALLTYPE CreateFontWrapper( 25 | ID3D11Device *pDevice, 26 | IDWriteFactory *pDWriteFactory, 27 | const FW1_FONTWRAPPERCREATEPARAMS *pCreateParams, 28 | IFW1FontWrapper **ppFontWrapper 29 | ); 30 | virtual HRESULT STDMETHODCALLTYPE CreateFontWrapper( 31 | ID3D11Device *pDevice, 32 | IFW1GlyphAtlas *pGlyphAtlas, 33 | IFW1GlyphProvider *pGlyphProvider, 34 | IFW1GlyphVertexDrawer *pGlyphVertexDrawer, 35 | IFW1GlyphRenderStates *pGlyphRenderStates, 36 | IDWriteFactory *pDWriteFactory, 37 | const FW1_DWRITEFONTPARAMS *pDefaultFontParams, 38 | IFW1FontWrapper **ppFontWrapper 39 | ); 40 | virtual HRESULT STDMETHODCALLTYPE CreateGlyphVertexDrawer( 41 | ID3D11Device *pDevice, 42 | UINT VertexBufferSize, 43 | IFW1GlyphVertexDrawer **ppGlyphVertexDrawer 44 | ); 45 | virtual HRESULT STDMETHODCALLTYPE CreateGlyphRenderStates( 46 | ID3D11Device *pDevice, 47 | BOOL DisableGeometryShader, 48 | BOOL AnisotropicFiltering, 49 | IFW1GlyphRenderStates **ppGlyphRenderStates 50 | ); 51 | virtual HRESULT STDMETHODCALLTYPE CreateTextRenderer( 52 | IFW1GlyphProvider *pGlyphProvider, 53 | IFW1TextRenderer **ppTextRenderer 54 | ); 55 | virtual HRESULT STDMETHODCALLTYPE CreateTextGeometry( 56 | IFW1TextGeometry **ppTextGeometry 57 | ); 58 | virtual HRESULT STDMETHODCALLTYPE CreateGlyphProvider( 59 | IFW1GlyphAtlas *pGlyphAtlas, 60 | IDWriteFactory *pDWriteFactory, 61 | IDWriteFontCollection *pFontCollection, 62 | UINT MaxGlyphWidth, 63 | UINT MaxGlyphHeight, 64 | IFW1GlyphProvider **ppGlyphProvider 65 | ); 66 | virtual HRESULT STDMETHODCALLTYPE CreateDWriteRenderTarget( 67 | IDWriteFactory *pDWriteFactory, 68 | UINT RenderTargetWidth, 69 | UINT RenderTargetHeight, 70 | IFW1DWriteRenderTarget **ppRenderTarget 71 | ); 72 | virtual HRESULT STDMETHODCALLTYPE CreateGlyphAtlas( 73 | ID3D11Device *pDevice, 74 | UINT GlyphSheetWidth, 75 | UINT GlyphSheetHeight, 76 | BOOL HardwareCoordBuffer, 77 | BOOL AllowOversizedGlyph, 78 | UINT MaxGlyphCountPerSheet, 79 | UINT MipLevels, 80 | UINT MaxGlyphSheetCount, 81 | IFW1GlyphAtlas **ppGlyphAtlas 82 | ); 83 | virtual HRESULT STDMETHODCALLTYPE CreateGlyphSheet( 84 | ID3D11Device *pDevice, 85 | UINT GlyphSheetWidth, 86 | UINT GlyphSheetHeight, 87 | BOOL HardwareCoordBuffer, 88 | BOOL AllowOversizedGlyph, 89 | UINT MaxGlyphCount, 90 | UINT MipLevels, 91 | IFW1GlyphSheet **ppGlyphSheet 92 | ); 93 | virtual HRESULT STDMETHODCALLTYPE CreateColor( 94 | UINT32 Color, 95 | IFW1ColorRGBA **ppColor 96 | ); 97 | 98 | // Public functions 99 | public: 100 | CFW1Factory(); 101 | 102 | HRESULT initFactory(); 103 | 104 | // Internal functions 105 | private: 106 | virtual ~CFW1Factory(); 107 | 108 | HRESULT createDWriteFactory(IDWriteFactory **ppDWriteFactory); 109 | 110 | void setErrorString(const wchar_t *str); 111 | 112 | // Internal data 113 | private: 114 | ULONG m_cRefCount; 115 | 116 | std::wstring m_lastError; 117 | CRITICAL_SECTION m_errorStringCriticalSection; 118 | 119 | private: 120 | CFW1Factory(const CFW1Factory&); 121 | CFW1Factory& operator=(const CFW1Factory&); 122 | }; 123 | 124 | 125 | }// namespace FW1FontWrapper 126 | 127 | 128 | #endif// IncludeGuard__FW1_CFW1Factory 129 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1FontWrapper.cpp: -------------------------------------------------------------------------------- 1 | // CFW1FontWrapper.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1FontWrapper.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1FontWrapper::CFW1FontWrapper() : 15 | m_pDevice(NULL), 16 | m_featureLevel(D3D_FEATURE_LEVEL_9_1), 17 | m_pDWriteFactory(NULL), 18 | 19 | m_pGlyphAtlas(NULL), 20 | m_pGlyphProvider(NULL), 21 | 22 | m_pGlyphRenderStates(NULL), 23 | m_pGlyphVertexDrawer(NULL), 24 | 25 | m_defaultTextInited(false), 26 | m_pDefaultTextFormat(NULL) 27 | { 28 | InitializeCriticalSection(&m_textRenderersCriticalSection); 29 | InitializeCriticalSection(&m_textGeometriesCriticalSection); 30 | } 31 | 32 | 33 | // Destruct 34 | CFW1FontWrapper::~CFW1FontWrapper() { 35 | SAFE_RELEASE(m_pFW1Factory); 36 | 37 | SAFE_RELEASE(m_pDevice); 38 | SAFE_RELEASE(m_pDWriteFactory); 39 | 40 | SAFE_RELEASE(m_pGlyphAtlas); 41 | SAFE_RELEASE(m_pGlyphProvider); 42 | 43 | SAFE_RELEASE(m_pGlyphRenderStates); 44 | SAFE_RELEASE(m_pGlyphVertexDrawer); 45 | 46 | while(!m_textRenderers.empty()) { 47 | m_textRenderers.top()->Release(); 48 | m_textRenderers.pop(); 49 | } 50 | 51 | while(!m_textGeometries.empty()) { 52 | m_textGeometries.top()->Release(); 53 | m_textGeometries.pop(); 54 | } 55 | 56 | SAFE_RELEASE(m_pDefaultTextFormat); 57 | 58 | DeleteCriticalSection(&m_textRenderersCriticalSection); 59 | DeleteCriticalSection(&m_textGeometriesCriticalSection); 60 | } 61 | 62 | 63 | // Init 64 | HRESULT CFW1FontWrapper::initFontWrapper( 65 | IFW1Factory *pFW1Factory, 66 | ID3D11Device *pDevice, 67 | IFW1GlyphAtlas *pGlyphAtlas, 68 | IFW1GlyphProvider *pGlyphProvider, 69 | IFW1GlyphVertexDrawer *pGlyphVertexDrawer, 70 | IFW1GlyphRenderStates *pGlyphRenderStates, 71 | IDWriteFactory *pDWriteFactory, 72 | const FW1_DWRITEFONTPARAMS *pDefaultFontParams 73 | ) { 74 | HRESULT hResult = initBaseObject(pFW1Factory); 75 | if(FAILED(hResult)) 76 | return hResult; 77 | 78 | if( 79 | pDevice == NULL || 80 | pGlyphAtlas == NULL || 81 | pGlyphProvider == NULL || 82 | pGlyphVertexDrawer == NULL || 83 | pGlyphRenderStates == NULL || 84 | pDWriteFactory == NULL 85 | ) 86 | return E_INVALIDARG; 87 | 88 | pDevice->AddRef(); 89 | m_pDevice = pDevice; 90 | m_featureLevel = m_pDevice->GetFeatureLevel(); 91 | 92 | pDWriteFactory->AddRef(); 93 | m_pDWriteFactory = pDWriteFactory; 94 | 95 | pGlyphAtlas->AddRef(); 96 | m_pGlyphAtlas = pGlyphAtlas; 97 | pGlyphProvider->AddRef(); 98 | m_pGlyphProvider = pGlyphProvider; 99 | 100 | pGlyphRenderStates->AddRef(); 101 | m_pGlyphRenderStates = pGlyphRenderStates; 102 | pGlyphVertexDrawer->AddRef(); 103 | m_pGlyphVertexDrawer = pGlyphVertexDrawer; 104 | 105 | // Create default text format for strings, if provided 106 | if(pDefaultFontParams->pszFontFamily != NULL && pDefaultFontParams->pszFontFamily[0] != 0) { 107 | IDWriteTextFormat *pTextFormat; 108 | hResult = m_pDWriteFactory->CreateTextFormat( 109 | pDefaultFontParams->pszFontFamily, 110 | NULL, 111 | pDefaultFontParams->FontWeight, 112 | pDefaultFontParams->FontStyle, 113 | pDefaultFontParams->FontStretch, 114 | 32.0f, 115 | (pDefaultFontParams->pszLocale != NULL) ? pDefaultFontParams->pszLocale : L"", 116 | &pTextFormat 117 | ); 118 | if(FAILED(hResult)) { 119 | m_lastError = L"Failed to create DWrite text format"; 120 | } 121 | else { 122 | m_pDefaultTextFormat = pTextFormat; 123 | m_defaultTextInited = true; 124 | 125 | hResult = S_OK; 126 | } 127 | } 128 | 129 | return hResult; 130 | } 131 | 132 | 133 | // Create text layout from string 134 | IDWriteTextLayout* CFW1FontWrapper::createTextLayout( 135 | const WCHAR *pszString, 136 | const WCHAR *pszFontFamily, 137 | FLOAT fontSize, 138 | const FW1_RECTF *pLayoutRect, 139 | UINT flags 140 | ) { 141 | if(m_defaultTextInited) { 142 | UINT32 stringLength = 0; 143 | while(pszString[stringLength] != 0) 144 | ++stringLength; 145 | 146 | // Create DWrite text layout for the string 147 | IDWriteTextLayout *pTextLayout; 148 | HRESULT hResult = m_pDWriteFactory->CreateTextLayout( 149 | pszString, 150 | stringLength, 151 | m_pDefaultTextFormat, 152 | pLayoutRect->Right - pLayoutRect->Left, 153 | pLayoutRect->Bottom - pLayoutRect->Top, 154 | &pTextLayout 155 | ); 156 | if(SUCCEEDED(hResult)) { 157 | // Layout settings 158 | DWRITE_TEXT_RANGE allText = {0, stringLength}; 159 | pTextLayout->SetFontSize(fontSize, allText); 160 | 161 | if(pszFontFamily != NULL) 162 | pTextLayout->SetFontFamilyName(pszFontFamily, allText); 163 | 164 | if((flags & FW1_NOWORDWRAP) != 0) 165 | pTextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); 166 | 167 | if(flags & FW1_RIGHT) 168 | pTextLayout->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING); 169 | else if(flags & FW1_CENTER) 170 | pTextLayout->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); 171 | if(flags & FW1_BOTTOM) 172 | pTextLayout->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_FAR); 173 | else if(flags & FW1_VCENTER) 174 | pTextLayout->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); 175 | 176 | return pTextLayout; 177 | } 178 | } 179 | 180 | return NULL; 181 | } 182 | 183 | 184 | }// namespace FW1FontWrapper 185 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1FontWrapper.h: -------------------------------------------------------------------------------- 1 | // CFW1FontWrapper.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1FontWrapper 4 | #define IncludeGuard__FW1_CFW1FontWrapper 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Font-wrapper simplifying drawing strings and text-layouts 13 | class CFW1FontWrapper : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1FontWrapper 19 | virtual HRESULT STDMETHODCALLTYPE GetFactory(IFW1Factory **ppFactory); 20 | 21 | virtual HRESULT STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice); 22 | virtual HRESULT STDMETHODCALLTYPE GetDWriteFactory(IDWriteFactory **ppDWriteFactory); 23 | virtual HRESULT STDMETHODCALLTYPE GetGlyphAtlas(IFW1GlyphAtlas **ppGlyphAtlas); 24 | virtual HRESULT STDMETHODCALLTYPE GetGlyphProvider(IFW1GlyphProvider **ppGlyphProvider); 25 | virtual HRESULT STDMETHODCALLTYPE GetRenderStates(IFW1GlyphRenderStates **ppRenderStates); 26 | virtual HRESULT STDMETHODCALLTYPE GetVertexDrawer(IFW1GlyphVertexDrawer **ppVertexDrawer); 27 | 28 | virtual void STDMETHODCALLTYPE DrawTextLayout( 29 | ID3D11DeviceContext *pContext, 30 | IDWriteTextLayout *pTextLayout, 31 | FLOAT OriginX, 32 | FLOAT OriginY, 33 | UINT32 Color, 34 | UINT Flags 35 | ); 36 | virtual void STDMETHODCALLTYPE DrawTextLayout( 37 | ID3D11DeviceContext *pContext, 38 | IDWriteTextLayout *pTextLayout, 39 | FLOAT OriginX, 40 | FLOAT OriginY, 41 | UINT32 Color, 42 | const FW1_RECTF *pClipRect, 43 | const FLOAT *pTransformMatrix, 44 | UINT Flags 45 | ); 46 | 47 | virtual void STDMETHODCALLTYPE DrawString( 48 | ID3D11DeviceContext *pContext, 49 | const WCHAR *pszString, 50 | FLOAT FontSize, 51 | FLOAT X, 52 | FLOAT Y, 53 | UINT32 Color, 54 | UINT Flags 55 | ); 56 | virtual void STDMETHODCALLTYPE DrawString( 57 | ID3D11DeviceContext *pContext, 58 | const WCHAR *pszString, 59 | const WCHAR *pszFontFamily, 60 | FLOAT FontSize, 61 | FLOAT X, 62 | FLOAT Y, 63 | UINT32 Color, 64 | UINT Flags 65 | ); 66 | virtual void STDMETHODCALLTYPE DrawString( 67 | ID3D11DeviceContext *pContext, 68 | const WCHAR *pszString, 69 | const WCHAR *pszFontFamily, 70 | FLOAT FontSize, 71 | const FW1_RECTF *pLayoutRect, 72 | UINT32 Color, 73 | const FW1_RECTF *pClipRect, 74 | const FLOAT *pTransformMatrix, 75 | UINT Flags 76 | ); 77 | 78 | virtual FW1_RECTF STDMETHODCALLTYPE MeasureString( 79 | const WCHAR *pszString, 80 | const WCHAR *pszFontFamily, 81 | FLOAT FontSize, 82 | const FW1_RECTF *pLayoutRect, 83 | UINT Flags 84 | ); 85 | 86 | virtual void STDMETHODCALLTYPE AnalyzeString( 87 | ID3D11DeviceContext *pContext, 88 | const WCHAR *pszString, 89 | const WCHAR *pszFontFamily, 90 | FLOAT FontSize, 91 | const FW1_RECTF *pLayoutRect, 92 | UINT32 Color, 93 | UINT Flags, 94 | IFW1TextGeometry *pTextGeometry 95 | ); 96 | 97 | virtual void STDMETHODCALLTYPE AnalyzeTextLayout( 98 | ID3D11DeviceContext *pContext, 99 | IDWriteTextLayout *pTextLayout, 100 | FLOAT OriginX, 101 | FLOAT OriginY, 102 | UINT32 Color, 103 | UINT Flags, 104 | IFW1TextGeometry *pTextGeometry 105 | ); 106 | 107 | virtual void STDMETHODCALLTYPE DrawGeometry( 108 | ID3D11DeviceContext *pContext, 109 | IFW1TextGeometry *pGeometry, 110 | const FW1_RECTF *pClipRect, 111 | const FLOAT *pTransformMatrix, 112 | UINT Flags 113 | ); 114 | 115 | virtual void STDMETHODCALLTYPE Flush(ID3D11DeviceContext *pContext); 116 | 117 | // Public functions 118 | public: 119 | CFW1FontWrapper(); 120 | 121 | HRESULT initFontWrapper( 122 | IFW1Factory *pFW1Factory, 123 | ID3D11Device *pDevice, 124 | IFW1GlyphAtlas *pGlyphAtlas, 125 | IFW1GlyphProvider *pGlyphProvider, 126 | IFW1GlyphVertexDrawer *pGlyphVertexDrawer, 127 | IFW1GlyphRenderStates *pGlyphRenderStates, 128 | IDWriteFactory *pDWriteFactory, 129 | const FW1_DWRITEFONTPARAMS *pDefaultFontParams 130 | ); 131 | 132 | // Internal functions 133 | private: 134 | virtual ~CFW1FontWrapper(); 135 | 136 | IDWriteTextLayout* createTextLayout( 137 | const WCHAR *pszString, 138 | const WCHAR *pszFontFamily, 139 | FLOAT fontSize, 140 | const FW1_RECTF *pLayoutRect, 141 | UINT flags 142 | ); 143 | 144 | // Internal data 145 | private: 146 | std::wstring m_lastError; 147 | 148 | ID3D11Device *m_pDevice; 149 | D3D_FEATURE_LEVEL m_featureLevel; 150 | IDWriteFactory *m_pDWriteFactory; 151 | 152 | IFW1GlyphAtlas *m_pGlyphAtlas; 153 | IFW1GlyphProvider *m_pGlyphProvider; 154 | 155 | IFW1GlyphRenderStates *m_pGlyphRenderStates; 156 | IFW1GlyphVertexDrawer *m_pGlyphVertexDrawer; 157 | 158 | CRITICAL_SECTION m_textRenderersCriticalSection; 159 | std::stack m_textRenderers; 160 | CRITICAL_SECTION m_textGeometriesCriticalSection; 161 | std::stack m_textGeometries; 162 | 163 | bool m_defaultTextInited; 164 | IDWriteTextFormat *m_pDefaultTextFormat; 165 | }; 166 | 167 | 168 | }// namespace FW1FontWrapper 169 | 170 | 171 | #endif// IncludeGuard__FW1_CFW1FontWrapper 172 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphAtlas.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphAtlas.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphAtlas.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1GlyphAtlas::CFW1GlyphAtlas() : 15 | m_pDevice(NULL), 16 | m_sheetWidth(0), 17 | m_sheetHeight(0), 18 | m_hardwareCoordBuffer(false), 19 | m_allowOversizedGlyph(false), 20 | m_maxGlyphCount(0), 21 | m_mipLevelCount(0), 22 | 23 | m_glyphSheets(0), 24 | m_sheetCount(0), 25 | m_maxSheetCount(0), 26 | m_currentSheetIndex(0), 27 | m_flushedSheetIndex(0) 28 | { 29 | InitializeCriticalSection(&m_glyphSheetsCriticalSection); 30 | } 31 | 32 | 33 | // Destruct 34 | CFW1GlyphAtlas::~CFW1GlyphAtlas() { 35 | SAFE_RELEASE(m_pDevice); 36 | 37 | for(UINT i=0; i < m_sheetCount; ++i) 38 | m_glyphSheets[i]->Release(); 39 | delete[] m_glyphSheets; 40 | 41 | DeleteCriticalSection(&m_glyphSheetsCriticalSection); 42 | } 43 | 44 | 45 | // Init 46 | HRESULT CFW1GlyphAtlas::initGlyphAtlas( 47 | IFW1Factory *pFW1Factory, 48 | ID3D11Device *pDevice, 49 | UINT sheetWidth, 50 | UINT sheetHeight, 51 | bool coordBuffer, 52 | bool allowOversizedGlyph, 53 | UINT maxGlyphCount, 54 | UINT mipLevelCount, 55 | UINT maxSheetCount 56 | ) { 57 | HRESULT hResult = initBaseObject(pFW1Factory); 58 | if(FAILED(hResult)) 59 | return hResult; 60 | 61 | if(pDevice == NULL) 62 | return E_INVALIDARG; 63 | 64 | pDevice->AddRef(); 65 | m_pDevice = pDevice; 66 | 67 | m_sheetWidth = sheetWidth; 68 | m_sheetHeight = sheetHeight; 69 | m_hardwareCoordBuffer = coordBuffer; 70 | m_allowOversizedGlyph = allowOversizedGlyph; 71 | m_mipLevelCount = mipLevelCount; 72 | m_maxGlyphCount = maxGlyphCount; 73 | 74 | m_maxSheetCount = 4096; 75 | if(maxSheetCount > 0 && maxSheetCount < 655536) 76 | m_maxSheetCount = maxSheetCount; 77 | m_glyphSheets = new IFW1GlyphSheet* [m_maxSheetCount]; 78 | 79 | // Default glyph 80 | BYTE glyph0Pixels[256]; 81 | FillMemory(glyph0Pixels, 256, 0xff); 82 | 83 | FW1_GLYPHMETRICS glyph0Metrics; 84 | glyph0Metrics.OffsetX = 0.0f; 85 | glyph0Metrics.OffsetY = 0.0f; 86 | glyph0Metrics.Width = 16; 87 | glyph0Metrics.Height = 16; 88 | 89 | UINT glyph0 = InsertGlyph(&glyph0Metrics, glyph0Pixels, 16, 1); 90 | if(glyph0 == 0xffffffff) 91 | return E_FAIL; 92 | else 93 | return S_OK; 94 | } 95 | 96 | 97 | // Create new glyph sheet 98 | HRESULT CFW1GlyphAtlas::createGlyphSheet(IFW1GlyphSheet **ppGlyphSheet) { 99 | IFW1GlyphSheet *pGlyphSheet; 100 | HRESULT hResult = m_pFW1Factory->CreateGlyphSheet( 101 | m_pDevice, 102 | m_sheetWidth, 103 | m_sheetHeight, 104 | m_hardwareCoordBuffer, 105 | m_allowOversizedGlyph, 106 | m_maxGlyphCount, 107 | m_mipLevelCount, 108 | &pGlyphSheet 109 | ); 110 | if(FAILED(hResult)) { 111 | } 112 | else { 113 | *ppGlyphSheet = pGlyphSheet; 114 | 115 | hResult = S_OK; 116 | } 117 | 118 | return hResult; 119 | } 120 | 121 | 122 | }// namespace FW1FontWrapper 123 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphAtlas.h: -------------------------------------------------------------------------------- 1 | // CFW1GlyphAtlas.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1GlyphAtlas 4 | #define IncludeGuard__FW1_CFW1GlyphAtlas 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | class CFW1GlyphAtlas : public CFW1Object { 13 | // Interface 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1GlyphAtlas 19 | virtual HRESULT STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice); 20 | 21 | virtual UINT STDMETHODCALLTYPE GetTotalGlyphCount(); 22 | virtual UINT STDMETHODCALLTYPE GetSheetCount(); 23 | 24 | virtual HRESULT STDMETHODCALLTYPE GetSheet(UINT SheetIndex, IFW1GlyphSheet **ppGlyphSheet); 25 | 26 | virtual const FW1_GLYPHCOORDS* STDMETHODCALLTYPE GetGlyphCoords(UINT SheetIndex); 27 | virtual HRESULT STDMETHODCALLTYPE BindSheet(ID3D11DeviceContext *pContext, UINT SheetIndex, UINT Flags); 28 | 29 | virtual UINT STDMETHODCALLTYPE InsertGlyph( 30 | const FW1_GLYPHMETRICS *pGlyphMetrics, 31 | const void *pGlyphData, 32 | UINT RowPitch, 33 | UINT PixelStride 34 | ); 35 | virtual UINT STDMETHODCALLTYPE InsertSheet(IFW1GlyphSheet *pGlyphSheet); 36 | virtual void STDMETHODCALLTYPE Flush(ID3D11DeviceContext *pContext); 37 | 38 | // Public functions 39 | public: 40 | CFW1GlyphAtlas(); 41 | 42 | HRESULT initGlyphAtlas( 43 | IFW1Factory *pFW1Factory, 44 | ID3D11Device *pDevice, 45 | UINT sheetWidth, 46 | UINT sheetHeight, 47 | bool coordBuffer, 48 | bool allowOversizedTexture, 49 | UINT maxGlyphCountPerSheet, 50 | UINT mipLevelCount, 51 | UINT maxSheetCount 52 | ); 53 | 54 | // Internal functions 55 | private: 56 | virtual ~CFW1GlyphAtlas(); 57 | 58 | HRESULT createGlyphSheet(IFW1GlyphSheet **ppGlyphSheet); 59 | 60 | // Internal data 61 | private: 62 | ID3D11Device *m_pDevice; 63 | UINT m_sheetWidth; 64 | UINT m_sheetHeight; 65 | bool m_hardwareCoordBuffer; 66 | bool m_allowOversizedGlyph; 67 | UINT m_maxGlyphCount; 68 | UINT m_mipLevelCount; 69 | 70 | IFW1GlyphSheet **m_glyphSheets; 71 | UINT m_sheetCount; 72 | UINT m_maxSheetCount; 73 | UINT m_currentSheetIndex; 74 | UINT m_flushedSheetIndex; 75 | 76 | CRITICAL_SECTION m_glyphSheetsCriticalSection; 77 | }; 78 | 79 | 80 | }// namespace FW1FontWrapper 81 | 82 | 83 | #endif// IncludeGuard__FW1_CFW1GlyphAtlas 84 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphAtlasInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphAtlasInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphAtlas.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1GlyphAtlas::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1GlyphAtlas))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Get the D3D11 device used by this atlas 27 | HRESULT STDMETHODCALLTYPE CFW1GlyphAtlas::GetDevice(ID3D11Device **ppDevice) { 28 | if(ppDevice == NULL) 29 | return E_INVALIDARG; 30 | 31 | m_pDevice->AddRef(); 32 | *ppDevice = m_pDevice; 33 | 34 | return S_OK; 35 | } 36 | 37 | 38 | // Get total glyph count in atlas 39 | UINT STDMETHODCALLTYPE CFW1GlyphAtlas::GetTotalGlyphCount() { 40 | UINT total = 0; 41 | 42 | for(UINT i=0; i < m_sheetCount; ++i) { 43 | FW1_GLYPHSHEETDESC desc; 44 | m_glyphSheets[i]->GetDesc(&desc); 45 | 46 | total += desc.GlyphCount; 47 | } 48 | 49 | return total; 50 | } 51 | 52 | 53 | // Get sheet count 54 | UINT STDMETHODCALLTYPE CFW1GlyphAtlas::GetSheetCount() { 55 | return m_sheetCount; 56 | } 57 | 58 | 59 | // Get sheet 60 | HRESULT STDMETHODCALLTYPE CFW1GlyphAtlas::GetSheet(UINT SheetIndex, IFW1GlyphSheet **ppGlyphSheet) { 61 | if(ppGlyphSheet == NULL) 62 | return E_INVALIDARG; 63 | 64 | if(SheetIndex < m_sheetCount) { 65 | *ppGlyphSheet = m_glyphSheets[SheetIndex]; 66 | 67 | return S_OK; 68 | } 69 | 70 | *ppGlyphSheet = NULL; 71 | 72 | return E_INVALIDARG; 73 | } 74 | 75 | // Get texture coordinates 76 | const FW1_GLYPHCOORDS* STDMETHODCALLTYPE CFW1GlyphAtlas::GetGlyphCoords(UINT SheetIndex) { 77 | if(SheetIndex < m_sheetCount) 78 | return m_glyphSheets[SheetIndex]->GetGlyphCoords(); 79 | 80 | return 0; 81 | } 82 | 83 | 84 | // Set sheet shader resources 85 | HRESULT STDMETHODCALLTYPE CFW1GlyphAtlas::BindSheet(ID3D11DeviceContext *pContext, UINT SheetIndex, UINT Flags) { 86 | if(SheetIndex < m_sheetCount) 87 | return m_glyphSheets[SheetIndex]->BindSheet(pContext, Flags); 88 | 89 | return E_INVALIDARG; 90 | } 91 | 92 | 93 | // Insert texture into atlas 94 | UINT STDMETHODCALLTYPE CFW1GlyphAtlas::InsertGlyph( 95 | const FW1_GLYPHMETRICS *pGlyphMetrics, 96 | const void *pGlyphData, 97 | UINT RowPitch, 98 | UINT PixelStride 99 | ) { 100 | UINT glyphIndex = 0xffffffff; 101 | UINT sheetIndex = 0; 102 | 103 | // Get open sheet range 104 | EnterCriticalSection(&m_glyphSheetsCriticalSection); 105 | UINT start = m_currentSheetIndex; 106 | UINT end = m_sheetCount; 107 | LeaveCriticalSection(&m_glyphSheetsCriticalSection); 108 | 109 | // Attempt to insert glyph 110 | for(UINT i=start; i < end; ++i) { 111 | IFW1GlyphSheet *pGlyphSheet = m_glyphSheets[i]; 112 | 113 | glyphIndex = pGlyphSheet->InsertGlyph(pGlyphMetrics, pGlyphData, RowPitch, PixelStride); 114 | if(glyphIndex != 0xffffffff) { 115 | sheetIndex = i; 116 | break; 117 | } 118 | } 119 | 120 | // Try to create a new glyph sheet on failure 121 | if(glyphIndex == 0xffffffff && m_sheetCount < m_maxSheetCount) { 122 | IFW1GlyphSheet *pGlyphSheet; 123 | if(SUCCEEDED(createGlyphSheet(&pGlyphSheet))) { 124 | glyphIndex = pGlyphSheet->InsertGlyph(pGlyphMetrics, pGlyphData, RowPitch, PixelStride); 125 | 126 | UINT newSheetIndex = InsertSheet(pGlyphSheet); 127 | if(newSheetIndex != 0xffffffff) 128 | sheetIndex = newSheetIndex; 129 | else 130 | glyphIndex = 0xffffffff; 131 | 132 | pGlyphSheet->Release(); 133 | } 134 | } 135 | 136 | if(glyphIndex == 0xffffffff) 137 | return 0xffffffff; 138 | 139 | return (sheetIndex << 16) | glyphIndex; 140 | } 141 | 142 | 143 | // Insert glyph sheets 144 | UINT STDMETHODCALLTYPE CFW1GlyphAtlas::InsertSheet(IFW1GlyphSheet *pGlyphSheet) { 145 | if(pGlyphSheet == NULL) 146 | return 0xffffffff; 147 | 148 | UINT sheetIndex = 0xffffffff; 149 | 150 | EnterCriticalSection(&m_glyphSheetsCriticalSection); 151 | if(m_sheetCount < m_maxSheetCount) { 152 | pGlyphSheet->AddRef(); 153 | 154 | sheetIndex = m_sheetCount; 155 | 156 | m_glyphSheets[sheetIndex] = pGlyphSheet; 157 | 158 | _WriteBarrier(); 159 | MemoryBarrier(); 160 | 161 | ++m_sheetCount; 162 | 163 | // Restrict the number of open sheets 164 | UINT numActiveSheets = 4; 165 | 166 | if(m_sheetCount > m_currentSheetIndex + numActiveSheets) { 167 | m_glyphSheets[m_currentSheetIndex]->CloseSheet(); 168 | 169 | ++m_currentSheetIndex; 170 | } 171 | } 172 | LeaveCriticalSection(&m_glyphSheetsCriticalSection); 173 | 174 | return sheetIndex; 175 | } 176 | 177 | 178 | // Flush all sheets with possible new glyphs 179 | void STDMETHODCALLTYPE CFW1GlyphAtlas::Flush(ID3D11DeviceContext *pContext) { 180 | UINT first = 0; 181 | UINT end = 0; 182 | 183 | EnterCriticalSection(&m_glyphSheetsCriticalSection); 184 | 185 | first = m_flushedSheetIndex; 186 | end = m_sheetCount; 187 | 188 | m_flushedSheetIndex = m_currentSheetIndex; 189 | 190 | LeaveCriticalSection(&m_glyphSheetsCriticalSection); 191 | 192 | for(UINT i=first; i < end; ++i) 193 | m_glyphSheets[i]->Flush(pContext); 194 | } 195 | 196 | 197 | }// namespace FW1FontWrapper 198 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphProvider.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphProvider.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphProvider.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1GlyphProvider::CFW1GlyphProvider() : 15 | m_pGlyphAtlas(NULL), 16 | 17 | m_pDWriteFactory(NULL), 18 | m_maxGlyphWidth(0), 19 | m_maxGlyphHeight(0), 20 | 21 | m_pFontCollection(NULL) 22 | { 23 | InitializeCriticalSection(&m_renderTargetsCriticalSection); 24 | InitializeCriticalSection(&m_glyphMapsCriticalSection); 25 | InitializeCriticalSection(&m_fontsCriticalSection); 26 | InitializeCriticalSection(&m_insertGlyphCriticalSection); 27 | } 28 | 29 | 30 | // Destruct 31 | CFW1GlyphProvider::~CFW1GlyphProvider() { 32 | SAFE_RELEASE(m_pGlyphAtlas); 33 | 34 | SAFE_RELEASE(m_pDWriteFactory); 35 | 36 | while(!m_glyphRenderTargets.empty()) { 37 | m_glyphRenderTargets.top()->Release(); 38 | m_glyphRenderTargets.pop(); 39 | } 40 | 41 | SAFE_RELEASE(m_pFontCollection); 42 | for(size_t i=0; i < m_fonts.size(); ++i) 43 | SAFE_RELEASE(m_fonts[i].pFontFace); 44 | 45 | for(FontMap::iterator it = m_fontMap.begin(); it != m_fontMap.end(); ++it) { 46 | GlyphMap *glyphMap = (*it).second; 47 | 48 | delete[] glyphMap->glyphs; 49 | delete glyphMap; 50 | } 51 | 52 | DeleteCriticalSection(&m_renderTargetsCriticalSection); 53 | DeleteCriticalSection(&m_glyphMapsCriticalSection); 54 | DeleteCriticalSection(&m_fontsCriticalSection); 55 | DeleteCriticalSection(&m_insertGlyphCriticalSection); 56 | } 57 | 58 | 59 | // Init glyph provider 60 | HRESULT CFW1GlyphProvider::initGlyphProvider( 61 | IFW1Factory *pFW1Factory, 62 | IFW1GlyphAtlas *pGlyphAtlas, 63 | IDWriteFactory *pDWriteFactory, 64 | IDWriteFontCollection *pFontCollection, 65 | UINT maxGlyphWidth, 66 | UINT maxGlyphHeight 67 | ) { 68 | HRESULT hResult = initBaseObject(pFW1Factory); 69 | if(FAILED(hResult)) 70 | return hResult; 71 | 72 | if(pGlyphAtlas == NULL || pDWriteFactory == NULL || pFontCollection == NULL) 73 | return E_INVALIDARG; 74 | 75 | pGlyphAtlas->AddRef(); 76 | m_pGlyphAtlas = pGlyphAtlas; 77 | 78 | pDWriteFactory->AddRef(); 79 | m_pDWriteFactory = pDWriteFactory; 80 | 81 | m_maxGlyphWidth = 384; 82 | if(maxGlyphWidth > 0 && maxGlyphWidth <= 8192) 83 | m_maxGlyphWidth = maxGlyphWidth; 84 | m_maxGlyphHeight = 384; 85 | if(maxGlyphHeight > 0 && maxGlyphHeight <= 8192) 86 | m_maxGlyphHeight = maxGlyphHeight; 87 | 88 | pFontCollection->AddRef(); 89 | m_pFontCollection = pFontCollection; 90 | 91 | return S_OK; 92 | } 93 | 94 | 95 | // Get font index from DWrite font-face 96 | UINT CFW1GlyphProvider::getFontIndexFromFontFace(IDWriteFontFace *pFontFace) { 97 | UINT fontIndex = 0xffffffff; 98 | 99 | EnterCriticalSection(&m_fontsCriticalSection); 100 | 101 | // Search for a matching fontface by pointer 102 | for(size_t i=0; i < m_fonts.size(); ++i) { 103 | const FontInfo &fontInfo = m_fonts[i]; 104 | 105 | if(pFontFace == fontInfo.pFontFace) { 106 | fontIndex = static_cast(i); 107 | break; 108 | } 109 | } 110 | 111 | LeaveCriticalSection(&m_fontsCriticalSection); 112 | 113 | // Get font-face name 114 | if(fontIndex == 0xffffffff) { 115 | std::wstring uniqueName = getUniqueNameFromFontFace(pFontFace); 116 | if(uniqueName.size() > 0) { 117 | IDWriteFontFace *pOldFontFace = NULL; 118 | 119 | pFontFace->AddRef(); 120 | 121 | EnterCriticalSection(&m_fontsCriticalSection); 122 | 123 | // Search for a matching fontface by name 124 | for(size_t i=0; i < m_fonts.size(); ++i) { 125 | FontInfo &fontInfo = m_fonts[i]; 126 | 127 | if(fontInfo.uniqueName == uniqueName) { 128 | pOldFontFace = fontInfo.pFontFace; 129 | fontInfo.pFontFace = pFontFace; 130 | fontIndex = static_cast(i); 131 | break; 132 | } 133 | } 134 | 135 | // Add new font 136 | if(fontIndex == 0xffffffff) { 137 | FontInfo fontInfo; 138 | 139 | fontInfo.pFontFace = pFontFace; 140 | fontInfo.uniqueName = uniqueName; 141 | 142 | fontIndex = static_cast(m_fonts.size()); 143 | m_fonts.push_back(fontInfo); 144 | } 145 | 146 | LeaveCriticalSection(&m_fontsCriticalSection); 147 | 148 | SAFE_RELEASE(pOldFontFace); 149 | } 150 | else 151 | fontIndex = 0; 152 | } 153 | 154 | return fontIndex; 155 | } 156 | 157 | 158 | // Get unique name for a DWrite font-face 159 | std::wstring CFW1GlyphProvider::getUniqueNameFromFontFace(IDWriteFontFace *pFontFace) { 160 | std::wstring uniqueName; 161 | 162 | IDWriteFont *pFont; 163 | HRESULT hResult = m_pFontCollection->GetFontFromFontFace(pFontFace, &pFont); 164 | if(SUCCEEDED(hResult)) { 165 | // Family name 166 | IDWriteFontFamily *pFontFamily; 167 | hResult = pFont->GetFontFamily(&pFontFamily); 168 | if(SUCCEEDED(hResult)) { 169 | IDWriteLocalizedStrings *pFamilyNames; 170 | hResult = pFontFamily->GetFamilyNames(&pFamilyNames); 171 | if(SUCCEEDED(hResult)) { 172 | UINT32 index; 173 | BOOL exists; 174 | hResult = pFamilyNames->FindLocaleName(L"en-us", &index, &exists); 175 | if(FAILED(hResult) || !exists) 176 | index = 0; 177 | 178 | if(pFamilyNames->GetCount() > index) { 179 | UINT32 length; 180 | hResult = pFamilyNames->GetStringLength(index, &length); 181 | if(SUCCEEDED(hResult)) { 182 | std::vector str(length+1); 183 | 184 | hResult = pFamilyNames->GetString(index, &str[0], length+1); 185 | if(SUCCEEDED(hResult)) 186 | uniqueName = &str[0]; 187 | } 188 | } 189 | 190 | pFamilyNames->Release(); 191 | } 192 | 193 | pFontFamily->Release(); 194 | } 195 | 196 | // Face name 197 | IDWriteLocalizedStrings *pFaceNames; 198 | hResult = pFont->GetFaceNames(&pFaceNames); 199 | if(SUCCEEDED(hResult)) { 200 | UINT32 index; 201 | BOOL exists; 202 | hResult = pFaceNames->FindLocaleName(L"en-us", &index, &exists); 203 | if(FAILED(hResult) || !exists) 204 | index = 0; 205 | 206 | if(pFaceNames->GetCount() > index) { 207 | UINT32 length; 208 | hResult = pFaceNames->GetStringLength(index, &length); 209 | if(SUCCEEDED(hResult)) { 210 | std::vector str(length+1); 211 | 212 | hResult = pFaceNames->GetString(index, &str[0], length+1); 213 | if(SUCCEEDED(hResult)) 214 | uniqueName.append(&str[0]); 215 | } 216 | } 217 | 218 | pFaceNames->Release(); 219 | } 220 | 221 | // Simulations 222 | if(uniqueName.size() > 0) { 223 | DWRITE_FONT_SIMULATIONS simulations = pFontFace->GetSimulations(); 224 | if(simulations == DWRITE_FONT_SIMULATIONS_BOLD) 225 | uniqueName += L"SimBold"; 226 | else if(simulations == DWRITE_FONT_SIMULATIONS_OBLIQUE) 227 | uniqueName += L"SimOblique"; 228 | } 229 | } 230 | 231 | return uniqueName; 232 | } 233 | 234 | 235 | // Render and insert new glyph into a glyph-map 236 | UINT CFW1GlyphProvider::insertNewGlyph(GlyphMap *glyphMap, UINT16 glyphIndex, IDWriteFontFace *pFontFace) { 237 | UINT glyphAtlasId = 0xffffffff; 238 | 239 | // Get a render target 240 | IFW1DWriteRenderTarget *pRenderTarget = NULL; 241 | 242 | EnterCriticalSection(&m_renderTargetsCriticalSection); 243 | 244 | if(!m_glyphRenderTargets.empty()) { 245 | pRenderTarget = m_glyphRenderTargets.top(); 246 | m_glyphRenderTargets.pop(); 247 | } 248 | 249 | LeaveCriticalSection(&m_renderTargetsCriticalSection); 250 | 251 | if(pRenderTarget == NULL) { 252 | IFW1DWriteRenderTarget *pNewRenderTarget; 253 | HRESULT hResult = m_pFW1Factory->CreateDWriteRenderTarget( 254 | m_pDWriteFactory, 255 | m_maxGlyphWidth, 256 | m_maxGlyphHeight, 257 | &pNewRenderTarget 258 | ); 259 | if(FAILED(hResult)) { 260 | } 261 | else { 262 | pRenderTarget = pNewRenderTarget; 263 | } 264 | } 265 | 266 | if(pRenderTarget != NULL) { 267 | // Draw the glyph image 268 | DWRITE_RENDERING_MODE renderingMode = DWRITE_RENDERING_MODE_DEFAULT; 269 | DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL; 270 | if((glyphMap->fontFlags & FW1_ALIASED) != 0) { 271 | renderingMode = DWRITE_RENDERING_MODE_ALIASED; 272 | measuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 273 | } 274 | 275 | FW1_GLYPHIMAGEDATA glyphData; 276 | HRESULT hResult = pRenderTarget->DrawGlyphTemp( 277 | pFontFace, 278 | glyphIndex, 279 | glyphMap->fontSize, 280 | renderingMode, 281 | measuringMode, 282 | &glyphData 283 | ); 284 | if(FAILED(hResult)) { 285 | } 286 | else { 287 | // Insert into the atlas and the glyph-map 288 | EnterCriticalSection(&m_insertGlyphCriticalSection); 289 | 290 | glyphAtlasId = glyphMap->glyphs[glyphIndex]; 291 | if(glyphAtlasId == 0xffffffff) { 292 | glyphAtlasId = m_pGlyphAtlas->InsertGlyph( 293 | &glyphData.Metrics, 294 | glyphData.pGlyphPixels, 295 | glyphData.RowPitch, 296 | glyphData.PixelStride 297 | ); 298 | if(glyphAtlasId != 0xffffffff) 299 | glyphMap->glyphs[glyphIndex] = glyphAtlasId; 300 | } 301 | 302 | LeaveCriticalSection(&m_insertGlyphCriticalSection); 303 | } 304 | 305 | // Keep the render target for future use 306 | EnterCriticalSection(&m_renderTargetsCriticalSection); 307 | m_glyphRenderTargets.push(pRenderTarget); 308 | LeaveCriticalSection(&m_renderTargetsCriticalSection); 309 | } 310 | 311 | return glyphAtlasId; 312 | } 313 | 314 | 315 | }// namespace FW1FontWrapper 316 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphProvider.h: -------------------------------------------------------------------------------- 1 | // CFW1GlyphProvider.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1GlyphProvider 4 | #define IncludeGuard__FW1_CFW1GlyphProvider 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Fonts and glyphs-maps collection to match glyphs to images in a glyph-atlas 13 | class CFW1GlyphProvider : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1GlyphProvider 19 | virtual HRESULT STDMETHODCALLTYPE GetGlyphAtlas(IFW1GlyphAtlas **ppGlyphAtlas); 20 | virtual HRESULT STDMETHODCALLTYPE GetDWriteFactory(IDWriteFactory **ppDWriteFactory); 21 | virtual HRESULT STDMETHODCALLTYPE GetDWriteFontCollection(IDWriteFontCollection **ppFontCollection); 22 | 23 | virtual const void* STDMETHODCALLTYPE GetGlyphMapFromFont( 24 | IDWriteFontFace *pFontFace, 25 | FLOAT FontSize, 26 | UINT FontFlags 27 | ); 28 | virtual UINT STDMETHODCALLTYPE GetAtlasIdFromGlyphIndex( 29 | const void* pGlyphMap, 30 | UINT16 GlyphIndex, 31 | IDWriteFontFace *pFontFace, 32 | UINT FontFlags 33 | ); 34 | 35 | // Public functions 36 | public: 37 | CFW1GlyphProvider(); 38 | 39 | HRESULT initGlyphProvider( 40 | IFW1Factory *pFW1Factory, 41 | IFW1GlyphAtlas *pGlyphAtlas, 42 | IDWriteFactory *pDWriteFactory, 43 | IDWriteFontCollection *pFontCollection, 44 | UINT maxGlyphWidth, 45 | UINT maxGlyphHeight 46 | ); 47 | 48 | // Internal types 49 | private: 50 | struct GlyphMap { 51 | FLOAT fontSize; 52 | UINT fontFlags; 53 | 54 | UINT *glyphs; 55 | UINT glyphCount; 56 | }; 57 | 58 | struct FontInfo { 59 | IDWriteFontFace *pFontFace; 60 | std::wstring uniqueName; 61 | }; 62 | 63 | typedef std::pair > FontId; 64 | typedef std::map FontMap; 65 | 66 | FontId makeFontId(UINT fontIndex, UINT fontFlags, FLOAT fontSize) { 67 | UINT relevantFlags = (fontFlags & (FW1_ALIASED)); 68 | return std::make_pair(fontIndex, std::make_pair(relevantFlags, fontSize)); 69 | } 70 | 71 | // Internal functions 72 | private: 73 | virtual ~CFW1GlyphProvider(); 74 | 75 | UINT getFontIndexFromFontFace(IDWriteFontFace *pFontFace); 76 | std::wstring getUniqueNameFromFontFace(IDWriteFontFace *pFontFace); 77 | 78 | UINT insertNewGlyph(GlyphMap *glyphMap, UINT16 glyphIndex, IDWriteFontFace *pFontFace); 79 | 80 | // Internal data 81 | private: 82 | IFW1GlyphAtlas *m_pGlyphAtlas; 83 | 84 | IDWriteFactory *m_pDWriteFactory; 85 | UINT m_maxGlyphWidth; 86 | UINT m_maxGlyphHeight; 87 | std::stack m_glyphRenderTargets; 88 | 89 | IDWriteFontCollection *m_pFontCollection; 90 | std::vector m_fonts; 91 | 92 | FontMap m_fontMap; 93 | 94 | CRITICAL_SECTION m_renderTargetsCriticalSection; 95 | CRITICAL_SECTION m_glyphMapsCriticalSection; 96 | CRITICAL_SECTION m_fontsCriticalSection; 97 | CRITICAL_SECTION m_insertGlyphCriticalSection; 98 | }; 99 | 100 | 101 | }// namespace FW1FontWrapper 102 | 103 | 104 | #endif// IncludeGuard__FW1_CFW1GlyphProvider 105 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphProviderInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphProviderInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphProvider.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1GlyphProvider::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1GlyphProvider))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Get glyph atlas 27 | HRESULT STDMETHODCALLTYPE CFW1GlyphProvider::GetGlyphAtlas(IFW1GlyphAtlas **ppGlyphAtlas) { 28 | if(ppGlyphAtlas == NULL) 29 | return E_INVALIDARG; 30 | 31 | m_pGlyphAtlas->AddRef(); 32 | *ppGlyphAtlas = m_pGlyphAtlas; 33 | 34 | return S_OK; 35 | } 36 | 37 | 38 | // Get DWrite factory 39 | HRESULT STDMETHODCALLTYPE CFW1GlyphProvider::GetDWriteFactory(IDWriteFactory **ppDWriteFactory) { 40 | if(ppDWriteFactory == NULL) 41 | return E_INVALIDARG; 42 | 43 | m_pDWriteFactory->AddRef(); 44 | *ppDWriteFactory = m_pDWriteFactory; 45 | 46 | return S_OK; 47 | } 48 | 49 | 50 | // Get DWrite font collection 51 | HRESULT STDMETHODCALLTYPE CFW1GlyphProvider::GetDWriteFontCollection(IDWriteFontCollection **ppFontCollection) { 52 | if(ppFontCollection == NULL) 53 | return E_INVALIDARG; 54 | 55 | m_pFontCollection->AddRef(); 56 | *ppFontCollection = m_pFontCollection; 57 | 58 | return S_OK; 59 | } 60 | 61 | 62 | // Get glyph map 63 | const void* STDMETHODCALLTYPE CFW1GlyphProvider::GetGlyphMapFromFont( 64 | IDWriteFontFace *pFontFace, 65 | FLOAT FontSize, 66 | UINT FontFlags 67 | ) { 68 | // Get font id 69 | UINT fontIndex = getFontIndexFromFontFace(pFontFace); 70 | FontId fontId = makeFontId(fontIndex, FontFlags, FontSize); 71 | 72 | const void *glyphMap = 0; 73 | 74 | // Get the glyph-map 75 | EnterCriticalSection(&m_glyphMapsCriticalSection); 76 | FontMap::iterator it = m_fontMap.find(fontId); 77 | if(it != m_fontMap.end()) 78 | glyphMap = (*it).second; 79 | LeaveCriticalSection(&m_glyphMapsCriticalSection); 80 | 81 | if(glyphMap == 0 && (FontFlags & FW1_NONEWGLYPHS) == 0) { 82 | // Create a new glyph-map 83 | GlyphMap *newGlyphMap = new GlyphMap; 84 | newGlyphMap->fontSize = FontSize; 85 | newGlyphMap->fontFlags = FontFlags; 86 | newGlyphMap->glyphCount = pFontFace->GetGlyphCount(); 87 | newGlyphMap->glyphs = new UINT[newGlyphMap->glyphCount]; 88 | for(UINT i=0; i < newGlyphMap->glyphCount; ++i) 89 | newGlyphMap->glyphs[i] = 0xffffffff; 90 | 91 | bool needless = false; 92 | 93 | // Inert the new glyph-map and map the font-id to its index 94 | EnterCriticalSection(&m_glyphMapsCriticalSection); 95 | 96 | it = m_fontMap.find(fontId); 97 | if(it != m_fontMap.end()) { 98 | glyphMap = (*it).second; 99 | needless = true; 100 | } 101 | else { 102 | m_fontMap.insert(std::make_pair(fontId, newGlyphMap)); 103 | glyphMap = newGlyphMap; 104 | } 105 | 106 | LeaveCriticalSection(&m_glyphMapsCriticalSection); 107 | 108 | if(needless) {// Simultaneous creation on two threads 109 | delete[] newGlyphMap->glyphs; 110 | delete newGlyphMap; 111 | } 112 | else { 113 | UINT glyphAtlasId = insertNewGlyph(newGlyphMap, 0, pFontFace); 114 | glyphAtlasId; 115 | } 116 | } 117 | 118 | return glyphMap; 119 | } 120 | 121 | 122 | // Get atlas id of a glyph 123 | UINT STDMETHODCALLTYPE CFW1GlyphProvider::GetAtlasIdFromGlyphIndex( 124 | const void *pGlyphMap, 125 | UINT16 GlyphIndex, 126 | IDWriteFontFace *pFontFace, 127 | UINT FontFlags 128 | ) { 129 | GlyphMap *glyphMap = static_cast(const_cast(pGlyphMap)); 130 | 131 | if(glyphMap == 0) 132 | return 0; 133 | 134 | if(GlyphIndex >= glyphMap->glyphCount) 135 | return 0; 136 | 137 | // Get the atlas id for this glyph 138 | UINT glyphAtlasId = glyphMap->glyphs[GlyphIndex]; 139 | if(glyphAtlasId == 0xffffffff && (FontFlags & FW1_NONEWGLYPHS) == 0) 140 | glyphAtlasId = insertNewGlyph(glyphMap, GlyphIndex, pFontFace); 141 | 142 | // Fall back to the font default-glyph or the atlas default-glyph on failure 143 | if(glyphAtlasId == 0xffffffff) { 144 | glyphAtlasId = glyphMap->glyphs[0]; 145 | 146 | if((FontFlags & FW1_NONEWGLYPHS) == 0) { 147 | if(glyphAtlasId == 0xffffffff) { 148 | if(GlyphIndex == 0) 149 | glyphAtlasId = 0; 150 | else 151 | glyphAtlasId = GetAtlasIdFromGlyphIndex(pGlyphMap, 0, pFontFace, FontFlags); 152 | } 153 | 154 | EnterCriticalSection(&m_insertGlyphCriticalSection); 155 | if(glyphMap->glyphs[GlyphIndex] == 0xffffffff) 156 | glyphMap->glyphs[GlyphIndex] = glyphAtlasId; 157 | LeaveCriticalSection(&m_insertGlyphCriticalSection); 158 | } 159 | 160 | if(glyphAtlasId == 0xffffffff) 161 | glyphAtlasId = 0; 162 | } 163 | 164 | return glyphAtlasId; 165 | } 166 | 167 | 168 | }// namespace FW1FontWrapper 169 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphRenderStates.h: -------------------------------------------------------------------------------- 1 | // CFW1GlyphRenderStates.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1GlyphRenderStates 4 | #define IncludeGuard__FW1_CFW1GlyphRenderStates 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Shader etc. needed to draw glyphs 13 | class CFW1GlyphRenderStates : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1GlyphRenderStates 19 | virtual HRESULT STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice); 20 | 21 | virtual void STDMETHODCALLTYPE SetStates(ID3D11DeviceContext *pContext, UINT Flags); 22 | virtual void STDMETHODCALLTYPE UpdateShaderConstants( 23 | ID3D11DeviceContext *pContext, 24 | const FW1_RECTF *pClipRect, 25 | const FLOAT *pTransformMatrix 26 | ); 27 | virtual BOOL STDMETHODCALLTYPE HasGeometryShader(); 28 | 29 | // Public functions 30 | public: 31 | CFW1GlyphRenderStates(); 32 | 33 | HRESULT initRenderResources( 34 | IFW1Factory *pFW1Factory, 35 | ID3D11Device *pDevice, 36 | bool wantGeometryShader, 37 | bool anisotropicFiltering 38 | ); 39 | 40 | // Internal types 41 | private: 42 | struct ShaderConstants { 43 | FLOAT TransformMatrix[16]; 44 | FLOAT ClipRect[4]; 45 | }; 46 | 47 | // Internal functions 48 | private: 49 | virtual ~CFW1GlyphRenderStates(); 50 | 51 | HRESULT createQuadShaders(); 52 | HRESULT createGlyphShaders(); 53 | HRESULT createPixelShaders(); 54 | HRESULT createConstantBuffer(); 55 | HRESULT createRenderStates(bool anisotropicFiltering); 56 | 57 | // Internal data 58 | private: 59 | std::wstring m_lastError; 60 | 61 | pD3DCompile m_pfnD3DCompile; 62 | 63 | ID3D11Device *m_pDevice; 64 | D3D_FEATURE_LEVEL m_featureLevel; 65 | 66 | ID3D11VertexShader *m_pVertexShaderQuad; 67 | ID3D11VertexShader *m_pVertexShaderClipQuad; 68 | ID3D11InputLayout *m_pQuadInputLayout; 69 | 70 | ID3D11VertexShader *m_pVertexShaderPoint; 71 | ID3D11InputLayout *m_pPointInputLayout; 72 | ID3D11GeometryShader *m_pGeometryShaderPoint; 73 | ID3D11GeometryShader *m_pGeometryShaderClipPoint; 74 | bool m_hasGeometryShader; 75 | 76 | ID3D11PixelShader *m_pPixelShader; 77 | ID3D11PixelShader *m_pPixelShaderClip; 78 | 79 | ID3D11Buffer *m_pConstantBuffer; 80 | 81 | ID3D11BlendState *m_pBlendState; 82 | ID3D11SamplerState *m_pSamplerState; 83 | ID3D11RasterizerState *m_pRasterizerState; 84 | ID3D11DepthStencilState *m_pDepthStencilState; 85 | }; 86 | 87 | 88 | }// namespace FW1FontWrapper 89 | 90 | 91 | #endif// IncludeGuard__FW1_CFW1GlyphRenderStates 92 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphRenderStatesInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphRenderStatesInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphRenderStates.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1GlyphRenderStates::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1GlyphRenderStates))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Get the D3D11 device used by the render states 27 | HRESULT STDMETHODCALLTYPE CFW1GlyphRenderStates::GetDevice(ID3D11Device **ppDevice) { 28 | if(ppDevice == NULL) 29 | return E_INVALIDARG; 30 | 31 | m_pDevice->AddRef(); 32 | *ppDevice = m_pDevice; 33 | 34 | return S_OK; 35 | } 36 | 37 | 38 | // Set render states for glyph drawing 39 | void STDMETHODCALLTYPE CFW1GlyphRenderStates::SetStates(ID3D11DeviceContext *pContext, UINT Flags) { 40 | if(m_hasGeometryShader && ((Flags & FW1_NOGEOMETRYSHADER) == 0)) { 41 | // Point vertices with geometry shader 42 | pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); 43 | pContext->IASetInputLayout(m_pPointInputLayout); 44 | pContext->VSSetShader(m_pVertexShaderPoint, NULL, 0); 45 | if((Flags & FW1_CLIPRECT) != 0) 46 | pContext->GSSetShader(m_pGeometryShaderClipPoint, NULL, 0); 47 | else 48 | pContext->GSSetShader(m_pGeometryShaderPoint, NULL, 0); 49 | pContext->PSSetShader(m_pPixelShader, NULL, 0); 50 | pContext->GSSetConstantBuffers(0, 1, &m_pConstantBuffer); 51 | } 52 | else { 53 | // Quads constructed on the CPU 54 | pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 55 | pContext->IASetInputLayout(m_pQuadInputLayout); 56 | if((Flags & FW1_CLIPRECT) != 0) { 57 | pContext->VSSetShader(m_pVertexShaderClipQuad, NULL, 0); 58 | pContext->PSSetShader(m_pPixelShaderClip, NULL, 0); 59 | } 60 | else { 61 | pContext->VSSetShader(m_pVertexShaderQuad, NULL, 0); 62 | pContext->PSSetShader(m_pPixelShader, NULL, 0); 63 | } 64 | pContext->VSSetConstantBuffers(0, 1, &m_pConstantBuffer); 65 | 66 | if(m_featureLevel >= D3D_FEATURE_LEVEL_10_0) 67 | pContext->GSSetShader(NULL, NULL, 0); 68 | } 69 | 70 | if(m_featureLevel >= D3D_FEATURE_LEVEL_11_0) { 71 | pContext->DSSetShader(NULL, NULL, 0); 72 | pContext->HSSetShader(NULL, NULL, 0); 73 | } 74 | 75 | pContext->OMSetBlendState(m_pBlendState, NULL, 0xffffffff); 76 | pContext->OMSetDepthStencilState(m_pDepthStencilState, 0); 77 | 78 | pContext->RSSetState(m_pRasterizerState); 79 | 80 | pContext->PSSetSamplers(0, 1, &m_pSamplerState); 81 | } 82 | 83 | 84 | // Update constant buffer 85 | void STDMETHODCALLTYPE CFW1GlyphRenderStates::UpdateShaderConstants( 86 | ID3D11DeviceContext *pContext, 87 | const FW1_RECTF *pClipRect, 88 | const FLOAT *pTransformMatrix 89 | ) { 90 | // Shader constants 91 | ShaderConstants constants; 92 | ZeroMemory(&constants, sizeof(constants)); 93 | 94 | // Transform matrix 95 | if(pTransformMatrix != NULL) 96 | CopyMemory(constants.TransformMatrix, pTransformMatrix, 16*sizeof(FLOAT)); 97 | else { 98 | // Get viewport size for orthographic transform 99 | FLOAT w = 512.0f; 100 | FLOAT h = 512.0f; 101 | 102 | D3D11_VIEWPORT vp; 103 | UINT nvp = 1; 104 | pContext->RSGetViewports(&nvp, &vp); 105 | if(nvp > 0) { 106 | if(vp.Width >= 1.0f && vp.Height >= 1.0f) { 107 | w = vp.Width; 108 | h = vp.Height; 109 | } 110 | } 111 | 112 | constants.TransformMatrix[0] = 2.0f / w; 113 | constants.TransformMatrix[12] = -1.0f; 114 | constants.TransformMatrix[5] = -2.0f / h; 115 | constants.TransformMatrix[13] = 1.0f; 116 | constants.TransformMatrix[10] = 1.0f; 117 | constants.TransformMatrix[15] = 1.0f; 118 | } 119 | 120 | // Clip rect 121 | if(pClipRect != NULL) { 122 | constants.ClipRect[0] = -pClipRect->Left; 123 | constants.ClipRect[1] = -pClipRect->Top; 124 | constants.ClipRect[2] = pClipRect->Right; 125 | constants.ClipRect[3] = pClipRect->Bottom; 126 | } 127 | else { 128 | constants.ClipRect[0] = FLT_MAX; 129 | constants.ClipRect[1] = FLT_MAX; 130 | constants.ClipRect[2] = FLT_MAX; 131 | constants.ClipRect[3] = FLT_MAX; 132 | } 133 | 134 | // Update constant buffer 135 | D3D11_MAPPED_SUBRESOURCE msr; 136 | HRESULT hResult = pContext->Map(m_pConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr); 137 | if(SUCCEEDED(hResult)) { 138 | CopyMemory(msr.pData, &constants, sizeof(constants)); 139 | 140 | pContext->Unmap(m_pConstantBuffer, 0); 141 | } 142 | } 143 | 144 | 145 | // Check for geometry shader 146 | BOOL STDMETHODCALLTYPE CFW1GlyphRenderStates::HasGeometryShader() { 147 | return (m_hasGeometryShader ? TRUE : FALSE); 148 | } 149 | 150 | 151 | }// namespace FW1FontWrapper 152 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphSheet.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphSheet.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphSheet.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1GlyphSheet::CFW1GlyphSheet() : 15 | m_sheetWidth(0), 16 | m_sheetHeight(0), 17 | m_hardwareCoordBuffer(false), 18 | m_allowOversizedGlyph(false), 19 | 20 | m_textureData(0), 21 | m_glyphCoords(0), 22 | m_maxGlyphCount(0), 23 | m_glyphCount(0), 24 | m_mipLevelCount(0), 25 | m_alignWidth(0), 26 | 27 | m_pDevice(NULL), 28 | 29 | m_pTexture(NULL), 30 | m_pTextureSRV(NULL), 31 | m_pCoordBuffer(NULL), 32 | m_pCoordBufferSRV(NULL), 33 | 34 | m_closed(false), 35 | m_static(false), 36 | 37 | m_heightRange(0), 38 | 39 | m_updatedGlyphCount(0) 40 | { 41 | ZeroMemory(&m_dirtyRect, sizeof(m_dirtyRect)); 42 | InitializeCriticalSection(&m_sheetCriticalSection); 43 | InitializeCriticalSection(&m_flushCriticalSection); 44 | } 45 | 46 | 47 | // Destruct 48 | CFW1GlyphSheet::~CFW1GlyphSheet() { 49 | delete[] m_textureData; 50 | delete[] m_glyphCoords; 51 | 52 | SAFE_RELEASE(m_pDevice); 53 | 54 | SAFE_RELEASE(m_pTexture); 55 | SAFE_RELEASE(m_pTextureSRV); 56 | SAFE_RELEASE(m_pCoordBuffer); 57 | SAFE_RELEASE(m_pCoordBufferSRV); 58 | 59 | delete m_heightRange; 60 | 61 | DeleteCriticalSection(&m_sheetCriticalSection); 62 | DeleteCriticalSection(&m_flushCriticalSection); 63 | } 64 | 65 | 66 | // Init 67 | HRESULT CFW1GlyphSheet::initGlyphSheet( 68 | IFW1Factory *pFW1Factory, 69 | ID3D11Device *pDevice, 70 | UINT sheetWidth, 71 | UINT sheetHeight, 72 | bool coordBuffer, 73 | bool allowOversizedGlyph, 74 | UINT maxGlyphCount, 75 | UINT mipLevelCount 76 | ) { 77 | HRESULT hResult = initBaseObject(pFW1Factory); 78 | if(FAILED(hResult)) 79 | return hResult; 80 | 81 | if(pDevice == NULL) 82 | return E_INVALIDARG; 83 | 84 | pDevice->AddRef(); 85 | m_pDevice = pDevice; 86 | 87 | // Sheet metrics 88 | m_sheetWidth = 512; 89 | if(sheetWidth > 0) 90 | m_sheetWidth = sheetWidth; 91 | m_sheetHeight = 512; 92 | if(sheetHeight > 0) 93 | m_sheetHeight = sheetHeight; 94 | 95 | if(coordBuffer) { 96 | D3D_FEATURE_LEVEL featureLevel = m_pDevice->GetFeatureLevel(); 97 | if(featureLevel >= D3D_FEATURE_LEVEL_10_0) 98 | m_hardwareCoordBuffer = true; 99 | } 100 | 101 | m_allowOversizedGlyph = allowOversizedGlyph; 102 | 103 | m_maxGlyphCount = 2048; 104 | if(maxGlyphCount > 0 && maxGlyphCount < 65535) 105 | m_maxGlyphCount = maxGlyphCount; 106 | 107 | if(mipLevelCount > 1) { 108 | m_mipLevelCount = std::min(mipLevelCount, 5U);// Reasonable mip limit considering borders 109 | m_alignWidth = (1 << (m_mipLevelCount - 1)); 110 | } 111 | else {// 0 defaults to 1 112 | m_mipLevelCount = 1; 113 | m_alignWidth = 1; 114 | } 115 | 116 | // Storage 117 | UINT textureSize = m_sheetWidth * m_sheetHeight; 118 | UINT mipSize = textureSize; 119 | for(UINT i=1;i>= 2; 121 | textureSize += mipSize; 122 | } 123 | 124 | m_textureData = new UINT8[textureSize]; 125 | ZeroMemory(m_textureData, textureSize); 126 | 127 | m_glyphCoords = new FW1_GLYPHCOORDS[m_maxGlyphCount]; 128 | 129 | m_heightRange = new HeightRange(m_sheetWidth / m_alignWidth); 130 | 131 | // Device texture/coord-buffer 132 | hResult = createDeviceResources(); 133 | 134 | if(SUCCEEDED(hResult)) 135 | hResult = S_OK; 136 | 137 | return hResult; 138 | } 139 | 140 | 141 | // Create sheet texture and (optionally) coord buffer 142 | HRESULT CFW1GlyphSheet::createDeviceResources() { 143 | // Create sheet texture 144 | D3D11_TEXTURE2D_DESC textureDesc; 145 | ID3D11Texture2D *pTexture; 146 | 147 | ZeroMemory(&textureDesc, sizeof(textureDesc)); 148 | textureDesc.Width = m_sheetWidth; 149 | textureDesc.Height = m_sheetHeight; 150 | textureDesc.ArraySize = 1; 151 | textureDesc.Format = DXGI_FORMAT_R8_UNORM; 152 | textureDesc.SampleDesc.Count = 1; 153 | textureDesc.Usage = D3D11_USAGE_DEFAULT; 154 | textureDesc.MipLevels = m_mipLevelCount; 155 | textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 156 | 157 | HRESULT hResult = m_pDevice->CreateTexture2D(&textureDesc, NULL, &pTexture); 158 | if(FAILED(hResult)) { 159 | m_lastError = L"Failed to create glyph sheet texture"; 160 | } 161 | else { 162 | ID3D11ShaderResourceView *pTextureSRV; 163 | 164 | hResult = m_pDevice->CreateShaderResourceView(pTexture, NULL, &pTextureSRV); 165 | if(FAILED(hResult)) { 166 | m_lastError = L"Failed to create shader resource view for glyph sheet texture"; 167 | } 168 | else { 169 | // Create coord buffer if enabled 170 | if(m_hardwareCoordBuffer) { 171 | D3D11_BUFFER_DESC bufferDesc; 172 | ID3D11Buffer *pBuffer; 173 | 174 | ZeroMemory(&bufferDesc, sizeof(bufferDesc)); 175 | bufferDesc.ByteWidth = m_maxGlyphCount * sizeof(FW1_GLYPHCOORDS); 176 | bufferDesc.Usage = D3D11_USAGE_DEFAULT; 177 | bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 178 | 179 | hResult = m_pDevice->CreateBuffer(&bufferDesc, NULL, &pBuffer); 180 | if(FAILED(hResult)) { 181 | m_lastError = L"Failed to create glyph coord buffer"; 182 | } 183 | else { 184 | D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; 185 | ID3D11ShaderResourceView *pBufferSRV; 186 | 187 | ZeroMemory(&bufferSRVDesc, sizeof(bufferSRVDesc)); 188 | bufferSRVDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; 189 | bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; 190 | bufferSRVDesc.Buffer.ElementOffset = 0; 191 | bufferSRVDesc.Buffer.ElementWidth = m_maxGlyphCount * 2;// Two float4 per glyphcoords 192 | 193 | hResult = m_pDevice->CreateShaderResourceView(pBuffer, &bufferSRVDesc, &pBufferSRV); 194 | if(FAILED(hResult)) { 195 | m_lastError = L"Failed to create shader resource view for glyph coord buffer"; 196 | } 197 | else { 198 | m_pCoordBuffer = pBuffer; 199 | m_pCoordBufferSRV = pBufferSRV; 200 | } 201 | 202 | if(FAILED(hResult)) 203 | pBuffer->Release(); 204 | } 205 | } 206 | 207 | if(SUCCEEDED(hResult)) { 208 | m_pTexture = pTexture; 209 | m_pTextureSRV = pTextureSRV; 210 | } 211 | else 212 | pTextureSRV->Release(); 213 | } 214 | 215 | if(FAILED(hResult)) 216 | pTexture->Release(); 217 | } 218 | 219 | return hResult; 220 | } 221 | 222 | 223 | // Height-range helper class, used to fit glyphs in the sheet 224 | 225 | CFW1GlyphSheet::HeightRange::HeightRange(UINT totalWidth) : m_totalWidth(totalWidth) { 226 | m_heights = new UINT[m_totalWidth]; 227 | ZeroMemory(m_heights, m_totalWidth * sizeof(UINT)); 228 | } 229 | 230 | CFW1GlyphSheet::HeightRange::~HeightRange() { 231 | delete[] m_heights; 232 | } 233 | 234 | UINT CFW1GlyphSheet::HeightRange::findMin(UINT width, UINT *outMin) { 235 | if(width > m_totalWidth) 236 | width = m_totalWidth; 237 | 238 | UINT currentMax = findMax(0, width); 239 | UINT currentMin = currentMax; 240 | UINT minX = 0; 241 | 242 | for(UINT i=1; i < m_totalWidth-width; ++i) { 243 | if(m_heights[i+width-1] >= currentMax) 244 | currentMax = m_heights[i+width-1]; 245 | else if(m_heights[i-1] == currentMax) { 246 | currentMax = findMax(i, width); 247 | if(currentMax < currentMin) { 248 | currentMin = currentMax; 249 | minX = i; 250 | } 251 | } 252 | } 253 | 254 | *outMin = currentMin; 255 | return minX; 256 | } 257 | 258 | void CFW1GlyphSheet::HeightRange::update(UINT startX, UINT width, UINT newHeight) { 259 | if(width > m_totalWidth) 260 | width = m_totalWidth; 261 | 262 | for(UINT i=0; i < width; ++i) 263 | m_heights[startX+i] = newHeight; 264 | } 265 | 266 | UINT CFW1GlyphSheet::HeightRange::findMax(UINT startX, UINT width) { 267 | UINT currentMax = m_heights[startX]; 268 | for(UINT i=1; i < width; ++i) 269 | currentMax = std::max(currentMax, m_heights[startX+i]); 270 | 271 | return currentMax; 272 | } 273 | 274 | 275 | }// namespace FW1FontWrapper 276 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphSheet.h: -------------------------------------------------------------------------------- 1 | // CFW1GlyphSheet.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1GlyphSheet 4 | #define IncludeGuard__FW1_CFW1GlyphSheet 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // A texture containing multiple glyphimages 13 | class CFW1GlyphSheet : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1GlyphSheet 19 | virtual HRESULT STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice); 20 | virtual void STDMETHODCALLTYPE GetDesc(FW1_GLYPHSHEETDESC *pDesc); 21 | 22 | virtual HRESULT STDMETHODCALLTYPE GetSheetTexture(ID3D11ShaderResourceView **ppSheetTextureSRV); 23 | virtual HRESULT STDMETHODCALLTYPE GetCoordBuffer(ID3D11ShaderResourceView **ppCoordBufferSRV); 24 | 25 | virtual const FW1_GLYPHCOORDS* STDMETHODCALLTYPE GetGlyphCoords(); 26 | virtual HRESULT STDMETHODCALLTYPE BindSheet(ID3D11DeviceContext *pContext, UINT Flags); 27 | 28 | virtual UINT STDMETHODCALLTYPE InsertGlyph( 29 | const FW1_GLYPHMETRICS *pGlyphMetrics, 30 | const void *pGlyphData, 31 | UINT RowPitch, 32 | UINT PixelStride 33 | ); 34 | virtual void STDMETHODCALLTYPE CloseSheet(); 35 | virtual void STDMETHODCALLTYPE Flush(ID3D11DeviceContext *pContext); 36 | 37 | // Public functions 38 | public: 39 | CFW1GlyphSheet(); 40 | 41 | HRESULT initGlyphSheet( 42 | IFW1Factory *pFW1Factory, 43 | ID3D11Device *pDevice, 44 | UINT sheetWidth, 45 | UINT sheetHeight, 46 | bool coordBuffer, 47 | bool allowOversizedGlyph, 48 | UINT maxGlyphCount, 49 | UINT mipLevelCount 50 | ); 51 | 52 | // Internal types 53 | private: 54 | struct RectUI { 55 | UINT left; 56 | UINT top; 57 | UINT right; 58 | UINT bottom; 59 | }; 60 | 61 | class HeightRange { 62 | public: 63 | HeightRange(UINT totalWidth); 64 | ~HeightRange(); 65 | 66 | UINT findMin(UINT width, UINT *outMin); 67 | void update(UINT startX, UINT width, UINT newHeight); 68 | 69 | private: 70 | HeightRange(); 71 | HeightRange(const HeightRange&); 72 | HeightRange& operator=(const HeightRange&); 73 | 74 | UINT findMax(UINT startX, UINT width); 75 | 76 | UINT *m_heights; 77 | UINT m_totalWidth; 78 | }; 79 | 80 | class CriticalSectionLock { 81 | public: 82 | CriticalSectionLock(LPCRITICAL_SECTION pCriticalSection) : m_pCriticalSection(pCriticalSection) { 83 | EnterCriticalSection(m_pCriticalSection); 84 | } 85 | ~CriticalSectionLock() { 86 | LeaveCriticalSection(m_pCriticalSection); 87 | } 88 | 89 | private: 90 | CriticalSectionLock(); 91 | CriticalSectionLock(const CriticalSectionLock&); 92 | CriticalSectionLock& operator=(const CriticalSectionLock&); 93 | 94 | LPCRITICAL_SECTION m_pCriticalSection; 95 | }; 96 | 97 | // Internal functions 98 | private: 99 | virtual ~CFW1GlyphSheet(); 100 | 101 | HRESULT createDeviceResources(); 102 | 103 | // Internal data 104 | private: 105 | std::wstring m_lastError; 106 | 107 | UINT m_sheetWidth; 108 | UINT m_sheetHeight; 109 | bool m_hardwareCoordBuffer; 110 | bool m_allowOversizedGlyph; 111 | UINT m_mipLevelCount; 112 | UINT m_alignWidth; 113 | 114 | UINT8 *m_textureData; 115 | FW1_GLYPHCOORDS *m_glyphCoords; 116 | UINT m_maxGlyphCount; 117 | UINT m_glyphCount; 118 | 119 | ID3D11Device *m_pDevice; 120 | 121 | ID3D11Texture2D *m_pTexture; 122 | ID3D11ShaderResourceView *m_pTextureSRV; 123 | ID3D11Buffer *m_pCoordBuffer; 124 | ID3D11ShaderResourceView *m_pCoordBufferSRV; 125 | 126 | bool m_closed; 127 | bool m_static; 128 | 129 | HeightRange *m_heightRange; 130 | 131 | UINT m_updatedGlyphCount; 132 | RectUI m_dirtyRect; 133 | CRITICAL_SECTION m_sheetCriticalSection; 134 | CRITICAL_SECTION m_flushCriticalSection; 135 | }; 136 | 137 | 138 | }// namespace FW1FontWrapper 139 | 140 | 141 | #endif// IncludeGuard__FW1_CFW1GlyphSheet 142 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphSheetInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphSheetInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphSheet.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1GlyphSheet::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1GlyphSheet))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Get the D3D11 device used by this sheet 27 | HRESULT STDMETHODCALLTYPE CFW1GlyphSheet::GetDevice(ID3D11Device **ppDevice) { 28 | if(ppDevice == NULL) 29 | return E_INVALIDARG; 30 | 31 | m_pDevice->AddRef(); 32 | *ppDevice = m_pDevice; 33 | 34 | return S_OK; 35 | } 36 | 37 | 38 | // Get sheet desc 39 | void STDMETHODCALLTYPE CFW1GlyphSheet::GetDesc(FW1_GLYPHSHEETDESC *pDesc) { 40 | pDesc->GlyphCount = m_glyphCount; 41 | pDesc->Width = m_sheetWidth; 42 | pDesc->Height = m_sheetHeight; 43 | pDesc->MipLevels = m_mipLevelCount; 44 | } 45 | 46 | 47 | // Get the sheet texture 48 | HRESULT STDMETHODCALLTYPE CFW1GlyphSheet::GetSheetTexture(ID3D11ShaderResourceView **ppSheetTextureSRV) { 49 | if(ppSheetTextureSRV == NULL) 50 | return E_INVALIDARG; 51 | 52 | m_pTextureSRV->AddRef(); 53 | *ppSheetTextureSRV = m_pTextureSRV; 54 | 55 | return S_OK; 56 | } 57 | 58 | 59 | // Get the glyph coordinate buffer 60 | HRESULT STDMETHODCALLTYPE CFW1GlyphSheet::GetCoordBuffer(ID3D11ShaderResourceView **ppCoordBufferSRV) { 61 | if(ppCoordBufferSRV == NULL) 62 | return E_INVALIDARG; 63 | 64 | if(m_pCoordBufferSRV != NULL) 65 | m_pCoordBufferSRV->AddRef(); 66 | *ppCoordBufferSRV = m_pCoordBufferSRV; 67 | 68 | return S_OK; 69 | } 70 | 71 | 72 | // Get glyph coordinate array for all glyphs in the sheet 73 | const FW1_GLYPHCOORDS* STDMETHODCALLTYPE CFW1GlyphSheet::GetGlyphCoords() { 74 | return m_glyphCoords; 75 | } 76 | 77 | 78 | // Set sheet shader resources 79 | HRESULT STDMETHODCALLTYPE CFW1GlyphSheet::BindSheet(ID3D11DeviceContext *pContext, UINT Flags) { 80 | pContext->PSSetShaderResources(0, 1, &m_pTextureSRV); 81 | if((Flags & FW1_NOGEOMETRYSHADER) == 0 && m_hardwareCoordBuffer) 82 | pContext->GSSetShaderResources(0, 1, &m_pCoordBufferSRV); 83 | 84 | return S_OK; 85 | } 86 | 87 | 88 | // Insert a new glyph in the sheet 89 | UINT STDMETHODCALLTYPE CFW1GlyphSheet::InsertGlyph( 90 | const FW1_GLYPHMETRICS *pGlyphMetrics, 91 | LPCVOID pGlyphData, 92 | UINT RowPitch, 93 | UINT PixelStride 94 | ) { 95 | if(m_closed) 96 | return 0xffffffff; 97 | if(m_glyphCount >= m_maxGlyphCount) 98 | return 0xffffffff; 99 | 100 | CriticalSectionLock lock(&m_sheetCriticalSection); 101 | 102 | if(m_closed) 103 | return 0xffffffff; 104 | if(m_glyphCount >= m_maxGlyphCount) 105 | return 0xffffffff; 106 | 107 | const UINT &width = pGlyphMetrics->Width; 108 | const UINT &height = pGlyphMetrics->Height; 109 | 110 | // Position the glyph if it fits 111 | UINT blockWidth = width / m_alignWidth + 1; 112 | if(width % m_alignWidth != 0) 113 | ++blockWidth; 114 | UINT blockHeight = height / m_alignWidth + 1; 115 | if(height % m_alignWidth != 0) 116 | ++blockHeight; 117 | 118 | UINT blockX; 119 | UINT blockY; 120 | UINT positionX; 121 | UINT positionY; 122 | 123 | if(m_glyphCount > 0 || !m_allowOversizedGlyph) { 124 | if(m_alignWidth + width + m_alignWidth > m_sheetWidth) 125 | return 0xffffffff; 126 | 127 | // Position the glyph at the lowest Y possible (fills reasonably well with different sized glyphs) 128 | blockX = m_heightRange->findMin(blockWidth, &blockY); 129 | 130 | positionX = m_alignWidth + blockX * m_alignWidth; 131 | positionY = m_alignWidth + blockY * m_alignWidth; 132 | 133 | if(positionY + height + m_alignWidth > m_sheetHeight) 134 | return 0xffffffff; 135 | } 136 | else { 137 | blockX = 0; 138 | blockY = 0; 139 | 140 | positionX = m_alignWidth; 141 | positionY = m_alignWidth; 142 | } 143 | 144 | m_heightRange->update(blockX, blockWidth, blockY + blockHeight); 145 | 146 | // Store glyph coordinates 147 | FLOAT coordOffset = static_cast(m_alignWidth) * 0.5f; 148 | 149 | UINT alignedWidth = (blockWidth - 1) * m_alignWidth; 150 | UINT alignedHeight = (blockHeight - 1) * m_alignWidth; 151 | 152 | FW1_GLYPHCOORDS glyphCoords; 153 | glyphCoords.TexCoordLeft = (static_cast(positionX) - coordOffset) / static_cast(m_sheetWidth); 154 | glyphCoords.TexCoordTop = (static_cast(positionY) - coordOffset) / static_cast(m_sheetHeight); 155 | glyphCoords.TexCoordRight = 156 | (static_cast(positionX + alignedWidth) + coordOffset) / static_cast(m_sheetWidth); 157 | glyphCoords.TexCoordBottom = 158 | (static_cast(positionY + alignedHeight) + coordOffset) / static_cast(m_sheetHeight); 159 | glyphCoords.PositionLeft = pGlyphMetrics->OffsetX - coordOffset; 160 | glyphCoords.PositionTop = pGlyphMetrics->OffsetY - coordOffset; 161 | glyphCoords.PositionRight = pGlyphMetrics->OffsetX + static_cast(alignedWidth) + coordOffset; 162 | glyphCoords.PositionBottom = pGlyphMetrics->OffsetY + static_cast(alignedHeight) + coordOffset; 163 | 164 | UINT glyphIndex = m_glyphCount; 165 | 166 | m_glyphCoords[glyphIndex] = glyphCoords; 167 | 168 | // Glyph pixels 169 | for(UINT i=0; i < height && i < m_sheetHeight-positionY; ++i) { 170 | const UINT8 *src = static_cast(pGlyphData) + i*RowPitch; 171 | UINT8 *dst = m_textureData + (positionY+i)*m_sheetWidth + positionX; 172 | for(UINT j=0; j < width && j < m_sheetWidth-positionX; ++j) 173 | dst[j] = src[j*PixelStride]; 174 | } 175 | 176 | // Update dirty rect to be flushed to device texture 177 | if(m_updatedGlyphCount == 0) { 178 | m_dirtyRect.left = positionX - m_alignWidth; 179 | m_dirtyRect.top = positionY - m_alignWidth; 180 | m_dirtyRect.right = std::min(positionX + width + m_alignWidth, m_sheetWidth); 181 | m_dirtyRect.bottom = std::min(positionY + height + m_alignWidth, m_sheetHeight); 182 | } 183 | else { 184 | m_dirtyRect.left = std::min(m_dirtyRect.left, positionX - m_alignWidth); 185 | m_dirtyRect.top = std::min(m_dirtyRect.top, positionY - m_alignWidth); 186 | m_dirtyRect.right = std::min(std::max(m_dirtyRect.right, positionX + width + m_alignWidth), m_sheetWidth); 187 | m_dirtyRect.bottom = std::min(std::max(m_dirtyRect.bottom, positionY + height + m_alignWidth), m_sheetHeight); 188 | } 189 | 190 | _WriteBarrier(); 191 | MemoryBarrier(); 192 | 193 | ++m_glyphCount; 194 | ++m_updatedGlyphCount; 195 | 196 | return glyphIndex; 197 | } 198 | 199 | 200 | // Disallow insertion of additional glyphs in this sheet 201 | void STDMETHODCALLTYPE CFW1GlyphSheet::CloseSheet() { 202 | EnterCriticalSection(&m_sheetCriticalSection); 203 | m_closed = true; 204 | LeaveCriticalSection(&m_sheetCriticalSection); 205 | } 206 | 207 | 208 | // Flush any inserted glyphs 209 | void STDMETHODCALLTYPE CFW1GlyphSheet::Flush(ID3D11DeviceContext *pContext) { 210 | EnterCriticalSection(&m_flushCriticalSection); 211 | if(!m_static) { 212 | EnterCriticalSection(&m_sheetCriticalSection); 213 | 214 | UINT glyphCount = m_glyphCount; 215 | RectUI dirtyRect = m_dirtyRect; 216 | 217 | UINT updatedGlyphCount = m_updatedGlyphCount; 218 | m_updatedGlyphCount = 0; 219 | 220 | if(m_closed) 221 | m_static = true; 222 | 223 | LeaveCriticalSection(&m_sheetCriticalSection); 224 | 225 | if(updatedGlyphCount > 0) { 226 | // Update coord buffer 227 | if(m_hardwareCoordBuffer) { 228 | UINT startIndex = glyphCount - updatedGlyphCount; 229 | UINT endIndex = glyphCount; 230 | 231 | D3D11_BOX dstBox; 232 | ZeroMemory(&dstBox, sizeof(dstBox)); 233 | dstBox.left = startIndex * sizeof(FW1_GLYPHCOORDS); 234 | dstBox.right = endIndex * sizeof(FW1_GLYPHCOORDS); 235 | dstBox.top = 0; 236 | dstBox.bottom = 1; 237 | dstBox.front = 0; 238 | dstBox.back = 1; 239 | 240 | pContext->UpdateSubresource( 241 | m_pCoordBuffer, 242 | 0, 243 | &dstBox, 244 | m_glyphCoords + startIndex, 245 | 0, 246 | 0 247 | ); 248 | } 249 | 250 | // Update texture 251 | if(dirtyRect.right > dirtyRect.left && dirtyRect.bottom > dirtyRect.top) { 252 | UINT8 *srcMem = m_textureData; 253 | 254 | D3D11_BOX dstBox; 255 | ZeroMemory(&dstBox, sizeof(dstBox)); 256 | dstBox.left = dirtyRect.left; 257 | dstBox.right = dirtyRect.right; 258 | dstBox.top = dirtyRect.top; 259 | dstBox.bottom = dirtyRect.bottom; 260 | dstBox.front = 0; 261 | dstBox.back = 1; 262 | 263 | // Update each mip-level 264 | for(UINT i=0; i < m_mipLevelCount; ++i) { 265 | pContext->UpdateSubresource( 266 | m_pTexture, 267 | D3D11CalcSubresource(i, 0, m_mipLevelCount), 268 | &dstBox, 269 | srcMem + dstBox.top * (m_sheetWidth >> i) + dstBox.left, 270 | m_sheetWidth >> i, 271 | 0 272 | ); 273 | 274 | if(i+1 < m_mipLevelCount) { 275 | UINT8 *nextMip = srcMem + (m_sheetWidth >> i) * (m_sheetHeight >> i); 276 | 277 | dstBox.left >>= 1; 278 | dstBox.right >>= 1; 279 | dstBox.top >>= 1; 280 | dstBox.bottom >>= 1; 281 | 282 | // Calculate the next mip-level for the current dirty-rect 283 | for(UINT j = dstBox.top; j < dstBox.bottom; ++j) { 284 | const UINT8 *src0 = srcMem + j * 2 * (m_sheetWidth >> i); 285 | const UINT8 *src1 = src0 + (m_sheetWidth >> i); 286 | UINT8 *dst = nextMip + j * (m_sheetWidth >> (i+1)); 287 | 288 | for(UINT k = dstBox.left; k < dstBox.right; ++k) { 289 | UINT src = src0[k*2] + src0[k*2+1] + src1[k*2] + src1[k*2+1]; 290 | dst[k] = static_cast(src >> 2); 291 | } 292 | } 293 | 294 | srcMem = nextMip; 295 | } 296 | } 297 | } 298 | } 299 | 300 | // This sheet is now static, save some memory 301 | if(m_static) { 302 | delete[] m_textureData; 303 | m_textureData = 0; 304 | } 305 | } 306 | 307 | LeaveCriticalSection(&m_flushCriticalSection); 308 | } 309 | 310 | 311 | }// namespace FW1FontWrapper 312 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphVertexDrawer.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphVertexDrawer.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphVertexDrawer.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1GlyphVertexDrawer::CFW1GlyphVertexDrawer() : 15 | m_pDevice(NULL), 16 | 17 | m_pVertexBuffer(NULL), 18 | m_pIndexBuffer(NULL), 19 | m_vertexBufferSize(0), 20 | m_maxIndexCount(0) 21 | { 22 | } 23 | 24 | 25 | // Destruct 26 | CFW1GlyphVertexDrawer::~CFW1GlyphVertexDrawer() { 27 | SAFE_RELEASE(m_pDevice); 28 | 29 | SAFE_RELEASE(m_pVertexBuffer); 30 | SAFE_RELEASE(m_pIndexBuffer); 31 | } 32 | 33 | 34 | // Init 35 | HRESULT CFW1GlyphVertexDrawer::initVertexDrawer( 36 | IFW1Factory *pFW1Factory, 37 | ID3D11Device *pDevice, 38 | UINT vertexBufferSize 39 | ) { 40 | HRESULT hResult = initBaseObject(pFW1Factory); 41 | if(FAILED(hResult)) 42 | return hResult; 43 | 44 | if(pDevice == NULL) 45 | return E_INVALIDARG; 46 | 47 | pDevice->AddRef(); 48 | m_pDevice = pDevice; 49 | D3D_FEATURE_LEVEL featureLevel = m_pDevice->GetFeatureLevel(); 50 | 51 | m_vertexBufferSize = 4096 * 16; 52 | if(vertexBufferSize >= 1024) { 53 | if(featureLevel < D3D_FEATURE_LEVEL_9_2) 54 | vertexBufferSize = std::min(vertexBufferSize, 512U*1024U); 55 | m_vertexBufferSize = vertexBufferSize; 56 | } 57 | 58 | m_maxIndexCount = (m_vertexBufferSize * 3) / (2 * sizeof(QuadVertex)); 59 | if(m_maxIndexCount < 64) 60 | m_maxIndexCount = 64; 61 | 62 | // Create device buffers 63 | hResult = createBuffers(); 64 | 65 | if(SUCCEEDED(hResult)) 66 | hResult = S_OK; 67 | 68 | return hResult; 69 | } 70 | 71 | 72 | // Create vertex/index buffers 73 | HRESULT CFW1GlyphVertexDrawer::createBuffers() { 74 | // Create vertex buffer 75 | D3D11_BUFFER_DESC vertexBufferDesc; 76 | ID3D11Buffer *pVertexBuffer; 77 | 78 | ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); 79 | vertexBufferDesc.ByteWidth = m_vertexBufferSize; 80 | vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; 81 | vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 82 | vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 83 | 84 | HRESULT hResult = m_pDevice->CreateBuffer(&vertexBufferDesc, NULL, &pVertexBuffer); 85 | if(FAILED(hResult)) { 86 | m_lastError = L"Failed to create vertex buffer"; 87 | } 88 | else { 89 | // Create index buffer 90 | D3D11_BUFFER_DESC indexBufferDesc; 91 | D3D11_SUBRESOURCE_DATA initData; 92 | ID3D11Buffer *pIndexBuffer; 93 | 94 | ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); 95 | indexBufferDesc.ByteWidth = sizeof(UINT16) * m_maxIndexCount; 96 | indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; 97 | indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; 98 | 99 | UINT16 *indices = new UINT16[m_maxIndexCount]; 100 | for(UINT i=0; i < m_maxIndexCount/6; ++i) { 101 | indices[i*6] = static_cast(i*4); 102 | indices[i*6+1] = static_cast(i*4+1); 103 | indices[i*6+2] = static_cast(i*4+2); 104 | indices[i*6+3] = static_cast(i*4+1); 105 | indices[i*6+4] = static_cast(i*4+3); 106 | indices[i*6+5] = static_cast(i*4+2); 107 | } 108 | 109 | ZeroMemory(&initData, sizeof(initData)); 110 | initData.pSysMem = indices; 111 | 112 | hResult = m_pDevice->CreateBuffer(&indexBufferDesc, &initData, &pIndexBuffer); 113 | if(FAILED(hResult)) { 114 | m_lastError = L"Failed to create index buffer"; 115 | } 116 | else { 117 | // Success 118 | m_pVertexBuffer = pVertexBuffer; 119 | m_pIndexBuffer = pIndexBuffer; 120 | 121 | hResult = S_OK; 122 | } 123 | 124 | delete[] indices; 125 | 126 | if(FAILED(hResult)) 127 | pVertexBuffer->Release(); 128 | } 129 | 130 | return hResult; 131 | } 132 | 133 | 134 | // Draw vertices 135 | UINT CFW1GlyphVertexDrawer::drawVertices( 136 | ID3D11DeviceContext *pContext, 137 | IFW1GlyphAtlas *pGlyphAtlas, 138 | const FW1_VERTEXDATA *vertexData, 139 | UINT preboundSheet 140 | ) { 141 | if(vertexData->SheetCount == 0 || vertexData->TotalVertexCount == 0) 142 | return preboundSheet; 143 | 144 | UINT maxVertexCount = m_vertexBufferSize / sizeof(FW1_GLYPHVERTEX); 145 | 146 | UINT currentSheet = 0; 147 | UINT activeSheet = preboundSheet; 148 | UINT currentVertex = 0; 149 | UINT nextSheetStart = vertexData->pVertexCounts[0]; 150 | 151 | while(currentVertex < vertexData->TotalVertexCount) { 152 | // Fill the vertex buffer 153 | UINT vertexCount = std::min(vertexData->TotalVertexCount - currentVertex, maxVertexCount); 154 | 155 | D3D11_MAPPED_SUBRESOURCE msr; 156 | HRESULT hResult = pContext->Map(m_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr); 157 | if(SUCCEEDED(hResult)) { 158 | CopyMemory(msr.pData, vertexData->pVertices + currentVertex, vertexCount * sizeof(FW1_GLYPHVERTEX)); 159 | 160 | pContext->Unmap(m_pVertexBuffer, 0); 161 | 162 | // Draw all glyphs in the buffer 163 | UINT drawnVertices = 0; 164 | while(drawnVertices < vertexCount) { 165 | while(currentVertex >= nextSheetStart) { 166 | ++currentSheet; 167 | nextSheetStart += vertexData->pVertexCounts[currentSheet]; 168 | } 169 | 170 | if(currentSheet != activeSheet) { 171 | // Bind sheet shader resources 172 | pGlyphAtlas->BindSheet(pContext, currentSheet, 0); 173 | activeSheet = currentSheet; 174 | } 175 | 176 | UINT drawCount = std::min(vertexCount - drawnVertices, nextSheetStart - currentVertex); 177 | pContext->Draw(drawCount, drawnVertices); 178 | 179 | drawnVertices += drawCount; 180 | currentVertex += drawCount; 181 | } 182 | } 183 | else 184 | break; 185 | } 186 | 187 | return activeSheet; 188 | } 189 | 190 | 191 | // Draw vertices as quads 192 | UINT CFW1GlyphVertexDrawer::drawGlyphsAsQuads( 193 | ID3D11DeviceContext *pContext, 194 | IFW1GlyphAtlas *pGlyphAtlas, 195 | const FW1_VERTEXDATA *vertexData, 196 | UINT preboundSheet 197 | ) { 198 | if(vertexData->SheetCount == 0 || vertexData->TotalVertexCount == 0) 199 | return preboundSheet; 200 | 201 | UINT maxVertexCount = m_vertexBufferSize / sizeof(QuadVertex); 202 | if(maxVertexCount > 4 * (m_maxIndexCount / 6)) 203 | maxVertexCount = 4 * (m_maxIndexCount / 6); 204 | if(maxVertexCount % 4 != 0) 205 | maxVertexCount -= (maxVertexCount % 4); 206 | 207 | UINT currentSheet = 0; 208 | UINT activeSheet = preboundSheet; 209 | const FW1_GLYPHCOORDS *sheetGlyphCoords = 0; 210 | if(activeSheet < vertexData->SheetCount) 211 | sheetGlyphCoords = pGlyphAtlas->GetGlyphCoords(activeSheet); 212 | UINT currentVertex = 0; 213 | UINT nextSheetStart = vertexData->pVertexCounts[0]; 214 | 215 | while(currentVertex < vertexData->TotalVertexCount) { 216 | // Fill the vertex buffer 217 | UINT vertexCount = std::min((vertexData->TotalVertexCount - currentVertex) * 4, maxVertexCount); 218 | 219 | D3D11_MAPPED_SUBRESOURCE msr; 220 | HRESULT hResult = pContext->Map(m_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr); 221 | if(SUCCEEDED(hResult)) { 222 | QuadVertex *bufferVertices = static_cast(msr.pData); 223 | 224 | // Convert to quads when filling the buffer 225 | UINT savedCurrentSheet = currentSheet; 226 | UINT savedActiveSheet = activeSheet; 227 | UINT savedNextSheetStart = nextSheetStart; 228 | UINT savedCurrentVertex = currentVertex; 229 | 230 | UINT drawnVertices = 0; 231 | while(drawnVertices < vertexCount) { 232 | while(currentVertex >= nextSheetStart) { 233 | ++currentSheet; 234 | nextSheetStart += vertexData->pVertexCounts[currentSheet]; 235 | } 236 | 237 | if(currentSheet != activeSheet) { 238 | sheetGlyphCoords = pGlyphAtlas->GetGlyphCoords(currentSheet); 239 | activeSheet = currentSheet; 240 | } 241 | 242 | UINT drawCount = std::min(vertexCount - drawnVertices, (nextSheetStart - currentVertex) * 4); 243 | 244 | for(UINT i=0; i < drawCount/4; ++i) { 245 | FW1_GLYPHVERTEX glyphVertex = vertexData->pVertices[currentVertex + i]; 246 | glyphVertex.PositionX = glyphVertex.PositionX; 247 | glyphVertex.PositionY = glyphVertex.PositionY; 248 | 249 | const FW1_GLYPHCOORDS &glyphCoords = sheetGlyphCoords[glyphVertex.GlyphIndex]; 250 | 251 | QuadVertex quadVertex; 252 | 253 | quadVertex.color = glyphVertex.GlyphColor; 254 | 255 | quadVertex.positionX = glyphVertex.PositionX + glyphCoords.PositionLeft; 256 | quadVertex.positionY = glyphVertex.PositionY + glyphCoords.PositionTop; 257 | quadVertex.texCoordX = glyphCoords.TexCoordLeft; 258 | quadVertex.texCoordY = glyphCoords.TexCoordTop; 259 | bufferVertices[drawnVertices + i*4 + 0] = quadVertex; 260 | 261 | quadVertex.positionX = glyphVertex.PositionX + glyphCoords.PositionRight; 262 | quadVertex.texCoordX = glyphCoords.TexCoordRight; 263 | bufferVertices[drawnVertices + i*4 + 1] = quadVertex; 264 | 265 | quadVertex.positionY = glyphVertex.PositionY + glyphCoords.PositionBottom; 266 | quadVertex.texCoordY = glyphCoords.TexCoordBottom; 267 | bufferVertices[drawnVertices + i*4 + 3] = quadVertex; 268 | 269 | quadVertex.positionX = glyphVertex.PositionX + glyphCoords.PositionLeft; 270 | quadVertex.texCoordX = glyphCoords.TexCoordLeft; 271 | bufferVertices[drawnVertices + i*4 + 2] = quadVertex; 272 | } 273 | 274 | drawnVertices += drawCount; 275 | currentVertex += drawCount / 4; 276 | } 277 | 278 | pContext->Unmap(m_pVertexBuffer, 0); 279 | 280 | // Draw all glyphs in the buffer 281 | currentSheet = savedCurrentSheet; 282 | activeSheet = savedActiveSheet; 283 | nextSheetStart = savedNextSheetStart; 284 | currentVertex = savedCurrentVertex; 285 | 286 | drawnVertices = 0; 287 | while(drawnVertices < vertexCount) { 288 | while(currentVertex >= nextSheetStart) { 289 | ++currentSheet; 290 | nextSheetStart += vertexData->pVertexCounts[currentSheet]; 291 | } 292 | 293 | if(currentSheet != activeSheet) { 294 | // Bind sheet shader resources 295 | pGlyphAtlas->BindSheet(pContext, currentSheet, FW1_NOGEOMETRYSHADER); 296 | activeSheet = currentSheet; 297 | } 298 | 299 | UINT drawCount = std::min(vertexCount - drawnVertices, (nextSheetStart - currentVertex) * 4); 300 | pContext->DrawIndexed((drawCount/2)*3, 0, drawnVertices); 301 | 302 | drawnVertices += drawCount; 303 | currentVertex += drawCount / 4; 304 | } 305 | } 306 | else 307 | break; 308 | } 309 | 310 | return activeSheet; 311 | } 312 | 313 | 314 | }// namespace FW1FontWrapper 315 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphVertexDrawer.h: -------------------------------------------------------------------------------- 1 | // CFW1GlyphVertexDrawer.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1GlyphVertexDrawer 4 | #define IncludeGuard__FW1_CFW1GlyphVertexDrawer 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Draws glyph-vertices from system memory using a dynamic vertex buffer 13 | class CFW1GlyphVertexDrawer : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1GlyphVertexDrawer 19 | virtual HRESULT STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice); 20 | 21 | virtual UINT STDMETHODCALLTYPE DrawVertices( 22 | ID3D11DeviceContext *pContext, 23 | IFW1GlyphAtlas *pGlyphAtlas, 24 | const FW1_VERTEXDATA *pVertexData, 25 | UINT Flags, 26 | UINT PreboundSheet 27 | ); 28 | 29 | // Public functions 30 | public: 31 | CFW1GlyphVertexDrawer(); 32 | 33 | HRESULT initVertexDrawer(IFW1Factory *pFW1Factory, ID3D11Device *pDevice, UINT vertexBufferSize); 34 | 35 | // Internal types 36 | private: 37 | struct QuadVertex { 38 | FLOAT positionX; 39 | FLOAT positionY; 40 | FLOAT texCoordX; 41 | FLOAT texCoordY; 42 | UINT32 color; 43 | }; 44 | 45 | // Internal functions 46 | private: 47 | virtual ~CFW1GlyphVertexDrawer(); 48 | 49 | HRESULT createBuffers(); 50 | 51 | UINT drawVertices( 52 | ID3D11DeviceContext *pContext, 53 | IFW1GlyphAtlas *pGlyphAtlas, 54 | const FW1_VERTEXDATA *vertexData, 55 | UINT preboundSheet 56 | ); 57 | UINT drawGlyphsAsQuads( 58 | ID3D11DeviceContext *pContext, 59 | IFW1GlyphAtlas *pGlyphAtlas, 60 | const FW1_VERTEXDATA *vertexData, 61 | UINT preboundSheet 62 | ); 63 | 64 | // Internal data 65 | private: 66 | std::wstring m_lastError; 67 | 68 | ID3D11Device *m_pDevice; 69 | 70 | ID3D11Buffer *m_pVertexBuffer; 71 | ID3D11Buffer *m_pIndexBuffer; 72 | UINT m_vertexBufferSize; 73 | UINT m_maxIndexCount; 74 | }; 75 | 76 | 77 | }// namespace FW1FontWrapper 78 | 79 | 80 | #endif// IncludeGuard__FW1_CFW1GlyphVertexDrawer 81 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1GlyphVertexDrawerInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1GlyphVertexDrawerInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1GlyphVertexDrawer.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1GlyphVertexDrawer::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1GlyphVertexDrawer))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Get the D3D11 device used by this vetex drawer 27 | HRESULT STDMETHODCALLTYPE CFW1GlyphVertexDrawer::GetDevice(ID3D11Device **ppDevice) { 28 | if(ppDevice == NULL) 29 | return E_INVALIDARG; 30 | 31 | m_pDevice->AddRef(); 32 | *ppDevice = m_pDevice; 33 | 34 | return S_OK; 35 | } 36 | 37 | 38 | // Draw vertices 39 | UINT STDMETHODCALLTYPE CFW1GlyphVertexDrawer::DrawVertices( 40 | ID3D11DeviceContext *pContext, 41 | IFW1GlyphAtlas *pGlyphAtlas, 42 | const FW1_VERTEXDATA *pVertexData, 43 | UINT Flags, 44 | UINT PreboundSheet 45 | ) { 46 | UINT stride; 47 | UINT offset = 0; 48 | 49 | if((Flags & FW1_NOGEOMETRYSHADER) == 0) 50 | stride = sizeof(FW1_GLYPHVERTEX); 51 | else { 52 | stride = sizeof(QuadVertex); 53 | if((Flags & FW1_BUFFERSPREPARED) == 0) 54 | pContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); 55 | } 56 | if((Flags & FW1_BUFFERSPREPARED) == 0) 57 | pContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset); 58 | 59 | if((Flags & FW1_NOGEOMETRYSHADER) == 0) 60 | return drawVertices(pContext, pGlyphAtlas, pVertexData, PreboundSheet); 61 | else 62 | return drawGlyphsAsQuads(pContext, pGlyphAtlas, pVertexData, PreboundSheet); 63 | } 64 | 65 | 66 | }// namespace FW1FontWrapper 67 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1Object.h: -------------------------------------------------------------------------------- 1 | // CFW1Object.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1Object 4 | #define IncludeGuard__FW1_CFW1Object 5 | 6 | 7 | namespace FW1FontWrapper { 8 | 9 | 10 | // Helper baseclass to avoid writing IUnknown and IFW1Object implementations once per class 11 | template 12 | class CFW1Object : public IBase { 13 | public: 14 | // IUnknown 15 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) = 0 { 16 | if(ppvObject == NULL) 17 | return E_INVALIDARG; 18 | 19 | if(IsEqualIID(riid, __uuidof(IUnknown))) { 20 | *ppvObject = static_cast(this); 21 | AddRef(); 22 | return S_OK; 23 | } 24 | else if(IsEqualIID(riid, __uuidof(IFW1Object))) { 25 | *ppvObject = static_cast(this); 26 | AddRef(); 27 | return S_OK; 28 | } 29 | 30 | *ppvObject = NULL; 31 | return E_NOINTERFACE; 32 | } 33 | 34 | virtual ULONG STDMETHODCALLTYPE AddRef() { 35 | return static_cast(InterlockedIncrement(reinterpret_cast(&m_cRefCount))); 36 | } 37 | 38 | virtual ULONG STDMETHODCALLTYPE Release() { 39 | ULONG newCount = static_cast(InterlockedDecrement(reinterpret_cast(&m_cRefCount))); 40 | 41 | if(newCount == 0) 42 | delete this; 43 | 44 | return newCount; 45 | } 46 | 47 | // IFW1Object 48 | virtual HRESULT STDMETHODCALLTYPE GetFactory(IFW1Factory **ppFW1Factory) { 49 | if(ppFW1Factory == NULL) 50 | return E_INVALIDARG; 51 | 52 | m_pFW1Factory->AddRef(); 53 | *ppFW1Factory = m_pFW1Factory; 54 | 55 | return S_OK; 56 | } 57 | 58 | // Internal functions 59 | protected: 60 | CFW1Object() : 61 | m_cRefCount(1), 62 | 63 | m_pFW1Factory(NULL) 64 | { 65 | } 66 | 67 | virtual ~CFW1Object() { 68 | if(m_pFW1Factory != NULL) 69 | m_pFW1Factory->Release(); 70 | } 71 | 72 | HRESULT initBaseObject(IFW1Factory *pFW1Factory) { 73 | if(pFW1Factory == NULL) 74 | return E_INVALIDARG; 75 | 76 | pFW1Factory->AddRef(); 77 | m_pFW1Factory = pFW1Factory; 78 | 79 | return S_OK; 80 | } 81 | 82 | // Internal data 83 | protected: 84 | IFW1Factory *m_pFW1Factory; 85 | 86 | private: 87 | ULONG m_cRefCount; 88 | 89 | private: 90 | CFW1Object(const CFW1Object&); 91 | CFW1Object& operator=(const CFW1Object&); 92 | }; 93 | 94 | 95 | }// namespace FW1FontWrapper 96 | 97 | 98 | #endif// IncludeGuard__FW1_CFW1Object 99 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1StateSaver.cpp: -------------------------------------------------------------------------------- 1 | // CFW1StateSaver.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1StateSaver.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1StateSaver::CFW1StateSaver() : 15 | m_savedState(false), 16 | m_featureLevel(D3D_FEATURE_LEVEL_11_0), 17 | m_pContext(NULL), 18 | m_primitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED), 19 | m_pInputLayout(NULL), 20 | m_pBlendState(NULL), 21 | m_sampleMask(0xffffffff), 22 | m_pDepthStencilState(NULL), 23 | m_stencilRef(0), 24 | m_pRasterizerState(NULL), 25 | m_pPSSRV(NULL), 26 | m_pSamplerState(NULL), 27 | m_pVS(NULL), 28 | m_numVSClassInstances(0), 29 | m_pVSConstantBuffer(NULL), 30 | m_pGS(NULL), 31 | m_numGSClassInstances(0), 32 | m_pGSConstantBuffer(NULL), 33 | m_pGSSRV(NULL), 34 | m_pPS(NULL), 35 | m_numPSClassInstances(0), 36 | m_pHS(NULL), 37 | m_numHSClassInstances(0), 38 | m_pDS(NULL), 39 | m_numDSClassInstances(0), 40 | m_pVB(NULL), 41 | m_vertexStride(0), 42 | m_vertexOffset(0), 43 | m_pIndexBuffer(NULL), 44 | m_indexFormat(DXGI_FORMAT_UNKNOWN), 45 | m_indexOffset(0) 46 | { 47 | for(int i=0; i < 4; ++i) 48 | m_blendFactor[i] = 0.0f; 49 | for(int i=0; i < 256; ++i) { 50 | m_pVSClassInstances[i] = NULL; 51 | m_pGSClassInstances[i] = NULL; 52 | m_pPSClassInstances[i] = NULL; 53 | m_pHSClassInstances[i] = NULL; 54 | m_pDSClassInstances[i] = NULL; 55 | } 56 | } 57 | 58 | 59 | // Destruct 60 | CFW1StateSaver::~CFW1StateSaver() { 61 | releaseSavedState(); 62 | } 63 | 64 | 65 | // Save all states that are changed by the font-wrapper when drawing a string 66 | HRESULT CFW1StateSaver::saveCurrentState(ID3D11DeviceContext *pContext) { 67 | if(m_savedState) 68 | releaseSavedState(); 69 | if(pContext == NULL) 70 | return E_INVALIDARG; 71 | 72 | ID3D11Device *pDevice; 73 | pContext->GetDevice(&pDevice); 74 | if(pDevice != NULL) { 75 | m_featureLevel = pDevice->GetFeatureLevel(); 76 | pDevice->Release(); 77 | } 78 | 79 | pContext->AddRef(); 80 | m_pContext = pContext; 81 | 82 | m_pContext->IAGetPrimitiveTopology(&m_primitiveTopology); 83 | m_pContext->IAGetInputLayout(&m_pInputLayout); 84 | 85 | m_pContext->OMGetBlendState(&m_pBlendState, m_blendFactor, &m_sampleMask); 86 | m_pContext->OMGetDepthStencilState(&m_pDepthStencilState, &m_stencilRef); 87 | 88 | m_pContext->RSGetState(&m_pRasterizerState); 89 | 90 | m_numVSClassInstances = 256; 91 | m_pContext->VSGetShader(&m_pVS, m_pVSClassInstances, &m_numVSClassInstances); 92 | m_pContext->VSGetConstantBuffers(0, 1, &m_pVSConstantBuffer); 93 | 94 | m_numPSClassInstances = 256; 95 | m_pContext->PSGetShader(&m_pPS, m_pPSClassInstances, &m_numPSClassInstances); 96 | m_pContext->PSGetShaderResources(0, 1, &m_pPSSRV); 97 | pContext->PSGetSamplers(0, 1, &m_pSamplerState); 98 | 99 | if(m_featureLevel >= D3D_FEATURE_LEVEL_10_0) { 100 | m_numGSClassInstances = 256; 101 | m_pContext->GSGetShader(&m_pGS, m_pGSClassInstances, &m_numGSClassInstances); 102 | m_pContext->GSGetConstantBuffers(0, 1, &m_pGSConstantBuffer); 103 | 104 | m_pContext->GSGetShaderResources(0, 1, &m_pGSSRV); 105 | 106 | if(m_featureLevel >= D3D_FEATURE_LEVEL_11_0) { 107 | m_numHSClassInstances = 256; 108 | m_pContext->HSGetShader(&m_pHS, m_pHSClassInstances, &m_numHSClassInstances); 109 | 110 | m_numDSClassInstances = 256; 111 | m_pContext->DSGetShader(&m_pDS, m_pDSClassInstances, &m_numDSClassInstances); 112 | } 113 | } 114 | 115 | m_pContext->IAGetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); 116 | 117 | m_pContext->IAGetIndexBuffer(&m_pIndexBuffer, &m_indexFormat, &m_indexOffset); 118 | 119 | m_savedState = true; 120 | 121 | return S_OK; 122 | } 123 | 124 | 125 | // Restore state 126 | HRESULT CFW1StateSaver::restoreSavedState() { 127 | if(!m_savedState) 128 | return E_FAIL; 129 | 130 | m_pContext->IASetPrimitiveTopology(m_primitiveTopology); 131 | m_pContext->IASetInputLayout(m_pInputLayout); 132 | 133 | m_pContext->OMSetBlendState(m_pBlendState, m_blendFactor, m_sampleMask); 134 | m_pContext->OMSetDepthStencilState(m_pDepthStencilState, m_stencilRef); 135 | 136 | m_pContext->RSSetState(m_pRasterizerState); 137 | 138 | m_pContext->VSSetShader(m_pVS, m_pVSClassInstances, m_numVSClassInstances); 139 | m_pContext->VSSetConstantBuffers(0, 1, &m_pVSConstantBuffer); 140 | 141 | m_pContext->PSSetShader(m_pPS, m_pPSClassInstances, m_numPSClassInstances); 142 | m_pContext->PSSetShaderResources(0, 1, &m_pPSSRV); 143 | m_pContext->PSSetSamplers(0, 1, &m_pSamplerState); 144 | 145 | if(m_featureLevel >= D3D_FEATURE_LEVEL_10_0) { 146 | m_pContext->GSSetShader(m_pGS, m_pGSClassInstances, m_numGSClassInstances); 147 | m_pContext->GSSetConstantBuffers(0, 1, &m_pGSConstantBuffer); 148 | 149 | m_pContext->GSSetShaderResources(0, 1, &m_pGSSRV); 150 | 151 | if(m_featureLevel >= D3D_FEATURE_LEVEL_11_0) { 152 | m_pContext->HSSetShader(m_pHS, m_pHSClassInstances, m_numHSClassInstances); 153 | 154 | m_pContext->DSSetShader(m_pDS, m_pDSClassInstances, m_numDSClassInstances); 155 | } 156 | } 157 | 158 | m_pContext->IASetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); 159 | 160 | m_pContext->IASetIndexBuffer(m_pIndexBuffer, m_indexFormat, m_indexOffset); 161 | 162 | return S_OK; 163 | } 164 | 165 | 166 | // Release state 167 | void CFW1StateSaver::releaseSavedState() { 168 | m_primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; 169 | SAFE_RELEASE(m_pInputLayout); 170 | SAFE_RELEASE(m_pBlendState); 171 | for(int i=0; i < 4; ++i) 172 | m_blendFactor[i] = 0.0f; 173 | m_sampleMask = 0xffffffff; 174 | SAFE_RELEASE(m_pDepthStencilState); 175 | m_stencilRef = 0; 176 | SAFE_RELEASE(m_pRasterizerState); 177 | SAFE_RELEASE(m_pPSSRV); 178 | SAFE_RELEASE(m_pSamplerState); 179 | SAFE_RELEASE(m_pVS); 180 | for(UINT i=0; i < m_numVSClassInstances; ++i) 181 | SAFE_RELEASE(m_pVSClassInstances[i]); 182 | m_numVSClassInstances = 0; 183 | SAFE_RELEASE(m_pVSConstantBuffer); 184 | SAFE_RELEASE(m_pGS); 185 | for(UINT i=0; i < m_numGSClassInstances; ++i) 186 | SAFE_RELEASE(m_pGSClassInstances[i]); 187 | m_numGSClassInstances = 0; 188 | SAFE_RELEASE(m_pGSConstantBuffer); 189 | SAFE_RELEASE(m_pGSSRV); 190 | SAFE_RELEASE(m_pPS); 191 | for(UINT i=0; i < m_numPSClassInstances; ++i) 192 | SAFE_RELEASE(m_pPSClassInstances[i]); 193 | m_numPSClassInstances = 0; 194 | SAFE_RELEASE(m_pHS); 195 | for(UINT i=0; i < m_numHSClassInstances; ++i) 196 | SAFE_RELEASE(m_pHSClassInstances[i]); 197 | m_numHSClassInstances = 0; 198 | SAFE_RELEASE(m_pDS); 199 | for(UINT i=0; i < m_numDSClassInstances; ++i) 200 | SAFE_RELEASE(m_pDSClassInstances[i]); 201 | m_numDSClassInstances = 0; 202 | SAFE_RELEASE(m_pVB); 203 | m_vertexStride = 0; 204 | m_vertexOffset = 0; 205 | SAFE_RELEASE(m_pIndexBuffer); 206 | m_indexFormat = DXGI_FORMAT_UNKNOWN; 207 | m_indexOffset = 0; 208 | 209 | SAFE_RELEASE(m_pContext); 210 | m_featureLevel = D3D_FEATURE_LEVEL_11_0; 211 | 212 | m_savedState = false; 213 | } 214 | 215 | 216 | }// namespace FW1FontWrapper 217 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1StateSaver.h: -------------------------------------------------------------------------------- 1 | // CFW1StateSaver.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1StateSaver 4 | #define IncludeGuard__FW1_CFW1StateSaver 5 | 6 | 7 | namespace FW1FontWrapper { 8 | 9 | 10 | // Saves all the states that can be changed when drawing a string 11 | class CFW1StateSaver { 12 | // Public functions 13 | public: 14 | CFW1StateSaver(); 15 | ~CFW1StateSaver(); 16 | 17 | HRESULT saveCurrentState(ID3D11DeviceContext *pContext); 18 | HRESULT restoreSavedState(); 19 | void releaseSavedState(); 20 | 21 | // Internal data 22 | private: 23 | bool m_savedState; 24 | D3D_FEATURE_LEVEL m_featureLevel; 25 | ID3D11DeviceContext *m_pContext; 26 | D3D11_PRIMITIVE_TOPOLOGY m_primitiveTopology; 27 | ID3D11InputLayout *m_pInputLayout; 28 | ID3D11BlendState *m_pBlendState; 29 | FLOAT m_blendFactor[4]; 30 | UINT m_sampleMask; 31 | ID3D11DepthStencilState *m_pDepthStencilState; 32 | UINT m_stencilRef; 33 | ID3D11RasterizerState *m_pRasterizerState; 34 | ID3D11ShaderResourceView *m_pPSSRV; 35 | ID3D11SamplerState *m_pSamplerState; 36 | ID3D11VertexShader *m_pVS; 37 | ID3D11ClassInstance *m_pVSClassInstances[256]; 38 | UINT m_numVSClassInstances; 39 | ID3D11Buffer *m_pVSConstantBuffer; 40 | ID3D11GeometryShader *m_pGS; 41 | ID3D11ClassInstance *m_pGSClassInstances[256]; 42 | UINT m_numGSClassInstances; 43 | ID3D11Buffer *m_pGSConstantBuffer; 44 | ID3D11ShaderResourceView *m_pGSSRV; 45 | ID3D11PixelShader *m_pPS; 46 | ID3D11ClassInstance *m_pPSClassInstances[256]; 47 | UINT m_numPSClassInstances; 48 | ID3D11HullShader *m_pHS; 49 | ID3D11ClassInstance *m_pHSClassInstances[256]; 50 | UINT m_numHSClassInstances; 51 | ID3D11DomainShader *m_pDS; 52 | ID3D11ClassInstance *m_pDSClassInstances[256]; 53 | UINT m_numDSClassInstances; 54 | ID3D11Buffer *m_pVB; 55 | UINT m_vertexStride; 56 | UINT m_vertexOffset; 57 | ID3D11Buffer *m_pIndexBuffer; 58 | DXGI_FORMAT m_indexFormat; 59 | UINT m_indexOffset; 60 | 61 | private: 62 | CFW1StateSaver(const CFW1StateSaver&); 63 | CFW1StateSaver& operator=(const CFW1StateSaver&); 64 | }; 65 | 66 | 67 | }// namespace FW1FontWrapper 68 | 69 | 70 | #endif// IncludeGuard__FW1_CFW1StateSaver 71 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextGeometry.cpp: -------------------------------------------------------------------------------- 1 | // CFW1TextGeometry.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1TextGeometry.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Construct 12 | CFW1TextGeometry::CFW1TextGeometry() : 13 | m_maxSheetIndex(0), 14 | m_sorted(false) 15 | { 16 | } 17 | 18 | 19 | // Destruct 20 | CFW1TextGeometry::~CFW1TextGeometry() { 21 | } 22 | 23 | 24 | // Init glyph provider 25 | HRESULT CFW1TextGeometry::initTextGeometry(IFW1Factory *pFW1Factory) { 26 | HRESULT hResult = initBaseObject(pFW1Factory); 27 | if(FAILED(hResult)) 28 | return hResult; 29 | 30 | return hResult; 31 | } 32 | 33 | 34 | }// namespace FW1FontWrapper 35 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextGeometry.h: -------------------------------------------------------------------------------- 1 | // CFW1TextGeometry.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1TextGeometry 4 | #define IncludeGuard__FW1_CFW1TextGeometry 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Vector of vertices with sorting per glyph sheet 13 | class CFW1TextGeometry : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1TextGeometry 19 | virtual void STDMETHODCALLTYPE Clear(); 20 | virtual void STDMETHODCALLTYPE AddGlyphVertex(const FW1_GLYPHVERTEX *pVertex); 21 | 22 | virtual FW1_VERTEXDATA STDMETHODCALLTYPE GetGlyphVerticesTemp(); 23 | 24 | // Public functions 25 | public: 26 | CFW1TextGeometry(); 27 | 28 | HRESULT initTextGeometry(IFW1Factory *pFW1Factory); 29 | 30 | // Internal functions 31 | private: 32 | virtual ~CFW1TextGeometry(); 33 | 34 | // Internal data 35 | private: 36 | std::vector m_vertices; 37 | std::vector m_sortedVertices; 38 | 39 | UINT m_maxSheetIndex; 40 | std::vector m_vertexCounts; 41 | std::vector m_vertexStartIndices; 42 | bool m_sorted; 43 | }; 44 | 45 | 46 | }// namespace FW1FontWrapper 47 | 48 | 49 | #endif// IncludeGuard__FW1_CFW1TextGeometry 50 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextGeometryInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1TextGeometryInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1TextGeometry.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1TextGeometry::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IFW1TextGeometry))) { 17 | *ppvObject = static_cast(this); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | 22 | return CFW1Object::QueryInterface(riid, ppvObject); 23 | } 24 | 25 | 26 | // Clear geometry 27 | void STDMETHODCALLTYPE CFW1TextGeometry::Clear() { 28 | m_vertices.clear(); 29 | m_maxSheetIndex = 0; 30 | 31 | m_sorted = false; 32 | } 33 | 34 | 35 | // Add a vertex 36 | void STDMETHODCALLTYPE CFW1TextGeometry::AddGlyphVertex(const FW1_GLYPHVERTEX *pVertex) { 37 | m_vertices.push_back(*pVertex); 38 | 39 | UINT sheetIndex = pVertex->GlyphIndex >> 16; 40 | m_maxSheetIndex = std::max(m_maxSheetIndex, sheetIndex); 41 | 42 | m_sorted = false; 43 | } 44 | 45 | 46 | // Get current glyph vertices 47 | FW1_VERTEXDATA STDMETHODCALLTYPE CFW1TextGeometry::GetGlyphVerticesTemp() { 48 | FW1_VERTEXDATA vertexData; 49 | 50 | if(!m_vertices.empty()) { 51 | UINT32 sheetCount = m_maxSheetIndex + 1; 52 | 53 | // Sort and prepare vertices 54 | if(!m_sorted) { 55 | m_sortedVertices.resize(m_vertices.size()); 56 | m_vertexCounts.resize(sheetCount); 57 | m_vertexStartIndices.resize(sheetCount); 58 | 59 | std::fill(m_vertexCounts.begin(), m_vertexCounts.end(), 0); 60 | 61 | UINT * const vertexCounts = &m_vertexCounts[0]; 62 | const FW1_GLYPHVERTEX * const vertices = &m_vertices[0]; 63 | const UINT32 vertexCount = static_cast(m_vertices.size()); 64 | 65 | for(UINT32 i=0; i < vertexCount; ++i) { 66 | UINT32 sheetIndex = vertices[i].GlyphIndex >> 16; 67 | 68 | ++vertexCounts[sheetIndex]; 69 | } 70 | 71 | UINT * const vertexStartIndices = &m_vertexStartIndices[0]; 72 | 73 | UINT currentStartIndex = 0; 74 | for(UINT32 i=0; i < sheetCount; ++i) { 75 | vertexStartIndices[i] = currentStartIndex; 76 | 77 | currentStartIndex += vertexCounts[i]; 78 | } 79 | 80 | FW1_GLYPHVERTEX * const sortedVertices = &m_sortedVertices[0]; 81 | 82 | for(UINT32 i=0; i < vertexCount; ++i) { 83 | const FW1_GLYPHVERTEX &vertex = vertices[i]; 84 | UINT32 sheetIndex = vertex.GlyphIndex >> 16; 85 | 86 | UINT &vertexIndex = vertexStartIndices[sheetIndex]; 87 | 88 | sortedVertices[vertexIndex] = vertex; 89 | sortedVertices[vertexIndex].GlyphIndex &= 0xffff; 90 | 91 | ++vertexIndex; 92 | } 93 | 94 | m_sorted = true; 95 | } 96 | 97 | vertexData.SheetCount = sheetCount; 98 | vertexData.pVertexCounts = &m_vertexCounts[0]; 99 | vertexData.TotalVertexCount = static_cast(m_vertices.size()); 100 | vertexData.pVertices = &m_sortedVertices[0]; 101 | } 102 | else { 103 | vertexData.SheetCount = 0; 104 | vertexData.pVertexCounts = 0; 105 | vertexData.TotalVertexCount = 0; 106 | vertexData.pVertices = 0; 107 | } 108 | 109 | return vertexData; 110 | } 111 | 112 | 113 | }// namespace FW1FontWrapper 114 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextRenderer.cpp: -------------------------------------------------------------------------------- 1 | // CFW1TextRenderer.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1TextRenderer.h" 6 | 7 | #define SAFE_RELEASE(pObject) { if(pObject) { (pObject)->Release(); (pObject) = NULL; } } 8 | 9 | 10 | namespace FW1FontWrapper { 11 | 12 | 13 | // Construct 14 | CFW1TextRenderer::CFW1TextRenderer() : 15 | m_pGlyphProvider(NULL), 16 | 17 | m_currentFlags(0), 18 | m_currentColor(0xff000000), 19 | 20 | m_cachedGlyphMap(0), 21 | m_pCachedGlyphMapFontFace(NULL), 22 | m_cachedGlyphMapFontSize(0), 23 | 24 | m_pDWriteTextRendererProxy(0) 25 | { 26 | } 27 | 28 | 29 | // Destruct 30 | CFW1TextRenderer::~CFW1TextRenderer() { 31 | SAFE_RELEASE(m_pGlyphProvider); 32 | 33 | delete m_pDWriteTextRendererProxy; 34 | } 35 | 36 | 37 | // Init 38 | HRESULT CFW1TextRenderer::initTextRenderer( 39 | IFW1Factory *pFW1Factory, 40 | IFW1GlyphProvider *pGlyphProvider 41 | ) { 42 | HRESULT hResult = initBaseObject(pFW1Factory); 43 | if(FAILED(hResult)) 44 | return hResult; 45 | 46 | if(pGlyphProvider == NULL) 47 | return E_INVALIDARG; 48 | 49 | pGlyphProvider->AddRef(); 50 | m_pGlyphProvider = pGlyphProvider; 51 | 52 | m_pDWriteTextRendererProxy = new CDWriteTextRendererProxy(this); 53 | 54 | return S_OK; 55 | } 56 | 57 | 58 | }// namespace FW1FontWrapper 59 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextRenderer.h: -------------------------------------------------------------------------------- 1 | // CFW1TextRenderer.h 2 | 3 | #ifndef IncludeGuard__FW1_CFW1TextRenderer 4 | #define IncludeGuard__FW1_CFW1TextRenderer 5 | 6 | #include "CFW1Object.h" 7 | 8 | 9 | namespace FW1FontWrapper { 10 | 11 | 12 | // Converts a DWrite text layout to vertices 13 | class CFW1TextRenderer : public CFW1Object { 14 | public: 15 | // IUnknown 16 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); 17 | 18 | // IFW1DWriteTextRenderer 19 | virtual HRESULT STDMETHODCALLTYPE GetGlyphProvider(IFW1GlyphProvider **ppGlyphProvider); 20 | 21 | virtual HRESULT STDMETHODCALLTYPE DrawTextLayout( 22 | IDWriteTextLayout *pTextLayout, 23 | FLOAT OriginX, 24 | FLOAT OriginY, 25 | UINT32 Color, 26 | UINT Flags, 27 | IFW1TextGeometry *pTextGeometry 28 | ); 29 | 30 | // Public functions 31 | public: 32 | CFW1TextRenderer(); 33 | 34 | HRESULT initTextRenderer( 35 | IFW1Factory *pFW1Factory, 36 | IFW1GlyphProvider *pGlyphProvider 37 | ); 38 | 39 | // Internal functions 40 | private: 41 | virtual ~CFW1TextRenderer(); 42 | 43 | // IDWritePixelSnapping interface (called via proxy) 44 | HRESULT IsPixelSnappingDisabled(void *clientDrawingContext, BOOL *isDisabled); 45 | HRESULT GetCurrentTransform(void *clientDrawingContext, DWRITE_MATRIX *transform); 46 | HRESULT GetPixelsPerDip(void *clientDrawingContext, FLOAT *pixelsPerDip); 47 | 48 | // IDWriteTextRenderer interface (called via proxy) 49 | HRESULT DrawGlyphRun( 50 | void *clientDrawingContext, 51 | FLOAT baselineOriginX, 52 | FLOAT baselineOriginY, 53 | DWRITE_MEASURING_MODE measuringMode, 54 | const DWRITE_GLYPH_RUN *glyphRun, 55 | const DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription, 56 | IUnknown *clientDrawingEffect 57 | ); 58 | HRESULT DrawUnderline( 59 | void *clientDrawingContext, 60 | FLOAT baselineOriginX, 61 | FLOAT baselineOriginY, 62 | const DWRITE_UNDERLINE *underline, 63 | IUnknown *clientDrawingEffect 64 | ); 65 | HRESULT DrawStrikethrough( 66 | void *clientDrawingContext, 67 | FLOAT baselineOriginX, 68 | FLOAT baselineOriginY, 69 | const DWRITE_STRIKETHROUGH *strikethrough, 70 | IUnknown *clientDrawingEffect 71 | ); 72 | HRESULT DrawInlineObject( 73 | void *clientDrawingContext, 74 | FLOAT originX, 75 | FLOAT originY, 76 | IDWriteInlineObject *inlineObject, 77 | BOOL isSideways, 78 | BOOL isRightToLeft, 79 | IUnknown *clientDrawingEffect 80 | ); 81 | 82 | // Internal data 83 | private: 84 | IFW1GlyphProvider *m_pGlyphProvider; 85 | 86 | UINT m_currentFlags; 87 | UINT32 m_currentColor; 88 | 89 | const void *m_cachedGlyphMap; 90 | IDWriteFontFace *m_pCachedGlyphMapFontFace; 91 | FLOAT m_cachedGlyphMapFontSize; 92 | 93 | 94 | // Proxy for IDWriteTextRenderer interface 95 | private: 96 | class CDWriteTextRendererProxy : public IDWriteTextRenderer { 97 | public: 98 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { 99 | return m_realObject->QueryInterface(riid, ppvObject); 100 | } 101 | virtual ULONG STDMETHODCALLTYPE AddRef() { 102 | return m_realObject->AddRef(); 103 | } 104 | virtual ULONG STDMETHODCALLTYPE Release() { 105 | return m_realObject->Release(); 106 | } 107 | 108 | virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(void *clientDrawingContext, BOOL *isDisabled) { 109 | return m_realObject->IsPixelSnappingDisabled(clientDrawingContext, isDisabled); 110 | } 111 | virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(void *clientDrawingContext, DWRITE_MATRIX *transform) { 112 | return m_realObject->GetCurrentTransform(clientDrawingContext, transform); 113 | } 114 | virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(void *clientDrawingContext, FLOAT *pixelsPerDip) { 115 | return m_realObject->GetPixelsPerDip(clientDrawingContext, pixelsPerDip); 116 | } 117 | 118 | virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, const DWRITE_GLYPH_RUN *glyphRun, const DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription, IUnknown *clientDrawingEffect) { 119 | return m_realObject->DrawGlyphRun(clientDrawingContext, baselineOriginX, baselineOriginY, measuringMode, glyphRun, glyphRunDescription, clientDrawingEffect); 120 | } 121 | virtual HRESULT STDMETHODCALLTYPE DrawUnderline(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_UNDERLINE *underline, IUnknown *clientDrawingEffect) { 122 | return m_realObject->DrawUnderline(clientDrawingContext, baselineOriginX, baselineOriginY, underline, clientDrawingEffect); 123 | } 124 | virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *clientDrawingEffect) { 125 | return m_realObject->DrawStrikethrough(clientDrawingContext, baselineOriginX, baselineOriginY, strikethrough, clientDrawingEffect); 126 | } 127 | virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(void *clientDrawingContext, FLOAT originX, FLOAT originY, IDWriteInlineObject *inlineObject, BOOL isSideways, BOOL isRightToLeft, IUnknown *clientDrawingEffect) { 128 | return m_realObject->DrawInlineObject(clientDrawingContext, originX, originY, inlineObject, isSideways, isRightToLeft, clientDrawingEffect); 129 | } 130 | 131 | public: 132 | CDWriteTextRendererProxy(CFW1TextRenderer *realObject) : m_realObject(realObject) {} 133 | 134 | private: 135 | CDWriteTextRendererProxy(const CDWriteTextRendererProxy&); 136 | CDWriteTextRendererProxy& operator=(const CDWriteTextRendererProxy&); 137 | 138 | private: 139 | CFW1TextRenderer *m_realObject; 140 | } *m_pDWriteTextRendererProxy; 141 | }; 142 | 143 | 144 | }// namespace FW1FontWrapper 145 | 146 | 147 | #endif// IncludeGuard__FW1_CFW1TextRenderer 148 | -------------------------------------------------------------------------------- /FW1FontWrapper/CFW1TextRendererInterface.cpp: -------------------------------------------------------------------------------- 1 | // CFW1TextRendererInterface.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1TextRenderer.h" 6 | 7 | 8 | namespace FW1FontWrapper { 9 | 10 | 11 | // Query interface 12 | HRESULT STDMETHODCALLTYPE CFW1TextRenderer::QueryInterface(REFIID riid, void **ppvObject) { 13 | if(ppvObject == NULL) 14 | return E_INVALIDARG; 15 | 16 | if(IsEqualIID(riid, __uuidof(IDWritePixelSnapping))) { 17 | *ppvObject = static_cast(m_pDWriteTextRendererProxy); 18 | AddRef(); 19 | return S_OK; 20 | } 21 | else if(IsEqualIID(riid, __uuidof(IDWriteTextRenderer))) { 22 | *ppvObject = static_cast(m_pDWriteTextRendererProxy); 23 | AddRef(); 24 | return S_OK; 25 | } 26 | else if(IsEqualIID(riid, __uuidof(IFW1TextRenderer))) { 27 | *ppvObject = static_cast(this); 28 | AddRef(); 29 | return S_OK; 30 | } 31 | 32 | return CFW1Object::QueryInterface(riid, ppvObject); 33 | } 34 | 35 | 36 | // IDWritePixelSnapping method 37 | HRESULT CFW1TextRenderer::IsPixelSnappingDisabled( 38 | void *clientDrawingContext, 39 | BOOL *isDisabled 40 | ) { 41 | clientDrawingContext; 42 | 43 | *isDisabled = FALSE; 44 | 45 | return S_OK; 46 | } 47 | 48 | 49 | // IDWritePixelSnapping method 50 | HRESULT CFW1TextRenderer::GetCurrentTransform( 51 | void *clientDrawingContext, 52 | DWRITE_MATRIX *transform 53 | ) { 54 | clientDrawingContext; 55 | 56 | transform->dx = 0.0f; 57 | transform->dy = 0.0f; 58 | transform->m11 = 1.0f; 59 | transform->m12 = 0.0f; 60 | transform->m21 = 0.0f; 61 | transform->m22 = 1.0f; 62 | 63 | return S_OK; 64 | } 65 | 66 | 67 | // IDWritePixelSnapping method 68 | HRESULT CFW1TextRenderer::GetPixelsPerDip(void *clientDrawingContext, FLOAT *pixelsPerDip) { 69 | clientDrawingContext; 70 | 71 | *pixelsPerDip = 96.0f; 72 | 73 | return S_OK; 74 | } 75 | 76 | 77 | // IDWriteTextRenderer method 78 | // Convert a run of glyphs to vertices 79 | HRESULT CFW1TextRenderer::DrawGlyphRun( 80 | void *clientDrawingContext, 81 | FLOAT baselineOriginX, 82 | FLOAT baselineOriginY, 83 | DWRITE_MEASURING_MODE measuringMode, 84 | const DWRITE_GLYPH_RUN *glyphRun, 85 | const DWRITE_GLYPH_RUN_DESCRIPTION *glyphRunDescription, 86 | IUnknown *clientDrawingEffect 87 | ) { 88 | glyphRunDescription; 89 | measuringMode; 90 | 91 | const UINT flags = m_currentFlags; 92 | 93 | // Get glyph map for the current font 94 | const void *glyphMap; 95 | if(glyphRun->fontFace == m_pCachedGlyphMapFontFace && glyphRun->fontEmSize == m_cachedGlyphMapFontSize) 96 | glyphMap = m_cachedGlyphMap; 97 | else { 98 | glyphMap = m_pGlyphProvider->GetGlyphMapFromFont(glyphRun->fontFace, glyphRun->fontEmSize, flags); 99 | 100 | // Cache the glyph map as it's likely to be used in subsequent glyph runs 101 | m_cachedGlyphMap = glyphMap; 102 | m_pCachedGlyphMapFontFace = glyphRun->fontFace; 103 | m_cachedGlyphMapFontSize = glyphRun->fontEmSize; 104 | } 105 | 106 | // Skip if not interested in the actual glyphs 107 | if((flags & FW1_ANALYZEONLY) != 0) 108 | return S_OK; 109 | 110 | if((flags & FW1_CACHEONLY) != 0) { 111 | // Only request the glyphs from the provider to have them drawn to the atlas 112 | for(UINT i=0; i < glyphRun->glyphCount; ++i) { 113 | UINT atlasId = m_pGlyphProvider->GetAtlasIdFromGlyphIndex( 114 | glyphMap, 115 | glyphRun->glyphIndices[i], 116 | glyphRun->fontFace, 117 | flags 118 | ); 119 | atlasId; 120 | } 121 | } 122 | else { 123 | // Glyph vertex 124 | FW1_GLYPHVERTEX glyphVertex; 125 | glyphVertex.PositionY = floor(baselineOriginY + 0.5f); 126 | glyphVertex.GlyphColor = m_currentColor; 127 | 128 | float positionX = floor(baselineOriginX + 0.5f); 129 | 130 | // Optional drawing effect 131 | if(clientDrawingEffect != NULL) { 132 | IFW1ColorRGBA *pColor; 133 | HRESULT hResult = clientDrawingEffect->QueryInterface(&pColor); 134 | if(SUCCEEDED(hResult)) { 135 | glyphVertex.GlyphColor = pColor->GetColor32(); 136 | pColor->Release(); 137 | } 138 | } 139 | 140 | // Add a vertex for each glyph in the run 141 | IFW1TextGeometry *pTextGeometry = static_cast(clientDrawingContext); 142 | if(pTextGeometry != NULL) { 143 | for(UINT i=0; i < glyphRun->glyphCount; ++i) { 144 | glyphVertex.GlyphIndex = m_pGlyphProvider->GetAtlasIdFromGlyphIndex( 145 | glyphMap, 146 | glyphRun->glyphIndices[i], 147 | glyphRun->fontFace, 148 | flags 149 | ); 150 | 151 | if((glyphRun->bidiLevel & 0x1) != 0) 152 | positionX -= glyphRun->glyphAdvances[i]; 153 | 154 | glyphVertex.PositionX = floor(positionX + 0.5f); 155 | pTextGeometry->AddGlyphVertex(&glyphVertex); 156 | 157 | if((glyphRun->bidiLevel & 0x1) == 0) 158 | positionX += glyphRun->glyphAdvances[i]; 159 | } 160 | } 161 | } 162 | 163 | return S_OK; 164 | } 165 | 166 | 167 | // IDWriteTextRenderer method 168 | HRESULT CFW1TextRenderer::DrawUnderline( 169 | void *clientDrawingContext, 170 | FLOAT baselineOriginX, 171 | FLOAT baselineOriginY, 172 | const DWRITE_UNDERLINE *underline, 173 | IUnknown *clientDrawingEffect 174 | ) { 175 | clientDrawingContext; 176 | baselineOriginX; 177 | baselineOriginY; 178 | underline; 179 | clientDrawingEffect; 180 | 181 | return E_NOTIMPL; 182 | } 183 | 184 | 185 | // IDWriteTextRenderer method 186 | HRESULT CFW1TextRenderer::DrawStrikethrough( 187 | void *clientDrawingContext, 188 | FLOAT baselineOriginX, 189 | FLOAT baselineOriginY, 190 | const DWRITE_STRIKETHROUGH *strikethrough, 191 | IUnknown *clientDrawingEffect 192 | ) { 193 | clientDrawingContext; 194 | baselineOriginX; 195 | baselineOriginY; 196 | strikethrough; 197 | clientDrawingEffect; 198 | 199 | return E_NOTIMPL; 200 | } 201 | 202 | 203 | // IDWriteTextRenderer method 204 | HRESULT CFW1TextRenderer::DrawInlineObject( 205 | void *clientDrawingContext, 206 | FLOAT originX, 207 | FLOAT originY, 208 | IDWriteInlineObject *inlineObject, 209 | BOOL isSideways, 210 | BOOL isRightToLeft, 211 | IUnknown *clientDrawingEffect 212 | ) { 213 | clientDrawingContext; 214 | originX; 215 | originY; 216 | inlineObject; 217 | isSideways; 218 | isRightToLeft; 219 | clientDrawingEffect; 220 | 221 | return E_NOTIMPL; 222 | } 223 | 224 | 225 | // Get glyph provider 226 | HRESULT STDMETHODCALLTYPE CFW1TextRenderer::GetGlyphProvider(IFW1GlyphProvider **ppGlyphProvider) { 227 | if(ppGlyphProvider == NULL) 228 | return E_INVALIDARG; 229 | 230 | m_pGlyphProvider->AddRef(); 231 | *ppGlyphProvider = m_pGlyphProvider; 232 | 233 | return S_OK; 234 | } 235 | 236 | 237 | // Draw a text layout 238 | HRESULT STDMETHODCALLTYPE CFW1TextRenderer::DrawTextLayout( 239 | IDWriteTextLayout *pTextLayout, 240 | FLOAT OriginX, 241 | FLOAT OriginY, 242 | UINT32 Color, 243 | UINT Flags, 244 | IFW1TextGeometry *pTextGeometry 245 | ) { 246 | m_currentFlags = Flags; 247 | m_currentColor = Color; 248 | 249 | m_cachedGlyphMap = 0; 250 | m_pCachedGlyphMapFontFace = NULL; 251 | m_cachedGlyphMapFontSize = 0.0f; 252 | 253 | return pTextLayout->Draw(pTextGeometry, m_pDWriteTextRendererProxy, OriginX, OriginY); 254 | } 255 | 256 | 257 | }// namespace FW1FontWrapper 258 | -------------------------------------------------------------------------------- /FW1FontWrapper/FW1CompileSettings.h: -------------------------------------------------------------------------------- 1 | // FW1CompileSettings.h 2 | 3 | #ifndef IncludeGuard__FW1_FW1CompileSettings_h 4 | #define IncludeGuard__FW1_FW1CompileSettings_h 5 | 6 | 7 | // Define if building a DLL for the font-wrapper 8 | #define FW1_COMPILETODLL 9 | 10 | // Define to use LoadLibrary instead of linking to DLLs 11 | #define FW1_DELAYLOAD_DWRITE_DLL 12 | #define FW1_DELAYLOAD_D3DCOMPILER_XX_DLL 13 | 14 | 15 | #endif// IncludeGuard__FW1_FW1CompileSettings_h 16 | -------------------------------------------------------------------------------- /FW1FontWrapper/FW1FontWrapper.cpp: -------------------------------------------------------------------------------- 1 | // FW1FontWrapper.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | #include "CFW1Factory.h" 6 | 7 | #ifndef FW1_DELAYLOAD_DWRITE_DLL 8 | #pragma comment (lib, "DWrite.lib") 9 | #endif 10 | 11 | #ifndef FW1_DELAYLOAD_D3DCOMPILER_XX_DLL 12 | #pragma comment (lib, "DWrite.lib") 13 | #endif 14 | 15 | #ifdef FW1_COMPILETODLL 16 | #ifndef _M_X64 17 | #pragma comment (linker, "/EXPORT:FW1CreateFactory=_FW1CreateFactory@8,@1") 18 | #endif 19 | #endif 20 | 21 | 22 | // Create FW1 factory 23 | extern "C" HRESULT STDMETHODCALLTYPE FW1CreateFactory(UINT32 Version, IFW1Factory **ppFactory) { 24 | if(Version != FW1_VERSION) 25 | return E_FAIL; 26 | 27 | if(ppFactory == NULL) 28 | return E_INVALIDARG; 29 | 30 | FW1FontWrapper::CFW1Factory *pFactory = new FW1FontWrapper::CFW1Factory; 31 | HRESULT hResult = pFactory->initFactory(); 32 | if(FAILED(hResult)) { 33 | pFactory->Release(); 34 | } 35 | else { 36 | *ppFactory = pFactory; 37 | 38 | hResult = S_OK; 39 | } 40 | 41 | return hResult; 42 | } 43 | -------------------------------------------------------------------------------- /FW1FontWrapper/FW1Precompiled.cpp: -------------------------------------------------------------------------------- 1 | // FW1Precompiled.cpp 2 | 3 | #include "FW1Precompiled.h" 4 | 5 | -------------------------------------------------------------------------------- /FW1FontWrapper/FW1Precompiled.h: -------------------------------------------------------------------------------- 1 | // FW1Precompiled.h 2 | 3 | #ifndef IncludeGuard__FW1_FW1Precompiled_h 4 | #define IncludeGuard__FW1_FW1Precompiled_h 5 | 6 | 7 | #define NOMINMAX 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "FW1CompileSettings.h" 21 | #include "FW1FontWrapper.h" 22 | 23 | 24 | #endif// IncludeGuard__FW1_FW1Precompiled_h 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 zH4x 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Minhook/include/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /Minhook/src/HDE/hde32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 3 | * Copyright (c) 2006-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde32.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE32_H_ 11 | #define _HDE32_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_DISP8 0x00000020 30 | #define F_DISP16 0x00000040 31 | #define F_DISP32 0x00000080 32 | #define F_RELATIVE 0x00000100 33 | #define F_2IMM16 0x00000800 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_ANY 0x3f000000 47 | 48 | #define PREFIX_SEGMENT_CS 0x2e 49 | #define PREFIX_SEGMENT_SS 0x36 50 | #define PREFIX_SEGMENT_DS 0x3e 51 | #define PREFIX_SEGMENT_ES 0x26 52 | #define PREFIX_SEGMENT_FS 0x64 53 | #define PREFIX_SEGMENT_GS 0x65 54 | #define PREFIX_LOCK 0xf0 55 | #define PREFIX_REPNZ 0xf2 56 | #define PREFIX_REPX 0xf3 57 | #define PREFIX_OPERAND_SIZE 0x66 58 | #define PREFIX_ADDRESS_SIZE 0x67 59 | 60 | #pragma pack(push,1) 61 | 62 | typedef struct { 63 | uint8_t len; 64 | uint8_t p_rep; 65 | uint8_t p_lock; 66 | uint8_t p_seg; 67 | uint8_t p_66; 68 | uint8_t p_67; 69 | uint8_t opcode; 70 | uint8_t opcode2; 71 | uint8_t modrm; 72 | uint8_t modrm_mod; 73 | uint8_t modrm_reg; 74 | uint8_t modrm_rm; 75 | uint8_t sib; 76 | uint8_t sib_scale; 77 | uint8_t sib_index; 78 | uint8_t sib_base; 79 | union { 80 | uint8_t imm8; 81 | uint16_t imm16; 82 | uint32_t imm32; 83 | } imm; 84 | union { 85 | uint8_t disp8; 86 | uint16_t disp16; 87 | uint32_t disp32; 88 | } disp; 89 | uint32_t flags; 90 | } hde32s; 91 | 92 | #pragma pack(pop) 93 | 94 | #ifdef __cplusplus 95 | extern "C" { 96 | #endif 97 | 98 | /* __cdecl */ 99 | unsigned int hde32_disasm(const void *code, hde32s *hs); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif /* _HDE32_H_ */ 106 | -------------------------------------------------------------------------------- /Minhook/src/HDE/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /Minhook/src/HDE/pstdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | 31 | // Integer types for HDE. 32 | typedef INT8 int8_t; 33 | typedef INT16 int16_t; 34 | typedef INT32 int32_t; 35 | typedef INT64 int64_t; 36 | typedef UINT8 uint8_t; 37 | typedef UINT16 uint16_t; 38 | typedef UINT32 uint32_t; 39 | typedef UINT64 uint64_t; 40 | -------------------------------------------------------------------------------- /Minhook/src/HDE/table32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xf1 30 | #define DELTA_FPU_MODRM 0xf8 31 | #define DELTA_PREFIXES 0x130 32 | #define DELTA_OP_LOCK_OK 0x1a1 33 | #define DELTA_OP2_LOCK_OK 0x1b9 34 | #define DELTA_OP_ONLY_MEM 0x1cb 35 | #define DELTA_OP2_ONLY_MEM 0x1da 36 | 37 | unsigned char hde32_table[] = { 38 | 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3, 39 | 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f, 40 | 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3, 41 | 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa, 42 | 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90, 43 | 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f, 44 | 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d, 45 | 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59, 46 | 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, 47 | 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0, 48 | 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01, 49 | 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11, 50 | 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8, 51 | 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca, 52 | 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff, 53 | 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03, 54 | 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00, 55 | 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00, 56 | 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 57 | 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 58 | 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f, 59 | 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a, 60 | 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, 61 | 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a, 62 | 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06, 63 | 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06, 64 | 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 65 | 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08, 66 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01, 67 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba, 68 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00, 69 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00, 70 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07, 71 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf, 72 | 0xe7,0x08,0x00,0xf0,0x02,0x00 73 | }; 74 | -------------------------------------------------------------------------------- /Minhook/src/HDE/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /Minhook/src/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | // Size of each memory slot. 32 | #if defined(_M_X64) || defined(__x86_64__) 33 | #define MEMORY_SLOT_SIZE 64 34 | #else 35 | #define MEMORY_SLOT_SIZE 32 36 | #endif 37 | 38 | VOID InitializeBuffer(VOID); 39 | VOID UninitializeBuffer(VOID); 40 | LPVOID AllocateBuffer(LPVOID pOrigin); 41 | VOID FreeBuffer(LPVOID pBuffer); 42 | BOOL IsExecutableAddress(LPVOID pAddress); 43 | -------------------------------------------------------------------------------- /Minhook/src/trampoline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #pragma pack(push, 1) 32 | 33 | // Structs for writing x86/x64 instructions. 34 | 35 | // 8-bit relative jump. 36 | typedef struct _JMP_REL_SHORT 37 | { 38 | UINT8 opcode; // EB xx: JMP +2+xx 39 | UINT8 operand; 40 | } JMP_REL_SHORT, *PJMP_REL_SHORT; 41 | 42 | // 32-bit direct relative jump/call. 43 | typedef struct _JMP_REL 44 | { 45 | UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx 46 | UINT32 operand; // Relative destination address 47 | } JMP_REL, *PJMP_REL, CALL_REL; 48 | 49 | // 64-bit indirect absolute jump. 50 | typedef struct _JMP_ABS 51 | { 52 | UINT8 opcode0; // FF25 00000000: JMP [+6] 53 | UINT8 opcode1; 54 | UINT32 dummy; 55 | UINT64 address; // Absolute destination address 56 | } JMP_ABS, *PJMP_ABS; 57 | 58 | // 64-bit indirect absolute call. 59 | typedef struct _CALL_ABS 60 | { 61 | UINT8 opcode0; // FF15 00000002: CALL [+6] 62 | UINT8 opcode1; 63 | UINT32 dummy0; 64 | UINT8 dummy1; // EB 08: JMP +10 65 | UINT8 dummy2; 66 | UINT64 address; // Absolute destination address 67 | } CALL_ABS; 68 | 69 | // 32-bit direct relative conditional jumps. 70 | typedef struct _JCC_REL 71 | { 72 | UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx 73 | UINT8 opcode1; 74 | UINT32 operand; // Relative destination address 75 | } JCC_REL; 76 | 77 | // 64bit indirect absolute conditional jumps that x64 lacks. 78 | typedef struct _JCC_ABS 79 | { 80 | UINT8 opcode; // 7* 0E: J** +16 81 | UINT8 dummy0; 82 | UINT8 dummy1; // FF25 00000000: JMP [+6] 83 | UINT8 dummy2; 84 | UINT32 dummy3; 85 | UINT64 address; // Absolute destination address 86 | } JCC_ABS; 87 | 88 | #pragma pack(pop) 89 | 90 | typedef struct _TRAMPOLINE 91 | { 92 | LPVOID pTarget; // [In] Address of the target function. 93 | LPVOID pDetour; // [In] Address of the detour function. 94 | LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function. 95 | 96 | #if defined(_M_X64) || defined(__x86_64__) 97 | LPVOID pRelay; // [Out] Address of the relay function. 98 | #endif 99 | BOOL patchAbove; // [Out] Should use the hot patch area? 100 | UINT nIP; // [Out] Number of the instruction boundaries. 101 | UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function. 102 | UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function. 103 | } TRAMPOLINE, *PTRAMPOLINE; 104 | 105 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct); 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RadicalHeights-Hack 2 | Features 3 | 4 | Box Esp 5 | Name Esp 6 | Distance Esp 7 | Bike Esp 8 | 9 | ![Screeshot](https://i.imgur.com/g0lwBoS.png) 10 | 11 | ### Links 12 | 13 | Made by @[ImShotZz](https://www.unknowncheats.me/forum/members/2116480.html) 14 | 15 | Unknowncheats post - [radical-heights-internal-source](https://www.unknowncheats.me/forum/radical-heights/279691-radical-heights-internal-source.html#post2116594) 16 | 17 | GitHub - [ImShotZz/RadicalHeights-Hack](https://github.com/ImShotZz/RadicalHeights-Hack) 18 | 19 | Download dll - [https://www.unknowncheats.me/forum/downloads.php?do=file&id=23548](https://www.unknowncheats.me/forum/downloads.php?do=file&id=23548) -------------------------------------------------------------------------------- /SDK.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zH4x/SoT-DLL/6f7cf448c937a63d9f068bdf10a679dfb15bf357/SDK.rar -------------------------------------------------------------------------------- /UE4-SDK-InternalHack-Zanzo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 14 for Windows Desktop 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d11hook", "d3d11hook.vcxproj", "{119F3BCC-4D4E-4FDA-877E-A708963BB87A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Debug|x64.ActiveCfg = Debug|x64 17 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Debug|x64.Build.0 = Debug|x64 18 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Debug|x86.ActiveCfg = Debug|Win32 19 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Debug|x86.Build.0 = Debug|Win32 20 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Release|x64.ActiveCfg = Release|x64 21 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Release|x64.Build.0 = Release|x64 22 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Release|x86.ActiveCfg = Release|Win32 23 | {119F3BCC-4D4E-4FDA-877E-A708963BB87A}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /bones.h: -------------------------------------------------------------------------------- 1 | enum eBone 2 | { 3 | Spine_01 = 9, 4 | Spine_02 = 10, 5 | Spine_03 = 13, 6 | Neck_01 = 66, 7 | Head = 67, 8 | 9 | Clavicle_r = 40, 10 | Upperarm_r = 41, 11 | Upperarm_twist_02_r = 63, 12 | LowerArm_r = 43, 13 | Lowerarm_twist_02_r = 62, 14 | Hand_r = 44, 15 | 16 | Clavicle_l = 14, 17 | Upperarm_l = 15, 18 | Upperarm_twist_02_l = 37, 19 | LowerArm_l = 17, 20 | Lowerarm_twist_02_l = 36, 21 | Hand_l = 18, 22 | 23 | Thigh_r = 83, 24 | Thigh_twist_01_r = 91, 25 | Calf_r = 84, 26 | Calf_twist_01_r = 85, 27 | Foot_r = 86, 28 | Ball_r = 87, 29 | 30 | Thigh_l = 74, 31 | Thigh_twist_01_l = 82, 32 | Calf_l = 75, 33 | Calf_twist_01_l = 76, 34 | Foot_l = 77, 35 | Ball_l = 78, 36 | }; -------------------------------------------------------------------------------- /d3d11hook.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {7c50d61e-4f3d-43e0-93ea-fd32c1c64471} 10 | 11 | 12 | {bb1ad4ad-90fc-46ab-8339-379f9f7a0308} 13 | 14 | 15 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 16 | h;hh;hpp;hxx;hm;inl;inc;xsd 17 | 18 | 19 | {35ed8296-1075-4b2e-9216-ed96fa4e91fe} 20 | 21 | 22 | {4e79f209-5893-4b06-a5bc-12aeef7ca9d8} 23 | 24 | 25 | 26 | 27 | Source 28 | 29 | 30 | Resource Files\FW1FontWrapper 31 | 32 | 33 | Resource Files\FW1FontWrapper 34 | 35 | 36 | Resource Files\FW1FontWrapper 37 | 38 | 39 | Resource Files\FW1FontWrapper 40 | 41 | 42 | Resource Files\FW1FontWrapper 43 | 44 | 45 | Resource Files\FW1FontWrapper 46 | 47 | 48 | Resource Files\FW1FontWrapper 49 | 50 | 51 | Resource Files\FW1FontWrapper 52 | 53 | 54 | Resource Files\FW1FontWrapper 55 | 56 | 57 | Resource Files\FW1FontWrapper 58 | 59 | 60 | Resource Files\FW1FontWrapper 61 | 62 | 63 | Resource Files\FW1FontWrapper 64 | 65 | 66 | Resource Files\FW1FontWrapper 67 | 68 | 69 | Resource Files\FW1FontWrapper 70 | 71 | 72 | Resource Files\FW1FontWrapper 73 | 74 | 75 | Resource Files\FW1FontWrapper 76 | 77 | 78 | Resource Files\MinHook 79 | 80 | 81 | Resource Files\MinHook 82 | 83 | 84 | Resource Files\MinHook 85 | 86 | 87 | Resource Files\MinHook 88 | 89 | 90 | Resource Files\MinHook 91 | 92 | 93 | Resource Files\MinHook 94 | 95 | 96 | Resource Files\MinHook 97 | 98 | 99 | Source 100 | 101 | 102 | Source 103 | 104 | 105 | Source 106 | 107 | 108 | Source 109 | 110 | 111 | Source 112 | 113 | 114 | Source 115 | 116 | 117 | Header Files 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | 130 | 131 | Resource Files\FW1FontWrapper 132 | 133 | 134 | Resource Files\FW1FontWrapper 135 | 136 | 137 | Resource Files\FW1FontWrapper 138 | 139 | 140 | Resource Files\FW1FontWrapper 141 | 142 | 143 | Resource Files\FW1FontWrapper 144 | 145 | 146 | Resource Files\FW1FontWrapper 147 | 148 | 149 | Resource Files\FW1FontWrapper 150 | 151 | 152 | Resource Files\FW1FontWrapper 153 | 154 | 155 | Resource Files\FW1FontWrapper 156 | 157 | 158 | Resource Files\FW1FontWrapper 159 | 160 | 161 | Resource Files\FW1FontWrapper 162 | 163 | 164 | Resource Files\FW1FontWrapper 165 | 166 | 167 | Resource Files\FW1FontWrapper 168 | 169 | 170 | Resource Files\FW1FontWrapper 171 | 172 | 173 | Resource Files\FW1FontWrapper 174 | 175 | 176 | Resource Files\FW1FontWrapper 177 | 178 | 179 | Resource Files\FW1FontWrapper 180 | 181 | 182 | Resource Files\FW1FontWrapper 183 | 184 | 185 | Resource Files\FW1FontWrapper 186 | 187 | 188 | Resource Files\FW1FontWrapper 189 | 190 | 191 | Resource Files\FW1FontWrapper 192 | 193 | 194 | Resource Files\FW1FontWrapper 195 | 196 | 197 | Resource Files\FW1FontWrapper 198 | 199 | 200 | Resource Files\FW1FontWrapper 201 | 202 | 203 | Resource Files\FW1FontWrapper 204 | 205 | 206 | Resource Files\MinHook 207 | 208 | 209 | Resource Files\MinHook 210 | 211 | 212 | Resource Files\MinHook 213 | 214 | 215 | Resource Files\MinHook 216 | 217 | 218 | Resource Files\MinHook 219 | 220 | 221 | Source 222 | 223 | 224 | Source 225 | 226 | 227 | Source\SDK 228 | 229 | 230 | Source\SDK 231 | 232 | 233 | Source\SDK 234 | 235 | 236 | Source\SDK 237 | 238 | 239 | 240 | 241 | Source 242 | 243 | 244 | -------------------------------------------------------------------------------- /d3d11hook.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /global.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "SDK.hpp" 5 | 6 | 7 | namespace Global 8 | { 9 | DWORD_PTR BaseAddress; 10 | MODULEINFO info; 11 | SDK::UWorld** m_UWorld; 12 | SDK::ULevel* m_PersistentLevel; 13 | SDK::ULocalPlayer* m_LocalPlayer; 14 | SDK::TArray* m_AActors; 15 | } -------------------------------------------------------------------------------- /hooks.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOOKS_H 2 | #define __HOOKS_H 3 | 4 | using D3D11PresentHook = HRESULT(__stdcall *) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); 5 | using D3D11DrawIndexedHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT IndexCount, UINT StartIndexLocation, INT BaseVertexLocation); 6 | using D3D11PSSetShaderResourcesHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT StartSlot, UINT NumViews, ID3D11ShaderResourceView *const *ppShaderResourceViews); 7 | using D3D11CreateQueryHook = void(__stdcall *) (ID3D11Device* pDevice, const D3D11_QUERY_DESC *pQueryDesc, ID3D11Query **ppQuery); 8 | 9 | using D3D11DrawIndexedInstancedHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation); 10 | using D3D11DrawHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT VertexCount, UINT StartVertexLocation); 11 | using D3D11DrawInstancedHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation); 12 | using D3D11DrawInstancedIndirectHook = void(__stdcall *) (ID3D11DeviceContext* pContext, ID3D11Buffer *pBufferForArgs, UINT AlignedByteOffsetForArgs); 13 | using D3D11DrawIndexedInstancedIndirectHook = void(__stdcall *) (ID3D11DeviceContext* pContext, ID3D11Buffer *pBufferForArgs, UINT AlignedByteOffsetForArgs); 14 | using D3D11VSSetConstantBuffersHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT StartSlot, UINT NumBuffers, ID3D11Buffer *const *ppConstantBuffers); 15 | using D3D11PSSetSamplersHook = void(__stdcall *) (ID3D11DeviceContext* pContext, UINT StartSlot, UINT NumSamplers, ID3D11SamplerState *const *ppSamplers); 16 | 17 | D3D11PresentHook phookD3D11Present = NULL; 18 | D3D11DrawIndexedHook phookD3D11DrawIndexed = NULL; 19 | D3D11PSSetShaderResourcesHook phookD3D11PSSetShaderResources = NULL; 20 | D3D11CreateQueryHook phookD3D11CreateQuery = NULL; 21 | 22 | D3D11DrawIndexedInstancedHook phookD3D11DrawIndexedInstanced = NULL; 23 | D3D11DrawHook phookD3D11Draw = NULL; 24 | D3D11DrawInstancedHook phookD3D11DrawInstanced = NULL; 25 | D3D11DrawInstancedIndirectHook phookD3D11DrawInstancedIndirect = NULL; 26 | D3D11DrawIndexedInstancedIndirectHook phookD3D11DrawIndexedInstancedIndirect = NULL; 27 | D3D11VSSetConstantBuffersHook phookD3D11VSSetConstantBuffers = NULL; 28 | D3D11PSSetSamplersHook phookD3D11PSSetSamplers = NULL; 29 | 30 | ID3D11Device *pDevice = NULL; 31 | ID3D11DeviceContext *pContext = NULL; 32 | 33 | DWORD_PTR* pSwapChainVtable = NULL; 34 | DWORD_PTR* pContextVTable = NULL; 35 | DWORD_PTR* pDeviceVTable = NULL; 36 | 37 | #endif -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | //d3d11 w2s for ut4 engine games by n7 2 | 3 | //init only once 4 | bool firstTime = true; 5 | 6 | //viewport 7 | UINT vps = 1; 8 | D3D11_VIEWPORT viewport; 9 | float ScreenCenterX; 10 | float ScreenCenterY; 11 | 12 | //vertex 13 | ID3D11Buffer* veBuffer; 14 | UINT Stride = 24; 15 | UINT veBufferOffset = 0; 16 | D3D11_BUFFER_DESC vedesc; 17 | 18 | //index 19 | ID3D11Buffer* inBuffer; 20 | DXGI_FORMAT inFormat; 21 | UINT inOffset; 22 | D3D11_BUFFER_DESC indesc; 23 | 24 | //rendertarget 25 | ID3D11Texture2D* RenderTargetTexture; 26 | ID3D11RenderTargetView* RenderTargetView = NULL; 27 | 28 | //shader 29 | ID3D11PixelShader* psRed = NULL; 30 | ID3D11PixelShader* psGreen = NULL; 31 | 32 | //pssetshaderresources 33 | UINT pssrStartSlot; 34 | D3D11_SHADER_RESOURCE_VIEW_DESC Descr; 35 | ID3D11ShaderResourceView* ShaderResourceView; 36 | D3D11_TEXTURE2D_DESC texdesc; 37 | 38 | //psgetConstantbuffers 39 | ID3D11Buffer* pcsBuffer; 40 | D3D11_BUFFER_DESC pscdesc; 41 | UINT pscStartSlot; 42 | 43 | //vsgetconstantbuffers 44 | ID3D11Buffer* mConstantBuffers; 45 | UINT vsConstant_StartSlot; 46 | 47 | UINT psStartSlot; 48 | UINT vsStartSlot; 49 | 50 | //used for logging/cycling through values 51 | bool logger = true; 52 | int countnum = 1; 53 | char szString[64]; 54 | 55 | #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } } 56 | 57 | void Misc(); 58 | void Aimbot(); 59 | 60 | //========================================================================================================================== 61 | 62 | //generate shader func 63 | HRESULT GenerateShader(ID3D11Device* pD3DDevice, ID3D11PixelShader** pShader, float r, float g, float b) 64 | { 65 | char szCast[] = "struct VS_OUT" 66 | "{" 67 | " float4 Position : SV_Position;" 68 | " float4 Color : COLOR0;" 69 | "};" 70 | 71 | "float4 main( VS_OUT input ) : SV_Target" 72 | "{" 73 | " float4 fake;" 74 | " fake.a = 0.5f;" 75 | " fake.r = %f;" 76 | " fake.g = %f;" 77 | " fake.b = %f;" 78 | " return fake;" 79 | "}"; 80 | ID3D10Blob* pBlob; 81 | char szPixelShader[1000]; 82 | 83 | sprintf_s(szPixelShader, szCast, r, g, b); 84 | 85 | ID3DBlob* d3dErrorMsgBlob; 86 | 87 | HRESULT hr = D3DCompile(szPixelShader, sizeof(szPixelShader), "shader", NULL, NULL, "main", "ps_4_0", NULL, NULL, 88 | &pBlob, &d3dErrorMsgBlob); 89 | 90 | if (FAILED(hr)) 91 | return hr; 92 | 93 | hr = pD3DDevice->CreatePixelShader((DWORD*)pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, pShader); 94 | 95 | if (FAILED(hr)) 96 | return hr; 97 | 98 | return S_OK; 99 | } 100 | 101 | //========================================================================================================================== 102 | 103 | //wh 104 | char* state; 105 | ID3D11RasterizerState* rwState; 106 | ID3D11RasterizerState* rsState; 107 | 108 | enum eDepthState 109 | { 110 | ENABLED, 111 | DISABLED, 112 | READ_NO_WRITE, 113 | NO_READ_NO_WRITE, 114 | _DEPTH_COUNT 115 | }; 116 | 117 | ID3D11DepthStencilState* myDepthStencilStates[static_cast(eDepthState::_DEPTH_COUNT)]; 118 | 119 | void SetDepthStencilState(eDepthState aState) 120 | { 121 | pContext->OMSetDepthStencilState(myDepthStencilStates[aState], 1); 122 | } 123 | 124 | static Vec4 Vec4MulMat4x4(const Vec4& v, float (*mat4x4)[4]) 125 | { 126 | Vec4 o; 127 | 128 | o.x = v.x * mat4x4[0][0] + v.y * mat4x4[1][0] + v.z * mat4x4[2][0] + v.w * mat4x4[3][0]; 129 | o.y = v.x * mat4x4[0][1] + v.y * mat4x4[1][1] + v.z * mat4x4[2][1] + v.w * mat4x4[3][1]; 130 | o.z = v.x * mat4x4[0][2] + v.y * mat4x4[1][2] + v.z * mat4x4[2][2] + v.w * mat4x4[3][2]; 131 | o.w = v.x * mat4x4[0][3] + v.y * mat4x4[1][3] + v.z * mat4x4[2][3] + v.w * mat4x4[3][3]; 132 | 133 | return o; 134 | } 135 | 136 | static Vec4 Vec3MulMat4x4(const Vec3& v, float (*mat4x4)[4]) 137 | { 138 | Vec4 o; 139 | 140 | o.x = v.x * mat4x4[0][0] + v.y * mat4x4[1][0] + v.z * mat4x4[2][0] + mat4x4[3][0]; 141 | o.y = v.x * mat4x4[0][1] + v.y * mat4x4[1][1] + v.z * mat4x4[2][1] + mat4x4[3][1]; 142 | o.z = v.x * mat4x4[0][2] + v.y * mat4x4[1][2] + v.z * mat4x4[2][2] + mat4x4[3][2]; 143 | o.w = v.x * mat4x4[0][3] + v.y * mat4x4[1][3] + v.z * mat4x4[2][3] + mat4x4[3][3]; 144 | 145 | return o; 146 | } 147 | 148 | static Vec3 Vec3MulMat4x3(const Vec3& v, float (*mat4x3)[3]) 149 | { 150 | Vec3 o; 151 | o.x = v.x * mat4x3[0][0] + v.y * mat4x3[1][0] + v.z * mat4x3[2][0] + mat4x3[3][0]; 152 | o.y = v.x * mat4x3[0][1] + v.y * mat4x3[1][1] + v.z * mat4x3[2][1] + mat4x3[3][1]; 153 | o.z = v.x * mat4x3[0][2] + v.y * mat4x3[1][2] + v.z * mat4x3[2][2] + mat4x3[3][2]; 154 | return o; 155 | } 156 | 157 | void MapBuffer(ID3D11Buffer* pStageBuffer, void** ppData, UINT* pByteWidth) 158 | { 159 | D3D11_MAPPED_SUBRESOURCE subRes; 160 | HRESULT res = pContext->Map(pStageBuffer, 0, D3D11_MAP_READ, 0, &subRes); 161 | 162 | D3D11_BUFFER_DESC desc; 163 | pStageBuffer->GetDesc(&desc); 164 | 165 | *ppData = subRes.pData; 166 | 167 | if (pByteWidth) 168 | *pByteWidth = desc.ByteWidth; 169 | } 170 | 171 | void UnmapBuffer(ID3D11Buffer* pStageBuffer) 172 | { 173 | pContext->Unmap(pStageBuffer, 0); 174 | } 175 | 176 | ID3D11Buffer* CopyBufferToCpu(ID3D11Buffer* pBuffer) 177 | { 178 | D3D11_BUFFER_DESC CBDesc; 179 | pBuffer->GetDesc(&CBDesc); 180 | 181 | ID3D11Buffer* pStageBuffer = NULL; 182 | { 183 | // create shadow buffer. 184 | D3D11_BUFFER_DESC desc; 185 | desc.BindFlags = 0; 186 | desc.ByteWidth = CBDesc.ByteWidth; 187 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 188 | desc.MiscFlags = 0; 189 | desc.StructureByteStride = 0; 190 | desc.Usage = D3D11_USAGE_STAGING; 191 | } 192 | 193 | if (pStageBuffer != NULL) 194 | pContext->CopyResource(pStageBuffer, pBuffer); 195 | 196 | return pStageBuffer; 197 | } -------------------------------------------------------------------------------- /renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma warning(disable:4005) 13 | #pragma warning(disable:4458) 14 | 15 | #include "FW1FontWrapper/FW1FontWrapper.h" 16 | #include "shader.h" 17 | 18 | using namespace DirectX; 19 | using namespace DirectX::PackedVector; 20 | 21 | using Vec4 = XMFLOAT4; 22 | using Vec3 = XMFLOAT3; 23 | using Vec2 = XMFLOAT2; 24 | 25 | using Color = XMVECTORF32; 26 | 27 | inline void throwIfFailed(HRESULT hr); 28 | 29 | template 30 | inline void safeRelease(Ty &comPtr); 31 | 32 | struct Vertex; 33 | struct Batch; 34 | 35 | class RenderList 36 | { 37 | using Ptr = std::unique_ptr; 38 | 39 | friend class Renderer; 40 | public: 41 | RenderList() = delete; 42 | 43 | RenderList(IFW1Factory *fontFactory, std::size_t maxVertices = 0) 44 | { 45 | vertices.reserve(maxVertices); 46 | throwIfFailed(fontFactory->CreateTextGeometry(&textGeometry)); 47 | } 48 | 49 | ~RenderList() 50 | { 51 | safeRelease(textGeometry); 52 | } 53 | 54 | void clear() 55 | { 56 | vertices.clear(); 57 | batches.clear(); 58 | textGeometry->Clear(); 59 | } 60 | 61 | protected: 62 | std::vector vertices; 63 | std::vector batches; 64 | 65 | IFW1TextGeometry *textGeometry; 66 | }; 67 | 68 | class Renderer 69 | : public std::enable_shared_from_this 70 | { 71 | public: 72 | Renderer(ID3D11Device *direct3DDevice, const std::wstring &defaultFontFamily = L"Verdana"); 73 | 74 | ~Renderer(); 75 | 76 | void begin(); 77 | void end(); 78 | void draw(const RenderList::Ptr &renderList); 79 | void draw(); 80 | 81 | void addVertex(const RenderList::Ptr &renderList, Vertex &vertex, D3D11_PRIMITIVE_TOPOLOGY topology); 82 | void addVertex(Vertex &vertex, D3D11_PRIMITIVE_TOPOLOGY topology); 83 | 84 | template 85 | void addVertices(const RenderList::Ptr &renderList, Vertex(&vertexArr)[N], D3D11_PRIMITIVE_TOPOLOGY topology); 86 | 87 | template 88 | void addVertices(Vertex(&vertexArr)[N], D3D11_PRIMITIVE_TOPOLOGY topology); 89 | 90 | void drawText(const RenderList::Ptr &renderList, const Vec2 &pos, const std::wstring &text, const Color &color, std::uint32_t flags = FW1_LEFT, 91 | float fontSize = 10.f, const std::wstring &fontFamily = {}); 92 | 93 | void drawText(const Vec2 &pos, const std::wstring &text, const Color &color, std::uint32_t flags = FW1_LEFT, 94 | float fontSize = 10.f, const std::wstring &fontFamily = {}); 95 | 96 | Vec2 getTextExtent(const std::wstring &text, float fontSize = 10.f, const std::wstring &fontFamily = {}) const; 97 | 98 | void drawPixel(const Vec2 &pos, const Color &color); 99 | void drawPixel(const RenderList::Ptr &renderList, const Vec2 &pos, const Color &color); 100 | void drawLine(const Vec2 &from, const Vec2 &to, const Color &color); 101 | void drawLine(const RenderList::Ptr &renderList, const Vec2 &from, const Vec2 &to, const Color &color); 102 | void drawFilledRect(const Vec4 &rect, const Color &color); 103 | void drawFilledRect(const RenderList::Ptr &renderList, const Vec4 &rect, const Color &color); 104 | void drawRect(const Vec4 &rect, float strokeWidth, const Color &color); 105 | void drawRect(const RenderList::Ptr &renderList, const Vec4 &rect, float strokeWidth, const Color &color); 106 | void drawOutlinedRect(const Vec4 &rect, float strokeWidth, const Color &strokeColor, const Color &fillColor); 107 | void drawOutlinedRect(const RenderList::Ptr &renderList, const Vec4 &rect, float strokeWidth, const Color &strokeColor, const Color &fillColor); 108 | void drawCircle(const Vec2 &pos, float radius, const Color &color); 109 | void drawCircle(const RenderList::Ptr &renderList, const Vec2 &pos, float radius, const Color &color); 110 | 111 | IFW1Factory *getFontFactory() const; 112 | 113 | std::shared_ptr ptr(); 114 | 115 | private: 116 | ID3D11DeviceContext * immediateContext; 117 | ID3D11Device *direct3DDevice; 118 | 119 | ID3D11InputLayout *inputLayout; 120 | ID3D11BlendState *blendState; 121 | ID3D11VertexShader *vertexShader; 122 | ID3D11PixelShader *pixelShader; 123 | ID3D11Buffer *vertexBuffer; 124 | ID3D11Buffer *screenProjectionBuffer; 125 | 126 | IFW1Factory *fontFactory; 127 | IFW1FontWrapper *fontWrapper; 128 | 129 | XMMATRIX projection; 130 | 131 | RenderList::Ptr renderList; 132 | 133 | std::size_t maxVertices; 134 | 135 | std::wstring defaultFontFamily; 136 | }; 137 | 138 | template 139 | void Renderer::addVertices(const RenderList::Ptr &renderList, Vertex(&vertexArr)[N], D3D11_PRIMITIVE_TOPOLOGY topology) 140 | { 141 | if (std::size(renderList->vertices) + N >= maxVertices) 142 | (&this->renderList == &renderList) ? draw(renderList) : throw std::exception( 143 | "Renderer::addVertex - Vertex buffer exhausted! Increase the size of the vertex buffer or add a custom implementation."); 144 | 145 | if (std::empty(renderList->batches) || renderList->batches.back().topology != topology) 146 | renderList->batches.emplace_back(0, topology); 147 | 148 | renderList->batches.back().count += N; 149 | 150 | renderList->vertices.resize(std::size(renderList->vertices) + N); 151 | std::memcpy(&renderList->vertices[std::size(renderList->vertices) - N], &vertexArr[0], N * sizeof(Vertex)); 152 | 153 | switch (topology) 154 | { 155 | case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP: 156 | case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: 157 | case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: 158 | case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: 159 | { 160 | Vertex seperator{}; 161 | addVertex(seperator, D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED); 162 | break; 163 | } 164 | default: 165 | break; 166 | } 167 | } 168 | 169 | template 170 | void Renderer::addVertices(Vertex(&vertexArr)[N], D3D11_PRIMITIVE_TOPOLOGY topology) 171 | { 172 | addVertices(renderList, vertexArr, topology); 173 | } 174 | 175 | inline void throwIfFailed(HRESULT hr) 176 | { 177 | if (FAILED(hr)) 178 | { 179 | throw std::exception("Crucial Direct3D 11 operation failed! "); 180 | } 181 | } 182 | 183 | template 184 | inline void safeRelease(Ty &comPtr) 185 | { 186 | static_assert(std::is_pointer::value, 187 | "safeRelease - comPtr not a pointer."); 188 | 189 | static_assert(std::is_base_of::type>::value, 190 | "safeRelease - remove_ptr::type is not a com object."); 191 | 192 | if (comPtr) 193 | { 194 | comPtr->Release(); 195 | comPtr = nullptr; 196 | } 197 | } 198 | 199 | struct Vertex 200 | { 201 | Vertex() = default; 202 | Vertex(float x, float y, float z, Color col) 203 | : pos(x, y, z), col(col) 204 | {} 205 | 206 | Vec3 pos; 207 | Color col; 208 | }; 209 | 210 | struct Batch 211 | { 212 | Batch(std::size_t count, D3D11_PRIMITIVE_TOPOLOGY topology) 213 | : count(count), topology(topology) 214 | {} 215 | 216 | std::size_t count; 217 | D3D11_PRIMITIVE_TOPOLOGY topology; 218 | }; -------------------------------------------------------------------------------- /shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | const char shader[] = R"(cbuffer screenProjectionBuffer : register(b0) 4 | { 5 | matrix projection; 6 | }; 7 | 8 | struct VS_OUTPUT 9 | { 10 | float4 pos : SV_POSITION; 11 | float4 col : COLOR; 12 | }; 13 | 14 | struct VS_INPUT 15 | { 16 | float4 pos : POSITION; 17 | float4 col : COLOR; 18 | }; 19 | 20 | VS_OUTPUT VS(VS_INPUT input) 21 | { 22 | VS_OUTPUT output; 23 | 24 | output.pos = mul(projection, float4(input.pos.xy, 0.f, 1.f)); 25 | output.col = input.col; 26 | 27 | return output; 28 | } 29 | 30 | float4 PS(VS_OUTPUT input) : SV_TARGET 31 | { 32 | return input.col; 33 | })"; -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "SDK.hpp" 3 | #include "global.h" 4 | 5 | #undef max 6 | #define M_PI 3.14159265358979323846f 7 | 8 | namespace Util 9 | { 10 | bool DataCompare(PBYTE pData, PBYTE bSig, char* szMask) 11 | { 12 | for (; *szMask; ++szMask, ++pData, ++bSig) 13 | { 14 | if (*szMask == 'x' && *pData != *bSig) 15 | return false; 16 | } 17 | return (*szMask) == 0; 18 | } 19 | 20 | PBYTE FindPattern(PBYTE dwAddress, DWORD dwSize, PBYTE pbSig, char* szMask, long offset) 21 | { 22 | size_t length = strlen(szMask); 23 | for (size_t i = NULL; i < dwSize - length; i++) 24 | { 25 | if (DataCompare(dwAddress + i, pbSig, szMask)) 26 | return dwAddress + i + offset; 27 | } 28 | return nullptr; 29 | } 30 | 31 | namespace Vector 32 | { 33 | SDK::FVector Add(SDK::FVector point1, SDK::FVector point2) 34 | { 35 | SDK::FVector vector{ 0, 0, 0 }; 36 | vector.X = point1.X + point2.X; 37 | vector.Y = point1.Y + point2.Y; 38 | vector.Z = point1.Z + point2.Z; 39 | return vector; 40 | } 41 | 42 | SDK::FVector Subtract(SDK::FVector point1, SDK::FVector point2) 43 | { 44 | SDK::FVector vector{ 0, 0, 0 }; 45 | vector.X = point1.X - point2.X; 46 | vector.Y = point1.Y - point2.Y; 47 | vector.Z = point1.Z - point2.Z; 48 | return vector; 49 | } 50 | 51 | SDK::FVector Square(SDK::FVector vector) 52 | { 53 | return SDK::FVector{ vector.X * vector.X, vector.Y * vector.Y, vector.Z * vector.Z }; 54 | } 55 | 56 | SDK::FVector Divide(SDK::FVector point1, float num) 57 | { 58 | SDK::FVector vector{ 0, 0, 0 }; 59 | vector.X = point1.X / num; 60 | vector.Y = point1.Y / num; 61 | vector.Z = point1.Z / num; 62 | return vector; 63 | } 64 | } 65 | 66 | namespace Vector2D 67 | { 68 | SDK::FVector2D Subtract(SDK::FVector2D point1, SDK::FVector2D point2) 69 | { 70 | SDK::FVector2D vector{ 0, 0 }; 71 | vector.X = point1.X - point2.X; 72 | vector.Y = point1.Y - point2.Y; 73 | return vector; 74 | } 75 | 76 | SDK::FVector2D Add(SDK::FVector2D point1, SDK::FVector2D point2) 77 | { 78 | SDK::FVector2D vector{ 0, 0 }; 79 | vector.X = point1.X + point2.X; 80 | vector.Y = point1.Y + point2.Y; 81 | return vector; 82 | } 83 | 84 | SDK::FVector2D Divide(SDK::FVector2D point1, float num) 85 | { 86 | SDK::FVector2D vector{ 0, 0 }; 87 | vector.X = point1.X / num; 88 | vector.Y = point1.Y / num; 89 | return vector; 90 | } 91 | } 92 | 93 | namespace Engine 94 | { 95 | DWORD_PTR boneAddress; 96 | SDK::FMatrix* GetBoneMatrix(SDK::USkeletalMeshComponent* mesh, SDK::FMatrix* result, int boneid) 97 | { 98 | return reinterpret_cast(boneAddress)(mesh, result, boneid); 99 | } 100 | 101 | void GetBoneLocation(SDK::USkeletalMeshComponent* mesh, SDK::FVector* result, int boneid) 102 | { 103 | SDK::FMatrix vMatrix; 104 | SDK::FMatrix *vTempMatrix = GetBoneMatrix(mesh, &vMatrix, boneid); 105 | *result = vMatrix.WPlane; 106 | } 107 | } 108 | 109 | bool IsLocalPlayer(SDK::AActor* player) 110 | { 111 | if (Global::m_LocalPlayer->PlayerController->AcknowledgedPawn == nullptr) 112 | return true; 113 | return (static_cast(player) == Global::m_LocalPlayer->PlayerController->AcknowledgedPawn); 114 | } 115 | 116 | std::wstring DistanceToString(float distance) 117 | { 118 | float meters = distance * 0.01f; 119 | std::wstringstream ss; 120 | 121 | if (meters < 1000.f) 122 | { 123 | ss << std::fixed << std::setprecision(0) << meters << "m"; 124 | } 125 | else 126 | { 127 | ss.precision(3); 128 | ss << std::fixed << std::setprecision(0) << (meters / 1000.f) << "km"; 129 | } 130 | return ss.str(); 131 | } 132 | 133 | float GetDistance(SDK::FVector x, SDK::FVector y) 134 | { 135 | auto z = Vector::Subtract(x, y); 136 | return sqrt(z.X * z.X + z.Y * z.Y + z.Z * z.Z); 137 | } 138 | 139 | float GetDistance2D(SDK::FVector2D point1, SDK::FVector2D point2) 140 | { 141 | SDK::FVector2D heading = Vector2D::Subtract(point2, point1); 142 | float distanceSquared; 143 | float distance; 144 | 145 | distanceSquared = heading.X * heading.X + heading.Y * heading.Y; 146 | distance = sqrt(distanceSquared); 147 | 148 | return distance; 149 | } 150 | } --------------------------------------------------------------------------------