From 2b1263bedf5512d3312c6722a10c2d1184de391e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 24 Aug 2005 14:50:41 +0000 Subject: [PATCH] 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 --- headers/private/app/ServerProtocol.h | 1 - headers/private/servers/app/ServerFont.h | 7 +- src/kits/interface/Font.cpp | 42 ++++++------ src/servers/app/ServerApp.cpp | 87 ++++++++++++++++++------ src/servers/app/ServerFont.cpp | 47 ++++++++++++- 5 files changed, 135 insertions(+), 49 deletions(-) diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index b4b1c2c3eb..2322c36fb4 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -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, diff --git a/headers/private/servers/app/ServerFont.h b/headers/private/servers/app/ServerFont.h index ea000a0b37..8e816a5b62 100644 --- a/headers/private/servers/app/ServerFont.h +++ b/headers/private/servers/app/ServerFont.h @@ -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, diff --git a/src/kits/interface/Font.cpp b/src/kits/interface/Font.cpp index 4d099b2d79..0fc7db90e2 100644 --- a/src/kits/interface/Font.cpp +++ b/src/kits/interface/Font.cpp @@ -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(length); - link.Attach(fFamilyID); - link.Attach(fStyleID); - link.Attach(fSize); - link.Attach(fSpacing); - - if (link.FlushWithReply(code) != B_OK - || code != SERVER_TRUE) - return 0.0; float width; - link.Read(&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(fFamilyID); + link.Attach(fStyleID); + link.Attach(fSize); + link.Attach(fSpacing); link.Attach(numStrings); for (int32 i = 0; i < numStrings; i++) { - link.AttachString(stringArray[i]); link.Attach(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(numBytes); - link.Attach(charArray, numBytes); + link.Attach(numChars); + + uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars); + link.Attach(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); } diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index b3639b6b29..a90b87ebc2 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -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(&length); link.Read(&family); link.Read(&style); link.Read(&size); link.Read(&spacing); + int32 numStrings; + link.Read(&numStrings); + + float widthArray[numStrings]; + int32 lengthArray[numStrings]; + char *stringArray[numStrings]; + for(int32 i=0; i(&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; iGetDisplayDriver()->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(width); + fLink.Attach(widthArray, sizeof(widthArray)); } else fLink.StartMessage(SERVER_FALSE); fLink.Flush(); - free(string); + for(int32 i=0; i(&famid); + link.Read(&styid); + int32 numChars; + link.Read(&numChars); + + uint32 numBytes; + link.Read(&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())); diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index cf59cf79d5..ab68ddf4f2 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -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; }