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