gfx/skia/trunk/src/gpu/GrTextStrike.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2010 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "GrAtlas.h"
     9 #include "GrGpu.h"
    10 #include "GrRectanizer.h"
    11 #include "GrTextStrike.h"
    12 #include "GrTextStrike_impl.h"
    13 #include "SkString.h"
    15 #include "SkDistanceFieldGen.h"
    17 ///////////////////////////////////////////////////////////////////////////////
    19 #define FONT_CACHE_STATS 0
    20 #if FONT_CACHE_STATS
    21 static int g_PurgeCount = 0;
    22 #endif
    24 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
    25     gpu->ref();
    26     for (int i = 0; i < kAtlasCount; ++i) {
    27         fAtlasMgr[i] = NULL;
    28     }
    30     fHead = fTail = NULL;
    31 }
    33 GrFontCache::~GrFontCache() {
    34     fCache.deleteAll();
    35     for (int i = 0; i < kAtlasCount; ++i) {
    36         delete fAtlasMgr[i];
    37     }
    38     fGpu->unref();
    39 #if FONT_CACHE_STATS
    40       GrPrintf("Num purges: %d\n", g_PurgeCount);
    41 #endif
    42 }
    44 static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
    45     static const GrPixelConfig sPixelConfigs[] = {
    46         kAlpha_8_GrPixelConfig,
    47         kRGB_565_GrPixelConfig,
    48         kSkia8888_GrPixelConfig,
    49         kSkia8888_GrPixelConfig
    50     };
    51     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sPixelConfigs) == kMaskFormatCount, array_size_mismatch);
    53     return sPixelConfigs[format];
    54 }
    56 static int mask_format_to_atlas_index(GrMaskFormat format) {
    57     static const int sAtlasIndices[] = {
    58         GrFontCache::kA8_AtlasType,
    59         GrFontCache::k565_AtlasType,
    60         GrFontCache::k8888_AtlasType,
    61         GrFontCache::k8888_AtlasType
    62     };
    63     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
    65     SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount);
    66     return sAtlasIndices[format];
    67 }
    69 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
    70                                           const Key& key) {
    71     GrMaskFormat format = scaler->getMaskFormat();
    72     GrPixelConfig config = mask_format_to_pixel_config(format);
    73     int atlasIndex = mask_format_to_atlas_index(format);
    74     if (NULL == fAtlasMgr[atlasIndex]) {
    75         fAtlasMgr[atlasIndex] = SkNEW_ARGS(GrAtlasMgr, (fGpu, config));
    76     }
    77     GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
    78                                       (this, scaler->getKey(), format, fAtlasMgr[atlasIndex]));
    79     fCache.insert(key, strike);
    81     if (fHead) {
    82         fHead->fPrev = strike;
    83     } else {
    84         SkASSERT(NULL == fTail);
    85         fTail = strike;
    86     }
    87     strike->fPrev = NULL;
    88     strike->fNext = fHead;
    89     fHead = strike;
    91     return strike;
    92 }
    94 void GrFontCache::freeAll() {
    95     fCache.deleteAll();
    96     for (int i = 0; i < kAtlasCount; ++i) {
    97         delete fAtlasMgr[i];
    98         fAtlasMgr[i] = NULL;
    99     }
   100     fHead = NULL;
   101     fTail = NULL;
   102 }
   104 void GrFontCache::purgeStrike(GrTextStrike* strike) {
   105     const GrFontCache::Key key(strike->fFontScalerKey);
   106     fCache.remove(key, strike);
   107     this->detachStrikeFromList(strike);
   108     delete strike;
   109 }
   111 bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) {
   112     SkASSERT(NULL != preserveStrike);
   114     GrAtlasMgr* atlasMgr = preserveStrike->fAtlasMgr;
   115     GrPlot* plot = atlasMgr->getUnusedPlot();
   116     if (NULL == plot) {
   117         return false;
   118     }
   119     plot->resetRects();
   121     GrTextStrike* strike = fHead;
   122     GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
   123     while (strike) {
   124         if (maskFormat != strike->fMaskFormat) {
   125             strike = strike->fNext;
   126             continue;
   127         }
   129         GrTextStrike* strikeToPurge = strike;
   130         strike = strikeToPurge->fNext;
   131         strikeToPurge->removePlot(plot);
   133         // clear out any empty strikes (except this one)
   134         if (strikeToPurge != preserveStrike && strikeToPurge->fAtlas.isEmpty()) {
   135             this->purgeStrike(strikeToPurge);
   136         }
   137     }
   139 #if FONT_CACHE_STATS
   140     ++g_PurgeCount;
   141 #endif
   143     return true;
   144 }
   146 #ifdef SK_DEBUG
   147 void GrFontCache::validate() const {
   148     int count = fCache.count();
   149     if (0 == count) {
   150         SkASSERT(!fHead);
   151         SkASSERT(!fTail);
   152     } else if (1 == count) {
   153         SkASSERT(fHead == fTail);
   154     } else {
   155         SkASSERT(fHead != fTail);
   156     }
   158     int count2 = 0;
   159     const GrTextStrike* strike = fHead;
   160     while (strike) {
   161         count2 += 1;
   162         strike = strike->fNext;
   163     }
   164     SkASSERT(count == count2);
   166     count2 = 0;
   167     strike = fTail;
   168     while (strike) {
   169         count2 += 1;
   170         strike = strike->fPrev;
   171     }
   172     SkASSERT(count == count2);
   173 }
   174 #endif
   176 #ifdef SK_DEVELOPER
   177 void GrFontCache::dump() const {
   178     static int gDumpCount = 0;
   179     for (int i = 0; i < kAtlasCount; ++i) {
   180         if (NULL != fAtlasMgr[i]) {
   181             GrTexture* texture = fAtlasMgr[i]->getTexture();
   182             if (NULL != texture) {
   183                 SkString filename;
   184                 filename.printf("fontcache_%d%d.png", gDumpCount, i);
   185                 texture->savePixels(filename.c_str());
   186             }
   187         }
   188     }
   189     ++gDumpCount;
   190 }
   191 #endif
   193 ///////////////////////////////////////////////////////////////////////////////
   195 #ifdef SK_DEBUG
   196     static int gCounter;
   197 #endif
   199 // this acts as the max magnitude for the distance field,
   200 // as well as the pad we need around the glyph
   201 #define DISTANCE_FIELD_RANGE   4
   203 /*
   204     The text strike is specific to a given font/style/matrix setup, which is
   205     represented by the GrHostFontScaler object we are given in getGlyph().
   207     We map a 32bit glyphID to a GrGlyph record, which in turn points to a
   208     atlas and a position within that texture.
   209  */
   211 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
   212                            GrMaskFormat format,
   213                            GrAtlasMgr* atlasMgr) : fPool(64) {
   214     fFontScalerKey = key;
   215     fFontScalerKey->ref();
   217     fFontCache = cache;     // no need to ref, it won't go away before we do
   218     fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
   220     fMaskFormat = format;
   222 #ifdef SK_DEBUG
   223 //    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
   224     gCounter += 1;
   225 #endif
   226 }
   228 // this signature is needed because it's used with
   229 // SkTDArray::visitAll() (see destructor)
   230 static void free_glyph(GrGlyph*& glyph) { glyph->free(); }
   232 GrTextStrike::~GrTextStrike() {
   233     fFontScalerKey->unref();
   234     fCache.getArray().visitAll(free_glyph);
   236 #ifdef SK_DEBUG
   237     gCounter -= 1;
   238 //    GrPrintf("~GrTextStrike %p %d\n", this, gCounter);
   239 #endif
   240 }
   242 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
   243                                      GrFontScaler* scaler) {
   244     SkIRect bounds;
   245     if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
   246         return NULL;
   247     }
   249     GrGlyph* glyph = fPool.alloc();
   250     // expand bounds to hold full distance field data
   251     if (fUseDistanceField) {
   252         bounds.fLeft   -= DISTANCE_FIELD_RANGE;
   253         bounds.fRight  += DISTANCE_FIELD_RANGE;
   254         bounds.fTop    -= DISTANCE_FIELD_RANGE;
   255         bounds.fBottom += DISTANCE_FIELD_RANGE;
   256     }
   257     glyph->init(packed, bounds);
   258     fCache.insert(packed, glyph);
   259     return glyph;
   260 }
   262 void GrTextStrike::removePlot(const GrPlot* plot) {
   263     SkTDArray<GrGlyph*>& glyphArray = fCache.getArray();
   264     for (int i = 0; i < glyphArray.count(); ++i) {
   265         if (plot == glyphArray[i]->fPlot) {
   266             glyphArray[i]->fPlot = NULL;
   267         }
   268     }
   270     fAtlasMgr->removePlot(&fAtlas, plot);
   271 }
   274 bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
   275 #if 0   // testing hack to force us to flush our cache often
   276     static int gCounter;
   277     if ((++gCounter % 10) == 0) return false;
   278 #endif
   280     SkASSERT(glyph);
   281     SkASSERT(scaler);
   282     SkASSERT(fCache.contains(glyph));
   283     SkASSERT(NULL == glyph->fPlot);
   285     SkAutoRef ar(scaler);
   287     int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
   289     GrPlot* plot;
   290     if (fUseDistanceField) {
   291         // we've already expanded the glyph dimensions to match the final size
   292         // but must shrink back down to get the packed glyph data
   293         int dfWidth = glyph->width();
   294         int dfHeight = glyph->height();
   295         int width = dfWidth - 2*DISTANCE_FIELD_RANGE;
   296         int height = dfHeight - 2*DISTANCE_FIELD_RANGE;
   297         int stride = width*bytesPerPixel;
   299         size_t size = width * height * bytesPerPixel;
   300         SkAutoSMalloc<1024> storage(size);
   301         if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride, storage.get())) {
   302             return false;
   303         }
   305         // alloc storage for distance field glyph
   306         size_t dfSize = dfWidth * dfHeight * bytesPerPixel;
   307         SkAutoSMalloc<1024> dfStorage(dfSize);
   309         if (1 == bytesPerPixel) {
   310             (void) SkGenerateDistanceFieldFromImage((unsigned char*)dfStorage.get(),
   311                                                     (unsigned char*)storage.get(),
   312                                                     width, height, DISTANCE_FIELD_RANGE);
   313         } else {
   314             // TODO: Fix color emoji
   315             // for now, copy glyph into distance field storage
   316             // this is not correct, but it won't crash
   317             sk_bzero(dfStorage.get(), dfSize);
   318             unsigned char* ptr = (unsigned char*) storage.get();
   319             unsigned char* dfPtr = (unsigned char*) dfStorage.get();
   320             size_t dfStride = dfWidth*bytesPerPixel;
   321             dfPtr += DISTANCE_FIELD_RANGE*dfStride;
   322             dfPtr += DISTANCE_FIELD_RANGE*bytesPerPixel;
   324             for (int i = 0; i < height; ++i) {
   325                 memcpy(dfPtr, ptr, stride);
   327                 dfPtr += dfStride;
   328                 ptr += stride;
   329             }
   330         }
   332         // copy to atlas
   333         plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get(),
   334                                      &glyph->fAtlasLocation);
   336     } else {
   337         size_t size = glyph->fBounds.area() * bytesPerPixel;
   338         SkAutoSMalloc<1024> storage(size);
   339         if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
   340                                          glyph->height(),
   341                                          glyph->width() * bytesPerPixel,
   342                                          storage.get())) {
   343             return false;
   344         }
   346         plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
   347                                      glyph->height(), storage.get(),
   348                                      &glyph->fAtlasLocation);
   349     }
   351     if (NULL == plot) {
   352         return false;
   353     }
   355     glyph->fPlot = plot;
   356     return true;
   357 }

mercurial