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