diff options
-rw-r--r-- | core/fxge/win32/fx_win32_dib.cpp | 8 | ||||
-rw-r--r-- | core/fxge/win32/fx_win32_gdipext.cpp | 806 | ||||
-rw-r--r-- | core/fxge/win32/win32_int.h | 3 |
3 files changed, 412 insertions, 405 deletions
diff --git a/core/fxge/win32/fx_win32_dib.cpp b/core/fxge/win32/fx_win32_dib.cpp index 6416b5af36..452d033f64 100644 --- a/core/fxge/win32/fx_win32_dib.cpp +++ b/core/fxge/win32/fx_win32_dib.cpp @@ -52,9 +52,9 @@ ByteString CFX_WindowsDIB::GetBitmapInfo( return result; } -RetainPtr<CFX_DIBitmap> _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, - LPVOID pData, - bool bAlpha) { +RetainPtr<CFX_DIBitmap> FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData, + bool bAlpha) { int width = pbmi->bmiHeader.biWidth; int height = pbmi->bmiHeader.biHeight; BOOL bBottomUp = true; @@ -97,7 +97,7 @@ RetainPtr<CFX_DIBitmap> _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromBuf(BITMAPINFO* pbmi, LPVOID pData) { - return _FX_WindowsDIB_LoadFromBuf(pbmi, pData, false); + return FX_WindowsDIB_LoadFromBuf(pbmi, pData, false); } HBITMAP CFX_WindowsDIB::GetDDBitmap(const RetainPtr<CFX_DIBitmap>& pBitmap, diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp index a617036ea7..d784a0fa37 100644 --- a/core/fxge/win32/fx_win32_gdipext.cpp +++ b/core/fxge/win32/fx_win32_gdipext.cpp @@ -89,6 +89,8 @@ using Gdiplus::UnitWorld; #define GdiFillType2Gdip(fill_type) \ (fill_type == ALTERNATE ? FillModeAlternate : FillModeWinding) +namespace { + enum { FuncId_GdipCreatePath2, FuncId_GdipSetPenDashStyle, @@ -170,7 +172,7 @@ enum { FuncId_GdipSetPenTransform, }; -static LPCSTR g_GdipFuncNames[] = { +LPCSTR g_GdipFuncNames[] = { "GdipCreatePath2", "GdipSetPenDashStyle", "GdipSetPenDashArray", @@ -500,23 +502,7 @@ typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenTransform)(GpPen* pen, #define CallFunc(funcname) \ ((FuncType_##funcname)GdiplusExt.m_Functions[FuncId_##funcname]) -void* CGdiplusExt::GdiAddFontMemResourceEx(void* pFontdata, - uint32_t size, - void* pdv, - uint32_t* num_face) { - if (!m_pGdiAddFontMemResourceEx) - return nullptr; - - return m_pGdiAddFontMemResourceEx((PVOID)pFontdata, (DWORD)size, (PVOID)pdv, - (DWORD*)num_face); -} - -bool CGdiplusExt::GdiRemoveFontMemResourceEx(void* handle) { - return m_pGdiRemoveFontMemResourseEx && - m_pGdiRemoveFontMemResourseEx((HANDLE)handle); -} - -static GpBrush* _GdipCreateBrush(DWORD argb) { +GpBrush* GdipCreateBrushImpl(DWORD argb) { CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; GpSolidFill* solidBrush = nullptr; @@ -524,7 +510,7 @@ static GpBrush* _GdipCreateBrush(DWORD argb) { return solidBrush; } -static RetainPtr<CFX_DIBitmap> StretchMonoToGray( +RetainPtr<CFX_DIBitmap> StretchMonoToGray( int dest_width, int dest_height, const RetainPtr<CFX_DIBitmap>& pSource, @@ -579,15 +565,15 @@ static RetainPtr<CFX_DIBitmap> StretchMonoToGray( return pStretched; } -static void OutputImageMask(GpGraphics* pGraphics, - BOOL bMonoDevice, - const RetainPtr<CFX_DIBitmap>& pBitmap, - int dest_left, - int dest_top, - int dest_width, - int dest_height, - FX_ARGB argb, - const FX_RECT* pClipRect) { +void OutputImageMask(GpGraphics* pGraphics, + BOOL bMonoDevice, + const RetainPtr<CFX_DIBitmap>& pBitmap, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + FX_ARGB argb, + const FX_RECT* pClipRect) { ASSERT(pBitmap->GetBPP() == 1); CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; @@ -668,13 +654,14 @@ static void OutputImageMask(GpGraphics* pGraphics, CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); CallFunc(GdipDisposeImage)(bitmap); } -static void OutputImage(GpGraphics* pGraphics, - const RetainPtr<CFX_DIBitmap>& pBitmap, - const FX_RECT* pSrcRect, - int dest_left, - int dest_top, - int dest_width, - int dest_height) { + +void OutputImage(GpGraphics* pGraphics, + const RetainPtr<CFX_DIBitmap>& pBitmap, + const FX_RECT* pSrcRect, + int dest_left, + int dest_top, + int dest_width, + int dest_height) { int src_width = pSrcRect->Width(), src_height = pSrcRect->Height(); CGdiplusExt& GdiplusExt = ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; @@ -737,6 +724,385 @@ static void OutputImage(GpGraphics* pGraphics, CallFunc(GdipDisposeImage)(bitmap); } +GpPen* GdipCreatePenImpl(const CFX_GraphStateData* pGraphState, + const CFX_Matrix* pMatrix, + DWORD argb, + bool bTextMode) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + float width = pGraphState ? pGraphState->m_LineWidth : 1.0f; + if (!bTextMode) { + float unit = pMatrix + ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) + : 1.0f; + if (width < unit) + width = unit; + } + GpPen* pPen = nullptr; + CallFunc(GdipCreatePen1)((Gdiplus::ARGB)argb, width, UnitWorld, &pPen); + LineCap lineCap = LineCapFlat; + DashCap dashCap = DashCapFlat; + bool bDashExtend = false; + switch (pGraphState->m_LineCap) { + case CFX_GraphStateData::LineCapButt: + lineCap = LineCapFlat; + break; + case CFX_GraphStateData::LineCapRound: + lineCap = LineCapRound; + dashCap = DashCapRound; + bDashExtend = true; + break; + case CFX_GraphStateData::LineCapSquare: + lineCap = LineCapSquare; + bDashExtend = true; + break; + } + CallFunc(GdipSetPenLineCap197819)(pPen, lineCap, lineCap, dashCap); + LineJoin lineJoin = LineJoinMiterClipped; + switch (pGraphState->m_LineJoin) { + case CFX_GraphStateData::LineJoinMiter: + lineJoin = LineJoinMiterClipped; + break; + case CFX_GraphStateData::LineJoinRound: + lineJoin = LineJoinRound; + break; + case CFX_GraphStateData::LineJoinBevel: + lineJoin = LineJoinBevel; + break; + } + CallFunc(GdipSetPenLineJoin)(pPen, lineJoin); + if (pGraphState->m_DashCount) { + float* pDashArray = FX_Alloc( + float, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); + int nCount = 0; + float on_leftover = 0, off_leftover = 0; + for (int i = 0; i < pGraphState->m_DashCount; i += 2) { + float on_phase = pGraphState->m_DashArray[i]; + float off_phase; + if (i == pGraphState->m_DashCount - 1) + off_phase = on_phase; + else + off_phase = pGraphState->m_DashArray[i + 1]; + on_phase /= width; + off_phase /= width; + if (on_phase + off_phase <= 0.00002f) { + on_phase = 1.0f / 10; + off_phase = 1.0f / 10; + } + if (bDashExtend) { + if (off_phase < 1) + off_phase = 0; + else + off_phase -= 1; + on_phase += 1; + } + if (on_phase == 0 || off_phase == 0) { + if (nCount == 0) { + on_leftover += on_phase; + off_leftover += off_phase; + } else { + pDashArray[nCount - 2] += on_phase; + pDashArray[nCount - 1] += off_phase; + } + } else { + pDashArray[nCount++] = on_phase + on_leftover; + on_leftover = 0; + pDashArray[nCount++] = off_phase + off_leftover; + off_leftover = 0; + } + } + CallFunc(GdipSetPenDashArray)(pPen, pDashArray, nCount); + float phase = pGraphState->m_DashPhase; + if (bDashExtend) { + if (phase < 0.5f) + phase = 0; + else + phase -= 0.5f; + } + CallFunc(GdipSetPenDashOffset)(pPen, phase); + FX_Free(pDashArray); + pDashArray = nullptr; + } + CallFunc(GdipSetPenMiterLimit)(pPen, pGraphState->m_MiterLimit); + return pPen; +} + +bool IsSmallTriangle(Gdiplus::PointF* points, + const CFX_Matrix* pMatrix, + int& v1, + int& v2) { + int pairs[] = {1, 2, 0, 2, 0, 1}; + for (int i = 0; i < 3; i++) { + int pair1 = pairs[i * 2]; + int pair2 = pairs[i * 2 + 1]; + + CFX_PointF p1(points[pair1].X, points[pair1].Y); + CFX_PointF p2(points[pair2].X, points[pair2].Y); + if (pMatrix) { + p1 = pMatrix->Transform(p1); + p2 = pMatrix->Transform(p2); + } + + CFX_PointF diff = p1 - p2; + float distance_square = (diff.x * diff.x) + (diff.y * diff.y); + if (distance_square < (1.0f * 2 + 1.0f / 4)) { + v1 = i; + v2 = pair1; + return true; + } + } + return false; +} + +class GpStream final : public IStream { + public: + GpStream() : m_RefCount(1), m_ReadPos(0) {} + ~GpStream() = default; + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void** ppvObject) override { + if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || + iid == __uuidof(ISequentialStream)) { + *ppvObject = static_cast<IStream*>(this); + AddRef(); + return S_OK; + } + return E_NOINTERFACE; + } + ULONG STDMETHODCALLTYPE AddRef() override { + return (ULONG)InterlockedIncrement(&m_RefCount); + } + ULONG STDMETHODCALLTYPE Release() override { + ULONG res = (ULONG)InterlockedDecrement(&m_RefCount); + if (res == 0) { + delete this; + } + return res; + } + + // ISequentialStream + HRESULT STDMETHODCALLTYPE Read(void* output, + ULONG cb, + ULONG* pcbRead) override { + if (pcbRead) + *pcbRead = 0; + + if (m_ReadPos >= m_InterStream.tellp()) + return HRESULT_FROM_WIN32(ERROR_END_OF_MEDIA); + + size_t bytes_left = m_InterStream.tellp() - m_ReadPos; + size_t bytes_out = + std::min(pdfium::base::checked_cast<size_t>(cb), bytes_left); + memcpy(output, m_InterStream.str().c_str() + m_ReadPos, bytes_out); + m_ReadPos += bytes_out; + if (pcbRead) + *pcbRead = (ULONG)bytes_out; + + return S_OK; + } + HRESULT STDMETHODCALLTYPE Write(const void* input, + ULONG cb, + ULONG* pcbWritten) override { + if (cb <= 0) { + if (pcbWritten) + *pcbWritten = 0; + return S_OK; + } + m_InterStream.write(reinterpret_cast<const char*>(input), cb); + if (pcbWritten) + *pcbWritten = cb; + return S_OK; + } + + // IStream + HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE CopyTo(IStream*, + ULARGE_INTEGER, + ULARGE_INTEGER*, + ULARGE_INTEGER*) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE Commit(DWORD) override { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE Revert() override { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, + ULARGE_INTEGER, + DWORD) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, + ULARGE_INTEGER, + DWORD) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE Clone(IStream** stream) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, + DWORD dwOrigin, + ULARGE_INTEGER* lpNewFilePointer) override { + std::streamoff start; + std::streamoff new_read_position; + switch (dwOrigin) { + case STREAM_SEEK_SET: + start = 0; + break; + case STREAM_SEEK_CUR: + start = m_ReadPos; + break; + case STREAM_SEEK_END: + start = m_InterStream.tellp(); + break; + default: + return STG_E_INVALIDFUNCTION; + } + new_read_position = start + liDistanceToMove.QuadPart; + if (new_read_position > m_InterStream.tellp()) + return STG_E_SEEKERROR; + + m_ReadPos = new_read_position; + if (lpNewFilePointer) + lpNewFilePointer->QuadPart = m_ReadPos; + + return S_OK; + } + HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, + DWORD grfStatFlag) override { + if (!pStatstg) + return STG_E_INVALIDFUNCTION; + + ZeroMemory(pStatstg, sizeof(STATSTG)); + pStatstg->cbSize.QuadPart = m_InterStream.tellp(); + return S_OK; + } + + private: + LONG m_RefCount; + std::streamoff m_ReadPos; + std::ostringstream m_InterStream; +}; + +struct PREVIEW3_DIBITMAP { + BITMAPINFO* pbmi; + int Stride; + LPBYTE pScan0; + GpBitmap* pBitmap; + Gdiplus::BitmapData* pBitmapData; + GpStream* pStream; +}; + +PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { + GpBitmap* pBitmap; + GpStream* pStream = nullptr; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + Gdiplus::Status status = Gdiplus::Ok; + if (args.flags == WINDIB_OPEN_PATHNAME) { + status = CallFunc(GdipCreateBitmapFromFileICM)((wchar_t*)args.path_name, + &pBitmap); + } else { + if (args.memory_size == 0 || !args.memory_base) + return nullptr; + + pStream = new GpStream; + pStream->Write(args.memory_base, (ULONG)args.memory_size, nullptr); + status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap); + } + if (status != Gdiplus::Ok) { + if (pStream) + pStream->Release(); + + return nullptr; + } + UINT height, width; + CallFunc(GdipGetImageHeight)(pBitmap, &height); + CallFunc(GdipGetImageWidth)(pBitmap, &width); + Gdiplus::PixelFormat pixel_format; + CallFunc(GdipGetImagePixelFormat)(pBitmap, &pixel_format); + int info_size = sizeof(BITMAPINFOHEADER); + int bpp = 24; + int dest_pixel_format = PixelFormat24bppRGB; + if (pixel_format == PixelFormat1bppIndexed) { + info_size += 8; + bpp = 1; + dest_pixel_format = PixelFormat1bppIndexed; + } else if (pixel_format == PixelFormat8bppIndexed) { + info_size += 1024; + bpp = 8; + dest_pixel_format = PixelFormat8bppIndexed; + } else if (pixel_format == PixelFormat32bppARGB) { + bpp = 32; + dest_pixel_format = PixelFormat32bppARGB; + } + LPBYTE buf = FX_Alloc(BYTE, info_size); + BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)buf; + pbmih->biBitCount = bpp; + pbmih->biCompression = BI_RGB; + pbmih->biHeight = -(int)height; + pbmih->biPlanes = 1; + pbmih->biWidth = width; + Gdiplus::Rect rect(0, 0, width, height); + Gdiplus::BitmapData* pBitmapData = FX_Alloc(Gdiplus::BitmapData, 1); + CallFunc(GdipBitmapLockBits)(pBitmap, &rect, ImageLockModeRead, + dest_pixel_format, pBitmapData); + if (pixel_format == PixelFormat1bppIndexed || + pixel_format == PixelFormat8bppIndexed) { + DWORD* ppal = (DWORD*)(buf + sizeof(BITMAPINFOHEADER)); + struct { + UINT flags; + UINT Count; + DWORD Entries[256]; + } pal; + int size = 0; + CallFunc(GdipGetImagePaletteSize)(pBitmap, &size); + CallFunc(GdipGetImagePalette)(pBitmap, (Gdiplus::ColorPalette*)&pal, size); + int entries = pixel_format == PixelFormat1bppIndexed ? 2 : 256; + for (int i = 0; i < entries; i++) { + ppal[i] = pal.Entries[i] & 0x00ffffff; + } + } + PREVIEW3_DIBITMAP* pInfo = FX_Alloc(PREVIEW3_DIBITMAP, 1); + pInfo->pbmi = (BITMAPINFO*)buf; + pInfo->pScan0 = (LPBYTE)pBitmapData->Scan0; + pInfo->Stride = pBitmapData->Stride; + pInfo->pBitmap = pBitmap; + pInfo->pBitmapData = pBitmapData; + pInfo->pStream = pStream; + return pInfo; +} + +void FreeDIBitmap(PREVIEW3_DIBITMAP* pInfo) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipBitmapUnlockBits)(pInfo->pBitmap, pInfo->pBitmapData); + CallFunc(GdipDisposeImage)(pInfo->pBitmap); + FX_Free(pInfo->pBitmapData); + FX_Free((LPBYTE)pInfo->pbmi); + if (pInfo->pStream) + pInfo->pStream->Release(); + FX_Free(pInfo); +} + +} // namespace + +void* CGdiplusExt::GdiAddFontMemResourceEx(void* pFontdata, + uint32_t size, + void* pdv, + uint32_t* num_face) { + if (!m_pGdiAddFontMemResourceEx) + return nullptr; + + return m_pGdiAddFontMemResourceEx((PVOID)pFontdata, (DWORD)size, (PVOID)pdv, + (DWORD*)num_face); +} + +bool CGdiplusExt::GdiRemoveFontMemResourceEx(void* handle) { + return m_pGdiRemoveFontMemResourseEx && + m_pGdiRemoveFontMemResourseEx((HANDLE)handle); +} + CGdiplusExt::CGdiplusExt() {} CGdiplusExt::~CGdiplusExt() { @@ -1016,134 +1382,7 @@ bool CGdiplusExt::StretchDIBits(HDC hDC, CallFunc(GdipDeleteGraphics)(pGraphics); return true; } -static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, - const CFX_Matrix* pMatrix, - DWORD argb, - bool bTextMode = false) { - CGdiplusExt& GdiplusExt = - ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - float width = pGraphState ? pGraphState->m_LineWidth : 1.0f; - if (!bTextMode) { - float unit = pMatrix - ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) - : 1.0f; - if (width < unit) - width = unit; - } - GpPen* pPen = nullptr; - CallFunc(GdipCreatePen1)((Gdiplus::ARGB)argb, width, UnitWorld, &pPen); - LineCap lineCap = LineCapFlat; - DashCap dashCap = DashCapFlat; - bool bDashExtend = false; - switch (pGraphState->m_LineCap) { - case CFX_GraphStateData::LineCapButt: - lineCap = LineCapFlat; - break; - case CFX_GraphStateData::LineCapRound: - lineCap = LineCapRound; - dashCap = DashCapRound; - bDashExtend = true; - break; - case CFX_GraphStateData::LineCapSquare: - lineCap = LineCapSquare; - bDashExtend = true; - break; - } - CallFunc(GdipSetPenLineCap197819)(pPen, lineCap, lineCap, dashCap); - LineJoin lineJoin = LineJoinMiterClipped; - switch (pGraphState->m_LineJoin) { - case CFX_GraphStateData::LineJoinMiter: - lineJoin = LineJoinMiterClipped; - break; - case CFX_GraphStateData::LineJoinRound: - lineJoin = LineJoinRound; - break; - case CFX_GraphStateData::LineJoinBevel: - lineJoin = LineJoinBevel; - break; - } - CallFunc(GdipSetPenLineJoin)(pPen, lineJoin); - if (pGraphState->m_DashCount) { - float* pDashArray = FX_Alloc( - float, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); - int nCount = 0; - float on_leftover = 0, off_leftover = 0; - for (int i = 0; i < pGraphState->m_DashCount; i += 2) { - float on_phase = pGraphState->m_DashArray[i]; - float off_phase; - if (i == pGraphState->m_DashCount - 1) - off_phase = on_phase; - else - off_phase = pGraphState->m_DashArray[i + 1]; - on_phase /= width; - off_phase /= width; - if (on_phase + off_phase <= 0.00002f) { - on_phase = 1.0f / 10; - off_phase = 1.0f / 10; - } - if (bDashExtend) { - if (off_phase < 1) - off_phase = 0; - else - off_phase -= 1; - on_phase += 1; - } - if (on_phase == 0 || off_phase == 0) { - if (nCount == 0) { - on_leftover += on_phase; - off_leftover += off_phase; - } else { - pDashArray[nCount - 2] += on_phase; - pDashArray[nCount - 1] += off_phase; - } - } else { - pDashArray[nCount++] = on_phase + on_leftover; - on_leftover = 0; - pDashArray[nCount++] = off_phase + off_leftover; - off_leftover = 0; - } - } - CallFunc(GdipSetPenDashArray)(pPen, pDashArray, nCount); - float phase = pGraphState->m_DashPhase; - if (bDashExtend) { - if (phase < 0.5f) - phase = 0; - else - phase -= 0.5f; - } - CallFunc(GdipSetPenDashOffset)(pPen, phase); - FX_Free(pDashArray); - pDashArray = nullptr; - } - CallFunc(GdipSetPenMiterLimit)(pPen, pGraphState->m_MiterLimit); - return pPen; -} -static bool IsSmallTriangle(Gdiplus::PointF* points, - const CFX_Matrix* pMatrix, - int& v1, - int& v2) { - int pairs[] = {1, 2, 0, 2, 0, 1}; - for (int i = 0; i < 3; i++) { - int pair1 = pairs[i * 2]; - int pair2 = pairs[i * 2 + 1]; - CFX_PointF p1(points[pair1].X, points[pair1].Y); - CFX_PointF p2(points[pair2].X, points[pair2].Y); - if (pMatrix) { - p1 = pMatrix->Transform(p1); - p2 = pMatrix->Transform(p2); - } - - CFX_PointF diff = p1 - p2; - float distance_square = (diff.x * diff.x) + (diff.y * diff.y); - if (distance_square < (1.0f * 2 + 1.0f / 4)) { - v1 = i; - v2 = pair1; - return true; - } - } - return false; -} bool CGdiplusExt::DrawPath(HDC hDC, const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device, @@ -1262,14 +1501,14 @@ bool CGdiplusExt::DrawPath(HDC hDC, return false; } if (new_fill_mode) { - GpBrush* pBrush = _GdipCreateBrush(fill_argb); + GpBrush* pBrush = GdipCreateBrushImpl(fill_argb); CallFunc(GdipSetPathFillMode)(pGpPath, GdiFillType2Gdip(new_fill_mode)); CallFunc(GdipFillPath)(pGraphics, pBrush, pGpPath); CallFunc(GdipDeleteBrush)(pBrush); } if (pGraphState && stroke_argb) { - GpPen* pPen = _GdipCreatePen(pGraphState, pObject2Device, stroke_argb, - !!(fill_mode & FX_STROKE_TEXT_MODE)); + GpPen* pPen = GdipCreatePenImpl(pGraphState, pObject2Device, stroke_argb, + !!(fill_mode & FX_STROKE_TEXT_MODE)); if (nSubPathes == 1) { CallFunc(GdipDrawPath)(pGraphics, pPen, pGpPath); } else { @@ -1297,241 +1536,6 @@ bool CGdiplusExt::DrawPath(HDC hDC, return true; } -class GpStream final : public IStream { - public: - GpStream() : m_RefCount(1), m_ReadPos(0) {} - - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, - void** ppvObject) override { - if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || - iid == __uuidof(ISequentialStream)) { - *ppvObject = static_cast<IStream*>(this); - AddRef(); - return S_OK; - } - return E_NOINTERFACE; - } - ULONG STDMETHODCALLTYPE AddRef() override { - return (ULONG)InterlockedIncrement(&m_RefCount); - } - ULONG STDMETHODCALLTYPE Release() override { - ULONG res = (ULONG)InterlockedDecrement(&m_RefCount); - if (res == 0) { - delete this; - } - return res; - } - - // ISequentialStream - HRESULT STDMETHODCALLTYPE Read(void* output, - ULONG cb, - ULONG* pcbRead) override { - if (pcbRead) - *pcbRead = 0; - - if (m_ReadPos >= m_InterStream.tellp()) - return HRESULT_FROM_WIN32(ERROR_END_OF_MEDIA); - - size_t bytes_left = m_InterStream.tellp() - m_ReadPos; - size_t bytes_out = - std::min(pdfium::base::checked_cast<size_t>(cb), bytes_left); - memcpy(output, m_InterStream.str().c_str() + m_ReadPos, bytes_out); - m_ReadPos += bytes_out; - if (pcbRead) - *pcbRead = (ULONG)bytes_out; - - return S_OK; - } - HRESULT STDMETHODCALLTYPE Write(const void* input, - ULONG cb, - ULONG* pcbWritten) override { - if (cb <= 0) { - if (pcbWritten) - *pcbWritten = 0; - return S_OK; - } - m_InterStream.write(reinterpret_cast<const char*>(input), cb); - if (pcbWritten) - *pcbWritten = cb; - return S_OK; - } - - // IStream - HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) override { - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE CopyTo(IStream*, - ULARGE_INTEGER, - ULARGE_INTEGER*, - ULARGE_INTEGER*) override { - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE Commit(DWORD) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE Revert() override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, - ULARGE_INTEGER, - DWORD) override { - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, - ULARGE_INTEGER, - DWORD) override { - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE Clone(IStream** stream) override { - return E_NOTIMPL; - } - HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, - DWORD dwOrigin, - ULARGE_INTEGER* lpNewFilePointer) override { - std::streamoff start; - std::streamoff new_read_position; - switch (dwOrigin) { - case STREAM_SEEK_SET: - start = 0; - break; - case STREAM_SEEK_CUR: - start = m_ReadPos; - break; - case STREAM_SEEK_END: - start = m_InterStream.tellp(); - break; - default: - return STG_E_INVALIDFUNCTION; - } - new_read_position = start + liDistanceToMove.QuadPart; - if (new_read_position > m_InterStream.tellp()) - return STG_E_SEEKERROR; - - m_ReadPos = new_read_position; - if (lpNewFilePointer) - lpNewFilePointer->QuadPart = m_ReadPos; - - return S_OK; - } - HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, - DWORD grfStatFlag) override { - if (!pStatstg) - return STG_E_INVALIDFUNCTION; - - ZeroMemory(pStatstg, sizeof(STATSTG)); - pStatstg->cbSize.QuadPart = m_InterStream.tellp(); - return S_OK; - } - - private: - LONG m_RefCount; - std::streamoff m_ReadPos; - std::ostringstream m_InterStream; -}; - -typedef struct { - BITMAPINFO* pbmi; - int Stride; - LPBYTE pScan0; - GpBitmap* pBitmap; - Gdiplus::BitmapData* pBitmapData; - GpStream* pStream; -} PREVIEW3_DIBITMAP; - -static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { - GpBitmap* pBitmap; - GpStream* pStream = nullptr; - CGdiplusExt& GdiplusExt = - ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - Gdiplus::Status status = Gdiplus::Ok; - if (args.flags == WINDIB_OPEN_PATHNAME) { - status = CallFunc(GdipCreateBitmapFromFileICM)((wchar_t*)args.path_name, - &pBitmap); - } else { - if (args.memory_size == 0 || !args.memory_base) - return nullptr; - - pStream = new GpStream; - pStream->Write(args.memory_base, (ULONG)args.memory_size, nullptr); - status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap); - } - if (status != Gdiplus::Ok) { - if (pStream) - pStream->Release(); - - return nullptr; - } - UINT height, width; - CallFunc(GdipGetImageHeight)(pBitmap, &height); - CallFunc(GdipGetImageWidth)(pBitmap, &width); - Gdiplus::PixelFormat pixel_format; - CallFunc(GdipGetImagePixelFormat)(pBitmap, &pixel_format); - int info_size = sizeof(BITMAPINFOHEADER); - int bpp = 24; - int dest_pixel_format = PixelFormat24bppRGB; - if (pixel_format == PixelFormat1bppIndexed) { - info_size += 8; - bpp = 1; - dest_pixel_format = PixelFormat1bppIndexed; - } else if (pixel_format == PixelFormat8bppIndexed) { - info_size += 1024; - bpp = 8; - dest_pixel_format = PixelFormat8bppIndexed; - } else if (pixel_format == PixelFormat32bppARGB) { - bpp = 32; - dest_pixel_format = PixelFormat32bppARGB; - } - LPBYTE buf = FX_Alloc(BYTE, info_size); - BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)buf; - pbmih->biBitCount = bpp; - pbmih->biCompression = BI_RGB; - pbmih->biHeight = -(int)height; - pbmih->biPlanes = 1; - pbmih->biWidth = width; - Gdiplus::Rect rect(0, 0, width, height); - Gdiplus::BitmapData* pBitmapData = FX_Alloc(Gdiplus::BitmapData, 1); - CallFunc(GdipBitmapLockBits)(pBitmap, &rect, ImageLockModeRead, - dest_pixel_format, pBitmapData); - if (pixel_format == PixelFormat1bppIndexed || - pixel_format == PixelFormat8bppIndexed) { - DWORD* ppal = (DWORD*)(buf + sizeof(BITMAPINFOHEADER)); - struct { - UINT flags; - UINT Count; - DWORD Entries[256]; - } pal; - int size = 0; - CallFunc(GdipGetImagePaletteSize)(pBitmap, &size); - CallFunc(GdipGetImagePalette)(pBitmap, (Gdiplus::ColorPalette*)&pal, size); - int entries = pixel_format == PixelFormat1bppIndexed ? 2 : 256; - for (int i = 0; i < entries; i++) { - ppal[i] = pal.Entries[i] & 0x00ffffff; - } - } - PREVIEW3_DIBITMAP* pInfo = FX_Alloc(PREVIEW3_DIBITMAP, 1); - pInfo->pbmi = (BITMAPINFO*)buf; - pInfo->pScan0 = (LPBYTE)pBitmapData->Scan0; - pInfo->Stride = pBitmapData->Stride; - pInfo->pBitmap = pBitmap; - pInfo->pBitmapData = pBitmapData; - pInfo->pStream = pStream; - return pInfo; -} - -static void FreeDIBitmap(PREVIEW3_DIBITMAP* pInfo) { - CGdiplusExt& GdiplusExt = - ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; - CallFunc(GdipBitmapUnlockBits)(pInfo->pBitmap, pInfo->pBitmapData); - CallFunc(GdipDisposeImage)(pInfo->pBitmap); - FX_Free(pInfo->pBitmapData); - FX_Free((LPBYTE)pInfo->pbmi); - if (pInfo->pStream) - pInfo->pStream->Release(); - FX_Free(pInfo); -} - -// TODO(tsepez): Really? Really? Move to header. -RetainPtr<CFX_DIBitmap> _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, - LPVOID pData, - bool bAlpha); - RetainPtr<CFX_DIBitmap> CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { PREVIEW3_DIBITMAP* pInfo = ::LoadDIBitmap(args); if (!pInfo) @@ -1549,7 +1553,7 @@ RetainPtr<CFX_DIBitmap> CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { dest_pitch); } } - RetainPtr<CFX_DIBitmap> pDIBitmap = _FX_WindowsDIB_LoadFromBuf( + RetainPtr<CFX_DIBitmap> pDIBitmap = FX_WindowsDIB_LoadFromBuf( pInfo->pbmi, pData, pInfo->pbmi->bmiHeader.biBitCount == 32); FX_Free(pData); FreeDIBitmap(pInfo); diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h index 8bc8290845..f27a420734 100644 --- a/core/fxge/win32/win32_int.h +++ b/core/fxge/win32/win32_int.h @@ -29,6 +29,9 @@ typedef HANDLE(__stdcall* FuncType_GdiAddFontMemResourceEx)(PVOID pbFont, DWORD* pcFonts); typedef BOOL(__stdcall* FuncType_GdiRemoveFontMemResourceEx)(HANDLE handle); +RetainPtr<CFX_DIBitmap> FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData, + bool bAlpha); class CGdiplusExt { public: CGdiplusExt(); |