summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src/modern_gdiplus.cpp
blob: cbc36d8f79322ee986828bd47dfbd1412bf33818 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
 * test for gdi+
 */

#include "stdafx.h"

#undef Translate	//otherwise will conflict with gdi plus Translate
#include <gdiplus.h>

#include "modern_global_structure.h"

#pragma comment(lib, "gdiplus.lib")

using namespace Gdiplus;

HBITMAP ske_CreateDIB32(int cx, int cy);

BYTE      saved_alpha;
ULONG_PTR g_gdiplusToken;
int       g_hottrack;

void InitGdiPlus(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	if (g_gdiplusToken == 0)
		GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, nullptr);
}

void ShutdownGdiPlus(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	if (g_gdiplusToken)
		GdiplusShutdown(g_gdiplusToken);
	g_gdiplusToken = 0;
}

static ColorMatrix ClrMatrix =
{
	1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
	0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
	0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
	0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
	0.0f, 0.0f, 0.0f, 0.0f, 1.0f
};

DWORD argb_from_cola(COLORREF col, BYTE alpha)
{
	return((BYTE)(alpha) << 24 | col);
}

HBITMAP GDIPlus_LoadGlyphImage(const wchar_t *tszFileName)
{
	// Create a Bitmap object from a JPEG file.
	Bitmap bitmap(tszFileName, 0);

	// Clone a portion of the bitmap.
	Bitmap* clone = bitmap.Clone(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), PixelFormat32bppPARGB);
	HBITMAP hbmp = nullptr;
	if (clone) {
		clone->GetHBITMAP(Color(0, 0, 0), &hbmp);
		delete clone;
	}
	return hbmp;
}

void DrawAvatarImageWithGDIp(HDC hDestDC, int x, int y, DWORD width, DWORD height, HBITMAP hbmp, int x1, int y1, DWORD width1, DWORD height1, DWORD flag, BYTE alpha)
{
	BITMAP bmp;
	Bitmap *bm;
	BYTE * bmbits = nullptr;
	GetObject(hbmp, sizeof(BITMAP), &bmp);
	Graphics g(hDestDC);
	if (bmp.bmBitsPixel == 32 && (flag&AVS_PREMULTIPLIED)) {
		bmbits = (BYTE*)bmp.bmBits;
		if (!bmbits) {
			bmbits = (BYTE*)malloc(bmp.bmHeight*bmp.bmWidthBytes);
			GetBitmapBits(hbmp, bmp.bmHeight*bmp.bmWidthBytes, bmbits);
		}
		bm = new Bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmWidthBytes, PixelFormat32bppPARGB, bmbits);
		bm->RotateFlip(RotateNoneFlipY);
		if (!bmp.bmBits) {
			bm->RotateFlip(RotateNoneFlipY);
			free(bmbits);
		}
	}
	else bm = new Bitmap(hbmp, nullptr);

	ImageAttributes attr;
	ColorMatrix Matrix =
	{
		1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 0.0f, ((float)alpha) / 255, 0.0f,
		0.0f, 0.0f, 0.0f, 0.0f, 1.0f
	};
	attr.SetColorMatrix(&Matrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);
	g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
	RectF rect((float)x, (float)y, (float)width, (float)height);
	g.DrawImage(bm, rect, (float)x1, (float)y1, (float)width1, (float)height1, UnitPixel, &attr, nullptr, nullptr);
	delete bm;
}

BOOL GDIPlus_AlphaBlend(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION * bf)
{
	Graphics g(hdcDest);
	BITMAP bmp;
	HBITMAP hbmp = (HBITMAP)GetCurrentObject(hdcSrc, OBJ_BITMAP);
	GetObject(hbmp, sizeof(BITMAP), &bmp);

	Bitmap *bm;
	if (bmp.bmBitsPixel == 32 && bf->AlphaFormat) {
		bm = new Bitmap(bmp.bmWidth, bmp.bmHeight, bmp.bmWidthBytes, PixelFormat32bppPARGB, (BYTE*)bmp.bmBits);
		bm->RotateFlip(RotateNoneFlipY);
	}
	else bm = new Bitmap(hbmp, nullptr);

	ImageAttributes attr;
	ColorMatrix Matrix =
	{
		1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 0.0f, ((float)bf->SourceConstantAlpha) / 255, 0.0f,
		0.0f, 0.0f, 0.0f, 0.0f, 1.0f
	};
	attr.SetColorMatrix(&Matrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);

	if (bf->BlendFlags & 128 && nWidthDest < nWidthSrc && nHeightDest < nHeightSrc) {
		g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
		g.SetPixelOffsetMode(PixelOffsetModeHalf);
		attr.SetGamma((REAL)0.8, ColorAdjustTypeBitmap);
	}
	else g.SetInterpolationMode(InterpolationModeLowQuality);

	RectF rect((float)nXOriginDest, (float)nYOriginDest, (float)nWidthDest, (float)nHeightDest);
	g.DrawImage(bm, rect, (float)nXOriginSrc, (float)nYOriginSrc, (float)nWidthSrc, (float)nHeightSrc, UnitPixel, &attr, nullptr, nullptr);
	delete bm;
	return TRUE;
}

COLORREF __inline _revcolref(COLORREF colref)
{
	return RGB(GetBValue(colref), GetGValue(colref), GetRValue(colref));
}

/////////////////////////////////////////////////////////////////////////////////
// GDIPlus_IsAnimatedGIF and GDIPlus_ExtractAnimatedGIF
// based on routine from http://www.codeproject.com/vcpp/gdiplus/imageexgdi.asp
//

BOOL GDIPlus_IsAnimatedGif(wchar_t * szName)
{
	int nFrameCount = 0;
	Image image(szName);
	UINT count = 0;

	count = image.GetFrameDimensionsCount();
	GUID* pDimensionIDs = new GUID[count];

	// Get the list of frame dimensions from the Image object.
	image.GetFrameDimensionsList(pDimensionIDs, count);

	// Get the number of frames in the first dimension.
	nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);

	delete[]  pDimensionIDs;

	return (BOOL)(nFrameCount > 1);
}

void GDIPlus_ExtractAnimatedGIF(wchar_t *szName, int width, int height, HBITMAP &pBitmap, int* &pframesDelay, int &pframesCount, SIZE &pSizeAvatar)
{
	int nFrameCount = 0;
	Bitmap image(szName);
	PropertyItem * pPropertyItem;

	UINT count = image.GetFrameDimensionsCount();
	GUID *pDimensionIDs = new GUID[count];

	// Get the list of frame dimensions from the Image object.
	image.GetFrameDimensionsList(pDimensionIDs, count);

	// Get the number of frames in the first dimension.
	nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);

	// Assume that the image has a property item of type PropertyItemEquipMake.
	// Get the size of that property item.
	int nSize = image.GetPropertyItemSize(PropertyTagFrameDelay);

	// Allocate a buffer to receive the property item.
	pPropertyItem = (PropertyItem*)malloc(nSize);

	image.GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem);

	int clipWidth;
	int clipHeight;
	int imWidth = image.GetWidth();
	int imHeight = image.GetHeight();
	float xscale = (float)width / imWidth;
	float yscale = (float)height / imHeight;
	xscale = min(xscale, yscale);
	clipWidth = (int)(xscale*imWidth + .5);
	clipHeight = (int)(xscale*imHeight + .5);

	HBITMAP hBitmap = ske_CreateDIB32(clipWidth*nFrameCount, height);
	HDC hdc = CreateCompatibleDC(nullptr);
	HBITMAP oldBmp = (HBITMAP)SelectObject(hdc, hBitmap);
	Graphics graphics(hdc);
	ImageAttributes attr;

	graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
	graphics.SetPixelOffsetMode(PixelOffsetModeHalf);
	int *delays = (int*)malloc(nFrameCount*sizeof(int));
	memset(delays, 0, nFrameCount*sizeof(int));

	// The GDIPlus strange behavior: without next 2 lines it will draw first frame anti aliased, but next - not
	GUID pageGuid = FrameDimensionTime;
	if (nFrameCount > 1)
		image.SelectActiveFrame(&pageGuid, 1);

	for (int i = 0; i < nFrameCount; i++) {
		image.SelectActiveFrame(&pageGuid, i);
		graphics.DrawImage(&image, Rect(i*clipWidth, 0, clipWidth, clipHeight), 0, 0, imWidth, imHeight, UnitPixel, &attr);
		long lPause = ((long*)pPropertyItem->value)[i] * 10;
		delays[i] = (int)lPause;
	}
	SelectObject(hdc, oldBmp);
	DeleteDC(hdc);
	free(pPropertyItem);
	delete[] pDimensionIDs;

	pBitmap = hBitmap;
	pframesDelay = delays;
	pframesCount = nFrameCount;
	pSizeAvatar.cx = clipWidth;
	pSizeAvatar.cy = clipHeight;

	GdiFlush();
}