BFont: Implement BFont::BoundingBox
Extracted as separate patch from CR 4790; implement BFont::BoundingBox as it was in BeOS. Returns a BRect that encloses any character in a font, scaled by the font size. Since the FreeType bbox is only valid for vector outlines, for bitmap fonts, return a BRect with the dimensions of the bitmap font that is closest to the font size. Tested with CharacterMap. Will update CharacterMap to use the bounding box once this change is landed. Note that bitmap font rendering doesn't appear to work at all. Change-ID: I8fc42ca0ddc0c77e04e0216001cd17e086ec7495 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5431 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
parent
764c0853e8
commit
094079b8c5
@ -826,6 +826,7 @@ BFont::BoundingBox() const
|
||||
link.StartMessage(AS_GET_FONT_BOUNDING_BOX);
|
||||
link.Attach<uint16>(fFamilyID);
|
||||
link.Attach<uint16>(fStyleID);
|
||||
link.Attach<float>(fSize);
|
||||
|
||||
int32 code;
|
||||
if (link.FlushWithReply(code) != B_OK
|
||||
|
@ -1951,18 +1951,34 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
|
||||
case AS_GET_FONT_BOUNDING_BOX:
|
||||
{
|
||||
FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n",
|
||||
FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX\n",
|
||||
Signature()));
|
||||
|
||||
// Attached Data:
|
||||
// 1) uint16 - family ID
|
||||
// 2) uint16 - style ID
|
||||
// 3) float - font size
|
||||
|
||||
// Returns:
|
||||
// 1) BRect - box holding entire font
|
||||
|
||||
// ToDo: implement me!
|
||||
fLink.StartMessage(B_ERROR);
|
||||
uint16 familyID, styleID;
|
||||
float size;
|
||||
|
||||
link.Read<uint16>(&familyID);
|
||||
link.Read<uint16>(&styleID);
|
||||
link.Read<float>(&size);
|
||||
|
||||
ServerFont font;
|
||||
|
||||
if (font.SetFamilyAndStyle(familyID, styleID) == B_OK && size > 0) {
|
||||
font.SetSize(size);
|
||||
|
||||
fLink.StartMessage(B_OK);
|
||||
fLink.Attach<BRect>(font.BoundingBox());
|
||||
} else
|
||||
fLink.StartMessage(B_BAD_VALUE);
|
||||
|
||||
fLink.Flush();
|
||||
break;
|
||||
}
|
||||
|
@ -256,6 +256,9 @@ ServerFont::SetStyle(FontStyle* style)
|
||||
|
||||
fFace = fStyle->PreservedFace(fFace);
|
||||
fDirection = fStyle->Direction();
|
||||
|
||||
// invalidate fBounds
|
||||
fBounds.Set(0, -1, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,6 +287,9 @@ ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID)
|
||||
|
||||
SetStyle(style);
|
||||
|
||||
// invalidate fBounds
|
||||
fBounds.Set(0, -1, 0, -1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -303,6 +309,16 @@ ServerFont::SetFamilyAndStyle(uint32 fontID)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ServerFont::SetSize(float value)
|
||||
{
|
||||
fSize = value;
|
||||
|
||||
// invalidate fBounds
|
||||
fBounds.Set(0, -1, 0, -1);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ServerFont::SetFace(uint16 face)
|
||||
{
|
||||
@ -339,6 +355,9 @@ ServerFont::SetFace(uint16 face)
|
||||
fFace = face;
|
||||
SetStyle(style);
|
||||
|
||||
// invalidate fBounds
|
||||
fBounds.Set(0, -1, 0, -1);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -1079,7 +1098,49 @@ ServerFont::StringWidth(const char *string, int32 numBytes,
|
||||
BRect
|
||||
ServerFont::BoundingBox()
|
||||
{
|
||||
// TODO: fBounds is nowhere calculated!
|
||||
FT_Face face = fStyle->FreeTypeFace();
|
||||
|
||||
if (fBounds.IsValid() &&
|
||||
fBounds.IntegerWidth() > 0 &&
|
||||
fBounds.IntegerHeight() > 0)
|
||||
return fBounds;
|
||||
|
||||
// if font has vector outlines, get the bounding box
|
||||
// from freetype and scale it by the font size
|
||||
if (IsScalable()) {
|
||||
FT_BBox bounds = face->bbox;
|
||||
fBounds.left = (float)bounds.xMin / (float)face->units_per_EM;
|
||||
fBounds.right = (float)bounds.xMax / (float)face->units_per_EM;
|
||||
fBounds.top = (float)bounds.yMin / (float)face->units_per_EM;
|
||||
fBounds.bottom = (float)bounds.yMax / (float)face->units_per_EM;
|
||||
|
||||
float scaledWidth = fBounds.Width() * fSize;
|
||||
float scaledHeight = fBounds.Height() * fSize;
|
||||
|
||||
fBounds.InsetBy((fBounds.Width() - scaledWidth) / 2.f,
|
||||
(fBounds.Height() - scaledHeight) / 2.f);
|
||||
} else {
|
||||
// otherwise find the bitmap that is closest in size
|
||||
// to the requested size
|
||||
float pixelSize = fSize * 64.f;
|
||||
float minDelta = abs(face->available_sizes[0].size - pixelSize);
|
||||
float width = face->available_sizes[0].x_ppem;
|
||||
float height = face->available_sizes[0].y_ppem;
|
||||
|
||||
for (int i = 1; i < face->num_fixed_sizes; ++i) {
|
||||
float delta = abs(face->available_sizes[i].size - pixelSize);
|
||||
if (delta < minDelta) {
|
||||
width = face->available_sizes[i].x_ppem;
|
||||
height = face->available_sizes[i].y_ppem;
|
||||
}
|
||||
}
|
||||
|
||||
fBounds.top = 0;
|
||||
fBounds.left = 0;
|
||||
fBounds.right = width / 64.f;
|
||||
fBounds.bottom = height / 64.f;
|
||||
}
|
||||
|
||||
return fBounds;
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,8 @@ class ServerFont {
|
||||
{ fSpacing = value; }
|
||||
void SetShear(float value)
|
||||
{ fShear = value; }
|
||||
void SetSize(float value)
|
||||
{ fSize = value; }
|
||||
void SetSize(float value);
|
||||
|
||||
void SetRotation(float value)
|
||||
{ fRotation = value; }
|
||||
void SetFalseBoldWidth(float value)
|
||||
|
Loading…
x
Reference in New Issue
Block a user