17daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta// Copyright 2014 PDFium Authors. All rights reserved.
27daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta// Use of this source code is governed by a BSD-style license that can be
37daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta// found in the LICENSE file.
47daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta
57daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
67daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta
77daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#include "../../../include/fxge/fx_ge.h"
87daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
97daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#include "../../../include/fxge/fx_ge_win32.h"
107daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#include "dwrite_int.h"
117daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta#include "../Microsoft SDK/include/DWrite.h"
127daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptatypedef HRESULT  (__stdcall *FuncType_DWriteCreateFactory)(__in DWRITE_FACTORY_TYPE, __in REFIID, __out IUnknown **);
137daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptatemplate <typename InterfaceType>
147daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptainline void SafeRelease(InterfaceType** currentObject)
157daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
167daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (*currentObject != NULL) {
177daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        (*currentObject)->Release();
187daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        *currentObject = NULL;
197daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
207daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
217daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptatemplate <typename InterfaceType>
227daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptainline InterfaceType* SafeAcquire(InterfaceType* newObject)
237daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
247daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (newObject != NULL) {
257daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        newObject->AddRef();
267daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
277daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    return newObject;
287daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
297daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaclass CDwFontFileStream : public IDWriteFontFileStream, public CFX_Object
307daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
317daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptapublic:
327daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    explicit CDwFontFileStream(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize);
337daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
347daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual ULONG   STDMETHODCALLTYPE AddRef();
357daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual ULONG   STDMETHODCALLTYPE Release();
367daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize, OUT void** fragmentContext);
377daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual void    STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
387daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
397daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
407daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    bool IsInitialized()
417daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    {
427daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        return resourcePtr_ != NULL;
437daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
447daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaprivate:
457daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    ULONG refCount_;
467daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    void const* resourcePtr_;
477daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWORD resourceSize_;
487daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta};
497daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaclass CDwFontFileLoader : public IDWriteFontFileLoader, public CFX_Object
507daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
517daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptapublic:
527daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
537daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual ULONG STDMETHODCALLTYPE AddRef();
547daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual ULONG STDMETHODCALLTYPE Release();
557daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize, OUT IDWriteFontFileStream** fontFileStream);
567daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta
577daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    static IDWriteFontFileLoader* GetLoader()
587daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    {
597daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        if (instance_ == NULL) {
607daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta            instance_ = FX_NEW CDwFontFileLoader();
617daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta            return instance_;
627daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        }
637daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        return instance_;
647daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
657daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    static bool IsLoaderInitialized()
667daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    {
677daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        return instance_ != NULL;
687daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
697daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaprivate:
707daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CDwFontFileLoader();
717daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    ULONG refCount_;
727daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    static IDWriteFontFileLoader* instance_;
737daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta};
747daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaclass CDwFontContext : public CFX_Object
757daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
767daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptapublic:
777daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CDwFontContext(IDWriteFactory* dwriteFactory);
787daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    ~CDwFontContext();
797daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    HRESULT Initialize();
807daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaprivate:
817daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CDwFontContext(CDwFontContext const&);
827daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    void operator=(CDwFontContext const&);
837daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    HRESULT hr_;
847daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteFactory* dwriteFactory_;
857daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta};
867daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaclass CDwGdiTextRenderer : public CFX_Object
877daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
887daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptapublic:
897daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CDwGdiTextRenderer(
907daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        CFX_DIBitmap* pBitmap,
917daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        IDWriteBitmapRenderTarget* bitmapRenderTarget,
927daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        IDWriteRenderingParams* renderingParams
937daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    );
94549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    CDwGdiTextRenderer::~CDwGdiTextRenderer();
95549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    HRESULT STDMETHODCALLTYPE DrawGlyphRun(
967daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        const FX_RECT& text_bbox,
977daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        __in_opt CFX_ClipRgn* pClipRgn,
987daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        __in_opt DWRITE_MATRIX const* pMatrix,
997daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        FLOAT baselineOriginX,
1007daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        FLOAT baselineOriginY,
1017daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        DWRITE_MEASURING_MODE measuringMode,
1027daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        __in DWRITE_GLYPH_RUN const* glyphRun,
1037daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        const COLORREF& textColor
1047daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    );
1057daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptaprivate:
1067daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CFX_DIBitmap* pBitmap_;
1077daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteBitmapRenderTarget* pRenderTarget_;
1087daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteRenderingParams* pRenderingParams_;
1097daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta};
1107daacbbbe7349677476a3d2fbf174dcf86f171beVineet GuptaCDWriteExt::CDWriteExt()
1117daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1127daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    m_hModule = NULL;
1137daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    m_pDWriteFactory = NULL;
1147daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    m_pDwFontContext = NULL;
1157daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    m_pDwTextRenderer = NULL;
1167daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
1177daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptavoid CDWriteExt::Load()
1187daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1197daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
1207daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptavoid CDWriteExt::Unload()
1217daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1227daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (m_pDwFontContext) {
1237daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        delete (CDwFontContext*)m_pDwFontContext;
1247daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        m_pDwFontContext = NULL;
1257daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1267daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    SafeRelease((IDWriteFactory**)&m_pDWriteFactory);
1277daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
1287daacbbbe7349677476a3d2fbf174dcf86f171beVineet GuptaCDWriteExt::~CDWriteExt()
1297daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1307daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    Unload();
1317daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
1327daacbbbe7349677476a3d2fbf174dcf86f171beVineet GuptaLPVOID	CDWriteExt::DwCreateFontFaceFromStream(FX_LPBYTE pData, FX_DWORD size, int simulation_style)
1337daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1347daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory;
1357daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteFontFile* pDwFontFile = NULL;
1367daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteFontFace* pDwFontFace = NULL;
1377daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    BOOL isSupportedFontType = FALSE;
1387daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWRITE_FONT_FILE_TYPE fontFileType;
1397daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWRITE_FONT_FACE_TYPE fontFaceType;
1407daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    UINT32 numberOfFaces;
1417daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWRITE_FONT_SIMULATIONS fontStyle = (DWRITE_FONT_SIMULATIONS)(simulation_style & 3);
1427daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    HRESULT hr = S_OK;
1437daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pDwFactory->CreateCustomFontFileReference(
1447daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             (void const*)pData,
1457daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             (UINT32)size,
1467daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             CDwFontFileLoader::GetLoader(),
1477daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &pDwFontFile
1487daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta         );
1497daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
1507daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
1517daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1527daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pDwFontFile->Analyze(
1537daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &isSupportedFontType,
1547daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &fontFileType,
1557daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &fontFaceType,
1567daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &numberOfFaces
1577daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta         );
1587daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr) || !isSupportedFontType || fontFaceType == DWRITE_FONT_FACE_TYPE_UNKNOWN) {
1597daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
1607daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1617daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pDwFactory->CreateFontFace(
1627daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             fontFaceType,
1637daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             1,
1647daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &pDwFontFile,
1657daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             0,
1667daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             fontStyle,
1677daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &pDwFontFace
1687daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta         );
1697daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
1707daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
1717daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1727daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    SafeRelease(&pDwFontFile);
1737daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    return pDwFontFace;
1747daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptafailed:
1757daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    SafeRelease(&pDwFontFile);
1767daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    return NULL;
1777daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
1787daacbbbe7349677476a3d2fbf174dcf86f171beVineet GuptaFX_BOOL CDWriteExt::DwCreateRenderingTarget(CFX_DIBitmap* pBitmap, void** renderTarget)
1797daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
1807daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (pBitmap->GetFormat() > FXDIB_Argb) {
1817daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        return FALSE;
1827daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1837daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteFactory* pDwFactory = (IDWriteFactory*)m_pDWriteFactory;
1847daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteGdiInterop* pGdiInterop = NULL;
1857daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteBitmapRenderTarget* pBitmapRenderTarget = NULL;
1867daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    IDWriteRenderingParams* pRenderingParams = NULL;
1877daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    HRESULT hr = S_OK;
1887daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pDwFactory->GetGdiInterop(&pGdiInterop);
1897daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
1907daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
1917daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
1927daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pGdiInterop->CreateBitmapRenderTarget(NULL, pBitmap->GetWidth(), pBitmap->GetHeight(),
1937daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta            &pBitmapRenderTarget);
1947daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
1957daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
1967daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
197549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    hr = pDwFactory->CreateCustomRenderingParams(
198549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin             1.0f,
1997daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             0.0f,
2007daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             1.0f,
2017daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             DWRITE_PIXEL_GEOMETRY_RGB,
2027daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             DWRITE_RENDERING_MODE_DEFAULT,
2037daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &pRenderingParams
2047daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta         );
2057daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
2067daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
2077daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
2087daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pBitmapRenderTarget->SetPixelsPerDip(1.0f);
2097daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (FAILED(hr)) {
2107daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
2117daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
2127daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    *(CDwGdiTextRenderer**)renderTarget = FX_NEW CDwGdiTextRenderer(pBitmap, pBitmapRenderTarget, pRenderingParams);
2137daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (*(CDwGdiTextRenderer**)renderTarget == NULL) {
2147daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        goto failed;
215549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    }
216549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    SafeRelease(&pGdiInterop);
217549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    SafeRelease(&pBitmapRenderTarget);
2187daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    SafeRelease(&pRenderingParams);
2197daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    return TRUE;
2207daacbbbe7349677476a3d2fbf174dcf86f171beVineet Guptafailed:
2217daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    SafeRelease(&pGdiInterop);
222549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    SafeRelease(&pBitmapRenderTarget);
223549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    SafeRelease(&pRenderingParams);
2247daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    return FALSE;
2257daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta}
2267daacbbbe7349677476a3d2fbf174dcf86f171beVineet GuptaFX_BOOL	CDWriteExt::DwRendingString(void* renderTarget, CFX_ClipRgn* pClipRgn, FX_RECT& stringRect, CFX_AffineMatrix* pMatrix,
227549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin                                    void *font, FX_FLOAT font_size, FX_ARGB text_color,
2287daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta                                    int glyph_count, unsigned short* glyph_indices,
2297daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta                                    FX_FLOAT baselineOriginX, FX_FLOAT baselineOriginY,
2307daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta                                    void* glyph_offsets,
2317daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta                                    FX_FLOAT* glyph_advances)
2327daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta{
2337daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (renderTarget == NULL) {
2347daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        return TRUE;
235549e2c4a9858a380b03eb6e2ff4861d2c6687d6aDmitry V. Levin    }
2367daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    CDwGdiTextRenderer* pTextRenderer = (CDwGdiTextRenderer*)renderTarget;
2377daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWRITE_MATRIX transform;
2387daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    DWRITE_GLYPH_RUN glyphRun;
2397daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    HRESULT hr = S_OK;
2407daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    if (pMatrix) {
2417daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.m11 = pMatrix->a;
2427daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.m12 = pMatrix->b;
2437daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.m21 = pMatrix->c;
2447daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.m22 = pMatrix->d;
2457daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.dx = pMatrix->e;
2467daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta        transform.dy = pMatrix->f;
2477daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    }
2487daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.fontFace = (IDWriteFontFace*)font;
2497daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.fontEmSize = font_size;
2507daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.glyphCount = glyph_count;
2517daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.glyphIndices = glyph_indices;
2527daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.glyphAdvances = glyph_advances;
2537daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.glyphOffsets = (DWRITE_GLYPH_OFFSET*)glyph_offsets;
2547daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.isSideways = FALSE;
2557daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    glyphRun.bidiLevel = 0;
2567daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta    hr = pTextRenderer->DrawGlyphRun(
2577daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             stringRect,
2587daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             pClipRgn,
2597daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             pMatrix ? &transform : NULL,
2607daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             baselineOriginX, baselineOriginY,
2617daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             DWRITE_MEASURING_MODE_NATURAL,
2627daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             &glyphRun,
2637daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta             RGB(FXARGB_R(text_color), FXARGB_G(text_color), FXARGB_B(text_color))
2647daacbbbe7349677476a3d2fbf174dcf86f171beVineet Gupta         );
265    return SUCCEEDED(hr) ? TRUE : FALSE;
266}
267void CDWriteExt::DwDeleteRenderingTarget(void* renderTarget)
268{
269    if (renderTarget) {
270        delete (CDwGdiTextRenderer*)renderTarget;
271    }
272}
273void CDWriteExt::DwDeleteFont(void* pFont)
274{
275    if (pFont) {
276        SafeRelease((IDWriteFontFace**)&pFont);
277    }
278}
279CDwFontFileStream::CDwFontFileStream(void const* fontFileReferenceKey, UINT32 fontFileReferenceKeySize)
280{
281    refCount_ = 0;
282    resourcePtr_ = fontFileReferenceKey;
283    resourceSize_ = fontFileReferenceKeySize;
284}
285HRESULT 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}
296ULONG STDMETHODCALLTYPE CDwFontFileStream::AddRef()
297{
298    return InterlockedIncrement((long*)(&refCount_));
299}
300ULONG STDMETHODCALLTYPE CDwFontFileStream::Release()
301{
302    ULONG newCount = InterlockedDecrement((long*)(&refCount_));
303    if (newCount == 0) {
304        delete this;
305    }
306    return newCount;
307}
308HRESULT 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}
326void STDMETHODCALLTYPE CDwFontFileStream::ReleaseFileFragment(void* fragmentContext)
327{
328}
329HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetFileSize(OUT UINT64* fileSize)
330{
331    *fileSize = resourceSize_;
332    return S_OK;
333}
334HRESULT STDMETHODCALLTYPE CDwFontFileStream::GetLastWriteTime(OUT UINT64* lastWriteTime)
335{
336    *lastWriteTime = 0;
337    return E_NOTIMPL;
338}
339IDWriteFontFileLoader* CDwFontFileLoader::instance_ = NULL;
340CDwFontFileLoader::CDwFontFileLoader() :
341    refCount_(0)
342{
343}
344HRESULT 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}
355ULONG STDMETHODCALLTYPE CDwFontFileLoader::AddRef()
356{
357    return InterlockedIncrement((long*)(&refCount_));
358}
359ULONG 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}
368HRESULT 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}
386CDwFontContext::CDwFontContext(IDWriteFactory* dwriteFactory) :
387    hr_(S_FALSE),
388    dwriteFactory_(SafeAcquire(dwriteFactory))
389{
390}
391CDwFontContext::~CDwFontContext()
392{
393    if(dwriteFactory_ && hr_ == S_OK) {
394        dwriteFactory_->UnregisterFontFileLoader(CDwFontFileLoader::GetLoader());
395    }
396    SafeRelease(&dwriteFactory_);
397}
398HRESULT CDwFontContext::Initialize()
399{
400    if (hr_ == S_FALSE) {
401        return hr_ = dwriteFactory_->RegisterFontFileLoader(CDwFontFileLoader::GetLoader());
402    }
403    return hr_;
404}
405CDwGdiTextRenderer::CDwGdiTextRenderer(CFX_DIBitmap* pBitmap, IDWriteBitmapRenderTarget* bitmapRenderTarget, IDWriteRenderingParams* renderingParams):
406    pBitmap_(pBitmap),
407    pRenderTarget_(SafeAcquire(bitmapRenderTarget)),
408    pRenderingParams_(SafeAcquire(renderingParams))
409{
410}
411CDwGdiTextRenderer::~CDwGdiTextRenderer()
412{
413    SafeRelease(&pRenderTarget_);
414    SafeRelease(&pRenderingParams_);
415}
416STDMETHODIMP 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