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 "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

View File

@ -23,16 +23,20 @@
// Author: DarkWyrm (bpmagic@columbus.rr.com)
// Description: Class to manage font-handling capabilities
//------------------------------------------------------------------------------
#include <Rect.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 <AppServerLink.h>
#include <Message.h>
#include <PortLink.h>
#include <Rect.h>
#include <ServerProtocol.h>
#include <Shape.h>
#include <String.h>
#include <moreUTF8.h>
#include <Font.h>
//----------------------------------------------------------------------------------------
// 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<float>(fSize);
link.Attach<float>(fRotation);
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);
// TODO: Support UTF8 characters
for(int32 i=0; i<numChars; i++)
link.Attach<char>(charArray[i]);
uint32 bytesInBuffer = UTF8CountBytes(charArray, numChars);
link.Attach<int32>(bytesInBuffer);
link.Attach(charArray, bytesInBuffer);
link.FlushWithReply(&code);
if(code!=SERVER_TRUE)
if (code != SERVER_TRUE)
return;
for(int32 i=0; i<numChars; i++)
link.Read<float>(&escapementArray[i]);
link.Read(escapementArray, numChars * sizeof(float));
}

View File

@ -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 <boot!home!config!lib>libopenbeos.so
libfreetype.so ;
textencoding libfreetype.so ;
LinkSharedOSLibs app_server :
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
// 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<float>(&ptsize);
msg.Read<float>(&rotation);
msg.Read<uint32>(&flags);
escapement_delta delta;
msg.Read<float>(&delta.nonspace);
msg.Read<float>(&delta.space);
int32 numChars;
msg.Read<int32>(&numChars);
char charArray[numChars];
/* char charArray[numChars];
for (int32 i = 0; i < numChars; 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;
msg.Read<port_id>(&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;

View File

@ -24,13 +24,20 @@
// Description: Shadow BFont class
//
//------------------------------------------------------------------------------
#include <ByteOrder.h>
#include <Shape.h>
#include "ServerFont.h"
#include "FontServer.h"
#include <UTF8.h>
#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