1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/include/fxge/fx_ge.h" 8 9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ 10 #include <dwrite.h> 11 12 #include "core/include/fxge/fx_ge_win32.h" 13 #include "dwrite_int.h" 14 15 typedef HRESULT(__stdcall* FuncType_DWriteCreateFactory)( 16 __in DWRITE_FACTORY_TYPE, 17 __in REFIID, 18 __out IUnknown**); 19 template <typename InterfaceType> 20 inline void SafeRelease(InterfaceType** currentObject) { 21 if (*currentObject) { 22 (*currentObject)->Release(); 23 *currentObject = NULL; 24 } 25 } 26 template <typename InterfaceType> 27 inline InterfaceType* SafeAcquire(InterfaceType* newObject) { 28 if (newObject) { 29 newObject->AddRef(); 30 } 31 return newObject; 32 } 33 class CDwFontFileStream final : public IDWriteFontFileStream { 34 public: 35 explicit CDwFontFileStream(void const* fontFileReferenceKey, 36 UINT32 fontFileReferenceKeySize); 37 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, 38 void** ppvObject); 39 virtual ULONG STDMETHODCALLTYPE AddRef(); 40 virtual ULONG STDMETHODCALLTYPE Release(); 41 virtual HRESULT STDMETHODCALLTYPE 42 ReadFileFragment(void const** fragmentStart, 43 UINT64 fileOffset, 44 UINT64 fragmentSize, 45 OUT void** fragmentContext); 46 virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext); 47 virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize); 48 virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime); 49 bool IsInitialized() { return resourcePtr_ != NULL; } 50 51 private: 52 ULONG refCount_; 53 void const* resourcePtr_; 54 DWORD resourceSize_; 55 }; 56 class CDwFontFileLoader final : public IDWriteFontFileLoader { 57 public: 58 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, 59 void** ppvObject); 60 virtual ULONG STDMETHODCALLTYPE AddRef(); 61 virtual ULONG STDMETHODCALLTYPE Release(); 62 virtual HRESULT STDMETHODCALLTYPE 63 CreateStreamFromKey(void const* fontFileReferenceKey, 64 UINT32 fontFileReferenceKeySize, 65 OUT IDWriteFontFileStream** fontFileStream); 66 67 static IDWriteFontFileLoader* GetLoader() { 68 if (!instance_) { 69 instance_ = new CDwFontFileLoader(); 70 } 71 return instance_; 72 } 73 static bool IsLoaderInitialized() { return instance_ != NULL; } 74 75 private: 76 CDwFontFileLoader(); 77 ULONG refCount_; 78 static IDWriteFontFileLoader* instance_; 79 }; 80 class CDwFontContext { 81 public: 82 CDwFontContext(IDWriteFactory* dwriteFactory); 83 ~CDwFontContext(); 84 HRESULT Initialize(); 85 86 private: 87 CDwFontContext(CDwFontContext const&); 88 void operator=(CDwFontContext const&); 89 HRESULT hr_; 90 IDWriteFactory* dwriteFactory_; 91 }; 92 class CDwGdiTextRenderer { 93 public: 94 CDwGdiTextRenderer(CFX_DIBitmap* pBitmap, 95 IDWriteBitmapRenderTarget* bitmapRenderTarget, 96 IDWriteRenderingParams* renderingParams); 97 ~CDwGdiTextRenderer(); 98 HRESULT STDMETHODCALLTYPE DrawGlyphRun(const FX_RECT& text_bbox, 99 __in_opt CFX_ClipRgn* pClipRgn, 100 __in_opt DWRITE_MATRIX const* pMatrix, 101 FLOAT baselineOriginX, 102 FLOAT baselineOriginY, 103 DWRITE_MEASURING_MODE measuringMode, 104 __in DWRITE_GLYPH_RUN const* glyphRun, 105 const COLORREF& textColor); 106 107 private: 108 CFX_DIBitmap* pBitmap_; 109 IDWriteBitmapRenderTarget* pRenderTarget_; 110 IDWriteRenderingParams* pRenderingParams_; 111 }; 112 CDWriteExt::CDWriteExt() { 113 m_hModule = NULL; 114 m_pDWriteFactory = NULL; 115 m_pDwFontContext = NULL; 116 m_pDwTextRenderer = NULL; 117 } 118 void CDWriteExt::Load() {} 119 void CDWriteExt::Unload() { 120 if (m_pDwFontContext) { 121 delete (CDwFontContext*)m_pDwFontContext; 122 m_pDwFontContext = NULL; 123 } 124 SafeRelease((IDWriteFactory**)&m_pDWriteFactory); 125 } 126 CDWriteExt::~CDWriteExt() { 127 Unload(); 128 } 129 LPVOID CDWriteExt::DwCreateFontFaceFromStream(uint8_t* pData, 130 FX_DWORD size, 131 int simulation_style) { 132 IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory; 133 IDWriteFontFile* pDwFontFile = NULL; 134 IDWriteFontFace* pDwFontFace = NULL; 135 BOOL isSupportedFontType = FALSE; 136 DWRITE_FONT_FILE_TYPE fontFileType; 137 DWRITE_FONT_FACE_TYPE fontFaceType; 138 UINT32 numberOfFaces; 139 DWRITE_FONT_SIMULATIONS fontStyle = 140 (DWRITE_FONT_SIMULATIONS)(simulation_style & 3); 141 HRESULT hr = S_OK; 142 hr = pDwFactory->CreateCustomFontFileReference( 143 (void const*)pData, (UINT32)size, CDwFontFileLoader::GetLoader(), 144 &pDwFontFile); 145 if (FAILED(hr)) { 146 goto failed; 147 } 148 hr = pDwFontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, 149 &numberOfFaces); 150 if (FAILED(hr) || !isSupportedFontType || 151 fontFaceType == DWRITE_FONT_FACE_TYPE_UNKNOWN) { 152 goto failed; 153 } 154 hr = pDwFactory->CreateFontFace(fontFaceType, 1, &pDwFontFile, 0, fontStyle, 155 &pDwFontFace); 156 if (FAILED(hr)) { 157 goto failed; 158 } 159 SafeRelease(&pDwFontFile); 160 return pDwFontFace; 161 failed: 162 SafeRelease(&pDwFontFile); 163 return NULL; 164 } 165 FX_BOOL CDWriteExt::DwCreateRenderingTarget(CFX_DIBitmap* pBitmap, 166 void** renderTarget) { 167 if (pBitmap->GetFormat() > FXDIB_Argb) { 168 return FALSE; 169 } 170 IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory; 171 IDWriteGdiInterop* pGdiInterop = NULL; 172 IDWriteBitmapRenderTarget* pBitmapRenderTarget = NULL; 173 IDWriteRenderingParams* pRenderingParams = NULL; 174 HRESULT hr = S_OK; 175 hr = pDwFactory->GetGdiInterop(&pGdiInterop); 176 if (FAILED(hr)) { 177 goto failed; 178 } 179 hr = pGdiInterop->CreateBitmapRenderTarget( 180 NULL, pBitmap->GetWidth(), pBitmap->GetHeight(), &pBitmapRenderTarget); 181 if (FAILED(hr)) { 182 goto failed; 183 } 184 hr = pDwFactory->CreateCustomRenderingParams( 185 1.0f, 0.0f, 1.0f, DWRITE_PIXEL_GEOMETRY_RGB, 186 DWRITE_RENDERING_MODE_DEFAULT, &pRenderingParams); 187 if (FAILED(hr)) { 188 goto failed; 189 } 190 hr = pBitmapRenderTarget->SetPixelsPerDip(1.0f); 191 if (FAILED(hr)) { 192 goto failed; 193 } 194 *(CDwGdiTextRenderer**)renderTarget = 195 new CDwGdiTextRenderer(pBitmap, pBitmapRenderTarget, pRenderingParams); 196 SafeRelease(&pGdiInterop); 197 SafeRelease(&pBitmapRenderTarget); 198 SafeRelease(&pRenderingParams); 199 return TRUE; 200 failed: 201 SafeRelease(&pGdiInterop); 202 SafeRelease(&pBitmapRenderTarget); 203 SafeRelease(&pRenderingParams); 204 return FALSE; 205 } 206 FX_BOOL CDWriteExt::DwRendingString(void* renderTarget, 207 CFX_ClipRgn* pClipRgn, 208 FX_RECT& stringRect, 209 CFX_Matrix* pMatrix, 210 void* font, 211 FX_FLOAT font_size, 212 FX_ARGB text_color, 213 int glyph_count, 214 unsigned short* glyph_indices, 215 FX_FLOAT baselineOriginX, 216 FX_FLOAT baselineOriginY, 217 void* glyph_offsets, 218 FX_FLOAT* glyph_advances) { 219 if (!renderTarget) { 220 return TRUE; 221 } 222 CDwGdiTextRenderer* pTextRenderer = (CDwGdiTextRenderer*)renderTarget; 223 DWRITE_MATRIX transform; 224 DWRITE_GLYPH_RUN glyphRun; 225 HRESULT hr = S_OK; 226 if (pMatrix) { 227 transform.m11 = pMatrix->a; 228 transform.m12 = pMatrix->b; 229 transform.m21 = pMatrix->c; 230 transform.m22 = pMatrix->d; 231 transform.dx = pMatrix->e; 232 transform.dy = pMatrix->f; 233 } 234 glyphRun.fontFace = (IDWriteFontFace*)font; 235 glyphRun.fontEmSize = font_size; 236 glyphRun.glyphCount = glyph_count; 237 glyphRun.glyphIndices = glyph_indices; 238 glyphRun.glyphAdvances = glyph_advances; 239 glyphRun.glyphOffsets = (DWRITE_GLYPH_OFFSET*)glyph_offsets; 240 glyphRun.isSideways = FALSE; 241 glyphRun.bidiLevel = 0; 242 hr = pTextRenderer->DrawGlyphRun( 243 stringRect, pClipRgn, pMatrix ? &transform : NULL, baselineOriginX, 244 baselineOriginY, DWRITE_MEASURING_MODE_NATURAL, &glyphRun, 245 RGB(FXARGB_R(text_color), FXARGB_G(text_color), FXARGB_B(text_color))); 246 return SUCCEEDED(hr); 247 } 248 void CDWriteExt::DwDeleteRenderingTarget(void* renderTarget) { 249 delete (CDwGdiTextRenderer*)renderTarget; 250 } 251 void CDWriteExt::DwDeleteFont(void* pFont) { 252 if (pFont) { 253 SafeRelease((IDWriteFontFace**)&pFont); 254 } 255 } 256 CDwFontFileStream::CDwFontFileStream(void const* fontFileReferenceKey, 257 UINT32 fontFileReferenceKeySize) { 258 refCount_ = 0; 259 resourcePtr_ = fontFileReferenceKey; 260 resourceSize_ = fontFileReferenceKeySize; 261 } 262 HRESULT STDMETHODCALLTYPE CDwFontFileStream::QueryInterface(REFIID iid, 263 void** ppvObject) { 264 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { 265 *ppvObject = this; 266 AddRef(); 267 return S_OK; 268 } 269 *ppvObject = NULL; 270 return E_NOINTERFACE; 271 } 272 ULONG STDMETHODCALLTYPE CDwFontFileStream::AddRef() { 273 return InterlockedIncrement((long*)(&refCount_)); 274 } 275 ULONG STDMETHODCALLTYPE CDwFontFileStream::Release() { 276 ULONG newCount = InterlockedDecrement((long*)(&refCount_)); 277 if (newCount == 0) { 278 delete this; 279 } 280 return newCount; 281 } 282 HRESULT STDMETHODCALLTYPE 283 CDwFontFileStream::ReadFileFragment(void const** fragmentStart, 284 UINT64 fileOffset, 285 UINT64 fragmentSize, 286 OUT void** fragmentContext) { 287 if (fileOffset <= resourceSize_ && 288 fragmentSize <= resourceSize_ - fileOffset) { 289 *fragmentStart = static_cast<uint8_t const*>(resourcePtr_) + 290 static_cast<size_t>(fileOffset); 291 *fragmentContext = NULL; 292 return S_OK; 293 } 294 *fragmentStart = NULL; 295 *fragmentContext = NULL; 296 return E_FAIL; 297 } 298 void STDMETHODCALLTYPE 299 CDwFontFileStream::ReleaseFileFragment(void* fragmentContext) {} 300 HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetFileSize(OUT UINT64* fileSize) { 301 *fileSize = resourceSize_; 302 return S_OK; 303 } 304 HRESULT STDMETHODCALLTYPE 305 CDwFontFileStream::GetLastWriteTime(OUT UINT64* lastWriteTime) { 306 *lastWriteTime = 0; 307 return E_NOTIMPL; 308 } 309 IDWriteFontFileLoader* CDwFontFileLoader::instance_ = NULL; 310 CDwFontFileLoader::CDwFontFileLoader() : refCount_(0) {} 311 HRESULT STDMETHODCALLTYPE CDwFontFileLoader::QueryInterface(REFIID iid, 312 void** ppvObject) { 313 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { 314 *ppvObject = this; 315 AddRef(); 316 return S_OK; 317 } 318 *ppvObject = NULL; 319 return E_NOINTERFACE; 320 } 321 ULONG STDMETHODCALLTYPE CDwFontFileLoader::AddRef() { 322 return InterlockedIncrement((long*)(&refCount_)); 323 } 324 ULONG STDMETHODCALLTYPE CDwFontFileLoader::Release() { 325 ULONG newCount = InterlockedDecrement((long*)(&refCount_)); 326 if (newCount == 0) { 327 instance_ = NULL; 328 delete this; 329 } 330 return newCount; 331 } 332 HRESULT STDMETHODCALLTYPE CDwFontFileLoader::CreateStreamFromKey( 333 void const* fontFileReferenceKey, 334 UINT32 fontFileReferenceKeySize, 335 OUT IDWriteFontFileStream** fontFileStream) { 336 *fontFileStream = NULL; 337 CDwFontFileStream* stream = 338 new CDwFontFileStream(fontFileReferenceKey, fontFileReferenceKeySize); 339 if (!stream->IsInitialized()) { 340 delete stream; 341 return E_FAIL; 342 } 343 *fontFileStream = SafeAcquire(stream); 344 return S_OK; 345 } 346 CDwFontContext::CDwFontContext(IDWriteFactory* dwriteFactory) 347 : hr_(S_FALSE), dwriteFactory_(SafeAcquire(dwriteFactory)) {} 348 CDwFontContext::~CDwFontContext() { 349 if (dwriteFactory_ && hr_ == S_OK) { 350 dwriteFactory_->UnregisterFontFileLoader(CDwFontFileLoader::GetLoader()); 351 } 352 SafeRelease(&dwriteFactory_); 353 } 354 HRESULT CDwFontContext::Initialize() { 355 if (hr_ == S_FALSE) { 356 return hr_ = dwriteFactory_->RegisterFontFileLoader( 357 CDwFontFileLoader::GetLoader()); 358 } 359 return hr_; 360 } 361 CDwGdiTextRenderer::CDwGdiTextRenderer( 362 CFX_DIBitmap* pBitmap, 363 IDWriteBitmapRenderTarget* bitmapRenderTarget, 364 IDWriteRenderingParams* renderingParams) 365 : pBitmap_(pBitmap), 366 pRenderTarget_(SafeAcquire(bitmapRenderTarget)), 367 pRenderingParams_(SafeAcquire(renderingParams)) {} 368 CDwGdiTextRenderer::~CDwGdiTextRenderer() { 369 SafeRelease(&pRenderTarget_); 370 SafeRelease(&pRenderingParams_); 371 } 372 STDMETHODIMP CDwGdiTextRenderer::DrawGlyphRun( 373 const FX_RECT& text_bbox, 374 __in_opt CFX_ClipRgn* pClipRgn, 375 __in_opt DWRITE_MATRIX const* pMatrix, 376 FLOAT baselineOriginX, 377 FLOAT baselineOriginY, 378 DWRITE_MEASURING_MODE measuringMode, 379 __in DWRITE_GLYPH_RUN const* glyphRun, 380 const COLORREF& textColor) { 381 HRESULT hr = S_OK; 382 if (pMatrix) { 383 hr = pRenderTarget_->SetCurrentTransform(pMatrix); 384 if (FAILED(hr)) { 385 return hr; 386 } 387 } 388 HDC hDC = pRenderTarget_->GetMemoryDC(); 389 HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC, OBJ_BITMAP); 390 BITMAP bitmap; 391 GetObject(hBitmap, sizeof bitmap, &bitmap); 392 CFX_DIBitmap dib; 393 dib.Create(bitmap.bmWidth, bitmap.bmHeight, 394 bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32, 395 (uint8_t*)bitmap.bmBits); 396 dib.CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), 397 text_bbox.Height(), pBitmap_, text_bbox.left, 398 text_bbox.top, FXDIB_BLEND_NORMAL, NULL); 399 hr = pRenderTarget_->DrawGlyphRun(baselineOriginX, baselineOriginY, 400 measuringMode, glyphRun, pRenderingParams_, 401 textColor); 402 if (FAILED(hr)) { 403 return hr; 404 } 405 pBitmap_->CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), 406 text_bbox.Height(), &dib, text_bbox.left, 407 text_bbox.top, FXDIB_BLEND_NORMAL, pClipRgn); 408 return hr; 409 } 410 #endif 411