2 * Copyright 2001-2015, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Jérôme Duval, jerome.duval@free.fr
8 * Axel Dörfler, axeld@pinc-software.de
9 * Stephan Aßmus <superstippi@gmx.de>
10 * Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
14 #include <AppServerLink.h>
15 #include <FontPrivate.h>
16 #include <ObjectList.h>
17 #include <ServerProtocol.h>
18 #include <truncate_string.h>
19 #include <utf8_functions.h>
36 const float kUninitializedAscent
= INFINITY
;
37 const uint32 kUninitializedExtraFlags
= 0xffffffff;
39 // The actual objects which the globals point to
40 static BFont sPlainFont
;
41 static BFont sBoldFont
;
42 static BFont sFixedFont
;
44 const BFont
* be_plain_font
= &sPlainFont
;
45 const BFont
* be_bold_font
= &sBoldFont
;
46 const BFont
* be_fixed_font
= &sFixedFont
;
58 BObjectList
<style
> styles
;
63 class FontList
: public BLocker
{
68 static FontList
* Default();
70 bool UpdatedOnServer();
72 status_t
FamilyAt(int32 index
, font_family
* _family
,
74 status_t
StyleAt(font_family family
, int32 index
,
75 font_style
* _style
, uint16
* _face
,
78 int32
CountFamilies();
79 int32
CountStyles(font_family family
);
82 status_t
_UpdateIfNecessary();
84 int32
_RevisionOnServer();
85 family
* _FindFamily(font_family name
);
86 static void _InitSingleton();
89 BObjectList
<family
> fFamilies
;
91 bigtime_t fLastUpdate
;
94 static pthread_once_t sDefaultInitOnce
;
95 static FontList
* sDefaultInstance
;
98 pthread_once_t
FontList::sDefaultInitOnce
= PTHREAD_ONCE_INIT
;
99 FontList
* FontList::sDefaultInstance
= NULL
;
101 } // unnamed namespace
108 compare_families(const family
* a
, const family
* b
)
110 // TODO: compare font names according to the user's locale settings
111 return strcmp(a
->name
.String(), b
->name
.String());
118 : BLocker("font list"),
126 FontList::~FontList()
134 if (sDefaultInstance
== NULL
)
135 pthread_once(&sDefaultInitOnce
, &_InitSingleton
);
137 return sDefaultInstance
;
142 FontList::UpdatedOnServer()
144 return _RevisionOnServer() != fRevision
;
149 FontList::FamilyAt(int32 index
, font_family
* _family
, uint32
* _flags
)
151 BAutolock
locker(this);
153 status_t status
= _UpdateIfNecessary();
157 ::family
* family
= fFamilies
.ItemAt(index
);
161 memcpy(*_family
, family
->name
.String(), family
->name
.Length() + 1);
163 *_flags
= family
->flags
;
169 FontList::StyleAt(font_family familyName
, int32 index
, font_style
* _style
,
170 uint16
* _face
, uint32
* _flags
)
172 BAutolock
locker(this);
174 status_t status
= _UpdateIfNecessary();
178 ::family
* family
= _FindFamily(familyName
);
182 ::style
* style
= family
->styles
.ItemAt(index
);
186 memcpy(*_style
, style
->name
.String(), style
->name
.Length() + 1);
188 *_face
= style
->face
;
190 *_flags
= style
->flags
;
196 FontList::CountFamilies()
198 BAutolock
locker(this);
200 _UpdateIfNecessary();
201 return fFamilies
.CountItems();
206 FontList::CountStyles(font_family familyName
)
208 BAutolock
locker(this);
210 _UpdateIfNecessary();
212 ::family
* family
= _FindFamily(familyName
);
216 return family
->styles
.CountItems();
225 int32 revision
= _RevisionOnServer();
226 fLastUpdate
= system_time();
228 // are we up-to-date already?
229 if (revision
== fRevision
)
232 fFamilies
.MakeEmpty();
235 BPrivate::AppServerLink link
;
237 for (int32 index
= 0;; index
++) {
238 link
.StartMessage(AS_GET_FAMILY_AND_STYLES
);
239 link
.Attach
<int32
>(index
);
242 if (link
.FlushWithReply(status
) != B_OK
246 ::family
* family
= new (nothrow
) ::family
;
250 link
.ReadString(family
->name
);
251 link
.Read
<uint32
>(&family
->flags
);
254 link
.Read
<int32
>(&styleCount
);
256 for (int32 i
= 0; i
< styleCount
; i
++) {
257 ::style
* style
= new (nothrow
) ::style
;
263 link
.ReadString(style
->name
);
264 link
.Read
<uint16
>(&style
->face
);
265 link
.Read
<uint32
>(&style
->flags
);
267 family
->styles
.AddItem(style
);
270 fFamilies
.BinaryInsert(family
, compare_families
);
273 fRevision
= revision
;
275 // if the font list has been changed in the mean time, just update again
276 if (UpdatedOnServer())
284 FontList::_UpdateIfNecessary()
286 // an updated font list is at least valid for 1 second
287 if (fLastUpdate
> system_time() - 1000000)
295 FontList::_RevisionOnServer()
297 BPrivate::AppServerLink link
;
298 link
.StartMessage(AS_GET_FONT_LIST_REVISION
);
301 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
305 link
.Read
<int32
>(&revision
);
312 FontList::_FindFamily(font_family name
)
314 if (fLastFamily
!= NULL
&& fLastFamily
->name
== name
)
319 fLastFamily
= const_cast< ::family
*>(fFamilies
.BinarySearch(family
,
326 FontList::_InitSingleton()
328 sDefaultInstance
= new FontList
;
331 } // unnamed namespace
338 _init_global_fonts_()
340 BPrivate::AppServerLink link
;
341 link
.StartMessage(AS_GET_SYSTEM_FONTS
);
344 if (link
.FlushWithReply(code
) != B_OK
346 printf("DEBUG: Couldn't initialize global fonts!\n");
350 char type
[B_OS_NAME_LENGTH
];
352 while (link
.ReadString(type
, sizeof(type
)) >= B_OK
&& type
[0]) {
354 BFont
* font
= &dummy
;
356 if (!strcmp(type
, "plain"))
358 else if (!strcmp(type
, "bold"))
360 else if (!strcmp(type
, "fixed"))
363 link
.Read
<uint16
>(&font
->fFamilyID
);
364 link
.Read
<uint16
>(&font
->fStyleID
);
365 link
.Read
<float>(&font
->fSize
);
366 link
.Read
<uint16
>(&font
->fFace
);
367 link
.Read
<uint32
>(&font
->fFlags
);
369 font
->fHeight
.ascent
= kUninitializedAscent
;
370 font
->fExtraFlags
= kUninitializedExtraFlags
;
376 _font_control_(BFont
* font
, int32 cmd
, void* data
)
382 get_font_cache_info(uint32 id
, void* set
)
389 set_font_cache_info(uint32 id
, void* set
)
395 // Private function used to replace the R5 hack which sets a system font
397 _set_system_font_(const char* which
, font_family family
, font_style style
,
400 // R5 used a global area offset table to set the system fonts in the Font
401 // preferences panel. Bleah.
402 BPrivate::AppServerLink link
;
404 link
.StartMessage(AS_SET_SYSTEM_FONT
);
405 link
.AttachString(which
, B_OS_NAME_LENGTH
);
406 link
.AttachString(family
, sizeof(font_family
));
407 link
.AttachString(style
, sizeof(font_style
));
408 link
.Attach
<float>(size
);
414 _get_system_default_font_(const char* which
, font_family family
,
415 font_style style
, float* _size
)
417 BPrivate::AppServerLink link
;
419 link
.StartMessage(AS_GET_SYSTEM_DEFAULT_FONT
);
420 link
.AttachString(which
, B_OS_NAME_LENGTH
);
422 int32 status
= B_ERROR
;
423 if (link
.FlushWithReply(status
) != B_OK
427 link
.ReadString(family
, sizeof(font_family
));
428 link
.ReadString(style
, sizeof(font_style
));
429 link
.Read
<float>(_size
);
434 // Returns the number of installed font families
436 count_font_families()
438 return FontList::Default()->CountFamilies();
442 // Returns the number of styles available for a font family
444 count_font_styles(font_family family
)
446 return FontList::Default()->CountStyles(family
);
450 // Retrieves the family name at the specified index
452 get_font_family(int32 index
, font_family
* _name
, uint32
* _flags
)
457 return FontList::Default()->FamilyAt(index
, _name
, _flags
);
461 // Retrieves the family name at the specified index
463 get_font_style(font_family family
, int32 index
, font_style
* _name
,
466 return get_font_style(family
, index
, _name
, NULL
, _flags
);
470 // Retrieves the family name at the specified index
472 get_font_style(font_family family
, int32 index
, font_style
* _name
,
473 uint16
* _face
, uint32
* _flags
)
475 // The face value returned by this function is not very reliable. At the
476 // same time, the value returned should be fairly reliable, returning the
477 // proper flag for 90%-99% of font names.
482 return FontList::Default()->StyleAt(family
, index
, _name
, _face
, _flags
);
486 // Updates the font family list
488 update_font_families(bool /*checkOnly*/)
490 return FontList::Default()->UpdatedOnServer();
499 // initialise for be_plain_font (avoid circular definition)
505 fFalseBoldWidth(0.0),
506 fSpacing(B_BITMAP_SPACING
),
507 fEncoding(B_UNICODE_UTF8
),
510 fExtraFlags(kUninitializedExtraFlags
)
512 if (be_plain_font
!= NULL
&& this != &sPlainFont
)
513 *this = *be_plain_font
;
515 fHeight
.ascent
= 7.0;
516 fHeight
.descent
= 2.0;
517 fHeight
.leading
= 13.0;
522 BFont::BFont(const BFont
& font
)
528 BFont::BFont(const BFont
* font
)
533 *this = *be_plain_font
;
537 // Sets the font's family and style all at once
539 BFont::SetFamilyAndStyle(const font_family family
, const font_style style
)
541 if (family
== NULL
&& style
== NULL
)
544 BPrivate::AppServerLink link
;
546 link
.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS
);
547 link
.AttachString(family
, sizeof(font_family
));
548 link
.AttachString(style
, sizeof(font_style
));
549 link
.Attach
<uint16
>(fFamilyID
);
550 link
.Attach
<uint16
>(0xffff);
551 link
.Attach
<uint16
>(fFace
);
553 int32 status
= B_ERROR
;
554 if (link
.FlushWithReply(status
) != B_OK
|| status
!= B_OK
)
557 link
.Read
<uint16
>(&fFamilyID
);
558 link
.Read
<uint16
>(&fStyleID
);
559 link
.Read
<uint16
>(&fFace
);
560 fHeight
.ascent
= kUninitializedAscent
;
561 fExtraFlags
= kUninitializedExtraFlags
;
567 // Sets the font's family and style all at once
569 BFont::SetFamilyAndStyle(uint32 code
)
571 // R5 has a bug here: the face is not updated even though the IDs are set.
572 // This is a problem because the face flag includes Regular/Bold/Italic
573 // information in addition to stuff like underlining and strikethrough.
574 // As a result, this will need a trip to the server and, thus, be slower
575 // than R5's in order to be correct
577 uint16 family
, style
;
578 style
= code
& 0xFFFF;
579 family
= (code
& 0xFFFF0000) >> 16;
581 BPrivate::AppServerLink link
;
582 link
.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS
);
583 link
.AttachString(NULL
); // no family and style name
584 link
.AttachString(NULL
);
585 link
.Attach
<uint16
>(family
);
586 link
.Attach
<uint16
>(style
);
587 link
.Attach
<uint16
>(fFace
);
590 if (link
.FlushWithReply(fontcode
) != B_OK
|| fontcode
!= B_OK
)
593 link
.Read
<uint16
>(&fFamilyID
);
594 link
.Read
<uint16
>(&fStyleID
);
595 link
.Read
<uint16
>(&fFace
);
596 fHeight
.ascent
= kUninitializedAscent
;
597 fExtraFlags
= kUninitializedExtraFlags
;
601 // Sets the font's family and face all at once
603 BFont::SetFamilyAndFace(const font_family family
, uint16 face
)
605 // To comply with the BeBook, this function will only set valid values
606 // i.e. passing a nonexistent family will cause only the face to be set.
607 // Additionally, if a particular face does not exist in a family, the
608 // closest match will be chosen.
610 BPrivate::AppServerLink link
;
611 link
.StartMessage(AS_GET_FAMILY_AND_STYLE_IDS
);
612 link
.AttachString(family
, sizeof(font_family
));
613 link
.AttachString(NULL
); // no style given
614 link
.Attach
<uint16
>(fFamilyID
);
615 link
.Attach
<uint16
>(0xffff);
616 link
.Attach
<uint16
>(face
);
618 int32 status
= B_ERROR
;
619 if (link
.FlushWithReply(status
) != B_OK
|| status
!= B_OK
)
622 link
.Read
<uint16
>(&fFamilyID
);
623 link
.Read
<uint16
>(&fStyleID
);
624 link
.Read
<uint16
>(&fFace
);
625 fHeight
.ascent
= kUninitializedAscent
;
626 fExtraFlags
= kUninitializedExtraFlags
;
633 BFont::SetSize(float size
)
636 fHeight
.ascent
= kUninitializedAscent
;
641 BFont::SetShear(float shear
)
644 fHeight
.ascent
= kUninitializedAscent
;
649 BFont::SetRotation(float rotation
)
651 fRotation
= rotation
;
652 fHeight
.ascent
= kUninitializedAscent
;
657 BFont::SetFalseBoldWidth(float width
)
659 fFalseBoldWidth
= width
;
664 BFont::SetSpacing(uint8 spacing
)
671 BFont::SetEncoding(uint8 encoding
)
673 fEncoding
= encoding
;
678 BFont::SetFace(uint16 face
)
683 SetFamilyAndFace(NULL
, face
);
688 BFont::SetFlags(uint32 flags
)
695 BFont::GetFamilyAndStyle(font_family
* family
, font_style
* style
) const
697 if (family
== NULL
&& style
== NULL
)
700 // it's okay to call this function with either family or style set to NULL
702 font_family familyBuffer
;
703 font_style styleBuffer
;
706 family
= &familyBuffer
;
708 style
= &styleBuffer
;
710 BPrivate::AppServerLink link
;
711 link
.StartMessage(AS_GET_FAMILY_AND_STYLE
);
712 link
.Attach
<uint16
>(fFamilyID
);
713 link
.Attach
<uint16
>(fStyleID
);
716 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
) {
717 // the least we can do is to clear the buffers
718 memset(*family
, 0, sizeof(font_family
));
719 memset(*style
, 0, sizeof(font_style
));
723 link
.ReadString(*family
, sizeof(font_family
));
724 link
.ReadString(*style
, sizeof(font_style
));
729 BFont::FamilyAndStyle() const
731 return (fFamilyID
<< 16UL) | fStyleID
;
750 BFont::Rotation() const
757 BFont::FalseBoldWidth() const
759 return fFalseBoldWidth
;
764 BFont::Spacing() const
771 BFont::Encoding() const
792 BFont::Direction() const
795 return (font_direction
)(fExtraFlags
>> B_PRIVATE_FONT_DIRECTION_SHIFT
);
800 BFont::IsFixed() const
803 return (fExtraFlags
& B_IS_FIXED
) != 0;
807 // Returns whether or not the font is fixed-width and contains both
808 // full and half-width characters.
810 BFont::IsFullAndHalfFixed() const
812 // This was left unimplemented as of R5. It is a way to work with both
813 // Kanji and Roman characters in the same fixed-width font.
816 return (fExtraFlags
& B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED
) != 0;
821 BFont::BoundingBox() const
823 BPrivate::AppServerLink link
;
824 link
.StartMessage(AS_GET_FONT_BOUNDING_BOX
);
825 link
.Attach
<uint16
>(fFamilyID
);
826 link
.Attach
<uint16
>(fStyleID
);
829 if (link
.FlushWithReply(code
) != B_OK
831 return BRect(0, 0, 0 ,0);
834 link
.Read
<BRect
>(&box
);
840 BFont::Blocks() const
842 BPrivate::AppServerLink link
;
843 link
.StartMessage(AS_GET_UNICODE_BLOCKS
);
844 link
.Attach
<uint16
>(fFamilyID
);
845 link
.Attach
<uint16
>(fStyleID
);
848 if (link
.FlushWithReply(status
) != B_OK
850 return unicode_block(~0LL, ~0LL);
853 unicode_block blocksForFont
;
854 link
.Read
<unicode_block
>(&blocksForFont
);
856 return blocksForFont
;
860 BFont::IncludesBlock(uint32 start
, uint32 end
) const
862 BPrivate::AppServerLink link
;
863 link
.StartMessage(AS_GET_HAS_UNICODE_BLOCK
);
864 link
.Attach
<uint16
>(fFamilyID
);
865 link
.Attach
<uint16
>(fStyleID
);
866 link
.Attach
<uint32
>(start
);
867 link
.Attach
<uint32
>(end
);
870 if (link
.FlushWithReply(status
) != B_OK
876 link
.Read
<bool>(&hasBlock
);
883 BFont::FileFormat() const
885 BPrivate::AppServerLink link
;
886 link
.StartMessage(AS_GET_FONT_FILE_FORMAT
);
887 link
.Attach
<uint16
>(fFamilyID
);
888 link
.Attach
<uint16
>(fStyleID
);
891 if (link
.FlushWithReply(status
) != B_OK
893 // just take a safe bet...
894 return B_TRUETYPE_WINDOWS
;
898 link
.Read
<uint16
>(&format
);
900 return (font_file_format
)format
;
905 BFont::CountTuned() const
907 BPrivate::AppServerLink link
;
908 link
.StartMessage(AS_GET_TUNED_COUNT
);
909 link
.Attach
<uint16
>(fFamilyID
);
910 link
.Attach
<uint16
>(fStyleID
);
913 if (link
.FlushWithReply(code
) != B_OK
918 link
.Read
<int32
>(&count
);
924 BFont::GetTunedInfo(int32 index
, tuned_font_info
* info
) const
929 BPrivate::AppServerLink link
;
930 link
.StartMessage(AS_GET_TUNED_INFO
);
931 link
.Attach
<uint16
>(fFamilyID
);
932 link
.Attach
<uint16
>(fStyleID
);
933 link
.Attach
<uint32
>(index
);
936 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
939 link
.Read
<tuned_font_info
>(info
);
944 BFont::TruncateString(BString
* inOut
, uint32 mode
, float width
) const
946 if (mode
== B_NO_TRUNCATION
)
949 // NOTE: Careful, we cannot directly use "inOut->String()" as result
950 // array, because the string length increases by 3 bytes in the worst
952 const char* string
= inOut
->String();
953 GetTruncatedStrings(&string
, 1, mode
, width
, inOut
);
958 BFont::GetTruncatedStrings(const char* stringArray
[], int32 numStrings
,
959 uint32 mode
, float width
, BString resultArray
[]) const
961 if (stringArray
!= NULL
&& numStrings
> 0) {
962 // the width of the "…" glyph
963 float ellipsisWidth
= StringWidth(B_UTF8_ELLIPSIS
);
965 for (int32 i
= 0; i
< numStrings
; i
++) {
966 resultArray
[i
] = stringArray
[i
];
967 int32 numChars
= resultArray
[i
].CountChars();
969 // get the escapement of each glyph in font units
970 float* escapementArray
= new float[numChars
];
971 GetEscapements(stringArray
[i
], numChars
, NULL
, escapementArray
);
973 truncate_string(resultArray
[i
], mode
, width
, escapementArray
,
974 fSize
, ellipsisWidth
, numChars
);
976 delete[] escapementArray
;
983 BFont::GetTruncatedStrings(const char* stringArray
[], int32 numStrings
,
984 uint32 mode
, float width
, char* resultArray
[]) const
986 if (stringArray
!= NULL
&& numStrings
> 0) {
987 for (int32 i
= 0; i
< numStrings
; i
++) {
988 BString
* strings
= new BString
[numStrings
];
989 GetTruncatedStrings(stringArray
, numStrings
, mode
, width
, strings
);
991 for (int32 i
= 0; i
< numStrings
; i
++)
992 strcpy(resultArray
[i
], strings
[i
].String());
1001 BFont::StringWidth(const char* string
) const
1006 int32 length
= strlen(string
);
1008 GetStringWidths(&string
, &length
, 1, &width
);
1015 BFont::StringWidth(const char* string
, int32 length
) const
1017 if (!string
|| length
< 1)
1021 GetStringWidths(&string
, &length
, 1, &width
);
1028 BFont::GetStringWidths(const char* stringArray
[], const int32 lengthArray
[],
1029 int32 numStrings
, float widthArray
[]) const
1031 if (stringArray
== NULL
|| lengthArray
== NULL
|| numStrings
< 1
1032 || widthArray
== NULL
) {
1036 BPrivate::AppServerLink link
;
1037 link
.StartMessage(AS_GET_STRING_WIDTHS
);
1038 link
.Attach
<uint16
>(fFamilyID
);
1039 link
.Attach
<uint16
>(fStyleID
);
1040 link
.Attach
<float>(fSize
);
1041 link
.Attach
<uint8
>(fSpacing
);
1042 link
.Attach
<int32
>(numStrings
);
1044 // TODO: all strings into a single array???
1045 // we do have a maximum message length, and it could be easily touched
1047 for (int32 i
= 0; i
< numStrings
; i
++)
1048 link
.AttachString(stringArray
[i
], lengthArray
[i
]);
1051 if (link
.FlushWithReply(status
) != B_OK
|| status
!= B_OK
)
1054 link
.Read(widthArray
, sizeof(float) * numStrings
);
1059 BFont::GetEscapements(const char charArray
[], int32 numChars
,
1060 float escapementArray
[]) const
1062 GetEscapements(charArray
, numChars
, NULL
, escapementArray
);
1067 BFont::GetEscapements(const char charArray
[], int32 numChars
,
1068 escapement_delta
* delta
, float escapementArray
[]) const
1070 if (charArray
== NULL
|| numChars
< 1 || escapementArray
== NULL
)
1073 BPrivate::AppServerLink link
;
1074 link
.StartMessage(AS_GET_ESCAPEMENTS_AS_FLOATS
);
1075 link
.Attach
<uint16
>(fFamilyID
);
1076 link
.Attach
<uint16
>(fStyleID
);
1077 link
.Attach
<float>(fSize
);
1078 link
.Attach
<uint8
>(fSpacing
);
1079 link
.Attach
<float>(fRotation
);
1080 link
.Attach
<uint32
>(fFlags
);
1082 link
.Attach
<float>(delta
? delta
->nonspace
: 0.0f
);
1083 link
.Attach
<float>(delta
? delta
->space
: 0.0f
);
1084 link
.Attach
<int32
>(numChars
);
1086 // TODO: Should we not worry about the port capacity here?!?
1087 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1088 link
.Attach
<int32
>(bytesInBuffer
);
1089 link
.Attach(charArray
, bytesInBuffer
);
1092 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1095 link
.Read(escapementArray
, numChars
* sizeof(float));
1100 BFont::GetEscapements(const char charArray
[], int32 numChars
,
1101 escapement_delta
* delta
, BPoint escapementArray
[]) const
1103 GetEscapements(charArray
, numChars
, delta
, escapementArray
, NULL
);
1108 BFont::GetEscapements(const char charArray
[], int32 numChars
,
1109 escapement_delta
* delta
, BPoint escapementArray
[],
1110 BPoint offsetArray
[]) const
1112 if (charArray
== NULL
|| numChars
< 1 || escapementArray
== NULL
)
1115 BPrivate::AppServerLink link
;
1116 link
.StartMessage(AS_GET_ESCAPEMENTS
);
1117 link
.Attach
<uint16
>(fFamilyID
);
1118 link
.Attach
<uint16
>(fStyleID
);
1119 link
.Attach
<float>(fSize
);
1120 link
.Attach
<uint8
>(fSpacing
);
1121 link
.Attach
<float>(fRotation
);
1122 link
.Attach
<uint32
>(fFlags
);
1124 link
.Attach
<float>(delta
? delta
->nonspace
: 0.0);
1125 link
.Attach
<float>(delta
? delta
->space
: 0.0);
1126 link
.Attach
<bool>(offsetArray
!= NULL
);
1127 link
.Attach
<int32
>(numChars
);
1129 // TODO: Should we not worry about the port capacity here?!?
1130 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1131 link
.Attach
<int32
>(bytesInBuffer
);
1132 link
.Attach(charArray
, bytesInBuffer
);
1135 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1138 link
.Read(escapementArray
, sizeof(BPoint
) * numChars
);
1140 link
.Read(offsetArray
, sizeof(BPoint
) * numChars
);
1145 BFont::GetEdges(const char charArray
[], int32 numChars
,
1146 edge_info edgeArray
[]) const
1148 if (!charArray
|| numChars
< 1 || !edgeArray
)
1152 BPrivate::AppServerLink link
;
1154 link
.StartMessage(AS_GET_EDGES
);
1155 link
.Attach
<uint16
>(fFamilyID
);
1156 link
.Attach
<uint16
>(fStyleID
);
1157 link
.Attach
<int32
>(numChars
);
1159 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1160 link
.Attach
<int32
>(bytesInBuffer
);
1161 link
.Attach(charArray
, bytesInBuffer
);
1163 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1166 link
.Read(edgeArray
, sizeof(edge_info
) * numChars
);
1171 BFont::GetHeight(font_height
* _height
) const
1173 if (_height
== NULL
)
1176 if (fHeight
.ascent
== kUninitializedAscent
) {
1177 // we don't have the font height cached yet
1178 BPrivate::AppServerLink link
;
1180 link
.StartMessage(AS_GET_FONT_HEIGHT
);
1181 link
.Attach
<uint16
>(fFamilyID
);
1182 link
.Attach
<uint16
>(fStyleID
);
1183 link
.Attach
<float>(fSize
);
1186 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1189 // Who put that "const" to this method? :-)
1190 // We made fHeight mutable for this, but we should drop the "const"
1192 link
.Read
<font_height
>(&fHeight
);
1200 BFont::GetBoundingBoxesAsGlyphs(const char charArray
[], int32 numChars
,
1201 font_metric_mode mode
, BRect boundingBoxArray
[]) const
1203 _GetBoundingBoxes(charArray
, numChars
, mode
, false, NULL
,
1204 boundingBoxArray
, false);
1209 BFont::GetBoundingBoxesAsString(const char charArray
[], int32 numChars
,
1210 font_metric_mode mode
, escapement_delta
* delta
,
1211 BRect boundingBoxArray
[]) const
1213 _GetBoundingBoxes(charArray
, numChars
, mode
, true, delta
,
1214 boundingBoxArray
, true);
1219 BFont::_GetBoundingBoxes(const char charArray
[], int32 numChars
,
1220 font_metric_mode mode
, bool string_escapement
, escapement_delta
* delta
,
1221 BRect boundingBoxArray
[], bool asString
) const
1223 if (charArray
== NULL
|| numChars
< 1 || boundingBoxArray
== NULL
)
1227 BPrivate::AppServerLink link
;
1229 link
.StartMessage(asString
1230 ? AS_GET_BOUNDINGBOXES_STRING
: AS_GET_BOUNDINGBOXES_CHARS
);
1231 link
.Attach
<uint16
>(fFamilyID
);
1232 link
.Attach
<uint16
>(fStyleID
);
1233 link
.Attach
<float>(fSize
);
1234 link
.Attach
<float>(fRotation
);
1235 link
.Attach
<float>(fShear
);
1236 link
.Attach
<float>(fFalseBoldWidth
);
1237 link
.Attach
<uint8
>(fSpacing
);
1239 link
.Attach
<uint32
>(fFlags
);
1240 link
.Attach
<font_metric_mode
>(mode
);
1241 link
.Attach
<bool>(string_escapement
);
1243 if (delta
!= NULL
) {
1244 link
.Attach
<escapement_delta
>(*delta
);
1246 escapement_delta emptyDelta
= {0, 0};
1247 link
.Attach
<escapement_delta
>(emptyDelta
);
1250 link
.Attach
<int32
>(numChars
);
1251 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1252 link
.Attach
<int32
>(bytesInBuffer
);
1253 link
.Attach(charArray
, bytesInBuffer
);
1255 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1258 link
.Read(boundingBoxArray
, sizeof(BRect
) * numChars
);
1263 BFont::GetBoundingBoxesForStrings(const char* stringArray
[], int32 numStrings
,
1264 font_metric_mode mode
, escapement_delta deltas
[],
1265 BRect boundingBoxArray
[]) const
1267 if (!stringArray
|| numStrings
< 1 || !boundingBoxArray
)
1271 BPrivate::AppServerLink link
;
1273 link
.StartMessage(AS_GET_BOUNDINGBOXES_STRINGS
);
1274 link
.Attach
<uint16
>(fFamilyID
);
1275 link
.Attach
<uint16
>(fStyleID
);
1276 link
.Attach
<float>(fSize
);
1277 link
.Attach
<float>(fRotation
);
1278 link
.Attach
<float>(fShear
);
1279 link
.Attach
<float>(fFalseBoldWidth
);
1280 link
.Attach
<uint8
>(fSpacing
);
1281 link
.Attach
<uint32
>(fFlags
);
1282 link
.Attach
<font_metric_mode
>(mode
);
1283 link
.Attach
<int32
>(numStrings
);
1286 for (int32 i
= 0; i
< numStrings
; i
++) {
1287 link
.AttachString(stringArray
[i
]);
1288 link
.Attach
<escapement_delta
>(deltas
[i
]);
1291 escapement_delta emptyDelta
= {0, 0};
1293 for (int32 i
= 0; i
< numStrings
; i
++) {
1294 link
.AttachString(stringArray
[i
]);
1295 link
.Attach
<escapement_delta
>(emptyDelta
);
1299 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1302 link
.Read(boundingBoxArray
, sizeof(BRect
) * numStrings
);
1307 BFont::GetGlyphShapes(const char charArray
[], int32 numChars
,
1308 BShape
* glyphShapeArray
[]) const
1310 // TODO: implement code specifically for passing BShapes to and
1312 if (!charArray
|| numChars
< 1 || !glyphShapeArray
)
1316 BPrivate::AppServerLink link
;
1318 link
.StartMessage(AS_GET_GLYPH_SHAPES
);
1319 link
.Attach
<uint16
>(fFamilyID
);
1320 link
.Attach
<uint16
>(fStyleID
);
1321 link
.Attach
<float>(fSize
);
1322 link
.Attach
<float>(fShear
);
1323 link
.Attach
<float>(fRotation
);
1324 link
.Attach
<float>(fFalseBoldWidth
);
1325 link
.Attach
<uint32
>(fFlags
);
1326 link
.Attach
<int32
>(numChars
);
1328 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1329 link
.Attach
<int32
>(bytesInBuffer
);
1330 link
.Attach(charArray
, bytesInBuffer
);
1332 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1335 for (int32 i
= 0; i
< numChars
; i
++)
1336 link
.ReadShape(glyphShapeArray
[i
]);
1341 BFont::GetHasGlyphs(const char charArray
[], int32 numChars
,
1342 bool hasArray
[]) const
1344 if (!charArray
|| numChars
< 1 || !hasArray
)
1348 BPrivate::AppServerLink link
;
1350 link
.StartMessage(AS_GET_HAS_GLYPHS
);
1351 link
.Attach
<uint16
>(fFamilyID
);
1352 link
.Attach
<uint16
>(fStyleID
);
1353 link
.Attach
<int32
>(numChars
);
1355 uint32 bytesInBuffer
= UTF8CountBytes(charArray
, numChars
);
1356 link
.Attach
<int32
>(bytesInBuffer
);
1357 link
.Attach(charArray
, bytesInBuffer
);
1359 if (link
.FlushWithReply(code
) != B_OK
|| code
!= B_OK
)
1362 link
.Read(hasArray
, sizeof(bool) * numChars
);
1367 BFont::operator=(const BFont
& font
)
1369 fFamilyID
= font
.fFamilyID
;
1370 fStyleID
= font
.fStyleID
;
1372 fShear
= font
.fShear
;
1373 fRotation
= font
.fRotation
;
1374 fFalseBoldWidth
= font
.fFalseBoldWidth
;
1375 fSpacing
= font
.fSpacing
;
1376 fEncoding
= font
.fEncoding
;
1378 fHeight
= font
.fHeight
;
1379 fFlags
= font
.fFlags
;
1380 fExtraFlags
= font
.fExtraFlags
;
1387 BFont::operator==(const BFont
& font
) const
1389 return fFamilyID
== font
.fFamilyID
1390 && fStyleID
== font
.fStyleID
1391 && fSize
== font
.fSize
1392 && fShear
== font
.fShear
1393 && fRotation
== font
.fRotation
1394 && fFalseBoldWidth
== font
.fFalseBoldWidth
1395 && fSpacing
== font
.fSpacing
1396 && fEncoding
== font
.fEncoding
1397 && fFace
== font
.fFace
;
1402 BFont::operator!=(const BFont
& font
) const
1404 return fFamilyID
!= font
.fFamilyID
1405 || fStyleID
!= font
.fStyleID
1406 || fSize
!= font
.fSize
1407 || fShear
!= font
.fShear
1408 || fRotation
!= font
.fRotation
1409 || fFalseBoldWidth
!= font
.fFalseBoldWidth
1410 || fSpacing
!= font
.fSpacing
1411 || fEncoding
!= font
.fEncoding
1412 || fFace
!= font
.fFace
;
1417 BFont::PrintToStream() const
1421 GetFamilyAndStyle(&family
, &style
);
1423 printf("BFont { %s (%d), %s (%d) 0x%x %f/%f %fpt (%f %f %f), %d }\n",
1424 family
, fFamilyID
, style
, fStyleID
, fFace
, fShear
, fRotation
, fSize
,
1425 fHeight
.ascent
, fHeight
.descent
, fHeight
.leading
, fEncoding
);
1430 BFont::_GetExtraFlags() const
1432 // TODO: this has to be const in order to allow other font getters to
1433 // stay const as well
1434 if (fExtraFlags
!= kUninitializedExtraFlags
)
1437 BPrivate::AppServerLink link
;
1438 link
.StartMessage(AS_GET_EXTRA_FONT_FLAGS
);
1439 link
.Attach
<uint16
>(fFamilyID
);
1440 link
.Attach
<uint16
>(fStyleID
);
1442 status_t status
= B_ERROR
;
1443 if (link
.FlushWithReply(status
) != B_OK
|| status
!= B_OK
) {
1444 // use defaut values for the flags
1445 fExtraFlags
= (uint32
)B_FONT_LEFT_TO_RIGHT
1446 << B_PRIVATE_FONT_DIRECTION_SHIFT
;
1450 link
.Read
<uint32
>(&fExtraFlags
);