From 9bdb0522c19c1f779f8e5c56e8faa4a749800cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 12 May 2005 15:09:30 +0000 Subject: [PATCH] Implemented BFont::GetEscapments() float version. It is pretty rough yet, but appears to handle UTF8 correctly. The optional escapement_delta is currently ignored. I didn't touch other functionality too much, until I know more about it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12645 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/servers/app/ServerFont.h | 179 ++++++++++++++--------- src/kits/interface/Font.cpp | 45 +++--- src/servers/app/Jamfile | 4 +- src/servers/app/ServerApp.cpp | 59 ++++++-- src/servers/app/ServerFont.cpp | 90 ++++++++++-- 5 files changed, 263 insertions(+), 114 deletions(-) diff --git a/headers/private/servers/app/ServerFont.h b/headers/private/servers/app/ServerFont.h index 689cd28974..74b77d54f8 100644 --- a/headers/private/servers/app/ServerFont.h +++ b/headers/private/servers/app/ServerFont.h @@ -31,81 +31,128 @@ #include #include "FontFamily.h" -class ServerFont -{ -public: - ServerFont(void); - ServerFont(FontStyle *style, float size=12.0, float frotation=0.0, float fshear=90.0, - uint16 flags=0, uint8 spacing=B_CHAR_SPACING); - ServerFont(const ServerFont &font); - ~ServerFont(void); +class ServerFont { + public: + ServerFont(); + ServerFont(FontStyle* style, + float size = 12.0, + float fRotation = 0.0, + float fShear = 90.0, + uint16 flags = 0, + uint8 spacing = B_CHAR_SPACING); + ServerFont(const ServerFont& font); + virtual ~ServerFont(); // TODO: make more advanced... - status_t InitCheck() const - { return fStyle ? B_OK : B_NO_INIT; } + status_t InitCheck() const + { return fStyle ? B_OK : B_NO_INIT; } - font_direction Direction(void) const { return fDirection; } - uint32 Encoding(void) const { return fEncoding; } - edge_info Edges(void) const { return fEdges; } - uint32 Flags(void) const { return fFlags; } - uint32 Spacing(void) const { return fSpacing; } - float Shear(void) const { return fshear; } - float Rotation(void) const { return frotation; } - float Size(void) const { return fSize; } - uint16 Face(void) const { return fFace; } - uint32 CountGlyphs(void) { return fStyle->GlyphCount(); } - int32 CountTuned(void); - font_file_format FileFormat(void); - - status_t SetFamilyAndStyle(const uint16 &familyID,const uint16 &styleID); - status_t SetFamilyAndStyle(const uint32 &fontID); - void SetDirection(const font_direction &dir) { fDirection=dir; } - void SetEdges(const edge_info &info) { fEdges=info; } - void SetEncoding(uint32 encoding) { fEncoding=encoding; } - void SetFlags(const uint32 &value) { fFlags=value; } - void SetSpacing(const uint32 &value) { fSpacing=value; } - void SetShear(const float &value) { fshear=value; } - void SetSize(const float &value) { fSize=value; } - void SetRotation(const float &value) { frotation=value; } - void SetFace(const uint32 &value) { fFace=value; } - - bool IsFixedWidth(void) const { return fStyle->IsFixedWidth(); } - bool IsScalable(void) const { return fStyle->IsScalable(); } - bool HasKerning(void) const { return fStyle->HasKerning(); } - bool HasTuned(void) const { return fStyle->HasTuned(); } - int32 TunedCount(void) const { return fStyle->TunedCount(); } - uint16 GlyphCount(void) const { return fStyle->GlyphCount(); } - uint16 CharMapCount(void) const { return fStyle->CharMapCount(); } - BShape **GetGlyphShapes(const char charArray[], int32 numChars) const; - BPoint *GetEscapements(const char charArray[], int32 numChars, - BPoint offsetArray[]) const; - - FT_Face GetFTFace() const { return fStyle->GetFTFace(); }; - - const char *GetStyle(void) const; - const char *GetFamily(void) const; - const char *GetPath(void) const { return fStyle->GetPath(); } - uint16 StyleID(void) const { return fStyle->GetID(); } - uint16 FamilyID(void) const { return fStyle->Family()->GetID(); } - uint32 GetFamilyAndStyle(void) const; + font_direction Direction() const + { return fDirection; } + uint32 Encoding() const + { return fEncoding; } + edge_info Edges() const + { return fEdges; } + uint32 Flags() const + { return fFlags; } + uint32 Spacing() const + { return fSpacing; } + float Shear() const + { return fShear; } + float Rotation() const + { return fRotation; } + float Size() const + { return fSize; } + uint16 Face() const + { return fFace; } + uint32 CountGlyphs() + { return fStyle->GlyphCount(); } + int32 CountTuned(); - BRect BoundingBox(void); - void Height(font_height *fh); + font_file_format FileFormat(); + + status_t SetFamilyAndStyle(const uint16& familyID, + const uint16& styleID); + status_t SetFamilyAndStyle(const uint32& fontID); - ServerFont &operator=(const ServerFont& font); + void SetDirection(const font_direction& dir) + { fDirection = dir; } + void SetEdges(const edge_info& info) + { fEdges = info; } + void SetEncoding(uint32 encoding) + { fEncoding = encoding; } + void SetFlags(const uint32& value) + { fFlags = value; } + void SetSpacing(const uint32& value) + { fSpacing = value; } + void SetShear(const float& value) + { fShear = value; } + void SetSize(const float& value) + { fSize = value; } + void SetRotation(const float& value) + { fRotation = value; } + void SetFace(const uint32& value) + { fFace = value; } + + bool IsFixedWidth() const + { return fStyle->IsFixedWidth(); } + bool IsScalable() const + { return fStyle->IsScalable(); } + bool HasKerning() const + { return fStyle->HasKerning(); } + bool HasTuned() const + { return fStyle->HasTuned(); } + int32 TunedCount() const + { return fStyle->TunedCount(); } + uint16 GlyphCount() const + { return fStyle->GlyphCount(); } + uint16 CharMapCount() const + { return fStyle->CharMapCount(); } + BShape** GetGlyphShapes(const char charArray[], + int32 numChars) const; + + BPoint* GetEscapements(const char charArray[], + int32 numChars, + BPoint offsetArray[]) const; + bool GetEscapements(const char charArray[], + int32 numChars, + float widthArray[], + escapement_delta delta) const; + + FT_Face GetFTFace() const + { return fStyle->GetFTFace(); }; + + const char* GetStyle() const; + const char* GetFamily() const; + const char* GetPath() const + { return fStyle->GetPath(); } + + uint16 StyleID() const + { return fStyle->GetID(); } + uint16 FamilyID() const + { return fStyle->Family()->GetID(); } + uint32 GetFamilyAndStyle() const; + + BRect BoundingBox(); + void Height(font_height* fh); + + ServerFont &operator=(const ServerFont& font); protected: friend class FontStyle; - FontStyle *fStyle; - edge_info fEdges; - float fSize, frotation, fshear; - BRect fBounds; - uint32 fFlags; - uint32 fSpacing; - uint16 fFace; - font_direction fDirection; - uint32 fEncoding; + + FontStyle* fStyle; + edge_info fEdges; + float fSize; + float fRotation; + float fShear; + BRect fBounds; + uint32 fFlags; + uint32 fSpacing; + uint16 fFace; + font_direction fDirection; + uint32 fEncoding; }; #endif diff --git a/src/kits/interface/Font.cpp b/src/kits/interface/Font.cpp index c2d226ae37..7ac9f0de4e 100644 --- a/src/kits/interface/Font.cpp +++ b/src/kits/interface/Font.cpp @@ -23,16 +23,20 @@ // Author: DarkWyrm (bpmagic@columbus.rr.com) // Description: Class to manage font-handling capabilities //------------------------------------------------------------------------------ -#include #include -#include -#include -#include -#include -#include -#include #include + +#include +#include +#include +#include #include +#include +#include + +#include + +#include //---------------------------------------------------------------------------------------- // Globals @@ -942,9 +946,9 @@ void BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta, float escapementArray[]) const { - if(!charArray || numChars<1 || !escapementArray) + if (!charArray || numChars<1 || !escapementArray) return; - + int32 code; BPrivate::BAppServerLink link; @@ -955,20 +959,25 @@ BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta * link.Attach(fSize); link.Attach(fRotation); link.Attach(fFlags); + + link.Attach(delta ? delta->nonspace : 0.0); + link.Attach(delta ? delta->space : 0.0); + // TODO: Should we not worry about the port capacity here?!? link.Attach(numChars); - - // TODO: Support UTF8 characters - for(int32 i=0; i(charArray[i]); - + + uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars); + link.Attach(bytesInBuffer); + + link.Attach(charArray, bytesInBuffer); + + link.FlushWithReply(&code); - if(code!=SERVER_TRUE) + if (code != SERVER_TRUE) return; - - for(int32 i=0; i(&escapementArray[i]); + + link.Read(escapementArray, numChars * sizeof(float)); } diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index f654a8bdaf..cb81814bb2 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -100,7 +100,7 @@ if $(TARGET_PLATFORM) = haiku { # link for Haiku LinkSharedOSLibs libappserver.so : - libroot.so libbe.so libfreetype.so ; + libroot.so libbe.so libfreetype.so libtextencoding.so ; LinkSharedOSLibs app_server : libroot.so libtranslation.so libz.so libpng.so libbe.so @@ -115,7 +115,7 @@ if $(TARGET_PLATFORM) = haiku { LinkSharedOSLibs libappserver.so : root be libopenbeos.so - libfreetype.so ; + textencoding libfreetype.so ; LinkSharedOSLibs app_server : root be game translation libz.so libpng.so libappserver.so diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 086aeb857f..12e3bad400 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -1805,13 +1805,18 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg) // 3) float - point size // 4) float - rotation // 5) uint32 - flags - // 6) int32 - numChars - // 7) char - char - // 8) port_id - reply port + + // 6) float - additional "nonspace" delta + // 7) float - additional "space" delta + + // 8) int32 - numChars + // 9) int32 - numBytes + // 10) char - the char buffer with size numBytes + + // 11) port_id - reply port // Returns: - // 1) float - escapement - // numChars times + // 1) float - escapement buffer with numChar entries uint16 famid, styid; uint32 flags; @@ -1822,21 +1827,51 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg) msg.Read(&ptsize); msg.Read(&rotation); msg.Read(&flags); + + escapement_delta delta; + msg.Read(&delta.nonspace); + msg.Read(&delta.space); int32 numChars; msg.Read(&numChars); - - char charArray[numChars]; + +/* char charArray[numChars]; for (int32 i = 0; i < numChars; i++) { msg.Read(&charArray[i]); - } - + }*/ + uint32 numBytes; + msg.Read(&numBytes); + + char* charArray = new char[numBytes]; + msg.Read(charArray, numBytes); + + float* escapements = new float[numChars]; + // figure out escapements + port_id replyport; msg.Read(&replyport); replylink.SetSendPort(replyport); - - // TODO: Implement AS_GET_ESCAPEMENTS_AS_FLOATS and the float version of ServerFont::GetEscapements() - replylink.StartMessage(SERVER_FALSE); + + ServerFont font; + bool success = false; + if (font.SetFamilyAndStyle(famid, styid) == B_OK) { + font.SetSize(ptsize); + font.SetRotation(rotation); + font.SetFlags(flags); + + if (font.GetEscapements(charArray, numChars, escapements, delta)) { + replylink.StartMessage(SERVER_TRUE); + replylink.Attach(escapements, numChars * sizeof(float)); + success = true; + } + } + + delete[] charArray; + delete[] escapements; + + if (!success) + replylink.StartMessage(SERVER_FALSE); + replylink.Flush(); break; diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index 5e2ba1d15a..8465647df5 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -24,13 +24,20 @@ // Description: Shadow BFont class // //------------------------------------------------------------------------------ +#include #include -#include "ServerFont.h" -#include "FontServer.h" +#include + #include "Angle.h" +#include "FontServer.h" +#include "moreUTF8.h" + #include FT_FREETYPE_H #include FT_OUTLINE_H +#include "ServerFont.h" + + /*! \brief Constructor \param style Style object to which the ServerFont belongs @@ -45,8 +52,8 @@ ServerFont::ServerFont(FontStyle *style, float size, float rotation, float shear { fStyle=style; fSize=size; - frotation=rotation; - fshear=shear; + fRotation=rotation; + fShear=shear; fFlags=flags; fSpacing=spacing; fDirection=B_FONT_LEFT_TO_RIGHT; @@ -65,8 +72,8 @@ ServerFont::ServerFont(void) { fStyle=NULL; fSize=0.0; - frotation=0.0; - fshear=90.0; + fRotation=0.0; + fShear=90.0; fFlags=0; fSpacing=B_STRING_SPACING; fDirection=B_FONT_LEFT_TO_RIGHT; @@ -83,8 +90,8 @@ ServerFont::ServerFont(const ServerFont &font) { fStyle=font.fStyle; fSize=font.fSize; - frotation=font.frotation; - fshear=font.fshear; + fRotation=font.fRotation; + fShear=font.fShear; fFlags=font.fFlags; fSpacing=font.fSpacing; fDirection=font.fDirection; @@ -112,8 +119,8 @@ ServerFont::~ServerFont(void) ServerFont& ServerFont::operator=(const ServerFont& font){ fStyle = font.fStyle; fSize = font.fSize; - frotation = font.frotation; - fshear = font.fshear; + fRotation = font.fRotation; + fShear = font.fShear; fFlags = font.fFlags; fSpacing = font.fSpacing; fDirection = B_FONT_LEFT_TO_RIGHT; @@ -247,8 +254,8 @@ ServerFont::GetGlyphShapes(const char charArray[], int32 numChars) const FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); - Angle rotation(frotation); - Angle shear(fshear); + Angle rotation(fRotation); + Angle shear(fShear); // First, rotate FT_Matrix rmatrix; @@ -283,9 +290,9 @@ ServerFont::GetGlyphShapes(const char charArray[], int32 numChars) const return shapes; } -BPoint * +BPoint* ServerFont::GetEscapements(const char charArray[], int32 numChars, - BPoint offsetArray[]) const + BPoint offsetArray[]) const { if (!charArray || numChars <= 0 || !offsetArray) return NULL; @@ -296,8 +303,8 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); - Angle rotation(frotation); - Angle shear(fshear); + Angle rotation(fRotation); + Angle shear(fShear); // First, rotate FT_Matrix rmatrix; @@ -319,6 +326,10 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, //FT_Vector pen; //FT_Set_Transform(face, &smatrix, &pen); + // TODO: I'm not sure if this the correct interpretation + // of the BeBook. Have actual tests been done here? + + // TODO: handle UTF8... see below!! BPoint *escapements = (BPoint *)malloc(sizeof(BPoint) * numChars); for (int i = 0; i < numChars; i++) { FT_Load_Char(face, charArray[i], FT_LOAD_NO_BITMAP); @@ -330,6 +341,53 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars, return escapements; } +bool +ServerFont::GetEscapements(const char charArray[], int32 numChars, + float widthArray[], escapement_delta delta) const +{ + if (!charArray || numChars <= 0) + return false; + + FT_Face face = fStyle->GetFTFace(); + if (!face) + return false; + + 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 = convertedLength / sizeof(uint16); + + for (int i = 0; i < numChars; i++) { + FT_Load_Char(face, glyphIndex[i], FT_LOAD_NO_BITMAP); + // TODO: It appears that "white spaces" are not handled correctly: + // metrics.width will be zero, which is in now way correct! + widthArray[i] = float(face->glyph->metrics.width / 64) / fSize; + // TODO: + // widthArray[i] += is_white_space(glyphIndex[i]) ? delta.space : delta.nonspace; + } + } + delete[] convertedBuffer; + + return ret >= B_OK; +} + /*! \brief Sets the ServerFont instance to whatever font is specified \param familyID ID number of the family to set