1af86ce75SJérôme Duval/*
295fdee0bSAxel Dörfler * Copyright 2001-2015, Haiku, Inc.
3af86ce75SJérôme Duval * Distributed under the terms of the MIT License.
4af86ce75SJérôme Duval *
5af86ce75SJérôme Duval * Authors:
69b1ad6f4SAxel Dörfler *		DarkWyrm <bpmagic@columbus.rr.com>
79b1ad6f4SAxel Dörfler *		J��r��me Duval, jerome.duval@free.fr
89b1ad6f4SAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
910f6ed94SStephan Aßmus *		Stephan A��mus <superstippi@gmx.de>
101d6aab33SStephan Aßmus *		Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
11af86ce75SJérôme Duval */
129b1ad6f4SAxel Dörfler
139b1ad6f4SAxel Dörfler
1493820f1eSAxel Dörfler#include <AppServerLink.h>
1593820f1eSAxel Dörfler#include <FontPrivate.h>
1693820f1eSAxel Dörfler#include <ObjectList.h>
1793820f1eSAxel Dörfler#include <ServerProtocol.h>
1893820f1eSAxel Dörfler#include <truncate_string.h>
1993820f1eSAxel Dörfler#include <utf8_functions.h>
209bdb0522SStephan Aßmus
21e37155c6SAxel Dörfler#include <Autolock.h>
22b2cc3454SAxel Dörfler#include <Font.h>
23e37155c6SAxel Dörfler#include <Locker.h>
249e6e69abSDarkWyrm#include <Message.h>
25edd19f3dSDarkWyrm#include <PortLink.h>
269bdb0522SStephan Aßmus#include <Rect.h>
279bdb0522SStephan Aßmus#include <Shape.h>
289bdb0522SStephan Aßmus#include <String.h>
299bdb0522SStephan Aßmus
3093820f1eSAxel Dörfler#include <new>
3193820f1eSAxel Dörfler#include <stdio.h>
3293820f1eSAxel Dörfler#include <stdlib.h>
33f1fafe31SAugustin Cavalier#include <pthread.h>
34f1fafe31SAugustin Cavalier
35edd19f3dSDarkWyrm
36758b1d0eSIngo Weinholdusing namespace std;
37edd19f3dSDarkWyrm
38ec769ec5SAxel Dörflerconst float kUninitializedAscent = INFINITY;
39b2cc3454SAxel Dörflerconst uint32 kUninitializedExtraFlags = 0xffffffff;
40ec769ec5SAxel Dörfler
41edd19f3dSDarkWyrm// The actual objects which the globals point to
4250df61f8SAxel Dörflerstatic BFont sPlainFont;
4350df61f8SAxel Dörflerstatic BFont sBoldFont;
4450df61f8SAxel Dörflerstatic BFont sFixedFont;
45edd19f3dSDarkWyrm
46569eed2dSStephan Aßmusconst BFont* be_plain_font = &sPlainFont;
47569eed2dSStephan Aßmusconst BFont* be_bold_font = &sBoldFont;
48569eed2dSStephan Aßmusconst BFont* be_fixed_font = &sFixedFont;
49edd19f3dSDarkWyrm
50edd19f3dSDarkWyrm
51e37155c6SAxel Dörflerstruct style {
52e37155c6SAxel Dörfler	BString	name;
53e37155c6SAxel Dörfler	uint16	face;
54e37155c6SAxel Dörfler	uint32	flags;
55e37155c6SAxel Dörfler};
56e37155c6SAxel Dörfler
57e37155c6SAxel Dörflerstruct family {
58e37155c6SAxel Dörfler	BString	name;
59e37155c6SAxel Dörfler	uint32	flags;
60e37155c6SAxel Dörfler	BObjectList<style> styles;
61e37155c6SAxel Dörfler};
62e37155c6SAxel Dörfler
630eb45760SIngo Weinholdnamespace {
64e37155c6SAxel Dörfler
65e37155c6SAxel Dörflerclass FontList : public BLocker {
66569eed2dSStephan Aßmuspublic:
67569eed2dSStephan Aßmus								FontList();
68569eed2dSStephan Aßmus	virtual						~FontList();
69569eed2dSStephan Aßmus
70569eed2dSStephan Aßmus	static	FontList*			Default();
71569eed2dSStephan Aßmus
72569eed2dSStephan Aßmus			bool				UpdatedOnServer();
73569eed2dSStephan Aßmus
74569eed2dSStephan Aßmus			status_t			FamilyAt(int32 index, font_family* _family,
75569eed2dSStephan Aßmus									uint32* _flags);
76569eed2dSStephan Aßmus			status_t			StyleAt(font_family family, int32 index,
77569eed2dSStephan Aßmus									font_style* _style, uint16* _face,
78569eed2dSStephan Aßmus									uint32* _flags);
79569eed2dSStephan Aßmus
80569eed2dSStephan Aßmus			int32				CountFamilies();
81569eed2dSStephan Aßmus			int32				CountStyles(font_family family);
82569eed2dSStephan Aßmus
83569eed2dSStephan Aßmusprivate:
84569eed2dSStephan Aßmus			status_t			_UpdateIfNecessary();
85569eed2dSStephan Aßmus			status_t			_Update();
86569eed2dSStephan Aßmus			int32				_RevisionOnServer();
87569eed2dSStephan Aßmus			family*				_FindFamily(font_family name);
88569eed2dSStephan Aßmus	static	void				_InitSingleton();
89569eed2dSStephan Aßmus
90569eed2dSStephan Aßmusprivate:
91569eed2dSStephan Aßmus			BObjectList<family>	fFamilies;
92569eed2dSStephan Aßmus			family*				fLastFamily;
93569eed2dSStephan Aßmus			bigtime_t			fLastUpdate;
94569eed2dSStephan Aßmus			int32				fRevision;
95569eed2dSStephan Aßmus
96569eed2dSStephan Aßmus	static	pthread_once_t		sDefaultInitOnce;
97569eed2dSStephan Aßmus	static	FontList*			sDefaultInstance;
98e37155c6SAxel Dörfler};
99e37155c6SAxel Dörfler
1000eb45760SIngo Weinholdpthread_once_t FontList::sDefaultInitOnce = PTHREAD_ONCE_INIT;
1010eb45760SIngo WeinholdFontList* FontList::sDefaultInstance = NULL;
102e37155c6SAxel Dörfler
1030eb45760SIngo Weinhold}	// unnamed namespace
104e37155c6SAxel Dörfler
105e37155c6SAxel Dörfler
106fff7b3cdSAxel Dörfler//	#pragma mark -
107fff7b3cdSAxel Dörfler
108fff7b3cdSAxel Dörfler
109fff7b3cdSAxel Dörflerstatic int
110fff7b3cdSAxel Dörflercompare_families(const family* a, const family* b)
111fff7b3cdSAxel Dörfler{
112fff7b3cdSAxel Dörfler	// TODO: compare font names according to the user's locale settings
113fff7b3cdSAxel Dörfler	return strcmp(a->name.String(), b->name.String());
114fff7b3cdSAxel Dörfler}
115fff7b3cdSAxel Dörfler
116fff7b3cdSAxel Dörfler
1170eb45760SIngo Weinholdnamespace {
118e37155c6SAxel Dörfler
119e37155c6SAxel DörflerFontList::FontList()
120e37155c6SAxel Dörfler	: BLocker("font list"),
121e37155c6SAxel Dörfler	fLastFamily(NULL),
122e37155c6SAxel Dörfler	fLastUpdate(0),
123e37155c6SAxel Dörfler	fRevision(0)
124e37155c6SAxel Dörfler{
125e37155c6SAxel Dörfler}
126e37155c6SAxel Dörfler
127e37155c6SAxel Dörfler
128e37155c6SAxel DörflerFontList::~FontList()
129e37155c6SAxel Dörfler{
130e37155c6SAxel Dörfler}
131e37155c6SAxel Dörfler
132e37155c6SAxel Dörfler
1330eb45760SIngo Weinhold/*static*/ FontList*
1340eb45760SIngo WeinholdFontList::Default()
1350eb45760SIngo Weinhold{
1360eb45760SIngo Weinhold	if (sDefaultInstance == NULL)
1370eb45760SIngo Weinhold		pthread_once(&sDefaultInitOnce, &_InitSingleton);
1380eb45760SIngo Weinhold
1390eb45760SIngo Weinhold	return sDefaultInstance;
1400eb45760SIngo Weinhold}
1410eb45760SIngo Weinhold
1420eb45760SIngo Weinhold
143e37155c6SAxel Dörflerbool
144e37155c6SAxel DörflerFontList::UpdatedOnServer()
145e37155c6SAxel Dörfler{
146e37155c6SAxel Dörfler	return _RevisionOnServer() != fRevision;
147e37155c6SAxel Dörfler}
148e37155c6SAxel Dörfler
149e37155c6SAxel Dörfler
150569eed2dSStephan Aßmusstatus_t
151569eed2dSStephan AßmusFontList::FamilyAt(int32 index, font_family* _family, uint32* _flags)
152569eed2dSStephan Aßmus{
153569eed2dSStephan Aßmus	BAutolock locker(this);
154569eed2dSStephan Aßmus
155569eed2dSStephan Aßmus	status_t status = _UpdateIfNecessary();
156569eed2dSStephan Aßmus	if (status < B_OK)
157569eed2dSStephan Aßmus		return status;
158569eed2dSStephan Aßmus
159569eed2dSStephan Aßmus	::family* family = fFamilies.ItemAt(index);
160569eed2dSStephan Aßmus	if (family == NULL)
161569eed2dSStephan Aßmus		return B_BAD_VALUE;
162569eed2dSStephan Aßmus
163569eed2dSStephan Aßmus	memcpy(*_family, family->name.String(), family->name.Length() + 1);
164569eed2dSStephan Aßmus	if (_flags)
165569eed2dSStephan Aßmus		*_flags = family->flags;
166569eed2dSStephan Aßmus	return B_OK;
167569eed2dSStephan Aßmus}
168569eed2dSStephan Aßmus
169569eed2dSStephan Aßmus
170569eed2dSStephan Aßmusstatus_t
171569eed2dSStephan AßmusFontList::StyleAt(font_family familyName, int32 index, font_style* _style,
172569eed2dSStephan Aßmus	uint16* _face, uint32* _flags)
173569eed2dSStephan Aßmus{
174569eed2dSStephan Aßmus	BAutolock locker(this);
175569eed2dSStephan Aßmus
176569eed2dSStephan Aßmus	status_t status = _UpdateIfNecessary();
177569eed2dSStephan Aßmus	if (status < B_OK)
178569eed2dSStephan Aßmus		return status;
179569eed2dSStephan Aßmus
180569eed2dSStephan Aßmus	::family* family = _FindFamily(familyName);
181569eed2dSStephan Aßmus	if (family == NULL)
182569eed2dSStephan Aßmus		return B_BAD_VALUE;
183569eed2dSStephan Aßmus
184569eed2dSStephan Aßmus	::style* style = family->styles.ItemAt(index);
185569eed2dSStephan Aßmus	if (style == NULL)
186569eed2dSStephan Aßmus		return B_BAD_VALUE;
187569eed2dSStephan Aßmus
188569eed2dSStephan Aßmus	memcpy(*_style, style->name.String(), style->name.Length() + 1);
189569eed2dSStephan Aßmus	if (_face)
190569eed2dSStephan Aßmus		*_face = style->face;
191569eed2dSStephan Aßmus	if (_flags)
192569eed2dSStephan Aßmus		*_flags = style->flags;
193569eed2dSStephan Aßmus	return B_OK;
194569eed2dSStephan Aßmus}
195569eed2dSStephan Aßmus
196569eed2dSStephan Aßmus
197e37155c6SAxel Dörflerint32
198569eed2dSStephan AßmusFontList::CountFamilies()
199e37155c6SAxel Dörfler{
200569eed2dSStephan Aßmus	BAutolock locker(this);
201e37155c6SAxel Dörfler
202569eed2dSStephan Aßmus	_UpdateIfNecessary();
203569eed2dSStephan Aßmus	return fFamilies.CountItems();
204569eed2dSStephan Aßmus}
205e37155c6SAxel Dörfler
206e37155c6SAxel Dörfler
207569eed2dSStephan Aßmusint32
208569eed2dSStephan AßmusFontList::CountStyles(font_family familyName)
209569eed2dSStephan Aßmus{
210569eed2dSStephan Aßmus	BAutolock locker(this);
211569eed2dSStephan Aßmus
212569eed2dSStephan Aßmus	_UpdateIfNecessary();
213569eed2dSStephan Aßmus
214569eed2dSStephan Aßmus	::family* family = _FindFamily(familyName);
215569eed2dSStephan Aßmus	if (family == NULL)
216569eed2dSStephan Aßmus		return 0;
217569eed2dSStephan Aßmus
218569eed2dSStephan Aßmus	return family->styles.CountItems();
219e37155c6SAxel Dörfler}
220e37155c6SAxel Dörfler
221e37155c6SAxel Dörfler
222e37155c6SAxel Dörflerstatus_t
223e37155c6SAxel DörflerFontList::_Update()
224e37155c6SAxel Dörfler{
225e37155c6SAxel Dörfler	// check version
226e37155c6SAxel Dörfler
227e37155c6SAxel Dörfler	int32 revision = _RevisionOnServer();
228e37155c6SAxel Dörfler	fLastUpdate = system_time();
229e37155c6SAxel Dörfler
230e37155c6SAxel Dörfler	// are we up-to-date already?
231e37155c6SAxel Dörfler	if (revision == fRevision)
232e37155c6SAxel Dörfler		return B_OK;
233e37155c6SAxel Dörfler
234e37155c6SAxel Dörfler	fFamilies.MakeEmpty();
235e37155c6SAxel Dörfler	fLastFamily = NULL;
236e37155c6SAxel Dörfler
237e37155c6SAxel Dörfler	BPrivate::AppServerLink link;
238e37155c6SAxel Dörfler
239e37155c6SAxel Dörfler	for (int32 index = 0;; index++) {
240e37155c6SAxel Dörfler		link.StartMessage(AS_GET_FAMILY_AND_STYLES);
241e37155c6SAxel Dörfler		link.Attach<int32>(index);
242e37155c6SAxel Dörfler
243e37155c6SAxel Dörfler		int32 status;
244e37155c6SAxel Dörfler		if (link.FlushWithReply(status) != B_OK
245e37155c6SAxel Dörfler			|| status != B_OK)
246e37155c6SAxel Dörfler			break;
247e37155c6SAxel Dörfler
248e37155c6SAxel Dörfler		::family* family = new (nothrow) ::family;
249e37155c6SAxel Dörfler		if (family == NULL)
250e37155c6SAxel Dörfler			return B_NO_MEMORY;
251e37155c6SAxel Dörfler
252e37155c6SAxel Dörfler		link.ReadString(family->name);
253e37155c6SAxel Dörfler		link.Read<uint32>(&family->flags);
254e37155c6SAxel Dörfler
255e37155c6SAxel Dörfler		int32 styleCount;
256e37155c6SAxel Dörfler		link.Read<int32>(&styleCount);
257e37155c6SAxel Dörfler
258e37155c6SAxel Dörfler		for (int32 i = 0; i < styleCount; i++) {
259e37155c6SAxel Dörfler			::style* style = new (nothrow) ::style;
260e37155c6SAxel Dörfler			if (style == NULL) {
261e37155c6SAxel Dörfler				delete family;
262e37155c6SAxel Dörfler				return B_NO_MEMORY;
263e37155c6SAxel Dörfler			}
2641d6aab33SStephan Aßmus
265e37155c6SAxel Dörfler			link.ReadString(style->name);
266e37155c6SAxel Dörfler			link.Read<uint16>(&style->face);
267e37155c6SAxel Dörfler			link.Read<uint32>(&style->flags);
268e37155c6SAxel Dörfler
269e37155c6SAxel Dörfler			family->styles.AddItem(style);
270e37155c6SAxel Dörfler		}
271e37155c6SAxel Dörfler
272fff7b3cdSAxel Dörfler		fFamilies.BinaryInsert(family, compare_families);
273e37155c6SAxel Dörfler	}
274e37155c6SAxel Dörfler
275e37155c6SAxel Dörfler	fRevision = revision;
276e37155c6SAxel Dörfler
277e37155c6SAxel Dörfler	// if the font list has been changed in the mean time, just update again
278e37155c6SAxel Dörfler	if (UpdatedOnServer())
279e37155c6SAxel Dörfler		_Update();
280e37155c6SAxel Dörfler
281e37155c6SAxel Dörfler	return B_OK;
282e37155c6SAxel Dörfler}
283e37155c6SAxel Dörfler
284e37155c6SAxel Dörfler
285e37155c6SAxel Dörflerstatus_t
286e37155c6SAxel DörflerFontList::_UpdateIfNecessary()
287e37155c6SAxel Dörfler{
288e37155c6SAxel Dörfler	// an updated font list is at least valid for 1 second
289e37155c6SAxel Dörfler	if (fLastUpdate > system_time() - 1000000)
290e37155c6SAxel Dörfler		return B_OK;
291e37155c6SAxel Dörfler
292e37155c6SAxel Dörfler	return _Update();
293e37155c6SAxel Dörfler}
294e37155c6SAxel Dörfler
295e37155c6SAxel Dörfler
296569eed2dSStephan Aßmusint32
297569eed2dSStephan AßmusFontList::_RevisionOnServer()
298569eed2dSStephan Aßmus{
299569eed2dSStephan Aßmus	BPrivate::AppServerLink link;
300569eed2dSStephan Aßmus	link.StartMessage(AS_GET_FONT_LIST_REVISION);
301569eed2dSStephan Aßmus
302569eed2dSStephan Aßmus	int32 code;
303569eed2dSStephan Aßmus	if (link.FlushWithReply(code) != B_OK || code != B_OK)
304569eed2dSStephan Aßmus		return B_ERROR;
305569eed2dSStephan Aßmus
306569eed2dSStephan Aßmus	int32 revision;
307569eed2dSStephan Aßmus	link.Read<int32>(&revision);
308569eed2dSStephan Aßmus
309569eed2dSStephan Aßmus	return revision;
310569eed2dSStephan Aßmus}
311569eed2dSStephan Aßmus
312569eed2dSStephan Aßmus
313e37155c6SAxel Dörflerfamily*
314e37155c6SAxel DörflerFontList::_FindFamily(font_family name)
315e37155c6SAxel Dörfler{
316e37155c6SAxel Dörfler	if (fLastFamily != NULL && fLastFamily->name == name)
317e37155c6SAxel Dörfler		return fLastFamily;
318e37155c6SAxel Dörfler
319fff7b3cdSAxel Dörfler	::family family;
320fff7b3cdSAxel Dörfler	family.name = name;
321e705558bSAxel Dörfler	fLastFamily = const_cast< ::family*>(fFamilies.BinarySearch(family,
322e705558bSAxel Dörfler		compare_families));
323fff7b3cdSAxel Dörfler	return fLastFamily;
324e37155c6SAxel Dörfler}
325e37155c6SAxel Dörfler
326e37155c6SAxel Dörfler
3270eb45760SIngo Weinhold/*static*/ void
3280eb45760SIngo WeinholdFontList::_InitSingleton()
3290eb45760SIngo Weinhold{
3300eb45760SIngo Weinhold	sDefaultInstance = new FontList;
3310eb45760SIngo Weinhold}
3320eb45760SIngo Weinhold
3330eb45760SIngo Weinhold}	// unnamed namespace
334e37155c6SAxel Dörfler
335e37155c6SAxel Dörfler
336e37155c6SAxel Dörfler//	#pragma mark -
337e37155c6SAxel Dörfler
338e37155c6SAxel Dörfler
33950df61f8SAxel Dörflervoid
340b2cc3454SAxel Dörfler_init_global_fonts_()
341edd19f3dSDarkWyrm{
342dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
343b2cc3454SAxel Dörfler	link.StartMessage(AS_GET_SYSTEM_FONTS);
344dd10337fSAxel Dörfler
345ec769ec5SAxel Dörfler	int32 code;
346dd10337fSAxel Dörfler	if (link.FlushWithReply(code) != B_OK
347b8cde449SAxel Dörfler		|| code != B_OK) {
348b2cc3454SAxel Dörfler		printf("DEBUG: Couldn't initialize global fonts!\n");
349d9bb1ef4SDarkWyrm		return;
350d9bb1ef4SDarkWyrm	}
351dd10337fSAxel Dörfler
352b2cc3454SAxel Dörfler	char type[B_OS_NAME_LENGTH];
353b2cc3454SAxel Dörfler
354b2cc3454SAxel Dörfler	while (link.ReadString(type, sizeof(type)) >= B_OK && type[0]) {
355b2cc3454SAxel Dörfler		BFont dummy;
356569eed2dSStephan Aßmus		BFont* font = &dummy;
357b2cc3454SAxel Dörfler
358b2cc3454SAxel Dörfler		if (!strcmp(type, "plain"))
359b2cc3454SAxel Dörfler			font = &sPlainFont;
360b2cc3454SAxel Dörfler		else if (!strcmp(type, "bold"))
361b2cc3454SAxel Dörfler			font = &sBoldFont;
362b2cc3454SAxel Dörfler		else if (!strcmp(type, "fixed"))
363b2cc3454SAxel Dörfler			font = &sFixedFont;
364b2cc3454SAxel Dörfler
365b2cc3454SAxel Dörfler		link.Read<uint16>(&font->fFamilyID);
366b2cc3454SAxel Dörfler		link.Read<uint16>(&font->fStyleID);
367b2cc3454SAxel Dörfler		link.Read<float>(&font->fSize);
368b2cc3454SAxel Dörfler		link.Read<uint16>(&font->fFace);
369b2cc3454SAxel Dörfler		link.Read<uint32>(&font->fFlags);
370b2cc3454SAxel Dörfler
371b2cc3454SAxel Dörfler		font->fHeight.ascent = kUninitializedAscent;
372b2cc3454SAxel Dörfler		font->fExtraFlags = kUninitializedExtraFlags;
373b2cc3454SAxel Dörfler	}
374edd19f3dSDarkWyrm}
375edd19f3dSDarkWyrm
3769b1ad6f4SAxel Dörfler
377569eed2dSStephan Aßmusvoid
378569eed2dSStephan Aßmus_font_control_(BFont* font, int32 cmd, void* data)
379839e7aa6SDarkWyrm{
380839e7aa6SDarkWyrm}
381839e7aa6SDarkWyrm
382569eed2dSStephan Aßmus
383569eed2dSStephan Aßmusstatus_t
384569eed2dSStephan Aßmusget_font_cache_info(uint32 id, void* set)
385839e7aa6SDarkWyrm{
386839e7aa6SDarkWyrm	return B_ERROR;
387839e7aa6SDarkWyrm}
388839e7aa6SDarkWyrm
389569eed2dSStephan Aßmus
390569eed2dSStephan Aßmusstatus_t
391569eed2dSStephan Aßmusset_font_cache_info(uint32 id, void* set)
392839e7aa6SDarkWyrm{
393839e7aa6SDarkWyrm	return B_ERROR;
394839e7aa6SDarkWyrm}
395b2cc3454SAxel Dörfler
396b2cc3454SAxel Dörfler
3971f7ff051SJohn Scipione// Private function used to replace the R5 hack which sets a system font
3984b31e304SDarkWyrmvoid
399569eed2dSStephan Aßmus_set_system_font_(const char* which, font_family family, font_style style,
4009b1ad6f4SAxel Dörfler	float size)
4014b31e304SDarkWyrm{
402c969b462SJohn Scipione	// R5 used a global area offset table to set the system fonts in the Font
403c969b462SJohn Scipione	// preferences panel. Bleah.
404b2cc3454SAxel Dörfler	BPrivate::AppServerLink link;
405b2cc3454SAxel Dörfler
406b2cc3454SAxel Dörfler	link.StartMessage(AS_SET_SYSTEM_FONT);
407f1d70d80SAxel Dörfler	link.AttachString(which, B_OS_NAME_LENGTH);
408f1d70d80SAxel Dörfler	link.AttachString(family, sizeof(font_family));
409f1d70d80SAxel Dörfler	link.AttachString(style, sizeof(font_style));
410b2cc3454SAxel Dörfler	link.Attach<float>(size);
411b2cc3454SAxel Dörfler	link.Flush();
4124b31e304SDarkWyrm}
4134b31e304SDarkWyrm
41450df61f8SAxel Dörfler
415f1d70d80SAxel Dörflerstatus_t
416f1d70d80SAxel Dörfler_get_system_default_font_(const char* which, font_family family,
417f1d70d80SAxel Dörfler	font_style style, float* _size)
418f1d70d80SAxel Dörfler{
419f1d70d80SAxel Dörfler	BPrivate::AppServerLink link;
420f1d70d80SAxel Dörfler
421f1d70d80SAxel Dörfler	link.StartMessage(AS_GET_SYSTEM_DEFAULT_FONT);
422f1d70d80SAxel Dörfler	link.AttachString(which, B_OS_NAME_LENGTH);
423f1d70d80SAxel Dörfler
424f1d70d80SAxel Dörfler	int32 status = B_ERROR;
425f1d70d80SAxel Dörfler	if (link.FlushWithReply(status) != B_OK
426f1d70d80SAxel Dörfler		|| status < B_OK)
427f1d70d80SAxel Dörfler		return status;
428f1d70d80SAxel Dörfler
429f1d70d80SAxel Dörfler	link.ReadString(family, sizeof(font_family));
430f1d70d80SAxel Dörfler	link.ReadString(style, sizeof(font_style));
431f1d70d80SAxel Dörfler	link.Read<float>(_size);
432f1d70d80SAxel Dörfler	return B_OK;
433f1d70d80SAxel Dörfler}
434f1d70d80SAxel Dörfler
435f1d70d80SAxel Dörfler
4361f7ff051SJohn Scipione// Returns the number of installed font families
43750df61f8SAxel Dörflerint32
438e37155c6SAxel Dörflercount_font_families()
439edd19f3dSDarkWyrm{
4400eb45760SIngo Weinhold	return FontList::Default()->CountFamilies();
441edd19f3dSDarkWyrm}
442edd19f3dSDarkWyrm
44350df61f8SAxel Dörfler
4441f7ff051SJohn Scipione// Returns the number of styles available for a font family
44550df61f8SAxel Dörflerint32
4465d1bd031SAxel Dörflercount_font_styles(font_family family)
447edd19f3dSDarkWyrm{
4480eb45760SIngo Weinhold	return FontList::Default()->CountStyles(family);
449edd19f3dSDarkWyrm}
450edd19f3dSDarkWyrm
45150df61f8SAxel Dörfler
4521f7ff051SJohn Scipione// Retrieves the family name at the specified index
45350df61f8SAxel Dörflerstatus_t
454569eed2dSStephan Aßmusget_font_family(int32 index, font_family* _name, uint32* _flags)
455edd19f3dSDarkWyrm{
4565d1bd031SAxel Dörfler	if (_name == NULL)
4579b1ad6f4SAxel Dörfler		return B_BAD_VALUE;
45850df61f8SAxel Dörfler
4590eb45760SIngo Weinhold	return FontList::Default()->FamilyAt(index, _name, _flags);
460edd19f3dSDarkWyrm}
461edd19f3dSDarkWyrm
46250df61f8SAxel Dörfler
4631f7ff051SJohn Scipione// Retrieves the family name at the specified index
46450df61f8SAxel Dörflerstatus_t
465569eed2dSStephan Aßmusget_font_style(font_family family, int32 index, font_style* _name,
466569eed2dSStephan Aßmus	uint32* _flags)
467edd19f3dSDarkWyrm{
468b8cde449SAxel Dörfler	return get_font_style(family, index, _name, NULL, _flags);
469edd19f3dSDarkWyrm}
470edd19f3dSDarkWyrm
47150df61f8SAxel Dörfler
4721f7ff051SJohn Scipione// Retrieves the family name at the specified index
47350df61f8SAxel Dörflerstatus_t
474569eed2dSStephan Aßmusget_font_style(font_family family, int32 index, font_style* _name,
475569eed2dSStephan Aßmus	uint16* _face, uint32* _flags)
476edd19f3dSDarkWyrm{
477c969b462SJohn Scipione	// The face value returned by this function is not very reliable. At the
478c969b462SJohn Scipione	// same time, the value returned should be fairly reliable, returning the
479c969b462SJohn Scipione	// proper flag for 90%-99% of font names.
480c969b462SJohn Scipione
481b8cde449SAxel Dörfler	if (_name == NULL)
4829b1ad6f4SAxel Dörfler		return B_BAD_VALUE;
483edd19f3dSDarkWyrm
4840eb45760SIngo Weinhold	return FontList::Default()->StyleAt(family, index, _name, _face, _flags);
485edd19f3dSDarkWyrm}
486edd19f3dSDarkWyrm
48750df61f8SAxel Dörfler
4881f7ff051SJohn Scipione// Updates the font family list
48950df61f8SAxel Dörflerbool
490e37155c6SAxel Dörflerupdate_font_families(bool /*checkOnly*/)
491edd19f3dSDarkWyrm{
4920eb45760SIngo Weinhold	return FontList::Default()->UpdatedOnServer();
493edd19f3dSDarkWyrm}
494edd19f3dSDarkWyrm
49550df61f8SAxel Dörfler
4969b1ad6f4SAxel Dörfler//	#pragma mark -
497edd19f3dSDarkWyrm
49850df61f8SAxel Dörfler
4991d6aab33SStephan AßmusBFont::BFont()
50050df61f8SAxel Dörfler	:
50150df61f8SAxel Dörfler	// initialise for be_plain_font (avoid circular definition)
50250df61f8SAxel Dörfler	fFamilyID(0),
50350df61f8SAxel Dörfler	fStyleID(0),
50450df61f8SAxel Dörfler	fSize(10.0),
505ac13e18bSMichael Lotz	fShear(90.0),
50650df61f8SAxel Dörfler	fRotation(0.0),
50710f6ed94SStephan Aßmus	fFalseBoldWidth(0.0),
50891233f88SStephan Aßmus	fSpacing(B_BITMAP_SPACING),
509569eed2dSStephan Aßmus	fEncoding(B_UNICODE_UTF8),
51050df61f8SAxel Dörfler	fFace(0),
511b2cc3454SAxel Dörfler	fFlags(0),
512b2cc3454SAxel Dörfler	fExtraFlags(kUninitializedExtraFlags)
5133ceb31b9SDarkWyrm{
5149b1ad6f4SAxel Dörfler	if (be_plain_font != NULL && this != &sPlainFont)
5159b1ad6f4SAxel Dörfler		*this = *be_plain_font;
5169b1ad6f4SAxel Dörfler	else {
5179b1ad6f4SAxel Dörfler		fHeight.ascent = 7.0;
5189b1ad6f4SAxel Dörfler		fHeight.descent = 2.0;
5199b1ad6f4SAxel Dörfler		fHeight.leading = 13.0;
5209b1ad6f4SAxel Dörfler	}
52134377c9bSDarkWyrm}
52234377c9bSDarkWyrm
52350df61f8SAxel Dörfler
524569eed2dSStephan AßmusBFont::BFont(const BFont& font)
52534377c9bSDarkWyrm{
5269b1ad6f4SAxel Dörfler	*this = font;
52734377c9bSDarkWyrm}
52834377c9bSDarkWyrm
52950df61f8SAxel Dörfler
530569eed2dSStephan AßmusBFont::BFont(const BFont* font)
53134377c9bSDarkWyrm{
5321f7ff051SJohn Scipione	if (font != NULL)
5339b1ad6f4SAxel Dörfler		*this = *font;
5349b1ad6f4SAxel Dörfler	else
5359b1ad6f4SAxel Dörfler		*this = *be_plain_font;
53634377c9bSDarkWyrm}
53734377c9bSDarkWyrm
53850df61f8SAxel Dörfler
5391f7ff051SJohn Scipione// Sets the font's family and style all at once
54050df61f8SAxel Dörflerstatus_t
54150df61f8SAxel DörflerBFont::SetFamilyAndStyle(const font_family family, const font_style style)
54234377c9bSDarkWyrm{
5439b1ad6f4SAxel Dörfler	if (family == NULL && style == NULL)
5449b1ad6f4SAxel Dörfler		return B_BAD_VALUE;
545dd10337fSAxel Dörfler
546dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
547dd10337fSAxel Dörfler
548b2cc3454SAxel Dörfler	link.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS);
549f1d70d80SAxel Dörfler	link.AttachString(family, sizeof(font_family));
550f1d70d80SAxel Dörfler	link.AttachString(style, sizeof(font_style));
551b8cde449SAxel Dörfler	link.Attach<uint16>(fFamilyID);
552b8cde449SAxel Dörfler	link.Attach<uint16>(0xffff);
5539b1ad6f4SAxel Dörfler	link.Attach<uint16>(fFace);
554dd10337fSAxel Dörfler
5556f121769SAxel Dörfler	int32 status = B_ERROR;
5561f7ff051SJohn Scipione	if (link.FlushWithReply(status) != B_OK || status != B_OK)
5579b1ad6f4SAxel Dörfler		return status;
558dd10337fSAxel Dörfler
5599b1ad6f4SAxel Dörfler	link.Read<uint16>(&fFamilyID);
5609b1ad6f4SAxel Dörfler	link.Read<uint16>(&fStyleID);
5619b1ad6f4SAxel Dörfler	link.Read<uint16>(&fFace);
562ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
56354a7f092SStephan Aßmus	fExtraFlags = kUninitializedExtraFlags;
564ec769ec5SAxel Dörfler
5655fbd2c2fSDarkWyrm	return B_OK;
56634377c9bSDarkWyrm}
56734377c9bSDarkWyrm
56850df61f8SAxel Dörfler
5691f7ff051SJohn Scipione// Sets the font's family and style all at once
57050df61f8SAxel Dörflervoid
571840476e1SJohn ScipioneBFont::SetFamilyAndStyle(uint32 code)
57234377c9bSDarkWyrm{
57310f6ed94SStephan Aßmus	// R5 has a bug here: the face is not updated even though the IDs are set.
57410f6ed94SStephan Aßmus	// This is a problem because the face flag includes Regular/Bold/Italic
57510f6ed94SStephan Aßmus	// information in addition to stuff like underlining and strikethrough.
57610f6ed94SStephan Aßmus	// As a result, this will need a trip to the server and, thus, be slower
57710f6ed94SStephan Aßmus	// than R5's in order to be correct
578dd10337fSAxel Dörfler
579b8cde449SAxel Dörfler	uint16 family, style;
580840476e1SJohn Scipione	style = code & 0xFFFF;
581840476e1SJohn Scipione	family = (code & 0xFFFF0000) >> 16;
582dd10337fSAxel Dörfler
583b8cde449SAxel Dörfler	BPrivate::AppServerLink link;
584b2cc3454SAxel Dörfler	link.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS);
585b8cde449SAxel Dörfler	link.AttachString(NULL);	// no family and style name
586b8cde449SAxel Dörfler	link.AttachString(NULL);
5879e6e69abSDarkWyrm	link.Attach<uint16>(family);
5889e6e69abSDarkWyrm	link.Attach<uint16>(style);
589b8cde449SAxel Dörfler	link.Attach<uint16>(fFace);
590dd10337fSAxel Dörfler
591840476e1SJohn Scipione	int32 fontcode;
592840476e1SJohn Scipione	if (link.FlushWithReply(fontcode) != B_OK || fontcode != B_OK)
5939e6e69abSDarkWyrm		return;
594dd10337fSAxel Dörfler
595b8cde449SAxel Dörfler	link.Read<uint16>(&fFamilyID);
596b8cde449SAxel Dörfler	link.Read<uint16>(&fStyleID);
597b8cde449SAxel Dörfler	link.Read<uint16>(&fFace);
598ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
59954a7f092SStephan Aßmus	fExtraFlags = kUninitializedExtraFlags;
60034377c9bSDarkWyrm}
60134377c9bSDarkWyrm
60250df61f8SAxel Dörfler
6031f7ff051SJohn Scipione// Sets the font's family and face all at once
60450df61f8SAxel Dörflerstatus_t
60550df61f8SAxel DörflerBFont::SetFamilyAndFace(const font_family family, uint16 face)
60634377c9bSDarkWyrm{
607c969b462SJohn Scipione	// To comply with the BeBook, this function will only set valid values
608c969b462SJohn Scipione	// i.e. passing a nonexistent family will cause only the face to be set.
609c969b462SJohn Scipione	// Additionally, if a particular  face does not exist in a family, the
610c969b462SJohn Scipione	// closest match will be chosen.
611c969b462SJohn Scipione
612b8cde449SAxel Dörfler	BPrivate::AppServerLink link;
613b2cc3454SAxel Dörfler	link.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS);
614f1d70d80SAxel Dörfler	link.AttachString(family, sizeof(font_family));
615b8cde449SAxel Dörfler	link.AttachString(NULL);	// no style given
616b8cde449SAxel Dörfler	link.Attach<uint16>(fFamilyID);
617b8cde449SAxel Dörfler	link.Attach<uint16>(0xffff);
618b8cde449SAxel Dörfler	link.Attach<uint16>(face);
619dd10337fSAxel Dörfler
6206f121769SAxel Dörfler	int32 status = B_ERROR;
6211f7ff051SJohn Scipione	if (link.FlushWithReply(status) != B_OK || status != B_OK)
622b8cde449SAxel Dörfler		return status;
623dd10337fSAxel Dörfler
624b8cde449SAxel Dörfler	link.Read<uint16>(&fFamilyID);
625b8cde449SAxel Dörfler	link.Read<uint16>(&fStyleID);
626b8cde449SAxel Dörfler	link.Read<uint16>(&fFace);
627ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
62854a7f092SStephan Aßmus	fExtraFlags = kUninitializedExtraFlags;
629b8cde449SAxel Dörfler
63034377c9bSDarkWyrm	return B_OK;
63134377c9bSDarkWyrm}
63234377c9bSDarkWyrm
63350df61f8SAxel Dörfler
63450df61f8SAxel Dörflervoid
63550df61f8SAxel DörflerBFont::SetSize(float size)
63634377c9bSDarkWyrm{
63750df61f8SAxel Dörfler	fSize = size;
638ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
63934377c9bSDarkWyrm}
64034377c9bSDarkWyrm
64150df61f8SAxel Dörfler
64250df61f8SAxel Dörflervoid
64350df61f8SAxel DörflerBFont::SetShear(float shear)
64434377c9bSDarkWyrm{
64550df61f8SAxel Dörfler	fShear = shear;
646ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
64734377c9bSDarkWyrm}
64834377c9bSDarkWyrm
64950df61f8SAxel Dörfler
65050df61f8SAxel Dörflervoid
65150df61f8SAxel DörflerBFont::SetRotation(float rotation)
65234377c9bSDarkWyrm{
65350df61f8SAxel Dörfler	fRotation = rotation;
654ec769ec5SAxel Dörfler	fHeight.ascent = kUninitializedAscent;
65534377c9bSDarkWyrm}
65634377c9bSDarkWyrm
65750df61f8SAxel Dörfler
65810f6ed94SStephan Aßmusvoid
65910f6ed94SStephan AßmusBFont::SetFalseBoldWidth(float width)
66010f6ed94SStephan Aßmus{
66110f6ed94SStephan Aßmus	fFalseBoldWidth = width;
66210f6ed94SStephan Aßmus}
66310f6ed94SStephan Aßmus
66410f6ed94SStephan Aßmus
66550df61f8SAxel Dörflervoid
66650df61f8SAxel DörflerBFont::SetSpacing(uint8 spacing)
66734377c9bSDarkWyrm{
66850df61f8SAxel Dörfler	fSpacing = spacing;
66934377c9bSDarkWyrm}
67034377c9bSDarkWyrm
67150df61f8SAxel Dörfler
67250df61f8SAxel Dörflervoid
67350df61f8SAxel DörflerBFont::SetEncoding(uint8 encoding)
67434377c9bSDarkWyrm{
67550df61f8SAxel Dörfler	fEncoding = encoding;
67634377c9bSDarkWyrm}
67734377c9bSDarkWyrm
67850df61f8SAxel Dörfler
67950df61f8SAxel Dörflervoid
68050df61f8SAxel DörflerBFont::SetFace(uint16 face)
68134377c9bSDarkWyrm{
682b8cde449SAxel Dörfler	if (face == fFace)
683b8cde449SAxel Dörfler		return;
684b8cde449SAxel Dörfler
685b8cde449SAxel Dörfler	SetFamilyAndFace(NULL, face);
68634377c9bSDarkWyrm}
68734377c9bSDarkWyrm
68850df61f8SAxel Dörfler
68950df61f8SAxel Dörflervoid
69050df61f8SAxel DörflerBFont::SetFlags(uint32 flags)
69134377c9bSDarkWyrm{
69250df61f8SAxel Dörfler	fFlags = flags;
69334377c9bSDarkWyrm}
69434377c9bSDarkWyrm
69550df61f8SAxel Dörfler
69650df61f8SAxel Dörflervoid
697569eed2dSStephan AßmusBFont::GetFamilyAndStyle(font_family* family, font_style* style) const
69834377c9bSDarkWyrm{
6999b1ad6f4SAxel Dörfler	if (family == NULL && style == NULL)
7005fbd2c2fS