1 /**
2  * @file gdiplusstringformat.h
3  * Copyright 2012, 2013 MinGW.org project
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 /* Created by Markus Koenig <markus@stber-koenig.de> */
25 #ifndef __GDIPLUS_STRINGFORMAT_H
26 #define __GDIPLUS_STRINGFORMAT_H
27 #pragma GCC system_header
28 #include <_mingw.h>
29 
30 /*
31  * GDI+ StringFormat class
32  */
33 
34 #ifndef __cplusplus
35 #error "A C++ compiler is required to include gdiplusstringformat.h."
36 #endif
37 
38 class StringFormat: public GdiplusBase
39 {
40 	friend class Graphics;
41 	friend class GraphicsPath;
42 
43 public:
44 	static const StringFormat* GenericDefault();
45 	static const StringFormat* GenericTypographic();
46 
47 	StringFormat(INT formatFlags = 0, LANGID language = LANG_NEUTRAL):
nativeStringFormat(NULL)48 			nativeStringFormat(NULL), lastStatus(Ok)
49 	{
50 		lastStatus = DllExports::GdipCreateStringFormat(
51 				formatFlags, language, &nativeStringFormat);
52 	}
StringFormat(const StringFormat * format)53 	StringFormat(const StringFormat *format):
54 			nativeStringFormat(NULL), lastStatus(Ok)
55 	{
56 		lastStatus = DllExports::GdipCloneStringFormat(
57 				format ? format->nativeStringFormat : NULL,
58 				&nativeStringFormat);
59 	}
~StringFormat()60 	~StringFormat()
61 	{
62 		DllExports::GdipDeleteStringFormat(nativeStringFormat);
63 	}
Clone()64 	StringFormat* Clone() const
65 	{
66 		GpStringFormat *cloneStringFormat = NULL;
67 		Status status = updateStatus(DllExports::GdipCloneStringFormat(
68 				nativeStringFormat, &cloneStringFormat));
69 		if (status == Ok) {
70 			StringFormat *result = new StringFormat(
71 					cloneStringFormat, lastStatus);
72 			if (!result) {
73 				DllExports::GdipDeleteStringFormat(cloneStringFormat);
74 				lastStatus = OutOfMemory;
75 			}
76 			return result;
77 		} else {
78 			return NULL;
79 		}
80 	}
81 
GetAlignment()82 	StringAlignment GetAlignment() const
83 	{
84 		StringAlignment result = StringAlignmentNear;
85 		updateStatus(DllExports::GdipGetStringFormatAlign(
86 				nativeStringFormat, &result));
87 		return result;
88 	}
GetDigitSubstitutionLanguage()89 	LANGID GetDigitSubstitutionLanguage() const
90 	{
91 		LANGID result = 0;
92 		StringDigitSubstitute method;
93 		updateStatus(DllExports::GdipGetStringFormatDigitSubstitution(
94 				nativeStringFormat, &result, &method));
95 		return result;
96 	}
GetDigitSubstitutionMethod()97 	StringDigitSubstitute GetDigitSubstitutionMethod() const
98 	{
99 		LANGID language;
100 		StringDigitSubstitute result = StringDigitSubstituteUser;
101 		updateStatus(DllExports::GdipGetStringFormatDigitSubstitution(
102 				nativeStringFormat, &language, &result));
103 		return result;
104 	}
GetFormatFlags()105 	INT GetFormatFlags() const
106 	{
107 		INT result = 0;
108 		updateStatus(DllExports::GdipGetStringFormatFlags(
109 				nativeStringFormat, &result));
110 		return result;
111 	}
GetHotkeyPrefix()112 	HotkeyPrefix GetHotkeyPrefix() const
113 	{
114 		HotkeyPrefix result = HotkeyPrefixNone;
115 		updateStatus(DllExports::GdipGetStringFormatHotkeyPrefix(
116 				nativeStringFormat, (INT*) &result));
117 		return result;
118 	}
GetLastStatus()119 	Status GetLastStatus() const
120 	{
121 		Status result = lastStatus;
122 		lastStatus = Ok;
123 		return result;
124 	}
GetLineAlignment()125 	StringAlignment GetLineAlignment() const
126 	{
127 		StringAlignment result = StringAlignmentNear;
128 		updateStatus(DllExports::GdipGetStringFormatLineAlign(
129 				nativeStringFormat, &result));
130 		return result;
131 	}
GetMeasurableCharacterRangeCount()132 	INT GetMeasurableCharacterRangeCount() const
133 	{
134 		INT result = 0;
135 		updateStatus(DllExports::GdipGetStringFormatMeasurableCharacterRangeCount(
136 				nativeStringFormat, &result));
137 		return result;
138 	}
GetTabStopCount()139 	INT GetTabStopCount() const
140 	{
141 		INT result = 0;
142 		updateStatus(DllExports::GdipGetStringFormatTabStopCount(
143 				nativeStringFormat, &result));
144 		return result;
145 	}
GetTabStops(INT count,REAL * firstTabOffset,REAL * tabStops)146 	Status GetTabStops(INT count, REAL *firstTabOffset, REAL *tabStops)
147 	{
148 		return updateStatus(DllExports::GdipGetStringFormatTabStops(
149 				nativeStringFormat, count,
150 				firstTabOffset, tabStops));
151 	}
GetTrimming()152 	StringTrimming GetTrimming() const
153 	{
154 		StringTrimming result = StringTrimmingNone;
155 		updateStatus(DllExports::GdipGetStringFormatTrimming(
156 				nativeStringFormat, &result));
157 		return result;
158 	}
SetAlignment(StringAlignment align)159 	Status SetAlignment(StringAlignment align)
160 	{
161 		return updateStatus(DllExports::GdipSetStringFormatAlign(
162 				nativeStringFormat, align));
163 	}
SetDigitSubstitution(LANGID language,StringDigitSubstitute substitute)164 	Status SetDigitSubstitution(LANGID language,
165 			StringDigitSubstitute substitute)
166 	{
167 		return updateStatus(DllExports::GdipSetStringFormatDigitSubstitution(
168 				nativeStringFormat, language, substitute));
169 	}
SetFormatFlags(INT flags)170 	Status SetFormatFlags(INT flags)
171 	{
172 		return updateStatus(DllExports::GdipSetStringFormatFlags(
173 				nativeStringFormat, flags));
174 	}
SetHotkeyPrefix(HotkeyPrefix hotkeyPrefix)175 	Status SetHotkeyPrefix(HotkeyPrefix hotkeyPrefix)
176 	{
177 		return updateStatus(DllExports::GdipSetStringFormatHotkeyPrefix(
178 				nativeStringFormat, (INT) hotkeyPrefix));
179 	}
SetLineAlignment(StringAlignment align)180 	Status SetLineAlignment(StringAlignment align)
181 	{
182 		return updateStatus(DllExports::GdipSetStringFormatLineAlign(
183 				nativeStringFormat, align));
184 	}
SetMeasurableCharacterRanges(INT rangeCount,const CharacterRange * ranges)185 	Status SetMeasurableCharacterRanges(INT rangeCount,
186 			const CharacterRange *ranges)
187 	{
188 		return updateStatus(DllExports::GdipSetStringFormatMeasurableCharacterRanges(
189 				nativeStringFormat, rangeCount, ranges));
190 	}
SetTabStops(REAL firstTabOffset,INT count,const REAL * tabStops)191 	Status SetTabStops(REAL firstTabOffset, INT count, const REAL *tabStops)
192 	{
193 		return updateStatus(DllExports::GdipSetStringFormatTabStops(
194 				nativeStringFormat, firstTabOffset,
195 				count, tabStops));
196 	}
SetTrimming(StringTrimming trimming)197 	Status SetTrimming(StringTrimming trimming)
198 	{
199 		return updateStatus(DllExports::GdipSetStringFormatTrimming(
200 				nativeStringFormat, trimming));
201 	}
202 
203 private:
StringFormat(GpStringFormat * stringFormat,Status status)204 	StringFormat(GpStringFormat *stringFormat, Status status):
205 		nativeStringFormat(stringFormat), lastStatus(status) {}
206 	StringFormat(const StringFormat&);
207 	StringFormat& operator=(const StringFormat&);
208 
updateStatus(Status newStatus)209 	Status updateStatus(Status newStatus) const
210 	{
211 		if (newStatus != Ok) lastStatus = newStatus;
212 		return newStatus;
213 	}
214 
215 	GpStringFormat *nativeStringFormat;
216 	mutable Status lastStatus;
217 };
218 
219 
220 // FIXME: do StringFormat::GenericDefault() et al. need to be thread safe?
221 // FIXME: maybe put this in gdiplus.c?
222 
223 extern "C" void *_GdipStringFormatCachedGenericDefault;
224 extern "C" void *_GdipStringFormatCachedGenericTypographic;
225 
GenericDefault()226 __inline__ const StringFormat* StringFormat::GenericDefault()
227 {
228 	if (!_GdipStringFormatCachedGenericDefault) {
229 		GpStringFormat *nativeStringFormat = 0;
230 		Status status = DllExports::GdipStringFormatGetGenericDefault(
231 				&nativeStringFormat);
232 		if (status == Ok && nativeStringFormat) {
233 			_GdipStringFormatCachedGenericDefault = (void*)
234 				new StringFormat(nativeStringFormat, Ok);
235 		}
236 	}
237 	return (StringFormat*) _GdipStringFormatCachedGenericDefault;
238 }
239 
GenericTypographic()240 __inline__ const StringFormat* StringFormat::GenericTypographic()
241 {
242 	if (!_GdipStringFormatCachedGenericTypographic) {
243 		GpStringFormat *nativeStringFormat = 0;
244 		Status status = DllExports::GdipStringFormatGetGenericTypographic(
245 				&nativeStringFormat);
246 		if (status == Ok && nativeStringFormat) {
247 			_GdipStringFormatCachedGenericTypographic = (void*)
248 				new StringFormat(nativeStringFormat, Ok);
249 		}
250 	}
251 	return (StringFormat*) _GdipStringFormatCachedGenericTypographic;
252 }
253 
254 
255 
256 #endif /* __GDIPLUS_STRINGFORMAT_H */
257