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:
Jérôme Duval
2005-08-24 14:50:41 +00:00
parent 2185eed6d2
commit 2b1263bedf
5 changed files with 135 additions and 49 deletions
-1
View File
@@ -124,7 +124,6 @@ enum {
AS_COUNT_FONT_FAMILIES, AS_COUNT_FONT_FAMILIES,
AS_COUNT_FONT_STYLES, AS_COUNT_FONT_STYLES,
AS_GET_STRING_WIDTH,
AS_GET_STRING_WIDTHS, AS_GET_STRING_WIDTHS,
AS_GET_EDGES, AS_GET_EDGES,
AS_GET_ESCAPEMENTS, AS_GET_ESCAPEMENTS,
+5 -2
View File
@@ -131,10 +131,13 @@ class ServerFont {
{ return fStyle->CharMapCount(); } { return fStyle->CharMapCount(); }
BShape** GetGlyphShapes(const char charArray[], BShape** GetGlyphShapes(const char charArray[],
int32 numChars) const; int32 numChars) const;
void GetHasGlyphs(const char charArray[], 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[], BPoint* GetEscapements(const char charArray[],
int32 numChars, int32 numChars,
+19 -23
View File
@@ -860,8 +860,12 @@ BFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
float float
BFont::StringWidth(const char *string) const BFont::StringWidth(const char *string) const
{ {
if (!string)
return 0.0;
int32 length = strlen(string); 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) if (!string || length < 1)
return 0.0; 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; float width;
link.Read<float>(&width); GetStringWidths(&string, &length, 1, &width);
return width; return width;
} }
@@ -903,11 +892,15 @@ BFont::GetStringWidths(const char *stringArray[], const int32 lengthArray[],
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_GET_STRING_WIDTHS); 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); link.Attach<int32>(numStrings);
for (int32 i = 0; i < numStrings; i++) { for (int32 i = 0; i < numStrings; i++) {
link.AttachString(stringArray[i]);
link.Attach<int32>(lengthArray[i]); link.Attach<int32>(lengthArray[i]);
link.AttachString(stringArray[i]);
} }
if (link.FlushWithReply(code) != B_OK if (link.FlushWithReply(code) != B_OK
@@ -1013,23 +1006,26 @@ BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *
void 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; return;
int32 code; int32 code;
BPrivate::AppServerLink link; BPrivate::AppServerLink link;
link.StartMessage(AS_GET_EDGES); link.StartMessage(AS_GET_EDGES);
link.Attach<int32>(numBytes); link.Attach<int32>(numChars);
link.Attach(charArray, numBytes);
uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars);
link.Attach<int32>(bytesInBuffer);
link.Attach(charArray, bytesInBuffer);
if (link.FlushWithReply(code) != B_OK if (link.FlushWithReply(code) != B_OK
|| code != SERVER_TRUE) || code != SERVER_TRUE)
return; return;
link.Read(edgeArray, sizeof(edge_info) * numBytes); link.Read(edgeArray, sizeof(edge_info) * numChars);
} }
+67 -20
View File
@@ -1348,53 +1348,68 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
// gFontServer->Unlock(); // gFontServer->Unlock();
break; 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: // Attached Data:
// 1) string String to measure // 1) uint16 ID of family
// 2) int32 string length to measure // 2) uint16 ID of style
// 3) uint16 ID of family // 3) float point size of font
// 4) uint16 ID of style // 4) uint8 spacing to use
// 5) float point size of font // 5) int32 numStrings
// 6) uint8 spacing to use // 6) int32 string length to measure (numStrings times)
// 7) string String to measure (numStrings times)
// Returns: // Returns:
// 1) float - width of the string in pixels // 1) float - width of the string in pixels (numStrings times)
char *string = NULL;
int32 length;
uint16 family, style; uint16 family, style;
float size, width = 0; float size;
uint8 spacing; uint8 spacing;
link.ReadString(&string);
link.Read<int32>(&length);
link.Read<uint16>(&family); link.Read<uint16>(&family);
link.Read<uint16>(&style); link.Read<uint16>(&style);
link.Read<float>(&size); link.Read<float>(&size);
link.Read<uint8>(&spacing); 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; ServerFont font;
if (length > 0 && font.SetFamilyAndStyle(family, style) == B_OK if (font.SetFamilyAndStyle(family, style) == B_OK
&& size > 0 && string) { && size > 0) {
font.SetSize(size); font.SetSize(size);
font.SetSpacing(spacing); 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, // NOTE: The line below will return the exact same thing. However,
// the line above uses the AGG rendering backend, for which glyph caching // the line above uses the AGG rendering backend, for which glyph caching
// actually works. It is about 20 times faster! // actually works. It is about 20 times faster!
//width = font.StringWidth(string, length); //width = font.StringWidth(string, length);
fLink.StartMessage(SERVER_TRUE); fLink.StartMessage(SERVER_TRUE);
fLink.Attach<float>(width); fLink.Attach(widthArray, sizeof(widthArray));
} else } else
fLink.StartMessage(SERVER_FALSE); fLink.StartMessage(SERVER_FALSE);
fLink.Flush(); fLink.Flush();
free(string); for(int32 i=0; i<numStrings; i++) {
delete[] stringArray[i];
}
break; break;
} }
case AS_GET_FONT_BOUNDING_BOX: case AS_GET_FONT_BOUNDING_BOX:
@@ -1766,6 +1781,38 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
fLink.Flush(); fLink.Flush();
break; 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: case AS_GET_ESCAPEMENTS:
{ {
FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature())); FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature()));
+44 -3
View File
@@ -370,11 +370,52 @@ ServerFont::GetHasGlyphs(const char charArray[], int32 numChars, bool hasArray[]
} }
} }
delete[] convertedBuffer; delete[] convertedBuffer;
}
/*for (int i = 0; i < numChars; i++) { // GetEdges
hasArray[i] = true; 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;
} }