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 "../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