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:
Dale Cieslak 2022-07-04 19:20:41 -07:00 committed by waddlesplash
parent 764c0853e8
commit 094079b8c5
4 changed files with 84 additions and 6 deletions

View File

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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)