From 764ec513eecbebd12781bcc96ce81ed5e736ee92 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Mon, 14 Mar 2016 13:35:12 -0400 Subject: Move core/src/ up to core/. This CL moves the core/src/ files up to core/ and fixes up the include guards, includes and build files. R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1800523005 . --- core/fxge/win32/fx_win32_gdipext.cpp | 1518 ++++++++++++++++++++++++++++++++++ 1 file changed, 1518 insertions(+) create mode 100644 core/fxge/win32/fx_win32_gdipext.cpp (limited to 'core/fxge/win32/fx_win32_gdipext.cpp') diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp new file mode 100644 index 0000000000..ce181bb448 --- /dev/null +++ b/core/fxge/win32/fx_win32_gdipext.cpp @@ -0,0 +1,1518 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/include/fxge/fx_ge.h" + +#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ +#include +#include + +namespace Gdiplus { +using std::min; +using std::max; +} // namespace Gdiplus + +#include + +#include "core/fxge/win32/win32_int.h" +#include "core/include/fxge/fx_ge_win32.h" + +using namespace Gdiplus; // NOLINT +using namespace Gdiplus::DllExports; // NOLINT + +#define GdiFillType2Gdip(fill_type) \ + (fill_type == ALTERNATE ? FillModeAlternate : FillModeWinding) + +enum { + FuncId_GdipCreatePath2, + FuncId_GdipSetPenDashStyle, + FuncId_GdipSetPenDashArray, + FuncId_GdipSetPenDashCap197819, + FuncId_GdipSetPenLineJoin, + FuncId_GdipSetPenWidth, + FuncId_GdipCreateFromHDC, + FuncId_GdipSetPageUnit, + FuncId_GdipSetSmoothingMode, + FuncId_GdipCreateSolidFill, + FuncId_GdipFillPath, + FuncId_GdipDeleteBrush, + FuncId_GdipCreatePen1, + FuncId_GdipSetPenMiterLimit, + FuncId_GdipDrawPath, + FuncId_GdipDeletePen, + FuncId_GdipDeletePath, + FuncId_GdipDeleteGraphics, + FuncId_GdipCreateBitmapFromFileICM, + FuncId_GdipCreateBitmapFromStreamICM, + FuncId_GdipGetImageHeight, + FuncId_GdipGetImageWidth, + FuncId_GdipGetImagePixelFormat, + FuncId_GdipBitmapLockBits, + FuncId_GdipGetImagePaletteSize, + FuncId_GdipGetImagePalette, + FuncId_GdipBitmapUnlockBits, + FuncId_GdipDisposeImage, + FuncId_GdipFillRectangle, + FuncId_GdipCreateBitmapFromScan0, + FuncId_GdipSetImagePalette, + FuncId_GdipSetInterpolationMode, + FuncId_GdipDrawImagePointsI, + FuncId_GdipCreateBitmapFromGdiDib, + FuncId_GdiplusStartup, + FuncId_GdipDrawLineI, + FuncId_GdipResetClip, + FuncId_GdipCreatePath, + FuncId_GdipAddPathPath, + FuncId_GdipSetPathFillMode, + FuncId_GdipSetClipPath, + FuncId_GdipGetClip, + FuncId_GdipCreateRegion, + FuncId_GdipGetClipBoundsI, + FuncId_GdipSetClipRegion, + FuncId_GdipWidenPath, + FuncId_GdipAddPathLine, + FuncId_GdipAddPathRectangle, + FuncId_GdipDeleteRegion, + FuncId_GdipGetDC, + FuncId_GdipReleaseDC, + FuncId_GdipSetPenLineCap197819, + FuncId_GdipSetPenDashOffset, + FuncId_GdipResetPath, + FuncId_GdipCreateRegionPath, + FuncId_GdipCreateFont, + FuncId_GdipGetFontSize, + FuncId_GdipCreateFontFamilyFromName, + FuncId_GdipSetTextRenderingHint, + FuncId_GdipDrawDriverString, + FuncId_GdipCreateMatrix2, + FuncId_GdipDeleteMatrix, + FuncId_GdipSetWorldTransform, + FuncId_GdipResetWorldTransform, + FuncId_GdipDeleteFontFamily, + FuncId_GdipDeleteFont, + FuncId_GdipNewPrivateFontCollection, + FuncId_GdipDeletePrivateFontCollection, + FuncId_GdipPrivateAddMemoryFont, + FuncId_GdipGetFontCollectionFamilyList, + FuncId_GdipGetFontCollectionFamilyCount, + FuncId_GdipSetTextContrast, + FuncId_GdipSetPixelOffsetMode, + FuncId_GdipGetImageGraphicsContext, + FuncId_GdipDrawImageI, + FuncId_GdipDrawImageRectI, + FuncId_GdipDrawString, + FuncId_GdipSetPenTransform, +}; +static LPCSTR g_GdipFuncNames[] = { + "GdipCreatePath2", + "GdipSetPenDashStyle", + "GdipSetPenDashArray", + "GdipSetPenDashCap197819", + "GdipSetPenLineJoin", + "GdipSetPenWidth", + "GdipCreateFromHDC", + "GdipSetPageUnit", + "GdipSetSmoothingMode", + "GdipCreateSolidFill", + "GdipFillPath", + "GdipDeleteBrush", + "GdipCreatePen1", + "GdipSetPenMiterLimit", + "GdipDrawPath", + "GdipDeletePen", + "GdipDeletePath", + "GdipDeleteGraphics", + "GdipCreateBitmapFromFileICM", + "GdipCreateBitmapFromStreamICM", + "GdipGetImageHeight", + "GdipGetImageWidth", + "GdipGetImagePixelFormat", + "GdipBitmapLockBits", + "GdipGetImagePaletteSize", + "GdipGetImagePalette", + "GdipBitmapUnlockBits", + "GdipDisposeImage", + "GdipFillRectangle", + "GdipCreateBitmapFromScan0", + "GdipSetImagePalette", + "GdipSetInterpolationMode", + "GdipDrawImagePointsI", + "GdipCreateBitmapFromGdiDib", + "GdiplusStartup", + "GdipDrawLineI", + "GdipResetClip", + "GdipCreatePath", + "GdipAddPathPath", + "GdipSetPathFillMode", + "GdipSetClipPath", + "GdipGetClip", + "GdipCreateRegion", + "GdipGetClipBoundsI", + "GdipSetClipRegion", + "GdipWidenPath", + "GdipAddPathLine", + "GdipAddPathRectangle", + "GdipDeleteRegion", + "GdipGetDC", + "GdipReleaseDC", + "GdipSetPenLineCap197819", + "GdipSetPenDashOffset", + "GdipResetPath", + "GdipCreateRegionPath", + "GdipCreateFont", + "GdipGetFontSize", + "GdipCreateFontFamilyFromName", + "GdipSetTextRenderingHint", + "GdipDrawDriverString", + "GdipCreateMatrix2", + "GdipDeleteMatrix", + "GdipSetWorldTransform", + "GdipResetWorldTransform", + "GdipDeleteFontFamily", + "GdipDeleteFont", + "GdipNewPrivateFontCollection", + "GdipDeletePrivateFontCollection", + "GdipPrivateAddMemoryFont", + "GdipGetFontCollectionFamilyList", + "GdipGetFontCollectionFamilyCount", + "GdipSetTextContrast", + "GdipSetPixelOffsetMode", + "GdipGetImageGraphicsContext", + "GdipDrawImageI", + "GdipDrawImageRectI", + "GdipDrawString", + "GdipSetPenTransform", +}; +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePath2)(GDIPCONST GpPointF*, + GDIPCONST BYTE*, + INT, + GpFillMode, + GpPath** path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashStyle)( + GpPen* pen, + GpDashStyle dashstyle); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashArray)(GpPen* pen, + GDIPCONST REAL* dash, + INT count); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashCap197819)( + GpPen* pen, + GpDashCap dashCap); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenLineJoin)(GpPen* pen, + GpLineJoin lineJoin); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenWidth)(GpPen* pen, REAL width); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFromHDC)(HDC hdc, + GpGraphics** graphics); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPageUnit)(GpGraphics* graphics, + GpUnit unit); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetSmoothingMode)( + GpGraphics* graphics, + SmoothingMode smoothingMode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateSolidFill)(ARGB color, + GpSolidFill** brush); +typedef GpStatus(WINGDIPAPI* FuncType_GdipFillPath)(GpGraphics* graphics, + GpBrush* brush, + GpPath* path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteBrush)(GpBrush* brush); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePen1)(ARGB color, + REAL width, + GpUnit unit, + GpPen** pen); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenMiterLimit)(GpPen* pen, + REAL miterLimit); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawPath)(GpGraphics* graphics, + GpPen* pen, + GpPath* path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePen)(GpPen* pen); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePath)(GpPath* path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteGraphics)(GpGraphics* graphics); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromFileICM)( + GDIPCONST WCHAR* filename, + GpBitmap** bitmap); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromStreamICM)( + IStream* stream, + GpBitmap** bitmap); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageWidth)(GpImage* image, + UINT* width); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageHeight)(GpImage* image, + UINT* height); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePixelFormat)( + GpImage* image, + PixelFormat* format); +typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapLockBits)( + GpBitmap* bitmap, + GDIPCONST GpRect* rect, + UINT flags, + PixelFormat format, + BitmapData* lockedBitmapData); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePalette)( + GpImage* image, + ColorPalette* palette, + INT size); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImagePaletteSize)(GpImage* image, + INT* size); +typedef GpStatus(WINGDIPAPI* FuncType_GdipBitmapUnlockBits)( + GpBitmap* bitmap, + BitmapData* lockedBitmapData); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDisposeImage)(GpImage* image); +typedef GpStatus(WINGDIPAPI* FuncType_GdipFillRectangle)(GpGraphics* graphics, + GpBrush* brush, + REAL x, + REAL y, + REAL width, + REAL height); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromScan0)( + INT width, + INT height, + INT stride, + PixelFormat format, + BYTE* scan0, + GpBitmap** bitmap); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetImagePalette)( + GpImage* image, + GDIPCONST ColorPalette* palette); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetInterpolationMode)( + GpGraphics* graphics, + InterpolationMode interpolationMode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImagePointsI)( + GpGraphics* graphics, + GpImage* image, + GDIPCONST GpPoint* dstpoints, + INT count); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateBitmapFromGdiDib)( + GDIPCONST BITMAPINFO* gdiBitmapInfo, + VOID* gdiBitmapData, + GpBitmap** bitmap); +typedef Status(WINAPI* FuncType_GdiplusStartup)( + OUT uintptr_t* token, + const GdiplusStartupInput* input, + OUT GdiplusStartupOutput* output); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawLineI)(GpGraphics* graphics, + GpPen* pen, + int x1, + int y1, + int x2, + int y2); +typedef GpStatus(WINGDIPAPI* FuncType_GdipResetClip)(GpGraphics* graphics); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreatePath)(GpFillMode brushMode, + GpPath** path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathPath)( + GpPath* path, + GDIPCONST GpPath* addingPath, + BOOL connect); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPathFillMode)(GpPath* path, + GpFillMode fillmode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetClipPath)(GpGraphics* graphics, + GpPath* path, + CombineMode combineMode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetClip)(GpGraphics* graphics, + GpRegion* region); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateRegion)(GpRegion** region); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetClipBoundsI)(GpGraphics* graphics, + GpRect* rect); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetClipRegion)( + GpGraphics* graphics, + GpRegion* region, + CombineMode combineMode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipWidenPath)(GpPath* nativePath, + GpPen* pen, + GpMatrix* matrix, + REAL flatness); +typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathLine)(GpPath* path, + REAL x1, + REAL y1, + REAL x2, + REAL y2); +typedef GpStatus(WINGDIPAPI* FuncType_GdipAddPathRectangle)(GpPath* path, + REAL x, + REAL y, + REAL width, + REAL height); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteRegion)(GpRegion* region); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetDC)(GpGraphics* graphics, + HDC* hdc); +typedef GpStatus(WINGDIPAPI* FuncType_GdipReleaseDC)(GpGraphics* graphics, + HDC hdc); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenLineCap197819)( + GpPen* pen, + GpLineCap startCap, + GpLineCap endCap, + GpDashCap dashCap); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenDashOffset)(GpPen* pen, + REAL offset); +typedef GpStatus(WINGDIPAPI* FuncType_GdipResetPath)(GpPath* path); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateRegionPath)(GpPath* path, + GpRegion** region); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFont)( + GDIPCONST GpFontFamily* fontFamily, + REAL emSize, + INT style, + Unit unit, + GpFont** font); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontSize)(GpFont* font, + REAL* size); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateFontFamilyFromName)( + GDIPCONST WCHAR* name, + GpFontCollection* fontCollection, + GpFontFamily** FontFamily); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetTextRenderingHint)( + GpGraphics* graphics, + TextRenderingHint mode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawDriverString)( + GpGraphics* graphics, + GDIPCONST UINT16* text, + INT length, + GDIPCONST GpFont* font, + GDIPCONST GpBrush* brush, + GDIPCONST PointF* positions, + INT flags, + GDIPCONST GpMatrix* matrix); +typedef GpStatus(WINGDIPAPI* FuncType_GdipCreateMatrix2)(REAL m11, + REAL m12, + REAL m21, + REAL m22, + REAL dx, + REAL dy, + GpMatrix** matrix); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteMatrix)(GpMatrix* matrix); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetWorldTransform)( + GpGraphics* graphics, + GpMatrix* matrix); +typedef GpStatus(WINGDIPAPI* FuncType_GdipResetWorldTransform)( + GpGraphics* graphics); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteFontFamily)( + GpFontFamily* FontFamily); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeleteFont)(GpFont* font); +typedef GpStatus(WINGDIPAPI* FuncType_GdipNewPrivateFontCollection)( + GpFontCollection** fontCollection); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDeletePrivateFontCollection)( + GpFontCollection** fontCollection); +typedef GpStatus(WINGDIPAPI* FuncType_GdipPrivateAddMemoryFont)( + GpFontCollection* fontCollection, + GDIPCONST void* memory, + INT length); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontCollectionFamilyList)( + GpFontCollection* fontCollection, + INT numSought, + GpFontFamily* gpfamilies[], + INT* numFound); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetFontCollectionFamilyCount)( + GpFontCollection* fontCollection, + INT* numFound); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetTextContrast)(GpGraphics* graphics, + UINT contrast); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPixelOffsetMode)( + GpGraphics* graphics, + PixelOffsetMode pixelOffsetMode); +typedef GpStatus(WINGDIPAPI* FuncType_GdipGetImageGraphicsContext)( + GpImage* image, + GpGraphics** graphics); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImageI)(GpGraphics* graphics, + GpImage* image, + INT x, + INT y); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawImageRectI)(GpGraphics* graphics, + GpImage* image, + INT x, + INT y, + INT width, + INT height); +typedef GpStatus(WINGDIPAPI* FuncType_GdipDrawString)( + GpGraphics* graphics, + GDIPCONST WCHAR* str, + INT length, + GDIPCONST GpFont* font, + GDIPCONST RectF* layoutRect, + GDIPCONST GpStringFormat* stringFormat, + GDIPCONST GpBrush* brush); +typedef GpStatus(WINGDIPAPI* FuncType_GdipSetPenTransform)(GpPen* pen, + GpMatrix* matrix); +#define CallFunc(funcname) \ + ((FuncType_##funcname)GdiplusExt.m_Functions[FuncId_##funcname]) +typedef HANDLE(__stdcall* FuncType_GdiAddFontMemResourceEx)(PVOID pbFont, + DWORD cbFont, + PVOID pdv, + DWORD* pcFonts); +typedef BOOL(__stdcall* FuncType_GdiRemoveFontMemResourceEx)(HANDLE handle); +void* CGdiplusExt::GdiAddFontMemResourceEx(void* pFontdata, + FX_DWORD size, + void* pdv, + FX_DWORD* num_face) { + if (m_pGdiAddFontMemResourceEx) { + return ((FuncType_GdiAddFontMemResourceEx)m_pGdiAddFontMemResourceEx)( + (PVOID)pFontdata, (DWORD)size, (PVOID)pdv, (DWORD*)num_face); + } + return NULL; +} +FX_BOOL CGdiplusExt::GdiRemoveFontMemResourceEx(void* handle) { + if (m_pGdiRemoveFontMemResourseEx) { + return ((FuncType_GdiRemoveFontMemResourceEx)m_pGdiRemoveFontMemResourseEx)( + (HANDLE)handle); + } + return FALSE; +} +static GpBrush* _GdipCreateBrush(DWORD argb) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpSolidFill* solidBrush = NULL; + CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); + return solidBrush; +} +static CFX_DIBitmap* _StretchMonoToGray(int dest_width, + int dest_height, + const CFX_DIBitmap* pSource, + FX_RECT* pClipRect) { + FX_BOOL bFlipX = dest_width < 0; + if (bFlipX) { + dest_width = -dest_width; + } + FX_BOOL bFlipY = dest_height < 0; + if (bFlipY) { + dest_height = -dest_height; + } + int result_width = pClipRect->Width(); + int result_height = pClipRect->Height(); + int result_pitch = (result_width + 3) / 4 * 4; + CFX_DIBitmap* pStretched = new CFX_DIBitmap; + if (!pStretched->Create(result_width, result_height, FXDIB_8bppRgb)) { + delete pStretched; + return NULL; + } + LPBYTE dest_buf = pStretched->GetBuffer(); + int src_width = pSource->GetWidth(); + int src_height = pSource->GetHeight(); + int y_unit = src_height / dest_height; + int x_unit = src_width / dest_width; + int area_unit = y_unit * x_unit; + LPBYTE src_buf = pSource->GetBuffer(); + int src_pitch = pSource->GetPitch(); + for (int dest_y = 0; dest_y < result_height; dest_y++) { + LPBYTE dest_scan = dest_buf + dest_y * result_pitch; + int src_y_start = bFlipY ? (dest_height - 1 - dest_y - pClipRect->top) + : (dest_y + pClipRect->top); + src_y_start = src_y_start * src_height / dest_height; + LPBYTE src_scan = src_buf + src_y_start * src_pitch; + for (int dest_x = 0; dest_x < result_width; dest_x++) { + int sum = 0; + int src_x_start = bFlipX ? (dest_width - 1 - dest_x - pClipRect->left) + : (dest_x + pClipRect->left); + src_x_start = src_x_start * src_width / dest_width; + int src_x_end = src_x_start + x_unit; + LPBYTE src_line = src_scan; + for (int src_y = 0; src_y < y_unit; src_y++) { + for (int src_x = src_x_start; src_x < src_x_end; src_x++) { + if (!(src_line[src_x / 8] & (1 << (7 - src_x % 8)))) { + sum += 255; + } + } + src_line += src_pitch; + } + dest_scan[dest_x] = 255 - sum / area_unit; + } + } + return pStretched; +} +static void OutputImageMask(GpGraphics* pGraphics, + BOOL bMonoDevice, + const 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; + int src_width = pBitmap->GetWidth(), src_height = pBitmap->GetHeight(); + int src_pitch = pBitmap->GetPitch(); + uint8_t* scan0 = pBitmap->GetBuffer(); + if (src_width == 1 && src_height == 1) { + if ((scan0[0] & 0x80) == 0) { + return; + } + GpSolidFill* solidBrush; + CallFunc(GdipCreateSolidFill)((ARGB)argb, &solidBrush); + if (dest_width < 0) { + dest_width = -dest_width; + dest_left -= dest_width; + } + if (dest_height < 0) { + dest_height = -dest_height; + dest_top -= dest_height; + } + CallFunc(GdipFillRectangle)(pGraphics, solidBrush, (float)dest_left, + (float)dest_top, (float)dest_width, + (float)dest_height); + CallFunc(GdipDeleteBrush)(solidBrush); + return; + } + if (!bMonoDevice && abs(dest_width) < src_width && + abs(dest_height) < src_height) { + FX_RECT image_rect(dest_left, dest_top, dest_left + dest_width, + dest_top + dest_height); + image_rect.Normalize(); + FX_RECT image_clip = image_rect; + image_clip.Intersect(*pClipRect); + if (image_clip.IsEmpty()) { + return; + } + image_clip.Offset(-image_rect.left, -image_rect.top); + CFX_DIBitmap* pStretched = NULL; + if (src_width * src_height > 10000) { + pStretched = + _StretchMonoToGray(dest_width, dest_height, pBitmap, &image_clip); + } else { + pStretched = + pBitmap->StretchTo(dest_width, dest_height, FALSE, &image_clip); + } + GpBitmap* bitmap; + CallFunc(GdipCreateBitmapFromScan0)(image_clip.Width(), image_clip.Height(), + (image_clip.Width() + 3) / 4 * 4, + PixelFormat8bppIndexed, + pStretched->GetBuffer(), &bitmap); + int a, r, g, b; + ArgbDecode(argb, a, r, g, b); + UINT pal[258]; + pal[0] = 0; + pal[1] = 256; + for (int i = 0; i < 256; i++) { + pal[i + 2] = ArgbEncode(i * a / 255, r, g, b); + } + CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); + CallFunc(GdipDrawImageI)(pGraphics, bitmap, + image_rect.left + image_clip.left, + image_rect.top + image_clip.top); + CallFunc(GdipDisposeImage)(bitmap); + delete pStretched; + return; + } + GpBitmap* bitmap; + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat1bppIndexed, scan0, &bitmap); + UINT palette[4] = {PaletteFlagsHasAlpha, 2, 0, argb}; + CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)palette); + Point destinationPoints[] = {Point(dest_left, dest_top), + Point(dest_left + dest_width, dest_top), + Point(dest_left, dest_top + dest_height)}; + CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); + CallFunc(GdipDisposeImage)(bitmap); +} +static void OutputImage(GpGraphics* pGraphics, + const 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; + if (pBitmap->GetBPP() == 1 && (pSrcRect->left % 8)) { + FX_RECT new_rect(0, 0, src_width, src_height); + CFX_DIBitmap* pCloned = pBitmap->Clone(pSrcRect); + if (!pCloned) { + return; + } + OutputImage(pGraphics, pCloned, &new_rect, dest_left, dest_top, dest_width, + dest_height); + delete pCloned; + return; + } + int src_pitch = pBitmap->GetPitch(); + uint8_t* scan0 = pBitmap->GetBuffer() + pSrcRect->top * src_pitch + + pBitmap->GetBPP() * pSrcRect->left / 8; + GpBitmap* bitmap = NULL; + switch (pBitmap->GetFormat()) { + case FXDIB_Argb: + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat32bppARGB, scan0, &bitmap); + break; + case FXDIB_Rgb32: + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat32bppRGB, scan0, &bitmap); + break; + case FXDIB_Rgb: + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat24bppRGB, scan0, &bitmap); + break; + case FXDIB_8bppRgb: { + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat8bppIndexed, scan0, + &bitmap); + UINT pal[258]; + pal[0] = 0; + pal[1] = 256; + for (int i = 0; i < 256; i++) { + pal[i + 2] = pBitmap->GetPaletteEntry(i); + } + CallFunc(GdipSetImagePalette)(bitmap, (ColorPalette*)pal); + break; + } + case FXDIB_1bppRgb: { + CallFunc(GdipCreateBitmapFromScan0)(src_width, src_height, src_pitch, + PixelFormat1bppIndexed, scan0, + &bitmap); + break; + } + } + if (dest_height < 0) { + dest_height--; + } + if (dest_width < 0) { + dest_width--; + } + Point destinationPoints[] = {Point(dest_left, dest_top), + Point(dest_left + dest_width, dest_top), + Point(dest_left, dest_top + dest_height)}; + CallFunc(GdipDrawImagePointsI)(pGraphics, bitmap, destinationPoints, 3); + CallFunc(GdipDisposeImage)(bitmap); +} +CGdiplusExt::CGdiplusExt() { + m_hModule = NULL; + m_GdiModule = NULL; + for (int i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { + m_Functions[i] = NULL; + } + m_pGdiAddFontMemResourceEx = NULL; + m_pGdiRemoveFontMemResourseEx = NULL; +} +void CGdiplusExt::Load() { + CFX_ByteString strPlusPath = ""; + FX_CHAR buf[MAX_PATH]; + GetSystemDirectoryA(buf, MAX_PATH); + strPlusPath += buf; + strPlusPath += "\\"; + strPlusPath += "GDIPLUS.DLL"; + m_hModule = LoadLibraryA(strPlusPath); + if (!m_hModule) { + return; + } + for (int i = 0; i < sizeof g_GdipFuncNames / sizeof(LPCSTR); i++) { + m_Functions[i] = GetProcAddress(m_hModule, g_GdipFuncNames[i]); + if (!m_Functions[i]) { + m_hModule = NULL; + return; + } + } + uintptr_t gdiplusToken; + GdiplusStartupInput gdiplusStartupInput; + ((FuncType_GdiplusStartup)m_Functions[FuncId_GdiplusStartup])( + &gdiplusToken, &gdiplusStartupInput, NULL); + m_GdiModule = LoadLibraryA("GDI32.DLL"); + if (!m_GdiModule) { + return; + } + m_pGdiAddFontMemResourceEx = + GetProcAddress(m_GdiModule, "AddFontMemResourceEx"); + m_pGdiRemoveFontMemResourseEx = + GetProcAddress(m_GdiModule, "RemoveFontMemResourceEx"); +} +CGdiplusExt::~CGdiplusExt() {} +LPVOID CGdiplusExt::LoadMemFont(LPBYTE pData, FX_DWORD size) { + GpFontCollection* pCollection = NULL; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipNewPrivateFontCollection)(&pCollection); + GpStatus status = + CallFunc(GdipPrivateAddMemoryFont)(pCollection, pData, size); + if (status == Ok) { + return pCollection; + } + CallFunc(GdipDeletePrivateFontCollection)(&pCollection); + return NULL; +} +void CGdiplusExt::DeleteMemFont(LPVOID pCollection) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeletePrivateFontCollection)((GpFontCollection**)&pCollection); +} +FX_BOOL CGdiplusExt::GdipCreateBitmap(CFX_DIBitmap* pBitmap, void** bitmap) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + PixelFormat format; + switch (pBitmap->GetFormat()) { + case FXDIB_Rgb: + format = PixelFormat24bppRGB; + break; + case FXDIB_Rgb32: + format = PixelFormat32bppRGB; + break; + case FXDIB_Argb: + format = PixelFormat32bppARGB; + break; + default: + return FALSE; + } + GpStatus status = CallFunc(GdipCreateBitmapFromScan0)( + pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap->GetPitch(), format, + pBitmap->GetBuffer(), (GpBitmap**)bitmap); + if (status == Ok) { + return TRUE; + } + return FALSE; +} +FX_BOOL CGdiplusExt::GdipCreateFromImage(void* bitmap, void** graphics) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpStatus status = CallFunc(GdipGetImageGraphicsContext)( + (GpBitmap*)bitmap, (GpGraphics**)graphics); + if (status == Ok) { + return TRUE; + } + return FALSE; +} +FX_BOOL CGdiplusExt::GdipCreateFontFamilyFromName(const FX_WCHAR* name, + void* pFontCollection, + void** pFamily) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpStatus status = CallFunc(GdipCreateFontFamilyFromName)( + (GDIPCONST WCHAR*)name, (GpFontCollection*)pFontCollection, + (GpFontFamily**)pFamily); + if (status == Ok) { + return TRUE; + } + return FALSE; +} +FX_BOOL CGdiplusExt::GdipCreateFontFromFamily(void* pFamily, + FX_FLOAT font_size, + int fontstyle, + int flag, + void** pFont) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpStatus status = + CallFunc(GdipCreateFont)((GpFontFamily*)pFamily, font_size, fontstyle, + Unit(flag), (GpFont**)pFont); + if (status == Ok) { + return TRUE; + } + return FALSE; +} +void CGdiplusExt::GdipGetFontSize(void* pFont, FX_FLOAT* size) { + REAL get_size; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpStatus status = CallFunc(GdipGetFontSize)((GpFont*)pFont, (REAL*)&get_size); + if (status == Ok) { + *size = (FX_FLOAT)get_size; + } else { + *size = 0; + } +} +void CGdiplusExt::GdipSetTextRenderingHint(void* graphics, int mode) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipSetTextRenderingHint)((GpGraphics*)graphics, + (TextRenderingHint)mode); +} +void CGdiplusExt::GdipSetPageUnit(void* graphics, FX_DWORD unit) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipSetPageUnit)((GpGraphics*)graphics, (GpUnit)unit); +} +FX_BOOL CGdiplusExt::GdipDrawDriverString(void* graphics, + unsigned short* text, + int length, + void* font, + void* brush, + void* positions, + int flags, + const void* matrix) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpStatus status = CallFunc(GdipDrawDriverString)( + (GpGraphics*)graphics, (GDIPCONST UINT16*)text, (INT)length, + (GDIPCONST GpFont*)font, (GDIPCONST GpBrush*)brush, + (GDIPCONST PointF*)positions, (INT)flags, (GDIPCONST GpMatrix*)matrix); + if (status == Ok) { + return TRUE; + } + return FALSE; +} +void CGdiplusExt::GdipCreateBrush(FX_DWORD fill_argb, void** pBrush) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipCreateSolidFill)((ARGB)fill_argb, (GpSolidFill**)pBrush); +} +void CGdiplusExt::GdipDeleteBrush(void* pBrush) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeleteBrush)((GpSolidFill*)pBrush); +} +void* CGdiplusExt::GdipCreateFontFromCollection(void* pFontCollection, + FX_FLOAT font_size, + int fontstyle) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + int numFamilies = 0; + GpStatus status = CallFunc(GdipGetFontCollectionFamilyCount)( + (GpFontCollection*)pFontCollection, &numFamilies); + if (status != Ok) { + return NULL; + } + GpFontFamily* family_list[1]; + status = CallFunc(GdipGetFontCollectionFamilyList)( + (GpFontCollection*)pFontCollection, 1, family_list, &numFamilies); + if (status != Ok) { + return NULL; + } + GpFont* pFont = NULL; + status = CallFunc(GdipCreateFont)(family_list[0], font_size, fontstyle, + UnitPixel, &pFont); + if (status != Ok) { + return NULL; + } + return pFont; +} +void CGdiplusExt::GdipCreateMatrix(FX_FLOAT a, + FX_FLOAT b, + FX_FLOAT c, + FX_FLOAT d, + FX_FLOAT e, + FX_FLOAT f, + void** matrix) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipCreateMatrix2)(a, b, c, d, e, f, (GpMatrix**)matrix); +} +void CGdiplusExt::GdipDeleteMatrix(void* matrix) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeleteMatrix)((GpMatrix*)matrix); +} +void CGdiplusExt::GdipDeleteFontFamily(void* pFamily) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeleteFontFamily)((GpFontFamily*)pFamily); +} +void CGdiplusExt::GdipDeleteFont(void* pFont) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeleteFont)((GpFont*)pFont); +} +void CGdiplusExt::GdipSetWorldTransform(void* graphics, void* pMatrix) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipSetWorldTransform)((GpGraphics*)graphics, (GpMatrix*)pMatrix); +} +void CGdiplusExt::GdipDisposeImage(void* bitmap) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDisposeImage)((GpBitmap*)bitmap); +} +void CGdiplusExt::GdipDeleteGraphics(void* graphics) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipDeleteGraphics)((GpGraphics*)graphics); +} +FX_BOOL CGdiplusExt::StretchBitMask(HDC hDC, + BOOL bMonoDevice, + const CFX_DIBitmap* pBitmap, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + FX_DWORD argb, + const FX_RECT* pClipRect, + int flags) { + ASSERT(pBitmap->GetBPP() == 1); + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + GpGraphics* pGraphics = NULL; + CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); + CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); + if (flags & FXDIB_NOSMOOTH) { + CallFunc(GdipSetInterpolationMode)(pGraphics, + InterpolationModeNearestNeighbor); + } else { + CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeHighQuality); + } + OutputImageMask(pGraphics, bMonoDevice, pBitmap, dest_left, dest_top, + dest_width, dest_height, argb, pClipRect); + CallFunc(GdipDeleteGraphics)(pGraphics); + return TRUE; +} +FX_BOOL CGdiplusExt::StretchDIBits(HDC hDC, + const CFX_DIBitmap* pBitmap, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + const FX_RECT* pClipRect, + int flags) { + GpGraphics* pGraphics; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); + CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); + if (flags & FXDIB_NOSMOOTH) { + CallFunc(GdipSetInterpolationMode)(pGraphics, + InterpolationModeNearestNeighbor); + } else if (pBitmap->GetWidth() > abs(dest_width) / 2 || + pBitmap->GetHeight() > abs(dest_height) / 2) { + CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeHighQuality); + } else { + CallFunc(GdipSetInterpolationMode)(pGraphics, InterpolationModeBilinear); + } + FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); + OutputImage(pGraphics, pBitmap, &src_rect, dest_left, dest_top, dest_width, + dest_height); + CallFunc(GdipDeleteGraphics)(pGraphics); + CallFunc(GdipDeleteGraphics)(pGraphics); + return TRUE; +} +static GpPen* _GdipCreatePen(const CFX_GraphStateData* pGraphState, + const CFX_Matrix* pMatrix, + DWORD argb, + FX_BOOL bTextMode = FALSE) { + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + FX_FLOAT width = pGraphState ? pGraphState->m_LineWidth : 1.0f; + if (!bTextMode) { + FX_FLOAT unit = + pMatrix ? 1.0f / ((pMatrix->GetXUnit() + pMatrix->GetYUnit()) / 2) + : 1.0f; + if (width < unit) { + width = unit; + } + } + GpPen* pPen = NULL; + CallFunc(GdipCreatePen1)((ARGB)argb, width, UnitWorld, &pPen); + LineCap lineCap; + DashCap dashCap = DashCapFlat; + FX_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; + 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) { + FX_FLOAT* pDashArray = FX_Alloc( + FX_FLOAT, pGraphState->m_DashCount + pGraphState->m_DashCount % 2); + int nCount = 0; + FX_FLOAT on_leftover = 0, off_leftover = 0; + for (int i = 0; i < pGraphState->m_DashCount; i += 2) { + FX_FLOAT on_phase = pGraphState->m_DashArray[i]; + FX_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); + FX_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 = NULL; + } + CallFunc(GdipSetPenMiterLimit)(pPen, pGraphState->m_MiterLimit); + return pPen; +} +static FX_BOOL IsSmallTriangle(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]; + FX_FLOAT x1 = points[pair1].X, x2 = points[pair2].X; + FX_FLOAT y1 = points[pair1].Y, y2 = points[pair2].Y; + if (pMatrix) { + pMatrix->Transform(x1, y1); + pMatrix->Transform(x2, y2); + } + FX_FLOAT dx = x1 - x2; + FX_FLOAT dy = y1 - y2; + FX_FLOAT distance_square = (dx * dx) + (dy * dy); + if (distance_square < (1.0f * 2 + 1.0f / 4)) { + v1 = i; + v2 = pair1; + return TRUE; + } + } + return FALSE; +} +FX_BOOL CGdiplusExt::DrawPath(HDC hDC, + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + FX_DWORD fill_argb, + FX_DWORD stroke_argb, + int fill_mode) { + int nPoints = pPathData->GetPointCount(); + if (nPoints == 0) { + return TRUE; + } + FX_PATHPOINT* pPoints = pPathData->GetPoints(); + GpGraphics* pGraphics = NULL; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + CallFunc(GdipCreateFromHDC)(hDC, &pGraphics); + CallFunc(GdipSetPageUnit)(pGraphics, UnitPixel); + CallFunc(GdipSetPixelOffsetMode)(pGraphics, PixelOffsetModeHalf); + GpMatrix* pMatrix = NULL; + if (pObject2Device) { + CallFunc(GdipCreateMatrix2)(pObject2Device->a, pObject2Device->b, + pObject2Device->c, pObject2Device->d, + pObject2Device->e, pObject2Device->f, &pMatrix); + CallFunc(GdipSetWorldTransform)(pGraphics, pMatrix); + } + PointF* points = FX_Alloc(PointF, nPoints); + BYTE* types = FX_Alloc(BYTE, nPoints); + int nSubPathes = 0; + FX_BOOL bSubClose = FALSE; + int pos_subclose = 0; + FX_BOOL bSmooth = FALSE; + int startpoint = 0; + for (int i = 0; i < nPoints; i++) { + points[i].X = pPoints[i].m_PointX; + points[i].Y = pPoints[i].m_PointY; + FX_FLOAT x, y; + if (pObject2Device) { + pObject2Device->Transform(pPoints[i].m_PointX, pPoints[i].m_PointY, x, y); + } else { + x = pPoints[i].m_PointX; + y = pPoints[i].m_PointY; + } + if (x > 50000 * 1.0f) { + points[i].X = 50000 * 1.0f; + } + if (x < -50000 * 1.0f) { + points[i].X = -50000 * 1.0f; + } + if (y > 50000 * 1.0f) { + points[i].Y = 50000 * 1.0f; + } + if (y < -50000 * 1.0f) { + points[i].Y = -50000 * 1.0f; + } + int point_type = pPoints[i].m_Flag & FXPT_TYPE; + if (point_type == FXPT_MOVETO) { + types[i] = PathPointTypeStart; + nSubPathes++; + bSubClose = FALSE; + startpoint = i; + } else if (point_type == FXPT_LINETO) { + types[i] = PathPointTypeLine; + if (pPoints[i - 1].m_Flag == FXPT_MOVETO && + (i == nPoints - 1 || pPoints[i + 1].m_Flag == FXPT_MOVETO) && + points[i].Y == points[i - 1].Y && points[i].X == points[i - 1].X) { + points[i].X += 0.01f; + continue; + } + if (!bSmooth && points[i].X != points[i - 1].X && + points[i].Y != points[i - 1].Y) { + bSmooth = TRUE; + } + } else if (point_type == FXPT_BEZIERTO) { + types[i] = PathPointTypeBezier; + bSmooth = TRUE; + } + if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE) { + if (bSubClose) { + types[pos_subclose] &= ~PathPointTypeCloseSubpath; + } else { + bSubClose = TRUE; + } + pos_subclose = i; + types[i] |= PathPointTypeCloseSubpath; + if (!bSmooth && points[i].X != points[startpoint].X && + points[i].Y != points[startpoint].Y) { + bSmooth = TRUE; + } + } + } + if (fill_mode & FXFILL_NOPATHSMOOTH) { + bSmooth = FALSE; + CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeNone); + } else if (!(fill_mode & FXFILL_FULLCOVER)) { + if (!bSmooth && (fill_mode & 3)) { + bSmooth = TRUE; + } + if (bSmooth || (pGraphState && pGraphState->m_LineWidth > 2)) { + CallFunc(GdipSetSmoothingMode)(pGraphics, SmoothingModeAntiAlias); + } + } + int new_fill_mode = fill_mode & 3; + if (nPoints == 4 && !pGraphState) { + int v1, v2; + if (IsSmallTriangle(points, pObject2Device, v1, v2)) { + GpPen* pPen = NULL; + CallFunc(GdipCreatePen1)(fill_argb, 1.0f, UnitPixel, &pPen); + CallFunc(GdipDrawLineI)( + pGraphics, pPen, FXSYS_round(points[v1].X), FXSYS_round(points[v1].Y), + FXSYS_round(points[v2].X), FXSYS_round(points[v2].Y)); + CallFunc(GdipDeletePen)(pPen); + return TRUE; + } + } + GpPath* pGpPath = NULL; + CallFunc(GdipCreatePath2)(points, types, nPoints, + GdiFillType2Gdip(new_fill_mode), &pGpPath); + if (!pGpPath) { + if (pMatrix) { + CallFunc(GdipDeleteMatrix)(pMatrix); + } + FX_Free(points); + FX_Free(types); + CallFunc(GdipDeleteGraphics)(pGraphics); + return FALSE; + } + if (new_fill_mode) { + GpBrush* pBrush = _GdipCreateBrush(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); + if (nSubPathes == 1) { + CallFunc(GdipDrawPath)(pGraphics, pPen, pGpPath); + } else { + int iStart = 0; + for (int i = 0; i < nPoints; i++) { + if (i == nPoints - 1 || types[i + 1] == PathPointTypeStart) { + GpPath* pSubPath; + CallFunc(GdipCreatePath2)(points + iStart, types + iStart, + i - iStart + 1, + GdiFillType2Gdip(new_fill_mode), &pSubPath); + iStart = i + 1; + CallFunc(GdipDrawPath)(pGraphics, pPen, pSubPath); + CallFunc(GdipDeletePath)(pSubPath); + } + } + } + CallFunc(GdipDeletePen)(pPen); + } + if (pMatrix) { + CallFunc(GdipDeleteMatrix)(pMatrix); + } + FX_Free(points); + FX_Free(types); + CallFunc(GdipDeletePath)(pGpPath); + CallFunc(GdipDeleteGraphics)(pGraphics); + return TRUE; +} +class GpStream final : public IStream { + LONG m_RefCount; + int m_ReadPos; + CFX_ByteTextBuf m_InterStream; + + public: + GpStream() { + m_RefCount = 1; + m_ReadPos = 0; + } + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void** ppvObject) { + if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || + iid == __uuidof(ISequentialStream)) { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + return E_NOINTERFACE; + } + virtual ULONG STDMETHODCALLTYPE AddRef(void) { + return (ULONG)InterlockedIncrement(&m_RefCount); + } + virtual ULONG STDMETHODCALLTYPE Release(void) { + ULONG res = (ULONG)InterlockedDecrement(&m_RefCount); + if (res == 0) { + delete this; + } + return res; + } + + public: + virtual HRESULT STDMETHODCALLTYPE Read(void* Output, + ULONG cb, + ULONG* pcbRead) { + size_t bytes_left; + size_t bytes_out; + if (pcbRead) { + *pcbRead = 0; + } + if (m_ReadPos == m_InterStream.GetLength()) { + return HRESULT_FROM_WIN32(ERROR_END_OF_MEDIA); + } + bytes_left = m_InterStream.GetLength() - m_ReadPos; + bytes_out = std::min(pdfium::base::checked_cast(cb), bytes_left); + FXSYS_memcpy(Output, m_InterStream.GetBuffer() + m_ReadPos, bytes_out); + m_ReadPos += (int32_t)bytes_out; + if (pcbRead) { + *pcbRead = (ULONG)bytes_out; + } + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE Write(void const* Input, + ULONG cb, + ULONG* pcbWritten) { + if (cb <= 0) { + if (pcbWritten) { + *pcbWritten = 0; + } + return S_OK; + } + m_InterStream.InsertBlock(m_InterStream.GetLength(), Input, cb); + if (pcbWritten) { + *pcbWritten = cb; + } + return S_OK; + } + + public: + virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, + ULARGE_INTEGER, + ULARGE_INTEGER*, + ULARGE_INTEGER*) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE Revert(void) { return E_NOTIMPL; } + virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, + ULARGE_INTEGER, + DWORD) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, + ULARGE_INTEGER, + DWORD) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Clone(IStream** stream) { + return E_NOTIMPL; + } + virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, + DWORD dwOrigin, + ULARGE_INTEGER* lpNewFilePointer) { + long start = 0; + long 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.GetLength(); + break; + default: + return STG_E_INVALIDFUNCTION; + break; + } + new_read_position = start + (long)liDistanceToMove.QuadPart; + if (new_read_position < 0 || + new_read_position > m_InterStream.GetLength()) { + return STG_E_SEEKERROR; + } + m_ReadPos = new_read_position; + if (lpNewFilePointer) { + lpNewFilePointer->QuadPart = m_ReadPos; + } + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) { + if (!pStatstg) { + return STG_E_INVALIDFUNCTION; + } + ZeroMemory(pStatstg, sizeof(STATSTG)); + pStatstg->cbSize.QuadPart = m_InterStream.GetLength(); + return S_OK; + } +}; +typedef struct { + BITMAPINFO* pbmi; + int Stride; + LPBYTE pScan0; + GpBitmap* pBitmap; + BitmapData* pBitmapData; + GpStream* pStream; +} PREVIEW3_DIBITMAP; +static PREVIEW3_DIBITMAP* LoadDIBitmap(WINDIB_Open_Args_ args) { + GpBitmap* pBitmap; + GpStream* pStream = NULL; + CGdiplusExt& GdiplusExt = + ((CWin32Platform*)CFX_GEModule::Get()->GetPlatformData())->m_GdiplusExt; + Status status = 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 NULL; + } + pStream = new GpStream; + pStream->Write(args.memory_base, (ULONG)args.memory_size, NULL); + status = CallFunc(GdipCreateBitmapFromStreamICM)(pStream, &pBitmap); + } + if (status != Ok) { + if (pStream) { + pStream->Release(); + } + return NULL; + } + UINT height, width; + CallFunc(GdipGetImageHeight)(pBitmap, &height); + CallFunc(GdipGetImageWidth)(pBitmap, &width); + 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; + Rect rect(0, 0, width, height); + BitmapData* pBitmapData = FX_Alloc(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, (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); +} +CFX_DIBitmap* _FX_WindowsDIB_LoadFromBuf(BITMAPINFO* pbmi, + LPVOID pData, + FX_BOOL bAlpha); +CFX_DIBitmap* CGdiplusExt::LoadDIBitmap(WINDIB_Open_Args_ args) { + PREVIEW3_DIBITMAP* pInfo = ::LoadDIBitmap(args); + if (!pInfo) { + return NULL; + } + int height = abs(pInfo->pbmi->bmiHeader.biHeight); + int width = pInfo->pbmi->bmiHeader.biWidth; + int dest_pitch = (width * pInfo->pbmi->bmiHeader.biBitCount + 31) / 32 * 4; + LPBYTE pData = FX_Alloc2D(BYTE, dest_pitch, height); + if (dest_pitch == pInfo->Stride) { + FXSYS_memcpy(pData, pInfo->pScan0, dest_pitch * height); + } else { + for (int i = 0; i < height; i++) { + FXSYS_memcpy(pData + dest_pitch * i, pInfo->pScan0 + pInfo->Stride * i, + dest_pitch); + } + } + CFX_DIBitmap* pDIBitmap = _FX_WindowsDIB_LoadFromBuf( + pInfo->pbmi, pData, pInfo->pbmi->bmiHeader.biBitCount == 32); + FX_Free(pData); + FreeDIBitmap(pInfo); + return pDIBitmap; +} +#endif -- cgit v1.2.3