LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/text - GrAtlasTextBlob.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 289 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 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             :  */
       7             : 
       8             : #include "GrAtlasTextBlob.h"
       9             : #include "GrBlurUtils.h"
      10             : #include "GrContext.h"
      11             : #include "GrPipelineBuilder.h"
      12             : #include "GrRenderTargetContext.h"
      13             : #include "GrTextUtils.h"
      14             : #include "SkColorFilter.h"
      15             : #include "SkDrawFilter.h"
      16             : #include "SkGlyphCache.h"
      17             : #include "SkTextBlobRunIterator.h"
      18             : #include "ops/GrAtlasTextOp.h"
      19             : 
      20           0 : sk_sp<GrAtlasTextBlob> GrAtlasTextBlob::Make(GrMemoryPool* pool, int glyphCount, int runCount) {
      21             :     // We allocate size for the GrAtlasTextBlob itself, plus size for the vertices array,
      22             :     // and size for the glyphIds array.
      23           0 :     size_t verticesCount = glyphCount * kVerticesPerGlyph * kMaxVASize;
      24             :     size_t size = sizeof(GrAtlasTextBlob) +
      25             :                   verticesCount +
      26           0 :                   glyphCount * sizeof(GrGlyph**) +
      27           0 :                   sizeof(GrAtlasTextBlob::Run) * runCount;
      28             : 
      29           0 :     void* allocation = pool->allocate(size);
      30             :     if (CACHE_SANITY_CHECK) {
      31             :         sk_bzero(allocation, size);
      32             :     }
      33             : 
      34           0 :     sk_sp<GrAtlasTextBlob> cacheBlob(new (allocation) GrAtlasTextBlob);
      35           0 :     cacheBlob->fSize = size;
      36             : 
      37             :     // setup offsets for vertices / glyphs
      38           0 :     cacheBlob->fVertices = sizeof(GrAtlasTextBlob) +
      39           0 :                            reinterpret_cast<unsigned char*>(cacheBlob.get());
      40           0 :     cacheBlob->fGlyphs = reinterpret_cast<GrGlyph**>(cacheBlob->fVertices + verticesCount);
      41           0 :     cacheBlob->fRuns = reinterpret_cast<GrAtlasTextBlob::Run*>(cacheBlob->fGlyphs + glyphCount);
      42             : 
      43             :     // Initialize runs
      44           0 :     for (int i = 0; i < runCount; i++) {
      45           0 :         new (&cacheBlob->fRuns[i]) GrAtlasTextBlob::Run;
      46             :     }
      47           0 :     cacheBlob->fRunCount = runCount;
      48           0 :     cacheBlob->fPool = pool;
      49           0 :     return cacheBlob;
      50             : }
      51             : 
      52           0 : SkGlyphCache* GrAtlasTextBlob::setupCache(int runIndex,
      53             :                                           const SkSurfaceProps& props,
      54             :                                           uint32_t scalerContextFlags,
      55             :                                           const SkPaint& skPaint,
      56             :                                           const SkMatrix* viewMatrix) {
      57           0 :     GrAtlasTextBlob::Run* run = &fRuns[runIndex];
      58             : 
      59             :     // if we have an override descriptor for the run, then we should use that
      60           0 :     SkAutoDescriptor* desc = run->fOverrideDescriptor.get() ? run->fOverrideDescriptor.get() :
      61           0 :                                                               &run->fDescriptor;
      62           0 :     SkScalerContextEffects effects;
      63           0 :     skPaint.getScalerContextDescriptor(&effects, desc, props, scalerContextFlags, viewMatrix);
      64           0 :     run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
      65           0 :     run->fPathEffect = sk_ref_sp(effects.fPathEffect);
      66           0 :     run->fRasterizer = sk_ref_sp(effects.fRasterizer);
      67           0 :     run->fMaskFilter = sk_ref_sp(effects.fMaskFilter);
      68           0 :     return SkGlyphCache::DetachCache(run->fTypeface.get(), effects, desc->getDesc());
      69             : }
      70             : 
      71           0 : void GrAtlasTextBlob::appendGlyph(int runIndex,
      72             :                                   const SkRect& positions,
      73             :                                   GrColor color,
      74             :                                   GrAtlasTextStrike* strike,
      75             :                                   GrGlyph* glyph,
      76             :                                   SkGlyphCache* cache, const SkGlyph& skGlyph,
      77             :                                   SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) {
      78           0 :     if (positions.isEmpty()) {
      79           0 :         return;
      80             :     }
      81             : 
      82             :     // If the glyph is too large we fall back to paths
      83           0 :     if (glyph->fTooLargeForAtlas) {
      84           0 :         this->appendLargeGlyph(glyph, cache, skGlyph, x, y, scale, treatAsBMP);
      85           0 :         return;
      86             :     }
      87             : 
      88           0 :     Run& run = fRuns[runIndex];
      89           0 :     GrMaskFormat format = glyph->fMaskFormat;
      90             : 
      91           0 :     Run::SubRunInfo* subRun = &run.fSubRunInfo.back();
      92           0 :     if (run.fInitialized && subRun->maskFormat() != format) {
      93           0 :         subRun = &run.push_back();
      94           0 :         subRun->setStrike(strike);
      95           0 :     } else if (!run.fInitialized) {
      96           0 :         subRun->setStrike(strike);
      97             :     }
      98             : 
      99           0 :     run.fInitialized = true;
     100             : 
     101           0 :     size_t vertexStride = GetVertexStride(format);
     102             : 
     103           0 :     subRun->setMaskFormat(format);
     104             : 
     105           0 :     subRun->joinGlyphBounds(positions);
     106           0 :     subRun->setColor(color);
     107             : 
     108           0 :     intptr_t vertex = reinterpret_cast<intptr_t>(this->fVertices + subRun->vertexEndIndex());
     109             : 
     110           0 :     if (kARGB_GrMaskFormat != glyph->fMaskFormat) {
     111             :         // V0
     112           0 :         SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
     113           0 :         position->set(positions.fLeft, positions.fTop);
     114           0 :         SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
     115           0 :         *colorPtr = color;
     116           0 :         vertex += vertexStride;
     117             : 
     118             :         // V1
     119           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     120           0 :         position->set(positions.fLeft, positions.fBottom);
     121           0 :         colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
     122           0 :         *colorPtr = color;
     123           0 :         vertex += vertexStride;
     124             : 
     125             :         // V2
     126           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     127           0 :         position->set(positions.fRight, positions.fBottom);
     128           0 :         colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
     129           0 :         *colorPtr = color;
     130           0 :         vertex += vertexStride;
     131             : 
     132             :         // V3
     133           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     134           0 :         position->set(positions.fRight, positions.fTop);
     135           0 :         colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
     136           0 :         *colorPtr = color;
     137             :     } else {
     138             :         // V0
     139           0 :         SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
     140           0 :         position->set(positions.fLeft, positions.fTop);
     141           0 :         vertex += vertexStride;
     142             : 
     143             :         // V1
     144           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     145           0 :         position->set(positions.fLeft, positions.fBottom);
     146           0 :         vertex += vertexStride;
     147             : 
     148             :         // V2
     149           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     150           0 :         position->set(positions.fRight, positions.fBottom);
     151           0 :         vertex += vertexStride;
     152             : 
     153             :         // V3
     154           0 :         position = reinterpret_cast<SkPoint*>(vertex);
     155           0 :         position->set(positions.fRight, positions.fTop);
     156             :     }
     157           0 :     subRun->appendVertices(vertexStride);
     158           0 :     fGlyphs[subRun->glyphEndIndex()] = glyph;
     159           0 :     subRun->glyphAppended();
     160             : }
     161             : 
     162           0 : void GrAtlasTextBlob::appendLargeGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph,
     163             :                                        SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) {
     164           0 :     if (nullptr == glyph->fPath) {
     165           0 :         const SkPath* glyphPath = cache->findPath(skGlyph);
     166           0 :         if (!glyphPath) {
     167           0 :             return;
     168             :         }
     169             : 
     170           0 :         glyph->fPath = new SkPath(*glyphPath);
     171             :     }
     172           0 :     fBigGlyphs.push_back(GrAtlasTextBlob::BigGlyph(*glyph->fPath, x, y, scale, treatAsBMP));
     173             : }
     174             : 
     175           0 : bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint,
     176             :                                      const SkMaskFilter::BlurRec& blurRec,
     177             :                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
     178             :     // If we have LCD text then our canonical color will be set to transparent, in this case we have
     179             :     // to regenerate the blob on any color change
     180             :     // We use the grPaint to get any color filter effects
     181           0 :     if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
     182           0 :         fFilteredPaintColor != paint.filteredSkColor()) {
     183           0 :         return true;
     184             :     }
     185             : 
     186           0 :     if (fInitialViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
     187           0 :         return true;
     188             :     }
     189             : 
     190           0 :     if (fInitialViewMatrix.hasPerspective() && !fInitialViewMatrix.cheapEqualTo(viewMatrix)) {
     191           0 :         return true;
     192             :     }
     193             : 
     194             :     // We only cache one masked version
     195           0 :     if (fKey.fHasBlur &&
     196           0 :         (fBlurRec.fSigma != blurRec.fSigma ||
     197           0 :          fBlurRec.fStyle != blurRec.fStyle ||
     198           0 :          fBlurRec.fQuality != blurRec.fQuality)) {
     199           0 :         return true;
     200             :     }
     201             : 
     202             :     // Similarly, we only cache one version for each style
     203           0 :     if (fKey.fStyle != SkPaint::kFill_Style &&
     204           0 :         (fStrokeInfo.fFrameWidth != paint.skPaint().getStrokeWidth() ||
     205           0 :          fStrokeInfo.fMiterLimit != paint.skPaint().getStrokeMiter() ||
     206           0 :          fStrokeInfo.fJoin != paint.skPaint().getStrokeJoin())) {
     207           0 :         return true;
     208             :     }
     209             : 
     210             :     // Mixed blobs must be regenerated.  We could probably figure out a way to do integer scrolls
     211             :     // for mixed blobs if this becomes an issue.
     212           0 :     if (this->hasBitmap() && this->hasDistanceField()) {
     213             :         // Identical viewmatrices and we can reuse in all cases
     214           0 :         if (fInitialViewMatrix.cheapEqualTo(viewMatrix) && x == fInitialX && y == fInitialY) {
     215           0 :             return false;
     216             :         }
     217           0 :         return true;
     218             :     }
     219             : 
     220           0 :     if (this->hasBitmap()) {
     221           0 :         if (fInitialViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
     222           0 :             fInitialViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
     223           0 :             fInitialViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
     224           0 :             fInitialViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
     225           0 :             return true;
     226             :         }
     227             : 
     228             :         // We can update the positions in the cachedtextblobs without regenerating the whole blob,
     229             :         // but only for integer translations.
     230             :         // This cool bit of math will determine the necessary translation to apply to the already
     231             :         // generated vertex coordinates to move them to the correct position
     232           0 :         SkScalar transX = viewMatrix.getTranslateX() +
     233           0 :                           viewMatrix.getScaleX() * (x - fInitialX) +
     234           0 :                           viewMatrix.getSkewX() * (y - fInitialY) -
     235           0 :                           fInitialViewMatrix.getTranslateX();
     236           0 :         SkScalar transY = viewMatrix.getTranslateY() +
     237           0 :                           viewMatrix.getSkewY() * (x - fInitialX) +
     238           0 :                           viewMatrix.getScaleY() * (y - fInitialY) -
     239           0 :                           fInitialViewMatrix.getTranslateY();
     240           0 :         if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) {
     241           0 :             return true;
     242             :         }
     243           0 :     } else if (this->hasDistanceField()) {
     244             :         // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
     245             :         // distance field being generated, so we have to regenerate in those cases
     246           0 :         SkScalar newMaxScale = viewMatrix.getMaxScale();
     247           0 :         SkScalar oldMaxScale = fInitialViewMatrix.getMaxScale();
     248           0 :         SkScalar scaleAdjust = newMaxScale / oldMaxScale;
     249           0 :         if (scaleAdjust < fMaxMinScale || scaleAdjust > fMinMaxScale) {
     250           0 :             return true;
     251             :         }
     252             :     }
     253             : 
     254             :     // It is possible that a blob has neither distanceField nor bitmaptext.  This is in the case
     255             :     // when all of the runs inside the blob are drawn as paths.  In this case, we always regenerate
     256             :     // the blob anyways at flush time, so no need to regenerate explicitly
     257           0 :     return false;
     258             : }
     259             : 
     260           0 : inline std::unique_ptr<GrLegacyMeshDrawOp> GrAtlasTextBlob::makeOp(
     261             :         const Run::SubRunInfo& info, int glyphCount, int run, int subRun,
     262             :         const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint& paint,
     263             :         const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable,
     264             :         bool useGammaCorrectDistanceTable, GrAtlasGlyphCache* cache) {
     265           0 :     GrMaskFormat format = info.maskFormat();
     266             : 
     267           0 :     std::unique_ptr<GrAtlasTextOp> op;
     268           0 :     if (info.drawAsDistanceFields()) {
     269           0 :         SkColor filteredColor = paint.filteredSkColor();
     270           0 :         bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
     271           0 :         op = GrAtlasTextOp::MakeDistanceField(glyphCount, cache, distanceAdjustTable,
     272             :                                               useGammaCorrectDistanceTable, filteredColor,
     273           0 :                                               info.hasUseLCDText(), useBGR);
     274             :     } else {
     275           0 :         op = GrAtlasTextOp::MakeBitmap(format, glyphCount, cache);
     276             :     }
     277           0 :     GrAtlasTextOp::Geometry& geometry = op->geometry();
     278           0 :     geometry.fViewMatrix = viewMatrix;
     279           0 :     geometry.fBlob = SkRef(this);
     280           0 :     geometry.fRun = run;
     281           0 :     geometry.fSubRun = subRun;
     282           0 :     geometry.fColor =
     283           0 :             info.maskFormat() == kARGB_GrMaskFormat ? GrColor_WHITE : paint.filteredPremulGrColor();
     284           0 :     geometry.fX = x;
     285           0 :     geometry.fY = y;
     286           0 :     op->init();
     287             : 
     288           0 :     return std::move(op);
     289             : }
     290             : 
     291           0 : inline void GrAtlasTextBlob::flushRun(GrRenderTargetContext* rtc, const GrClip& clip, int run,
     292             :                                       const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     293             :                                       const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
     294             :                                       const GrDistanceFieldAdjustTable* distanceAdjustTable,
     295             :                                       GrAtlasGlyphCache* cache) {
     296           0 :     int lastRun = fRuns[run].fSubRunInfo.count() - 1;
     297           0 :     for (int subRun = 0; subRun <= lastRun; subRun++) {
     298           0 :         const Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
     299           0 :         GrPaint grPaint;
     300           0 :         if (!paint.toGrPaint(info.maskFormat(), rtc, viewMatrix, &grPaint)) {
     301           0 :             continue;
     302             :         }
     303           0 :         int glyphCount = info.glyphCount();
     304           0 :         if (0 == glyphCount) {
     305           0 :             continue;
     306             :         }
     307             : 
     308             :         std::unique_ptr<GrLegacyMeshDrawOp> op(
     309             :                 this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, paint, props,
     310           0 :                              distanceAdjustTable, rtc->isGammaCorrect(), cache));
     311           0 :         GrPipelineBuilder pipelineBuilder(std::move(grPaint), GrAAType::kNone);
     312             : 
     313           0 :         rtc->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
     314             :     }
     315           0 : }
     316             : 
     317           0 : static void calculate_translation(bool applyVM,
     318             :                                   const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY,
     319             :                                   const SkMatrix& currentViewMatrix, SkScalar currentX,
     320             :                                   SkScalar currentY, SkScalar* transX, SkScalar* transY) {
     321           0 :     if (applyVM) {
     322           0 :         *transX = newViewMatrix.getTranslateX() +
     323           0 :                   newViewMatrix.getScaleX() * (newX - currentX) +
     324           0 :                   newViewMatrix.getSkewX() * (newY - currentY) -
     325           0 :                   currentViewMatrix.getTranslateX();
     326             : 
     327           0 :         *transY = newViewMatrix.getTranslateY() +
     328           0 :                   newViewMatrix.getSkewY() * (newX - currentX) +
     329           0 :                   newViewMatrix.getScaleY() * (newY - currentY) -
     330           0 :                   currentViewMatrix.getTranslateY();
     331             :     } else {
     332           0 :         *transX = newX - currentX;
     333           0 :         *transY = newY - currentY;
     334             :     }
     335           0 : }
     336             : 
     337           0 : void GrAtlasTextBlob::flushBigGlyphs(GrContext* context, GrRenderTargetContext* rtc,
     338             :                                      const GrClip& clip, const SkPaint& paint,
     339             :                                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     340             :                                      const SkIRect& clipBounds) {
     341             :     SkScalar transX, transY;
     342           0 :     for (int i = 0; i < fBigGlyphs.count(); i++) {
     343           0 :         GrAtlasTextBlob::BigGlyph& bigGlyph = fBigGlyphs[i];
     344           0 :         calculate_translation(bigGlyph.fTreatAsBMP, viewMatrix, x, y,
     345           0 :                               fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY);
     346             :         SkMatrix ctm;
     347           0 :         ctm.setScale(bigGlyph.fScale, bigGlyph.fScale);
     348           0 :         ctm.postTranslate(bigGlyph.fX + transX, bigGlyph.fY + transY);
     349           0 :         if (!bigGlyph.fTreatAsBMP) {
     350           0 :             ctm.postConcat(viewMatrix);
     351             :         }
     352             : 
     353           0 :         GrBlurUtils::drawPathWithMaskFilter(context, rtc, clip, bigGlyph.fPath, paint, ctm, nullptr,
     354           0 :                                             clipBounds, false);
     355             :     }
     356           0 : }
     357             : 
     358           0 : void GrAtlasTextBlob::flushRunAsPaths(GrContext* context, GrRenderTargetContext* rtc,
     359             :                                       const SkSurfaceProps& props, const SkTextBlobRunIterator& it,
     360             :                                       const GrClip& clip, const GrTextUtils::Paint& paint,
     361             :                                       SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
     362             :                                       const SkIRect& clipBounds, SkScalar x, SkScalar y) {
     363           0 :     size_t textLen = it.glyphCount() * sizeof(uint16_t);
     364           0 :     const SkPoint& offset = it.offset();
     365             : 
     366           0 :     GrTextUtils::RunPaint runPaint(&paint, drawFilter, props);
     367           0 :     if (!runPaint.modifyForRun(it)) {
     368           0 :         return;
     369             :     }
     370             : 
     371           0 :     switch (it.positioning()) {
     372             :         case SkTextBlob::kDefault_Positioning:
     373           0 :             GrTextUtils::DrawTextAsPath(context, rtc, clip, runPaint, viewMatrix,
     374           0 :                                         (const char*)it.glyphs(), textLen, x + offset.x(),
     375           0 :                                         y + offset.y(), clipBounds);
     376           0 :             break;
     377             :         case SkTextBlob::kHorizontal_Positioning:
     378           0 :             GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
     379           0 :                                            (const char*)it.glyphs(), textLen, it.pos(), 1,
     380           0 :                                            SkPoint::Make(x, y + offset.y()), clipBounds);
     381           0 :             break;
     382             :         case SkTextBlob::kFull_Positioning:
     383           0 :             GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, runPaint, viewMatrix,
     384           0 :                                            (const char*)it.glyphs(), textLen, it.pos(), 2,
     385           0 :                                            SkPoint::Make(x, y), clipBounds);
     386           0 :             break;
     387             :     }
     388             : }
     389             : 
     390           0 : void GrAtlasTextBlob::flushCached(GrContext* context, GrRenderTargetContext* rtc,
     391             :                                   const SkTextBlob* blob, const SkSurfaceProps& props,
     392             :                                   const GrDistanceFieldAdjustTable* distanceAdjustTable,
     393             :                                   const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter,
     394             :                                   const GrClip& clip, const SkMatrix& viewMatrix,
     395             :                                   const SkIRect& clipBounds, SkScalar x, SkScalar y) {
     396             :     // We loop through the runs of the blob, flushing each.  If any run is too large, then we flush
     397             :     // it as paths
     398           0 :     SkTextBlobRunIterator it(blob);
     399           0 :     for (int run = 0; !it.done(); it.next(), run++) {
     400           0 :         if (fRuns[run].fDrawAsPaths) {
     401             :             this->flushRunAsPaths(context, rtc, props, it, clip, paint, drawFilter, viewMatrix,
     402           0 :                                   clipBounds, x, y);
     403           0 :             continue;
     404             :         }
     405           0 :         this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
     406           0 :                        context->getAtlasGlyphCache());
     407             :     }
     408             : 
     409             :     // Now flush big glyphs
     410           0 :     this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
     411           0 : }
     412             : 
     413           0 : void GrAtlasTextBlob::flushThrowaway(GrContext* context, GrRenderTargetContext* rtc,
     414             :                                      const SkSurfaceProps& props,
     415             :                                      const GrDistanceFieldAdjustTable* distanceAdjustTable,
     416             :                                      const GrTextUtils::Paint& paint, const GrClip& clip,
     417             :                                      const SkMatrix& viewMatrix, const SkIRect& clipBounds,
     418             :                                      SkScalar x, SkScalar y) {
     419           0 :     for (int run = 0; run < fRunCount; run++) {
     420           0 :         this->flushRun(rtc, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable,
     421           0 :                        context->getAtlasGlyphCache());
     422             :     }
     423             : 
     424             :     // Now flush big glyphs
     425           0 :     this->flushBigGlyphs(context, rtc, clip, paint, viewMatrix, x, y, clipBounds);
     426           0 : }
     427             : 
     428           0 : std::unique_ptr<GrLegacyMeshDrawOp> GrAtlasTextBlob::test_makeOp(
     429             :         int glyphCount, int run, int subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
     430             :         const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
     431             :         const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache) {
     432           0 :     const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
     433             :     return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, paint, props,
     434           0 :                         distanceAdjustTable, false, cache);
     435             : }
     436             : 
     437           0 : void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) {
     438           0 :     SkASSERT_RELEASE(l.fSize == r.fSize);
     439           0 :     SkASSERT_RELEASE(l.fPool == r.fPool);
     440             : 
     441           0 :     SkASSERT_RELEASE(l.fBlurRec.fSigma == r.fBlurRec.fSigma);
     442           0 :     SkASSERT_RELEASE(l.fBlurRec.fStyle == r.fBlurRec.fStyle);
     443           0 :     SkASSERT_RELEASE(l.fBlurRec.fQuality == r.fBlurRec.fQuality);
     444             : 
     445           0 :     SkASSERT_RELEASE(l.fStrokeInfo.fFrameWidth == r.fStrokeInfo.fFrameWidth);
     446           0 :     SkASSERT_RELEASE(l.fStrokeInfo.fMiterLimit == r.fStrokeInfo.fMiterLimit);
     447           0 :     SkASSERT_RELEASE(l.fStrokeInfo.fJoin == r.fStrokeInfo.fJoin);
     448             : 
     449           0 :     SkASSERT_RELEASE(l.fBigGlyphs.count() == r.fBigGlyphs.count());
     450           0 :     for (int i = 0; i < l.fBigGlyphs.count(); i++) {
     451           0 :         const BigGlyph& lBigGlyph = l.fBigGlyphs[i];
     452           0 :         const BigGlyph& rBigGlyph = r.fBigGlyphs[i];
     453             : 
     454           0 :         SkASSERT_RELEASE(lBigGlyph.fPath == rBigGlyph.fPath);
     455             :         // We can't assert that these have the same translations
     456             :     }
     457             : 
     458           0 :     SkASSERT_RELEASE(l.fKey == r.fKey);
     459             :     //SkASSERT_RELEASE(l.fPaintColor == r.fPaintColor); // Colors might not actually be identical
     460           0 :     SkASSERT_RELEASE(l.fMaxMinScale == r.fMaxMinScale);
     461           0 :     SkASSERT_RELEASE(l.fMinMaxScale == r.fMinMaxScale);
     462           0 :     SkASSERT_RELEASE(l.fTextType == r.fTextType);
     463             : 
     464           0 :     SkASSERT_RELEASE(l.fRunCount == r.fRunCount);
     465           0 :     for (int i = 0; i < l.fRunCount; i++) {
     466           0 :         const Run& lRun = l.fRuns[i];
     467           0 :         const Run& rRun = r.fRuns[i];
     468             : 
     469           0 :         if (lRun.fTypeface.get()) {
     470           0 :             SkASSERT_RELEASE(rRun.fTypeface.get());
     471           0 :             SkASSERT_RELEASE(SkTypeface::Equal(lRun.fTypeface.get(), rRun.fTypeface.get()));
     472             :         } else {
     473           0 :             SkASSERT_RELEASE(!rRun.fTypeface.get());
     474             :         }
     475             : 
     476             : 
     477           0 :         SkASSERT_RELEASE(lRun.fDescriptor.getDesc());
     478           0 :         SkASSERT_RELEASE(rRun.fDescriptor.getDesc());
     479           0 :         SkASSERT_RELEASE(*lRun.fDescriptor.getDesc() == *rRun.fDescriptor.getDesc());
     480             : 
     481           0 :         if (lRun.fOverrideDescriptor.get()) {
     482           0 :             SkASSERT_RELEASE(lRun.fOverrideDescriptor->getDesc());
     483           0 :             SkASSERT_RELEASE(rRun.fOverrideDescriptor.get() && rRun.fOverrideDescriptor->getDesc());
     484           0 :             SkASSERT_RELEASE(*lRun.fOverrideDescriptor->getDesc() ==
     485             :                              *rRun.fOverrideDescriptor->getDesc());
     486             :         } else {
     487           0 :             SkASSERT_RELEASE(!rRun.fOverrideDescriptor.get());
     488             :         }
     489             : 
     490             :         // color can be changed
     491             :         //SkASSERT(lRun.fColor == rRun.fColor);
     492           0 :         SkASSERT_RELEASE(lRun.fInitialized == rRun.fInitialized);
     493           0 :         SkASSERT_RELEASE(lRun.fDrawAsPaths == rRun.fDrawAsPaths);
     494             : 
     495           0 :         SkASSERT_RELEASE(lRun.fSubRunInfo.count() == rRun.fSubRunInfo.count());
     496           0 :         for(int j = 0; j < lRun.fSubRunInfo.count(); j++) {
     497           0 :             const Run::SubRunInfo& lSubRun = lRun.fSubRunInfo[j];
     498           0 :             const Run::SubRunInfo& rSubRun = rRun.fSubRunInfo[j];
     499             : 
     500             :             // TODO we can do this check, but we have to apply the VM to the old vertex bounds
     501             :             //SkASSERT_RELEASE(lSubRun.vertexBounds() == rSubRun.vertexBounds());
     502             : 
     503           0 :             if (lSubRun.strike()) {
     504           0 :                 SkASSERT_RELEASE(rSubRun.strike());
     505           0 :                 SkASSERT_RELEASE(GrAtlasTextStrike::GetKey(*lSubRun.strike()) ==
     506             :                                  GrAtlasTextStrike::GetKey(*rSubRun.strike()));
     507             : 
     508             :             } else {
     509           0 :                 SkASSERT_RELEASE(!rSubRun.strike());
     510             :             }
     511             : 
     512           0 :             SkASSERT_RELEASE(lSubRun.vertexStartIndex() == rSubRun.vertexStartIndex());
     513           0 :             SkASSERT_RELEASE(lSubRun.vertexEndIndex() == rSubRun.vertexEndIndex());
     514           0 :             SkASSERT_RELEASE(lSubRun.glyphStartIndex() == rSubRun.glyphStartIndex());
     515           0 :             SkASSERT_RELEASE(lSubRun.glyphEndIndex() == rSubRun.glyphEndIndex());
     516           0 :             SkASSERT_RELEASE(lSubRun.maskFormat() == rSubRun.maskFormat());
     517           0 :             SkASSERT_RELEASE(lSubRun.drawAsDistanceFields() == rSubRun.drawAsDistanceFields());
     518           0 :             SkASSERT_RELEASE(lSubRun.hasUseLCDText() == rSubRun.hasUseLCDText());
     519             :         }
     520             :     }
     521           0 : }
     522             : 
     523           0 : void GrAtlasTextBlob::Run::SubRunInfo::computeTranslation(const SkMatrix& viewMatrix,
     524             :                                                           SkScalar x, SkScalar y, SkScalar* transX,
     525             :                                                           SkScalar* transY) {
     526           0 :     calculate_translation(!this->drawAsDistanceFields(), viewMatrix, x, y,
     527           0 :                           fCurrentViewMatrix, fX, fY, transX, transY);
     528           0 :     fCurrentViewMatrix = viewMatrix;
     529           0 :     fX = x;
     530           0 :     fY = y;
     531           0 : }

Generated by: LCOV version 1.13