1/*
2 * gdiplusstringformat.h
3 *
4 * GDI+ StringFormat class
5 *
6 * This file is part of the w32api package.
7 *
8 * Contributors:
9 *   Created by Markus Koenig <markus@stber-koenig.de>
10 *
11 * THIS SOFTWARE IS NOT COPYRIGHTED
12 *
13 * This source code is offered for use in the public domain. You may
14 * use, modify or distribute it freely.
15 *
16 * This code is distributed in the hope that it will be useful but
17 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
18 * DISCLAIMED. This includes but is not limited to warranties of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 */
22
23#ifndef __GDIPLUS_STRINGFORMAT_H
24#define __GDIPLUS_STRINGFORMAT_H
25#if __GNUC__ >=3
26#pragma GCC system_header
27#endif
28
29#ifndef __cplusplus
30#error "A C++ compiler is required to include gdiplusstringformat.h."
31#endif
32
33class StringFormat: public GdiplusBase
34{
35	friend class Graphics;
36	friend class GraphicsPath;
37
38public:
39	static const StringFormat* GenericDefault();
40	static const StringFormat* GenericTypographic();
41
42	StringFormat(INT formatFlags = 0, LANGID language = LANG_NEUTRAL):
43			nativeStringFormat(NULL), lastStatus(Ok)
44	{
45		lastStatus = DllExports::GdipCreateStringFormat(
46				formatFlags, language, &nativeStringFormat);
47	}
48	StringFormat(const StringFormat *format):
49			nativeStringFormat(NULL), lastStatus(Ok)
50	{
51		lastStatus = DllExports::GdipCloneStringFormat(
52				format ? format->nativeStringFormat : NULL,
53				&nativeStringFormat);
54	}
55	~StringFormat()
56	{
57		DllExports::GdipDeleteStringFormat(nativeStringFormat);
58	}
59	StringFormat* Clone() const
60	{
61		GpStringFormat *cloneStringFormat = NULL;
62		Status status = updateStatus(DllExports::GdipCloneStringFormat(
63				nativeStringFormat, &cloneStringFormat));
64		if (status == Ok) {
65			StringFormat *result = new StringFormat(
66					cloneStringFormat, lastStatus);
67			if (!result) {
68				DllExports::GdipDeleteStringFormat(cloneStringFormat);
69				lastStatus = OutOfMemory;
70			}
71			return result;
72		} else {
73			return NULL;
74		}
75	}
76
77	StringAlignment GetAlignment() const
78	{
79		StringAlignment result = StringAlignmentNear;
80		updateStatus(DllExports::GdipGetStringFormatAlign(
81				nativeStringFormat, &result));
82		return result;
83	}
84	LANGID GetDigitSubstitutionLanguage() const
85	{
86		LANGID result = 0;
87		StringDigitSubstitute method;
88		updateStatus(DllExports::GdipGetStringFormatDigitSubstitution(
89				nativeStringFormat, &result, &method));
90		return result;
91	}
92	StringDigitSubstitute GetDigitSubstitutionMethod() const
93	{
94		LANGID language;
95		StringDigitSubstitute result = StringDigitSubstituteUser;
96		updateStatus(DllExports::GdipGetStringFormatDigitSubstitution(
97				nativeStringFormat, &language, &result));
98		return result;
99	}
100	INT GetFormatFlags() const
101	{
102		INT result = 0;
103		updateStatus(DllExports::GdipGetStringFormatFlags(
104				nativeStringFormat, &result));
105		return result;
106	}
107	HotkeyPrefix GetHotkeyPrefix() const
108	{
109		HotkeyPrefix result = HotkeyPrefixNone;
110		updateStatus(DllExports::GdipGetStringFormatHotkeyPrefix(
111				nativeStringFormat, (INT*) &result));
112		return result;
113	}
114	Status GetLastStatus() const
115	{
116		Status result = lastStatus;
117		lastStatus = Ok;
118		return result;
119	}
120	StringAlignment GetLineAlignment() const
121	{
122		StringAlignment result = StringAlignmentNear;
123		updateStatus(DllExports::GdipGetStringFormatLineAlign(
124				nativeStringFormat, &result));
125		return result;
126	}
127	INT GetMeasurableCharacterRangeCount() const
128	{
129		INT result = 0;
130		updateStatus(DllExports::GdipGetStringFormatMeasurableCharacterRangeCount(
131				nativeStringFormat, &result));
132		return result;
133	}
134	INT GetTabStopCount() const
135	{
136		INT result = 0;
137		updateStatus(DllExports::GdipGetStringFormatTabStopCount(
138				nativeStringFormat, &result));
139		return result;
140	}
141	Status GetTabStops(INT count, REAL *firstTabOffset, REAL *tabStops)
142	{
143		return updateStatus(DllExports::GdipGetStringFormatTabStops(
144				nativeStringFormat, count,
145				firstTabOffset, tabStops));
146	}
147	StringTrimming GetTrimming() const
148	{
149		StringTrimming result = StringTrimmingNone;
150		updateStatus(DllExports::GdipGetStringFormatTrimming(
151				nativeStringFormat, &result));
152		return result;
153	}
154	Status SetAlignment(StringAlignment align)
155	{
156		return updateStatus(DllExports::GdipSetStringFormatAlign(
157				nativeStringFormat, align));
158	}
159	Status SetDigitSubstitution(LANGID language,
160			StringDigitSubstitute substitute)
161	{
162		return updateStatus(DllExports::GdipSetStringFormatDigitSubstitution(
163				nativeStringFormat, language, substitute));
164	}
165	Status SetFormatFlags(INT flags)
166	{
167		return updateStatus(DllExports::GdipSetStringFormatFlags(
168				nativeStringFormat, flags));
169	}
170	Status SetHotkeyPrefix(HotkeyPrefix hotkeyPrefix)
171	{
172		return updateStatus(DllExports::GdipSetStringFormatHotkeyPrefix(
173				nativeStringFormat, (INT) hotkeyPrefix));
174	}
175	Status SetLineAlignment(StringAlignment align)
176	{
177		return updateStatus(DllExports::GdipSetStringFormatLineAlign(
178				nativeStringFormat, align));
179	}
180	Status SetMeasurableCharacterRanges(INT rangeCount,
181			const CharacterRange *ranges)
182	{
183		return updateStatus(DllExports::GdipSetStringFormatMeasurableCharacterRanges(
184				nativeStringFormat, rangeCount, ranges));
185	}
186	Status SetTabStops(REAL firstTabOffset, INT count, const REAL *tabStops)
187	{
188		return updateStatus(DllExports::GdipSetStringFormatTabStops(
189				nativeStringFormat, firstTabOffset,
190				count, tabStops));
191	}
192	Status SetTrimming(StringTrimming trimming)
193	{
194		return updateStatus(DllExports::GdipSetStringFormatTrimming(
195				nativeStringFormat, trimming));
196	}
197
198private:
199	StringFormat(GpStringFormat *stringFormat, Status status):
200		nativeStringFormat(stringFormat), lastStatus(status) {}
201	StringFormat(const StringFormat&);
202	StringFormat& operator=(const StringFormat&);
203
204	Status updateStatus(Status newStatus) const
205	{
206		if (newStatus != Ok) lastStatus = newStatus;
207		return newStatus;
208	}
209
210	GpStringFormat *nativeStringFormat;
211	mutable Status lastStatus;
212};
213
214
215// FIXME: do StringFormat::GenericDefault() et al. need to be thread safe?
216// FIXME: maybe put this in gdiplus.c?
217
218extern "C" void *_GdipStringFormatCachedGenericDefault;
219extern "C" void *_GdipStringFormatCachedGenericTypographic;
220
221__inline__ const StringFormat* StringFormat::GenericDefault()
222{
223	if (!_GdipStringFormatCachedGenericDefault) {
224		GpStringFormat *nativeStringFormat = 0;
225		Status status = DllExports::GdipStringFormatGetGenericDefault(
226				&nativeStringFormat);
227		if (status == Ok && nativeStringFormat) {
228			_GdipStringFormatCachedGenericDefault = (void*)
229				new StringFormat(nativeStringFormat, Ok);
230		}
231	}
232	return (StringFormat*) _GdipStringFormatCachedGenericDefault;
233}
234
235__inline__ const StringFormat* StringFormat::GenericTypographic()
236{
237	if (!_GdipStringFormatCachedGenericTypographic) {
238		GpStringFormat *nativeStringFormat = 0;
239		Status status = DllExports::GdipStringFormatGetGenericTypographic(
240				&nativeStringFormat);
241		if (status == Ok && nativeStringFormat) {
242			_GdipStringFormatCachedGenericTypographic = (void*)
243				new StringFormat(nativeStringFormat, Ok);
244		}
245	}
246	return (StringFormat*) _GdipStringFormatCachedGenericTypographic;
247}
248
249
250
251#endif /* __GDIPLUS_STRINGFORMAT_H */
252