aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-09-19 13:07:38 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-19 13:07:39 -0700
commit681e65b19940e10f39bf1237b4b35aa94677b3d0 (patch)
tree8267b18ae1fd466c1ad107ba30be291f373c7a72
parent5d9ab2816f5e595a5b7cba9d4b7fae169e21c66e (diff)
Don't try to add large glyphs to the font atlas.
When the glyph data is invalid we can try to allocate a ridiculous amount of memory. This adds a check to cover such cases. BUG=414581 R=egdaniel@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/585853003
-rwxr-xr-xsrc/gpu/GrBitmapTextContext.cpp38
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp38
-rw-r--r--src/gpu/GrTextStrike.cpp13
-rw-r--r--src/gpu/GrTextStrike.h4
4 files changed, 57 insertions, 36 deletions
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 9ef8da254a..4210517526 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -454,30 +454,32 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
if (NULL == glyph->fPlot) {
- if (fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
- }
+ if (!fStrike->glyphTooLargeForAtlas(glyph)) {
+ if (fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
- // try to clear out an unused plot before we flush
- if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
- }
+ // try to clear out an unused plot before we flush
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
- if (c_DumpFontCache) {
+ if (c_DumpFontCache) {
#ifdef SK_DEVELOPER
- fContext->getFontCache()->dump();
+ fContext->getFontCache()->dump();
#endif
- }
+ }
- // flush any accumulated draws to allow us to free up a plot
- this->flushGlyphs();
- fContext->flush();
+ // flush any accumulated draws to allow us to free up a plot
+ this->flushGlyphs();
+ fContext->flush();
- // we should have an unused plot now
- if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
+ // we should have an unused plot now
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
}
if (NULL == glyph->fPath) {
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 18058be17f..313c02ac51 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -273,30 +273,32 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
*/
if (NULL == glyph->fPlot) {
- if (fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
- }
+ if (!fStrike->glyphTooLargeForAtlas(glyph)) {
+ if (fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
- // try to clear out an unused plot before we flush
- if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
- }
+ // try to clear out an unused plot before we flush
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
- if (c_DumpFontCache) {
+ if (c_DumpFontCache) {
#ifdef SK_DEVELOPER
- fContext->getFontCache()->dump();
+ fContext->getFontCache()->dump();
#endif
- }
+ }
- // before we purge the cache, we must flush any accumulated draws
- this->flushGlyphs();
- fContext->flush();
+ // before we purge the cache, we must flush any accumulated draws
+ this->flushGlyphs();
+ fContext->flush();
- // we should have an unused plot now
- if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
- fStrike->addGlyphToAtlas(glyph, scaler)) {
- goto HAS_ATLAS;
+ // we should have an unused plot now
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
+ goto HAS_ATLAS;
+ }
}
if (NULL == glyph->fPath) {
diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp
index 24fa707548..fa97f73f05 100644
--- a/src/gpu/GrTextStrike.cpp
+++ b/src/gpu/GrTextStrike.cpp
@@ -289,6 +289,19 @@ void GrTextStrike::removePlot(const GrPlot* plot) {
GrAtlas::RemovePlot(&fPlotUsage, plot);
}
+bool GrTextStrike::glyphTooLargeForAtlas(GrGlyph* glyph) {
+ int width = glyph->fBounds.width();
+ int height = glyph->fBounds.height();
+ int pad = fUseDistanceField ? 2 * SK_DistanceFieldPad : 0;
+ if (width + pad > GR_PLOT_WIDTH) {
+ return true;
+ }
+ if (height + pad > GR_PLOT_HEIGHT) {
+ return true;
+ }
+
+ return false;
+}
bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
#if 0 // testing hack to force us to flush our cache often
diff --git a/src/gpu/GrTextStrike.h b/src/gpu/GrTextStrike.h
index a5bb6ae5db..401bd73259 100644
--- a/src/gpu/GrTextStrike.h
+++ b/src/gpu/GrTextStrike.h
@@ -37,6 +37,10 @@ public:
GrTexture* getTexture() const { return fAtlas->getTexture(); }
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
+ // returns true if glyph (or glyph+padding for distance field)
+ // is too large to ever fit in texture atlas subregions (GrPlots)
+ bool glyphTooLargeForAtlas(GrGlyph*);
+ // returns true if glyph successfully added to texture atlas, false otherwise
bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
// testing