reworked BFont::GetStringWidths and BFont::StringWidth
implemented BFont::GetEdges git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14057 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2185eed6d2
commit
2b1263bedf
|
@ -124,7 +124,6 @@ enum {
|
|||
AS_COUNT_FONT_FAMILIES,
|
||||
AS_COUNT_FONT_STYLES,
|
||||
|
||||
AS_GET_STRING_WIDTH,
|
||||
AS_GET_STRING_WIDTHS,
|
||||
AS_GET_EDGES,
|
||||
AS_GET_ESCAPEMENTS,
|
||||
|
|
|
@ -131,10 +131,13 @@ class ServerFont {
|
|||
{ return fStyle->CharMapCount(); }
|
||||
|
||||
BShape** GetGlyphShapes(const char charArray[],
|
||||
int32 numChars) const;
|
||||
int32 numChars) const;
|
||||
|
||||
void GetHasGlyphs(const char charArray[],
|
||||
int32 numChars, bool hasArray[]) const;
|
||||
int32 numChars, bool hasArray[]) const;
|
||||
|
||||
void GetEdges(const char charArray[],
|
||||
int32 numChars, edge_info edgeArray[]) const;
|
||||
|
||||
BPoint* GetEscapements(const char charArray[],
|
||||
int32 numChars,
|
||||
|
|
|
@ -860,8 +860,12 @@ BFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
|
|||
float
|
||||
BFont::StringWidth(const char *string) const
|
||||
{
|
||||
if (!string)
|
||||
return 0.0;
|
||||
int32 length = strlen(string);
|
||||
return StringWidth(string, length);
|
||||
float width;
|
||||
GetStringWidths(&string, &length, 1, &width);
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
|
@ -870,24 +874,9 @@ BFont::StringWidth(const char *string, int32 length) const
|
|||
{
|
||||
if (!string || length < 1)
|
||||
return 0.0;
|
||||
|
||||
int32 code;
|
||||
BPrivate::AppServerLink link;
|
||||
|
||||
link.StartMessage(AS_GET_STRING_WIDTH);
|
||||
link.AttachString(string);
|
||||
link.Attach<int32>(length);
|
||||
link.Attach<uint16>(fFamilyID);
|
||||
link.Attach<uint16>(fStyleID);
|
||||
link.Attach<float>(fSize);
|
||||
link.Attach<uint8>(fSpacing);
|
||||
|
||||
if (link.FlushWithReply(code) != B_OK
|
||||
|| code != SERVER_TRUE)
|
||||
return 0.0;
|
||||
|
||||
float width;
|
||||
link.Read<float>(&width);
|
||||
GetStringWidths(&string, &length, 1, &width);
|
||||
return width;
|
||||
}
|
||||
|
||||
|
@ -903,11 +892,15 @@ BFont::GetStringWidths(const char *stringArray[], const int32 lengthArray[],
|
|||
BPrivate::AppServerLink link;
|
||||
|
||||
link.StartMessage(AS_GET_STRING_WIDTHS);
|
||||
link.Attach<uint16>(fFamilyID);
|
||||
link.Attach<uint16>(fStyleID);
|
||||
link.Attach<float>(fSize);
|
||||
link.Attach<uint8>(fSpacing);
|
||||
link.Attach<int32>(numStrings);
|
||||
|
||||
for (int32 i = 0; i < numStrings; i++) {
|
||||
link.AttachString(stringArray[i]);
|
||||
link.Attach<int32>(lengthArray[i]);
|
||||
link.AttachString(stringArray[i]);
|
||||
}
|
||||
|
||||
if (link.FlushWithReply(code) != B_OK
|
||||
|
@ -1013,23 +1006,26 @@ BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *
|
|||
|
||||
|
||||
void
|
||||
BFont::GetEdges(const char charArray[], int32 numBytes, edge_info edgeArray[]) const
|
||||
BFont::GetEdges(const char charArray[], int32 numChars, edge_info edgeArray[]) const
|
||||
{
|
||||
if (!charArray || numBytes < 1 || !edgeArray)
|
||||
if (!charArray || numChars < 1 || !edgeArray)
|
||||
return;
|
||||
|
||||
int32 code;
|
||||
BPrivate::AppServerLink link;
|
||||
|
||||
link.StartMessage(AS_GET_EDGES);
|
||||
link.Attach<int32>(numBytes);
|
||||
link.Attach(charArray, numBytes);
|
||||
link.Attach<int32>(numChars);
|
||||
|
||||
uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars);
|
||||
link.Attach<int32>(bytesInBuffer);
|
||||
link.Attach(charArray, bytesInBuffer);
|
||||
|
||||
if (link.FlushWithReply(code) != B_OK
|
||||
|| code != SERVER_TRUE)
|
||||
return;
|
||||
|
||||
link.Read(edgeArray, sizeof(edge_info) * numBytes);
|
||||
link.Read(edgeArray, sizeof(edge_info) * numChars);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1348,53 +1348,68 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||
// gFontServer->Unlock();
|
||||
break;
|
||||
}
|
||||
case AS_GET_STRING_WIDTH:
|
||||
case AS_GET_STRING_WIDTHS:
|
||||
{
|
||||
FTRACE(("ServerApp %s: AS_GET_STRING_WIDTH\n", Signature()));
|
||||
FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature()));
|
||||
// Attached Data:
|
||||
// 1) string String to measure
|
||||
// 2) int32 string length to measure
|
||||
// 3) uint16 ID of family
|
||||
// 4) uint16 ID of style
|
||||
// 5) float point size of font
|
||||
// 6) uint8 spacing to use
|
||||
|
||||
// 1) uint16 ID of family
|
||||
// 2) uint16 ID of style
|
||||
// 3) float point size of font
|
||||
// 4) uint8 spacing to use
|
||||
// 5) int32 numStrings
|
||||
// 6) int32 string length to measure (numStrings times)
|
||||
// 7) string String to measure (numStrings times)
|
||||
|
||||
// Returns:
|
||||
// 1) float - width of the string in pixels
|
||||
char *string = NULL;
|
||||
int32 length;
|
||||
// 1) float - width of the string in pixels (numStrings times)
|
||||
|
||||
uint16 family, style;
|
||||
float size, width = 0;
|
||||
float size;
|
||||
uint8 spacing;
|
||||
|
||||
link.ReadString(&string);
|
||||
link.Read<int32>(&length);
|
||||
link.Read<uint16>(&family);
|
||||
link.Read<uint16>(&style);
|
||||
link.Read<float>(&size);
|
||||
link.Read<uint8>(&spacing);
|
||||
int32 numStrings;
|
||||
link.Read<int32>(&numStrings);
|
||||
|
||||
float widthArray[numStrings];
|
||||
int32 lengthArray[numStrings];
|
||||
char *stringArray[numStrings];
|
||||
for(int32 i=0; i<numStrings; i++) {
|
||||
link.Read<int32>(&lengthArray[i]);
|
||||
stringArray[i] = new char[lengthArray[i]];
|
||||
link.ReadString(&stringArray[i]);
|
||||
}
|
||||
|
||||
ServerFont font;
|
||||
|
||||
if (length > 0 && font.SetFamilyAndStyle(family, style) == B_OK
|
||||
&& size > 0 && string) {
|
||||
if (font.SetFamilyAndStyle(family, style) == B_OK
|
||||
&& size > 0) {
|
||||
|
||||
font.SetSize(size);
|
||||
font.SetSpacing(spacing);
|
||||
|
||||
width = fDesktop->GetDisplayDriver()->StringWidth(string, length, font);
|
||||
for (int32 i=0; i<numStrings; i++)
|
||||
if (!stringArray[i] || lengthArray[i] <= 0)
|
||||
widthArray[i] = 0.0;
|
||||
else
|
||||
widthArray[i] = fDesktop->GetDisplayDriver()->StringWidth(stringArray[i], lengthArray[i], font);
|
||||
// NOTE: The line below will return the exact same thing. However,
|
||||
// the line above uses the AGG rendering backend, for which glyph caching
|
||||
// actually works. It is about 20 times faster!
|
||||
//width = font.StringWidth(string, length);
|
||||
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
fLink.Attach<float>(width);
|
||||
fLink.Attach(widthArray, sizeof(widthArray));
|
||||
} else
|
||||
fLink.StartMessage(SERVER_FALSE);
|
||||
|
||||
fLink.Flush();
|
||||
free(string);
|
||||
for(int32 i=0; i<numStrings; i++) {
|
||||
delete[] stringArray[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AS_GET_FONT_BOUNDING_BOX:
|
||||
|
@ -1766,6 +1781,38 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|||
fLink.Flush();
|
||||
break;
|
||||
}
|
||||
case AS_GET_EDGES:
|
||||
{
|
||||
FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature()));
|
||||
// Attached Data:
|
||||
// 1) uint16 - family ID
|
||||
// 2) uint16 - style ID
|
||||
// 3) int32 - numChars
|
||||
// 4) int32 - numBytes
|
||||
// 5) char - the char buffer with size numBytes
|
||||
|
||||
uint16 famid, styid;
|
||||
link.Read<uint16>(&famid);
|
||||
link.Read<uint16>(&styid);
|
||||
int32 numChars;
|
||||
link.Read<int32>(&numChars);
|
||||
|
||||
uint32 numBytes;
|
||||
link.Read<uint32>(&numBytes);
|
||||
char* charArray = new char[numBytes];
|
||||
link.Read(charArray, numBytes);
|
||||
|
||||
ServerFont font;
|
||||
if (font.SetFamilyAndStyle(famid, styid) == B_OK) {
|
||||
edge_info edgeArray[numChars];
|
||||
font.GetEdges(charArray, numChars, edgeArray);
|
||||
fLink.StartMessage(SERVER_TRUE);
|
||||
fLink.Attach(edgeArray, sizeof(edgeArray));
|
||||
} else
|
||||
fLink.StartMessage(SERVER_FALSE);
|
||||
fLink.Flush();
|
||||
break;
|
||||
}
|
||||
case AS_GET_ESCAPEMENTS:
|
||||
{
|
||||
FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature()));
|
||||
|
|
|
@ -370,11 +370,52 @@ ServerFont::GetHasGlyphs(const char charArray[], int32 numChars, bool hasArray[]
|
|||
}
|
||||
}
|
||||
delete[] convertedBuffer;
|
||||
}
|
||||
|
||||
|
||||
/*for (int i = 0; i < numChars; i++) {
|
||||
hasArray[i] = true;
|
||||
}*/
|
||||
// GetEdges
|
||||
void
|
||||
ServerFont::GetEdges(const char charArray[], int32 numChars, edge_info edgeArray[]) const
|
||||
{
|
||||
if (!fStyle || !charArray || numChars <= 0 || !edgeArray)
|
||||
return;
|
||||
|
||||
FT_Face face = fStyle->GetFTFace();
|
||||
if (!face)
|
||||
return;
|
||||
|
||||
FT_Set_Char_Size(face, 0, int32(fSize * 64), 72, 72);
|
||||
|
||||
// UTF8 handling...this can probably be smarter
|
||||
// Here is what I do in the AGGTextRenderer to handle UTF8...
|
||||
// It is probably highly inefficient, so it should be reviewed.
|
||||
int32 numBytes = UTF8CountBytes(charArray, numChars);
|
||||
int32 convertedLength = numBytes * 2;
|
||||
char* convertedBuffer = new char[convertedLength];
|
||||
|
||||
int32 state = 0;
|
||||
status_t ret;
|
||||
if ((ret = convert_from_utf8(B_UNICODE_CONVERSION,
|
||||
charArray, &numBytes,
|
||||
convertedBuffer, &convertedLength,
|
||||
&state, B_SUBSTITUTE)) >= B_OK
|
||||
&& (ret = swap_data(B_INT16_TYPE, convertedBuffer, convertedLength,
|
||||
B_SWAP_BENDIAN_TO_HOST)) >= B_OK) {
|
||||
|
||||
uint16* glyphIndex = (uint16*)convertedBuffer;
|
||||
// just to be sure
|
||||
numChars = min_c((uint32)numChars, convertedLength / sizeof(uint16));
|
||||
|
||||
for (int i = 0; i < numChars; i++) {
|
||||
FT_Load_Char(face, glyphIndex[i], FT_LOAD_NO_BITMAP);
|
||||
if (face->glyph) {
|
||||
edgeArray[i].left = float(face->glyph->metrics.horiBearingX /64) / fSize;
|
||||
edgeArray[i].right = float((face->glyph->metrics.horiBearingX
|
||||
+ face->glyph->metrics.width - face->glyph->metrics.horiAdvance)/64) /fSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] convertedBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue