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
This commit is contained in:
Stephan Aßmus 2005-05-12 15:09:30 +00:00
parent 2309ba4c1f
commit 9bdb0522c1
5 changed files with 263 additions and 114 deletions

View File

@ -31,81 +31,128 @@
#include <Font.h> #include <Font.h>
#include "FontFamily.h" #include "FontFamily.h"
class ServerFont class ServerFont {
{ public:
public: ServerFont();
ServerFont(void); ServerFont(FontStyle* style,
ServerFont(FontStyle *style, float size=12.0, float frotation=0.0, float fshear=90.0, float size = 12.0,
uint16 flags=0, uint8 spacing=B_CHAR_SPACING); float fRotation = 0.0,
ServerFont(const ServerFont &font); float fShear = 90.0,
~ServerFont(void); uint16 flags = 0,
uint8 spacing = B_CHAR_SPACING);
ServerFont(const ServerFont& font);
virtual ~ServerFont();
// TODO: make more advanced... // TODO: make more advanced...
status_t InitCheck() const status_t InitCheck() const
{ return fStyle ? B_OK : B_NO_INIT; } { return fStyle ? B_OK : B_NO_INIT; }
font_direction Direction(void) const { return fDirection; } font_direction Direction() const
uint32 Encoding(void) const { return fEncoding; } { return fDirection; }
edge_info Edges(void) const { return fEdges; } uint32 Encoding() const
uint32 Flags(void) const { return fFlags; } { return fEncoding; }
uint32 Spacing(void) const { return fSpacing; } edge_info Edges() const
float Shear(void) const { return fshear; } { return fEdges; }
float Rotation(void) const { return frotation; } uint32 Flags() const
float Size(void) const { return fSize; } { return fFlags; }
uint16 Face(void) const { return fFace; } uint32 Spacing() const
uint32 CountGlyphs(void) { return fStyle->GlyphCount(); } { return fSpacing; }
int32 CountTuned(void); float Shear() const
font_file_format FileFormat(void); { return fShear; }
float Rotation() const
status_t SetFamilyAndStyle(const uint16 &familyID,const uint16 &styleID); { return fRotation; }
status_t SetFamilyAndStyle(const uint32 &fontID); float Size() const
void SetDirection(const font_direction &dir) { fDirection=dir; } { return fSize; }
void SetEdges(const edge_info &info) { fEdges=info; } uint16 Face() const
void SetEncoding(uint32 encoding) { fEncoding=encoding; } { return fFace; }
void SetFlags(const uint32 &value) { fFlags=value; } uint32 CountGlyphs()
void SetSpacing(const uint32 &value) { fSpacing=value; } { return fStyle->GlyphCount(); }
void SetShear(const float &value) { fshear=value; } int32 CountTuned();
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;
BRect BoundingBox(void); font_file_format FileFormat();
void Height(font_height *fh);
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: protected:
friend class FontStyle; friend class FontStyle;
FontStyle *fStyle;
edge_info fEdges; FontStyle* fStyle;
float fSize, frotation, fshear; edge_info fEdges;
BRect fBounds; float fSize;
uint32 fFlags; float fRotation;
uint32 fSpacing; float fShear;
uint16 fFace; BRect fBounds;
font_direction fDirection; uint32 fFlags;
uint32 fEncoding; uint32 fSpacing;
uint16 fFace;
font_direction fDirection;
uint32 fEncoding;
}; };
#endif #endif

View File

@ -23,16 +23,20 @@
// Author: DarkWyrm (bpmagic@columbus.rr.com) // Author: DarkWyrm (bpmagic@columbus.rr.com)
// Description: Class to manage font-handling capabilities // Description: Class to manage font-handling capabilities
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include <Rect.h>
#include <stdio.h> #include <stdio.h>
#include <Font.h>
#include <Message.h>
#include <String.h>
#include <Shape.h>
#include <PortLink.h>
#include <AppServerLink.h>
#include <stdlib.h> #include <stdlib.h>
#include <AppServerLink.h>
#include <Message.h>
#include <PortLink.h>
#include <Rect.h>
#include <ServerProtocol.h> #include <ServerProtocol.h>
#include <Shape.h>
#include <String.h>
#include <moreUTF8.h>
#include <Font.h>
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
// Globals // Globals
@ -942,9 +946,9 @@ void
BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta, BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta,
float escapementArray[]) const float escapementArray[]) const
{ {
if(!charArray || numChars<1 || !escapementArray) if (!charArray || numChars<1 || !escapementArray)
return; return;
int32 code; int32 code;
BPrivate::BAppServerLink link; BPrivate::BAppServerLink link;
@ -955,20 +959,25 @@ BFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *
link.Attach<float>(fSize); link.Attach<float>(fSize);
link.Attach<float>(fRotation); link.Attach<float>(fRotation);
link.Attach<uint32>(fFlags); link.Attach<uint32>(fFlags);
link.Attach<float>(delta ? delta->nonspace : 0.0);
link.Attach<float>(delta ? delta->space : 0.0);
// TODO: Should we not worry about the port capacity here?!?
link.Attach<int32>(numChars); link.Attach<int32>(numChars);
// TODO: Support UTF8 characters uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars);
for(int32 i=0; i<numChars; i++) link.Attach<int32>(bytesInBuffer);
link.Attach<char>(charArray[i]);
link.Attach(charArray, bytesInBuffer);
link.FlushWithReply(&code); link.FlushWithReply(&code);
if(code!=SERVER_TRUE) if (code != SERVER_TRUE)
return; return;
for(int32 i=0; i<numChars; i++) link.Read(escapementArray, numChars * sizeof(float));
link.Read<float>(&escapementArray[i]);
} }

View File

@ -100,7 +100,7 @@ if $(TARGET_PLATFORM) = haiku {
# link for Haiku # link for Haiku
LinkSharedOSLibs libappserver.so : LinkSharedOSLibs libappserver.so :
libroot.so libbe.so libfreetype.so ; libroot.so libbe.so libfreetype.so libtextencoding.so ;
LinkSharedOSLibs app_server : LinkSharedOSLibs app_server :
libroot.so libtranslation.so libz.so libpng.so libbe.so libroot.so libtranslation.so libz.so libpng.so libbe.so
@ -115,7 +115,7 @@ if $(TARGET_PLATFORM) = haiku {
LinkSharedOSLibs libappserver.so : LinkSharedOSLibs libappserver.so :
root be <boot!home!config!lib>libopenbeos.so root be <boot!home!config!lib>libopenbeos.so
libfreetype.so ; textencoding libfreetype.so ;
LinkSharedOSLibs app_server : LinkSharedOSLibs app_server :
root be game translation libz.so libpng.so libappserver.so root be game translation libz.so libpng.so libappserver.so

View File

@ -1805,13 +1805,18 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg)
// 3) float - point size // 3) float - point size
// 4) float - rotation // 4) float - rotation
// 5) uint32 - flags // 5) uint32 - flags
// 6) int32 - numChars
// 7) char - char // 6) float - additional "nonspace" delta
// 8) port_id - reply port // 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: // Returns:
// 1) float - escapement // 1) float - escapement buffer with numChar entries
// numChars times
uint16 famid, styid; uint16 famid, styid;
uint32 flags; uint32 flags;
@ -1822,21 +1827,51 @@ ServerApp::DispatchMessage(int32 code, LinkMsgReader &msg)
msg.Read<float>(&ptsize); msg.Read<float>(&ptsize);
msg.Read<float>(&rotation); msg.Read<float>(&rotation);
msg.Read<uint32>(&flags); msg.Read<uint32>(&flags);
escapement_delta delta;
msg.Read<float>(&delta.nonspace);
msg.Read<float>(&delta.space);
int32 numChars; int32 numChars;
msg.Read<int32>(&numChars); msg.Read<int32>(&numChars);
char charArray[numChars]; /* char charArray[numChars];
for (int32 i = 0; i < numChars; i++) { for (int32 i = 0; i < numChars; i++) {
msg.Read<char>(&charArray[i]); msg.Read<char>(&charArray[i]);
} }*/
uint32 numBytes;
msg.Read<uint32>(&numBytes);
char* charArray = new char[numBytes];
msg.Read(charArray, numBytes);
float* escapements = new float[numChars];
// figure out escapements
port_id replyport; port_id replyport;
msg.Read<port_id>(&replyport); msg.Read<port_id>(&replyport);
replylink.SetSendPort(replyport); replylink.SetSendPort(replyport);
// TODO: Implement AS_GET_ESCAPEMENTS_AS_FLOATS and the float version of ServerFont::GetEscapements() ServerFont font;
replylink.StartMessage(SERVER_FALSE); 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(); replylink.Flush();
break; break;

View File

@ -24,13 +24,20 @@
// Description: Shadow BFont class // Description: Shadow BFont class
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include <ByteOrder.h>
#include <Shape.h> #include <Shape.h>
#include "ServerFont.h" #include <UTF8.h>
#include "FontServer.h"
#include "Angle.h" #include "Angle.h"
#include "FontServer.h"
#include "moreUTF8.h"
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_OUTLINE_H #include FT_OUTLINE_H
#include "ServerFont.h"
/*! /*!
\brief Constructor \brief Constructor
\param style Style object to which the ServerFont belongs \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; fStyle=style;
fSize=size; fSize=size;
frotation=rotation; fRotation=rotation;
fshear=shear; fShear=shear;
fFlags=flags; fFlags=flags;
fSpacing=spacing; fSpacing=spacing;
fDirection=B_FONT_LEFT_TO_RIGHT; fDirection=B_FONT_LEFT_TO_RIGHT;
@ -65,8 +72,8 @@ ServerFont::ServerFont(void)
{ {
fStyle=NULL; fStyle=NULL;
fSize=0.0; fSize=0.0;
frotation=0.0; fRotation=0.0;
fshear=90.0; fShear=90.0;
fFlags=0; fFlags=0;
fSpacing=B_STRING_SPACING; fSpacing=B_STRING_SPACING;
fDirection=B_FONT_LEFT_TO_RIGHT; fDirection=B_FONT_LEFT_TO_RIGHT;
@ -83,8 +90,8 @@ ServerFont::ServerFont(const ServerFont &font)
{ {
fStyle=font.fStyle; fStyle=font.fStyle;
fSize=font.fSize; fSize=font.fSize;
frotation=font.frotation; fRotation=font.fRotation;
fshear=font.fshear; fShear=font.fShear;
fFlags=font.fFlags; fFlags=font.fFlags;
fSpacing=font.fSpacing; fSpacing=font.fSpacing;
fDirection=font.fDirection; fDirection=font.fDirection;
@ -112,8 +119,8 @@ ServerFont::~ServerFont(void)
ServerFont& ServerFont::operator=(const ServerFont& font){ ServerFont& ServerFont::operator=(const ServerFont& font){
fStyle = font.fStyle; fStyle = font.fStyle;
fSize = font.fSize; fSize = font.fSize;
frotation = font.frotation; fRotation = font.fRotation;
fshear = font.fshear; fShear = font.fShear;
fFlags = font.fFlags; fFlags = font.fFlags;
fSpacing = font.fSpacing; fSpacing = font.fSpacing;
fDirection = B_FONT_LEFT_TO_RIGHT; 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); FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72);
Angle rotation(frotation); Angle rotation(fRotation);
Angle shear(fshear); Angle shear(fShear);
// First, rotate // First, rotate
FT_Matrix rmatrix; FT_Matrix rmatrix;
@ -283,9 +290,9 @@ ServerFont::GetGlyphShapes(const char charArray[], int32 numChars) const
return shapes; return shapes;
} }
BPoint * BPoint*
ServerFont::GetEscapements(const char charArray[], int32 numChars, ServerFont::GetEscapements(const char charArray[], int32 numChars,
BPoint offsetArray[]) const BPoint offsetArray[]) const
{ {
if (!charArray || numChars <= 0 || !offsetArray) if (!charArray || numChars <= 0 || !offsetArray)
return NULL; return NULL;
@ -296,8 +303,8 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars,
FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72); FT_Set_Char_Size(face, 0, int32(fSize) * 64, 72, 72);
Angle rotation(frotation); Angle rotation(fRotation);
Angle shear(fshear); Angle shear(fShear);
// First, rotate // First, rotate
FT_Matrix rmatrix; FT_Matrix rmatrix;
@ -319,6 +326,10 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars,
//FT_Vector pen; //FT_Vector pen;
//FT_Set_Transform(face, &smatrix, &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); BPoint *escapements = (BPoint *)malloc(sizeof(BPoint) * numChars);
for (int i = 0; i < numChars; i++) { for (int i = 0; i < numChars; i++) {
FT_Load_Char(face, charArray[i], FT_LOAD_NO_BITMAP); FT_Load_Char(face, charArray[i], FT_LOAD_NO_BITMAP);
@ -330,6 +341,53 @@ ServerFont::GetEscapements(const char charArray[], int32 numChars,
return escapements; 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 \brief Sets the ServerFont instance to whatever font is specified
\param familyID ID number of the family to set \param familyID ID number of the family to set