1// Copyright 2010-2012 The W32 Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build windows
6
7package w32
8
9import (
10	"errors"
11	"fmt"
12	"syscall"
13	"unsafe"
14)
15
16const (
17	Ok                        = 0
18	GenericError              = 1
19	InvalidParameter          = 2
20	OutOfMemory               = 3
21	ObjectBusy                = 4
22	InsufficientBuffer        = 5
23	NotImplemented            = 6
24	Win32Error                = 7
25	WrongState                = 8
26	Aborted                   = 9
27	FileNotFound              = 10
28	ValueOverflow             = 11
29	AccessDenied              = 12
30	UnknownImageFormat        = 13
31	FontFamilyNotFound        = 14
32	FontStyleNotFound         = 15
33	NotTrueTypeFont           = 16
34	UnsupportedGdiplusVersion = 17
35	GdiplusNotInitialized     = 18
36	PropertyNotFound          = 19
37	PropertyNotSupported      = 20
38	ProfileNotFound           = 21
39)
40
41func GetGpStatus(s int32) string {
42	switch s {
43	case Ok:
44		return "Ok"
45	case GenericError:
46		return "GenericError"
47	case InvalidParameter:
48		return "InvalidParameter"
49	case OutOfMemory:
50		return "OutOfMemory"
51	case ObjectBusy:
52		return "ObjectBusy"
53	case InsufficientBuffer:
54		return "InsufficientBuffer"
55	case NotImplemented:
56		return "NotImplemented"
57	case Win32Error:
58		return "Win32Error"
59	case WrongState:
60		return "WrongState"
61	case Aborted:
62		return "Aborted"
63	case FileNotFound:
64		return "FileNotFound"
65	case ValueOverflow:
66		return "ValueOverflow"
67	case AccessDenied:
68		return "AccessDenied"
69	case UnknownImageFormat:
70		return "UnknownImageFormat"
71	case FontFamilyNotFound:
72		return "FontFamilyNotFound"
73	case FontStyleNotFound:
74		return "FontStyleNotFound"
75	case NotTrueTypeFont:
76		return "NotTrueTypeFont"
77	case UnsupportedGdiplusVersion:
78		return "UnsupportedGdiplusVersion"
79	case GdiplusNotInitialized:
80		return "GdiplusNotInitialized"
81	case PropertyNotFound:
82		return "PropertyNotFound"
83	case PropertyNotSupported:
84		return "PropertyNotSupported"
85	case ProfileNotFound:
86		return "ProfileNotFound"
87	}
88	return "Unknown Status Value"
89}
90
91var (
92	token uintptr
93
94	modgdiplus = syscall.NewLazyDLL("gdiplus.dll")
95
96	procGdipCreateBitmapFromFile     = modgdiplus.NewProc("GdipCreateBitmapFromFile")
97	procGdipCreateBitmapFromHBITMAP  = modgdiplus.NewProc("GdipCreateBitmapFromHBITMAP")
98	procGdipCreateHBITMAPFromBitmap  = modgdiplus.NewProc("GdipCreateHBITMAPFromBitmap")
99	procGdipCreateBitmapFromResource = modgdiplus.NewProc("GdipCreateBitmapFromResource")
100	procGdipCreateBitmapFromStream   = modgdiplus.NewProc("GdipCreateBitmapFromStream")
101	procGdipDisposeImage             = modgdiplus.NewProc("GdipDisposeImage")
102	procGdiplusShutdown              = modgdiplus.NewProc("GdiplusShutdown")
103	procGdiplusStartup               = modgdiplus.NewProc("GdiplusStartup")
104)
105
106func GdipCreateBitmapFromFile(filename string) (*uintptr, error) {
107	var bitmap *uintptr
108	ret, _, _ := procGdipCreateBitmapFromFile.Call(
109		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
110		uintptr(unsafe.Pointer(&bitmap)))
111
112	if ret != Ok {
113		return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromFile failed with status '%s' for file '%s'", GetGpStatus(int32(ret)), filename))
114	}
115
116	return bitmap, nil
117}
118
119func GdipCreateBitmapFromResource(instance HINSTANCE, resId *uint16) (*uintptr, error) {
120	var bitmap *uintptr
121	ret, _, _ := procGdipCreateBitmapFromResource.Call(
122		uintptr(instance),
123		uintptr(unsafe.Pointer(resId)),
124		uintptr(unsafe.Pointer(&bitmap)))
125
126	if ret != Ok {
127		return nil, errors.New(fmt.Sprintf("GdiCreateBitmapFromResource failed with status '%s'", GetGpStatus(int32(ret))))
128	}
129
130	return bitmap, nil
131}
132
133func GdipCreateBitmapFromStream(stream *IStream) (*uintptr, error) {
134	var bitmap *uintptr
135	ret, _, _ := procGdipCreateBitmapFromStream.Call(
136		uintptr(unsafe.Pointer(stream)),
137		uintptr(unsafe.Pointer(&bitmap)))
138
139	if ret != Ok {
140		return nil, errors.New(fmt.Sprintf("GdipCreateBitmapFromStream failed with status '%s'", GetGpStatus(int32(ret))))
141	}
142
143	return bitmap, nil
144}
145
146func GdipCreateHBITMAPFromBitmap(bitmap *uintptr, background uint32) (HBITMAP, error) {
147	var hbitmap HBITMAP
148	ret, _, _ := procGdipCreateHBITMAPFromBitmap.Call(
149		uintptr(unsafe.Pointer(bitmap)),
150		uintptr(unsafe.Pointer(&hbitmap)),
151		uintptr(background))
152
153	if ret != Ok {
154		return 0, errors.New(fmt.Sprintf("GdipCreateHBITMAPFromBitmap failed with status '%s'", GetGpStatus(int32(ret))))
155	}
156
157	return hbitmap, nil
158}
159
160func GdipDisposeImage(image *uintptr) {
161	procGdipDisposeImage.Call(uintptr(unsafe.Pointer(image)))
162}
163
164func GdiplusShutdown() {
165	procGdiplusShutdown.Call(token)
166}
167
168func GdiplusStartup(input *GdiplusStartupInput, output *GdiplusStartupOutput) {
169	ret, _, _ := procGdiplusStartup.Call(
170		uintptr(unsafe.Pointer(&token)),
171		uintptr(unsafe.Pointer(input)),
172		uintptr(unsafe.Pointer(output)))
173
174	if ret != Ok {
175		panic("GdiplusStartup failed with status " + GetGpStatus(int32(ret)))
176	}
177}
178