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

View File

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

View File

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

View File

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

View File

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