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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
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"
12 typedef HRESULT (__stdcall *FuncType_DWriteCreateFactory)(__in DWRITE_FACTORY_TYPE, __in REFIID, __out IUnknown **);
13 template <typename InterfaceType>
14 inline void SafeRelease(InterfaceType** currentObject)
16 if (*currentObject != NULL) {
17 (*currentObject)->Release();
18 *currentObject = NULL;
21 template <typename InterfaceType>
22 inline InterfaceType* SafeAcquire(InterfaceType* newObject)
24 if (newObject != NULL) {
29 class CDwFontFileStream FX_FINAL : public IDWriteFontFileStream, public CFX_Object
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);
42 return resourcePtr_ != NULL;
46 void const* resourcePtr_;
49 class CDwFontFileLoader FX_FINAL : public IDWriteFontFileLoader, public CFX_Object
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);
57 static IDWriteFontFileLoader* GetLoader()
59 if (instance_ == NULL) {
60 instance_ = FX_NEW CDwFontFileLoader();
65 static bool IsLoaderInitialized()
67 return instance_ != NULL;
72 static IDWriteFontFileLoader* instance_;
74 class CDwFontContext : public CFX_Object
77 CDwFontContext(IDWriteFactory* dwriteFactory);
81 CDwFontContext(CDwFontContext const&);
82 void operator=(CDwFontContext const&);
84 IDWriteFactory* dwriteFactory_;
86 class CDwGdiTextRenderer : public CFX_Object
90 CFX_DIBitmap* pBitmap,
91 IDWriteBitmapRenderTarget* bitmapRenderTarget,
92 IDWriteRenderingParams* renderingParams
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
106 CFX_DIBitmap* pBitmap_;
107 IDWriteBitmapRenderTarget* pRenderTarget_;
108 IDWriteRenderingParams* pRenderingParams_;
110 CDWriteExt::CDWriteExt()
113 m_pDWriteFactory = NULL;
114 m_pDwFontContext = NULL;
115 m_pDwTextRenderer = NULL;
117 void CDWriteExt::Load()
120 void CDWriteExt::Unload()
122 if (m_pDwFontContext) {
123 delete (CDwFontContext*)m_pDwFontContext;
124 m_pDwFontContext = NULL;
126 SafeRelease((IDWriteFactory**)&m_pDWriteFactory);
128 CDWriteExt::~CDWriteExt()
132 LPVOID CDWriteExt::DwCreateFontFaceFromStream(FX_LPBYTE pData, FX_DWORD size, int simulation_style)
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);
143 hr = pDwFactory->CreateCustomFontFileReference(
146 CDwFontFileLoader::GetLoader(),
152 hr = pDwFontFile->Analyze(
153 &isSupportedFontType,
158 if (FAILED(hr) || !isSupportedFontType || fontFaceType == DWRITE_FONT_FACE_TYPE_UNKNOWN) {
161 hr = pDwFactory->CreateFontFace(
172 SafeRelease(&pDwFontFile);
175 SafeRelease(&pDwFontFile);
178 FX_BOOL CDWriteExt::DwCreateRenderingTarget(CFX_DIBitmap* pBitmap, void** renderTarget)
180 if (pBitmap->GetFormat() > FXDIB_Argb) {
183 IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory;
184 IDWriteGdiInterop* pGdiInterop = NULL;
185 IDWriteBitmapRenderTarget* pBitmapRenderTarget = NULL;
186 IDWriteRenderingParams* pRenderingParams = NULL;
188 hr = pDwFactory->GetGdiInterop(&pGdiInterop);
192 hr = pGdiInterop->CreateBitmapRenderTarget(NULL, pBitmap->GetWidth(), pBitmap->GetHeight(),
193 &pBitmapRenderTarget);
197 hr = pDwFactory->CreateCustomRenderingParams(
201 DWRITE_PIXEL_GEOMETRY_RGB,
202 DWRITE_RENDERING_MODE_DEFAULT,
208 hr = pBitmapRenderTarget->SetPixelsPerDip(1.0f);
212 *(CDwGdiTextRenderer**)renderTarget = FX_NEW CDwGdiTextRenderer(pBitmap, pBitmapRenderTarget, pRenderingParams);
213 if (*(CDwGdiTextRenderer**)renderTarget == NULL) {
216 SafeRelease(&pGdiInterop);
217 SafeRelease(&pBitmapRenderTarget);
218 SafeRelease(&pRenderingParams);
221 SafeRelease(&pGdiInterop);
222 SafeRelease(&pBitmapRenderTarget);
223 SafeRelease(&pRenderingParams);
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,
231 FX_FLOAT* glyph_advances)
233 if (renderTarget == NULL) {
236 CDwGdiTextRenderer* pTextRenderer = (CDwGdiTextRenderer*)renderTarget;
237 DWRITE_MATRIX transform;
238 DWRITE_GLYPH_RUN glyphRun;
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;
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(
259 pMatrix ? &transform : NULL,
260 baselineOriginX, baselineOriginY,
261 DWRITE_MEASURING_MODE_NATURAL,
263 RGB(FXARGB_R(text_color), FXARGB_G(text_color), FXARGB_B(text_color))
265 return SUCCEEDED(hr) ? TRUE : FALSE;
267 void CDWriteExt::DwDeleteRenderingTarget(void* renderTarget)
270 delete (CDwGdiTextRenderer*)renderTarget;
273 void CDWriteExt::DwDeleteFont(void* pFont)
276 SafeRelease((IDWriteFontFace**)&pFont);
279 CDwFontFileStream::CDwFontFileStream(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize)
282 resourcePtr_ = fontFileReferenceKey;
283 resourceSize_ = fontFileReferenceKeySize;
285 HRESULT STDMETHODCALLTYPE CDwFontFileStream::QueryInterface(REFIID iid, void** ppvObject)
287 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
293 return E_NOINTERFACE;
296 ULONG STDMETHODCALLTYPE CDwFontFileStream::AddRef()
298 return InterlockedIncrement((long*)(&refCount_));
300 ULONG STDMETHODCALLTYPE CDwFontFileStream::Release()
302 ULONG newCount = InterlockedDecrement((long*)(&refCount_));
308 HRESULT STDMETHODCALLTYPE CDwFontFileStream::ReadFileFragment(
309 void const** fragmentStart,
312 OUT void** fragmentContext
315 if (fileOffset <= resourceSize_ &&
316 fragmentSize <= resourceSize_ - fileOffset) {
317 *fragmentStart = static_cast<FX_BYTE const*>(resourcePtr_) + static_cast<size_t>(fileOffset);
318 *fragmentContext = NULL;
321 *fragmentStart = NULL;
322 *fragmentContext = NULL;
326 void STDMETHODCALLTYPE CDwFontFileStream::ReleaseFileFragment(void* fragmentContext)
329 HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetFileSize(OUT UINT64* fileSize)
331 *fileSize = resourceSize_;
334 HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetLastWriteTime(OUT UINT64* lastWriteTime)
339 IDWriteFontFileLoader* CDwFontFileLoader::instance_ = NULL;
340 CDwFontFileLoader::CDwFontFileLoader() :
344 HRESULT STDMETHODCALLTYPE CDwFontFileLoader::QueryInterface(REFIID iid, void** ppvObject)
346 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
352 return E_NOINTERFACE;
355 ULONG STDMETHODCALLTYPE CDwFontFileLoader::AddRef()
357 return InterlockedIncrement((long*)(&refCount_));
359 ULONG STDMETHODCALLTYPE CDwFontFileLoader::Release()
361 ULONG newCount = InterlockedDecrement((long*)(&refCount_));
368 HRESULT STDMETHODCALLTYPE CDwFontFileLoader::CreateStreamFromKey(
369 void const* fontFileReferenceKey,
370 UINT32 fontFileReferenceKeySize,
371 OUT IDWriteFontFileStream** fontFileStream
374 *fontFileStream = NULL;
375 CDwFontFileStream* stream = FX_NEW CDwFontFileStream(fontFileReferenceKey, fontFileReferenceKeySize);
376 if (stream == NULL) {
377 return E_OUTOFMEMORY;
379 if (!stream->IsInitialized()) {
383 *fontFileStream = SafeAcquire(stream);
386 CDwFontContext::CDwFontContext(IDWriteFactory* dwriteFactory) :
388 dwriteFactory_(SafeAcquire(dwriteFactory))
391 CDwFontContext::~CDwFontContext()
393 if(dwriteFactory_ && hr_ == S_OK) {
394 dwriteFactory_->UnregisterFontFileLoader(CDwFontFileLoader::GetLoader());
396 SafeRelease(&dwriteFactory_);
398 HRESULT CDwFontContext::Initialize()
400 if (hr_ == S_FALSE) {
401 return hr_ = dwriteFactory_->RegisterFontFileLoader(CDwFontFileLoader::GetLoader());
405 CDwGdiTextRenderer::CDwGdiTextRenderer(CFX_DIBitmap* pBitmap, IDWriteBitmapRenderTarget* bitmapRenderTarget, IDWriteRenderingParams* renderingParams):
407 pRenderTarget_(SafeAcquire(bitmapRenderTarget)),
408 pRenderingParams_(SafeAcquire(renderingParams))
411 CDwGdiTextRenderer::~CDwGdiTextRenderer()
413 SafeRelease(&pRenderTarget_);
414 SafeRelease(&pRenderingParams_);
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
429 hr = pRenderTarget_->SetCurrentTransform(pMatrix);
434 HDC hDC = pRenderTarget_->GetMemoryDC();
435 HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC, OBJ_BITMAP);
437 GetObject(hBitmap, sizeof bitmap, &bitmap);
442 bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32,
443 (FX_LPBYTE)bitmap.bmBits
456 hr = pRenderTarget_->DrawGlyphRun(
467 pBitmap_->CompositeBitmap(