app_server: Add char limit to GlyphLayoutEngine::LayoutGlyphs().

Many of the consumers fill in data into preallocated arrays. Some of
them already ignored values past the array size manually, some didn't.

Add a maxChar argument and set it from the incoming array sizes for
the various consumer cases.
This commit is contained in:
Michael Lotz 2018-12-29 00:25:48 +01:00
parent 64a11edb02
commit 8071db3259
5 changed files with 37 additions and 44 deletions

View File

@ -2204,7 +2204,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID);
if (status == B_OK) {
status = font.GetHasGlyphs(charArray, numBytes, hasArray);
status = font.GetHasGlyphs(charArray, numBytes, numChars,
hasArray);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(hasArray, numChars * sizeof(bool));
@ -2251,7 +2252,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID);
if (status == B_OK) {
status = font.GetEdges(charArray, numBytes, edgeArray);
status = font.GetEdges(charArray, numBytes, numChars,
edgeArray);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(edgeArray, numChars * sizeof(edge_info));
@ -2503,7 +2505,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// TODO: implement for real
if (font.GetBoundingBoxes(charArray, numBytes,
rectArray, stringEscapement, mode, delta,
numChars, rectArray, stringEscapement, mode, delta,
code == AS_GET_BOUNDINGBOXES_STRING) == B_OK) {
fLink.StartMessage(B_OK);

View File

@ -696,16 +696,17 @@ class HasGlyphsConsumer {
status_t
ServerFont::GetHasGlyphs(const char* string, int32 numBytes,
ServerFont::GetHasGlyphs(const char* string, int32 numBytes, int32 numChars,
bool* hasArray) const
{
if (!string || numBytes <= 0 || !hasArray)
if (string == NULL || numBytes <= 0 || numChars <= 0 || hasArray == NULL)
return B_BAD_DATA;
HasGlyphsConsumer consumer(hasArray);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
NULL, fSpacing))
numChars, NULL, fSpacing)) {
return B_OK;
}
return B_ERROR;
}
@ -745,15 +746,15 @@ class EdgesConsumer {
status_t
ServerFont::GetEdges(const char* string, int32 numBytes,
ServerFont::GetEdges(const char* string, int32 numBytes, int32 numChars,
edge_info* edges) const
{
if (!string || numBytes <= 0 || !edges)
if (string == NULL || numBytes <= 0 || numChars <= 0 || edges == NULL)
return B_BAD_DATA;
EdgesConsumer consumer(edges, fSize);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
NULL, fSpacing)) {
numChars, NULL, fSpacing)) {
return B_OK;
}
@ -780,12 +781,10 @@ ServerFont::GetEdges(const char* string, int32 numBytes,
class BPointEscapementConsumer {
public:
BPointEscapementConsumer(BPoint* escapements, BPoint* offsets,
int32 numChars, float size)
BPointEscapementConsumer(BPoint* escapements, BPoint* offsets, float size)
:
fEscapements(escapements),
fOffsets(offsets),
fNumChars(numChars),
fSize(size)
{
}
@ -808,9 +807,6 @@ public:
private:
inline bool _Set(int32 index, double x, double y)
{
if (index >= fNumChars)
return false;
fEscapements[index].x = x / fSize;
fEscapements[index].y = y / fSize;
if (fOffsets) {
@ -827,8 +823,7 @@ private:
BPoint* fEscapements;
BPoint* fOffsets;
int32 fNumChars;
float fSize;
float fSize;
};
@ -840,10 +835,9 @@ ServerFont::GetEscapements(const char* string, int32 numBytes, int32 numChars,
if (!string || numBytes <= 0 || !escapementArray)
return B_BAD_DATA;
BPointEscapementConsumer consumer(escapementArray, offsetArray, numChars,
fSize);
BPointEscapementConsumer consumer(escapementArray, offsetArray, fSize);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
&delta, fSpacing)) {
numChars, &delta, fSpacing)) {
return B_OK;
}
@ -853,10 +847,9 @@ ServerFont::GetEscapements(const char* string, int32 numBytes, int32 numChars,
class WidthEscapementConsumer {
public:
WidthEscapementConsumer(float* widths, int32 numChars, float size)
WidthEscapementConsumer(float* widths, float size)
:
fWidths(widths),
fNumChars(numChars),
fSize(size)
{
}
@ -873,16 +866,12 @@ public:
FontCacheEntry* entry, double x, double y, double advanceX,
double advanceY)
{
if (index >= fNumChars)
return false;
fWidths[index] = advanceX / fSize;
return true;
}
private:
float* fWidths;
int32 fNumChars;
float fSize;
};
@ -895,9 +884,9 @@ ServerFont::GetEscapements(const char* string, int32 numBytes, int32 numChars,
if (!string || numBytes <= 0 || !widthArray)
return B_BAD_DATA;
WidthEscapementConsumer consumer(widthArray, numChars, fSize);
WidthEscapementConsumer consumer(widthArray, fSize);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
&delta, fSpacing)) {
numChars, &delta, fSpacing)) {
return B_OK;
}
@ -997,19 +986,19 @@ class BoundingBoxConsumer {
status_t
ServerFont::GetBoundingBoxes(const char* string, int32 numBytes,
ServerFont::GetBoundingBoxes(const char* string, int32 numBytes, int32 numChars,
BRect rectArray[], bool stringEscapement, font_metric_mode mode,
escapement_delta delta, bool asString)
{
// TODO: The font_metric_mode is not used
if (!string || numBytes <= 0 || !rectArray)
if (string == NULL || numBytes <= 0 || numChars <= 0 || rectArray == NULL)
return B_BAD_DATA;
Transformable transform(EmbeddedTransformation());
BoundingBoxConsumer consumer(transform, rectArray, asString);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
stringEscapement ? &delta : NULL, fSpacing)) {
numChars, stringEscapement ? &delta : NULL, fSpacing)) {
return B_OK;
}
return B_ERROR;
@ -1034,7 +1023,7 @@ ServerFont::GetBoundingBoxesForStrings(char *charArray[], size_t lengthArray[],
BoundingBoxConsumer consumer(transform, NULL, true);
if (!GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
&delta, fSpacing)) {
INT32_MAX, &delta, fSpacing)) {
return B_ERROR;
}
@ -1077,7 +1066,7 @@ ServerFont::StringWidth(const char *string, int32 numBytes,
StringWidthConsumer consumer;
if (!GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
deltaArray, fSpacing)) {
INT32_MAX, deltaArray, fSpacing)) {
return 0.0;
}

View File

@ -116,10 +116,12 @@ class ServerFont {
int32 numChars, BShape *shapeArray[]) const;
status_t GetHasGlyphs(const char charArray[],
int32 numBytes, bool hasArray[]) const;
int32 numBytes, int32 numChars,
bool hasArray[]) const;
status_t GetEdges(const char charArray[], int32 numBytes,
edge_info edgeArray[]) const;
int32 numChars, edge_info edgeArray[])
const;
status_t GetEscapements(const char charArray[],
int32 numBytes, int32 numChars,
@ -133,8 +135,8 @@ class ServerFont {
float widthArray[]) const;
status_t GetBoundingBoxes(const char charArray[],
int32 numBytes, BRect rectArray[],
bool stringEscapement,
int32 numBytes, int32 numChars,
BRect rectArray[], bool stringEscapement,
font_metric_mode mode,
escapement_delta delta,
bool asString);

View File

@ -363,8 +363,8 @@ AGGTextRenderer::RenderString(const char* string, uint32 length,
transformedOutline, transformedContourOutline,
transform, transformOffset, nextCharPos, *this);
GlyphLayoutEngine::LayoutGlyphs(renderer, fFont, string, length, delta,
fFont.Spacing(), NULL, cacheReference);
GlyphLayoutEngine::LayoutGlyphs(renderer, fFont, string, length, INT32_MAX,
delta, fFont.Spacing(), NULL, cacheReference);
return transform.TransformBounds(renderer.Bounds());
}
@ -400,8 +400,8 @@ AGGTextRenderer::RenderString(const char* string, uint32 length,
transformedOutline, transformedContourOutline,
transform, transformOffset, nextCharPos, *this);
GlyphLayoutEngine::LayoutGlyphs(renderer, fFont, string, length, NULL,
fFont.Spacing(), offsets, cacheReference);
GlyphLayoutEngine::LayoutGlyphs(renderer, fFont, string, length, INT32_MAX,
NULL, fFont.Spacing(), offsets, cacheReference);
return transform.TransformBounds(renderer.Bounds());
}

View File

@ -90,7 +90,7 @@ public:
static bool LayoutGlyphs(GlyphConsumer& consumer,
const ServerFont& font,
const char* utf8String,
int32 length,
int32 length, int32 maxChars,
const escapement_delta* delta = NULL,
uint8 spacing = B_BITMAP_SPACING,
const BPoint* offsets = NULL,
@ -171,7 +171,7 @@ template<class GlyphConsumer>
inline bool
GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer,
const ServerFont& font,
const char* utf8String, int32 length,
const char* utf8String, int32 length, int32 maxChars,
const escapement_delta* delta, uint8 spacing,
const BPoint* offsets, FontCacheReference* _cacheReference)
{
@ -217,7 +217,7 @@ GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer,
int32 index = 0;
bool writeLocked = false;
const char* start = utf8String;
while ((charCode = UTF8ToCharCode(&utf8String))) {
while (maxChars-- > 0 && (charCode = UTF8ToCharCode(&utf8String)) != 0) {
if (offsets != NULL) {
// Use direct glyph locations instead of calculating them