From 8071db325921c68819177ef5d8727a1379ebf59a Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 29 Dec 2018 00:25:48 +0100 Subject: [PATCH] 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. --- src/servers/app/ServerApp.cpp | 8 +-- src/servers/app/ServerFont.cpp | 49 +++++++------------ src/servers/app/ServerFont.h | 10 ++-- .../app/drawing/Painter/AGGTextRenderer.cpp | 8 +-- src/servers/app/font/GlyphLayoutEngine.h | 6 +-- 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 7abbbac0b8..95d5d71170 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -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); diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index e7c16a369c..a045ace457 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -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; } diff --git a/src/servers/app/ServerFont.h b/src/servers/app/ServerFont.h index 4f9b94d038..b5a5e7d702 100644 --- a/src/servers/app/ServerFont.h +++ b/src/servers/app/ServerFont.h @@ -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); diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp index 4324e09fac..6110cef95e 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp @@ -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()); } diff --git a/src/servers/app/font/GlyphLayoutEngine.h b/src/servers/app/font/GlyphLayoutEngine.h index 9acd9ab1de..c3c666c3b3 100644 --- a/src/servers/app/font/GlyphLayoutEngine.h +++ b/src/servers/app/font/GlyphLayoutEngine.h @@ -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 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