LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkDevice.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 46 260 17.7 %
Date: 2017-07-14 16:53:18 Functions: 10 38 26.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 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 "SkDevice.h"
       9             : #include "SkColorFilter.h"
      10             : #include "SkDraw.h"
      11             : #include "SkDrawFilter.h"
      12             : #include "SkImageCacherator.h"
      13             : #include "SkImageFilter.h"
      14             : #include "SkImageFilterCache.h"
      15             : #include "SkImagePriv.h"
      16             : #include "SkImage_Base.h"
      17             : #include "SkLatticeIter.h"
      18             : #include "SkPatchUtils.h"
      19             : #include "SkPathMeasure.h"
      20             : #include "SkPathPriv.h"
      21             : #include "SkRSXform.h"
      22             : #include "SkRasterClip.h"
      23             : #include "SkShader.h"
      24             : #include "SkSpecialImage.h"
      25             : #include "SkTLazy.h"
      26             : #include "SkTextBlobRunIterator.h"
      27             : #include "SkTextToPathIter.h"
      28             : #include "SkVertices.h"
      29             : 
      30          85 : SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
      31             :     : fInfo(info)
      32          85 :     , fSurfaceProps(surfaceProps)
      33             : {
      34          85 :     fOrigin.setZero();
      35          85 :     fCTM.reset();
      36          85 : }
      37             : 
      38          22 : void SkBaseDevice::setOrigin(const SkMatrix& globalCTM, int x, int y) {
      39          22 :     fOrigin.set(x, y);
      40          22 :     fCTM = globalCTM;
      41          22 :     fCTM.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
      42          22 : }
      43             : 
      44        2656 : void SkBaseDevice::setGlobalCTM(const SkMatrix& ctm) {
      45        2656 :     fCTM = ctm;
      46        2656 :     if (fOrigin.fX | fOrigin.fY) {
      47         207 :         fCTM.postTranslate(-SkIntToScalar(fOrigin.fX), -SkIntToScalar(fOrigin.fY));
      48             :     }
      49        2656 : }
      50             : 
      51           0 : bool SkBaseDevice::clipIsWideOpen() const {
      52           0 :     if (kRect_ClipType == this->onGetClipType()) {
      53           0 :         SkRegion rgn;
      54           0 :         this->onAsRgnClip(&rgn);
      55           0 :         SkASSERT(rgn.isRect());
      56           0 :         return rgn.getBounds() == SkIRect::MakeWH(this->width(), this->height());
      57             :     } else {
      58           0 :         return false;
      59             :     }
      60             : }
      61             : 
      62          22 : SkPixelGeometry SkBaseDevice::CreateInfo::AdjustGeometry(const SkImageInfo& info,
      63             :                                                          TileUsage tileUsage,
      64             :                                                          SkPixelGeometry geo,
      65             :                                                          bool preserveLCDText) {
      66          22 :     switch (tileUsage) {
      67             :         case kPossible_TileUsage:
      68             :             // (we think) for compatibility with old clients, we assume this layer can support LCD
      69             :             // even though they may not have marked it as opaque... seems like we should update
      70             :             // our callers (reed/robertphilips).
      71           0 :             break;
      72             :         case kNever_TileUsage:
      73          22 :             if (!preserveLCDText) {
      74           0 :                 geo = kUnknown_SkPixelGeometry;
      75             :             }
      76          22 :             break;
      77             :     }
      78          22 :     return geo;
      79             : }
      80             : 
      81           0 : static inline bool is_int(float x) {
      82           0 :     return x == (float) sk_float_round2int(x);
      83             : }
      84             : 
      85           0 : void SkBaseDevice::drawRegion(const SkRegion& region, const SkPaint& paint) {
      86           0 :     const SkMatrix& ctm = this->ctm();
      87           0 :     bool isNonTranslate = ctm.getType() & ~(SkMatrix::kTranslate_Mask);
      88           0 :     bool complexPaint = paint.getStyle() != SkPaint::kFill_Style || paint.getMaskFilter() ||
      89           0 :                         paint.getPathEffect();
      90           0 :     bool antiAlias = paint.isAntiAlias() && (!is_int(ctm.getTranslateX()) ||
      91           0 :                                              !is_int(ctm.getTranslateY()));
      92           0 :     if (isNonTranslate || complexPaint || antiAlias) {
      93           0 :         SkPath path;
      94           0 :         region.getBoundaryPath(&path);
      95           0 :         return this->drawPath(path, paint, nullptr, false);
      96             :     }
      97             : 
      98           0 :     SkRegion::Iterator it(region);
      99           0 :     while (!it.done()) {
     100           0 :         this->drawRect(SkRect::Make(it.rect()), paint);
     101           0 :         it.next();
     102             :     }
     103             : }
     104             : 
     105           0 : void SkBaseDevice::drawArc(const SkRect& oval, SkScalar startAngle,
     106             :                            SkScalar sweepAngle, bool useCenter, const SkPaint& paint) {
     107           0 :     SkPath path;
     108           0 :     bool isFillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect();
     109           0 :     SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
     110           0 :                                   isFillNoPathEffect);
     111           0 :     this->drawPath(path, paint);
     112           0 : }
     113             : 
     114           0 : void SkBaseDevice::drawDRRect(const SkRRect& outer,
     115             :                               const SkRRect& inner, const SkPaint& paint) {
     116           0 :     SkPath path;
     117           0 :     path.addRRect(outer);
     118           0 :     path.addRRect(inner);
     119           0 :     path.setFillType(SkPath::kEvenOdd_FillType);
     120           0 :     path.setIsVolatile(true);
     121             : 
     122           0 :     const SkMatrix* preMatrix = nullptr;
     123           0 :     const bool pathIsMutable = true;
     124           0 :     this->drawPath(path, paint, preMatrix, pathIsMutable);
     125           0 : }
     126             : 
     127           0 : void SkBaseDevice::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
     128             :                              const SkPoint texCoords[4], SkBlendMode bmode, const SkPaint& paint) {
     129           0 :     SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &this->ctm());
     130           0 :     auto vertices = SkPatchUtils::MakeVertices(cubics, colors, texCoords, lod.width(), lod.height());
     131           0 :     if (vertices) {
     132           0 :         this->drawVertices(vertices.get(), bmode, paint);
     133             :     }
     134           0 : }
     135             : 
     136           0 : void SkBaseDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
     137             :                                 const SkPaint &paint, SkDrawFilter* drawFilter) {
     138             : 
     139           0 :     SkPaint runPaint = paint;
     140             : 
     141           0 :     SkTextBlobRunIterator it(blob);
     142           0 :     for (;!it.done(); it.next()) {
     143           0 :         size_t textLen = it.glyphCount() * sizeof(uint16_t);
     144           0 :         const SkPoint& offset = it.offset();
     145             :         // applyFontToPaint() always overwrites the exact same attributes,
     146             :         // so it is safe to not re-seed the paint for this reason.
     147           0 :         it.applyFontToPaint(&runPaint);
     148             : 
     149           0 :         if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
     150             :             // A false return from filter() means we should abort the current draw.
     151           0 :             runPaint = paint;
     152           0 :             continue;
     153             :         }
     154             : 
     155           0 :         runPaint.setFlags(this->filterTextFlags(runPaint));
     156             : 
     157           0 :         switch (it.positioning()) {
     158             :         case SkTextBlob::kDefault_Positioning:
     159           0 :             this->drawText(it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint);
     160           0 :             break;
     161             :         case SkTextBlob::kHorizontal_Positioning:
     162           0 :             this->drawPosText(it.glyphs(), textLen, it.pos(), 1,
     163           0 :                               SkPoint::Make(x, y + offset.y()), runPaint);
     164           0 :             break;
     165             :         case SkTextBlob::kFull_Positioning:
     166           0 :             this->drawPosText(it.glyphs(), textLen, it.pos(), 2,
     167           0 :                               SkPoint::Make(x, y), runPaint);
     168           0 :             break;
     169             :         default:
     170           0 :             SkFAIL("unhandled positioning mode");
     171             :         }
     172             : 
     173           0 :         if (drawFilter) {
     174             :             // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
     175           0 :             runPaint = paint;
     176             :         }
     177             :     }
     178           0 : }
     179             : 
     180           4 : void SkBaseDevice::drawImage(const SkImage* image, SkScalar x, SkScalar y,
     181             :                              const SkPaint& paint) {
     182           8 :     SkBitmap bm;
     183           4 :     if (as_IB(image)->getROPixels(&bm, this->imageInfo().colorSpace())) {
     184           4 :         this->drawBitmap(bm, SkMatrix::MakeTrans(x, y), paint);
     185             :     }
     186           4 : }
     187             : 
     188         140 : void SkBaseDevice::drawImageRect(const SkImage* image, const SkRect* src,
     189             :                                  const SkRect& dst, const SkPaint& paint,
     190             :                                  SkCanvas::SrcRectConstraint constraint) {
     191         280 :     SkBitmap bm;
     192         140 :     if (as_IB(image)->getROPixels(&bm, this->imageInfo().colorSpace())) {
     193         140 :         this->drawBitmapRect(bm, src, dst, paint, constraint);
     194             :     }
     195         140 : }
     196             : 
     197           0 : void SkBaseDevice::drawImageNine(const SkImage* image, const SkIRect& center,
     198             :                                  const SkRect& dst, const SkPaint& paint) {
     199           0 :     SkLatticeIter iter(image->width(), image->height(), center, dst);
     200             : 
     201             :     SkRect srcR, dstR;
     202           0 :     while (iter.next(&srcR, &dstR)) {
     203           0 :         this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
     204             :     }
     205           0 : }
     206             : 
     207           0 : void SkBaseDevice::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
     208             :                                   const SkRect& dst, const SkPaint& paint) {
     209           0 :     SkLatticeIter iter(bitmap.width(), bitmap.height(), center, dst);
     210             : 
     211             :     SkRect srcR, dstR;
     212           0 :     while (iter.next(&srcR, &dstR)) {
     213           0 :         this->drawBitmapRect(bitmap, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
     214             :     }
     215           0 : }
     216             : 
     217           0 : void SkBaseDevice::drawImageLattice(const SkImage* image,
     218             :                                     const SkCanvas::Lattice& lattice, const SkRect& dst,
     219             :                                     const SkPaint& paint) {
     220           0 :     SkLatticeIter iter(lattice, dst);
     221             : 
     222             :     SkRect srcR, dstR;
     223           0 :     while (iter.next(&srcR, &dstR)) {
     224           0 :         this->drawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
     225             :     }
     226           0 : }
     227             : 
     228           0 : void SkBaseDevice::drawBitmapLattice(const SkBitmap& bitmap,
     229             :                                      const SkCanvas::Lattice& lattice, const SkRect& dst,
     230             :                                      const SkPaint& paint) {
     231           0 :     SkLatticeIter iter(lattice, dst);
     232             : 
     233             :     SkRect srcR, dstR;
     234           0 :     while (iter.next(&srcR, &dstR)) {
     235           0 :         this->drawBitmapRect(bitmap, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
     236             :     }
     237           0 : }
     238             : 
     239           0 : void SkBaseDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
     240             :                              const SkRect tex[], const SkColor colors[], int count,
     241             :                              SkBlendMode mode, const SkPaint& paint) {
     242           0 :     SkPath path;
     243           0 :     path.setIsVolatile(true);
     244             : 
     245           0 :     for (int i = 0; i < count; ++i) {
     246             :         SkPoint quad[4];
     247           0 :         xform[i].toQuad(tex[i].width(), tex[i].height(), quad);
     248             : 
     249             :         SkMatrix localM;
     250           0 :         localM.setRSXform(xform[i]);
     251           0 :         localM.preTranslate(-tex[i].left(), -tex[i].top());
     252             : 
     253           0 :         SkPaint pnt(paint);
     254             :         sk_sp<SkShader> shader = atlas->makeShader(SkShader::kClamp_TileMode,
     255             :                                                    SkShader::kClamp_TileMode,
     256           0 :                                                    &localM);
     257           0 :         if (!shader) {
     258           0 :             break;
     259             :         }
     260           0 :         pnt.setShader(std::move(shader));
     261             : 
     262           0 :         if (colors) {
     263           0 :             pnt.setColorFilter(SkColorFilter::MakeModeFilter(colors[i], (SkBlendMode)mode));
     264             :         }
     265             : 
     266           0 :         path.rewind();
     267           0 :         path.addPoly(quad, 4, true);
     268           0 :         path.setConvexity(SkPath::kConvex_Convexity);
     269           0 :         this->drawPath(path, pnt, nullptr, true);
     270             :     }
     271           0 : }
     272             : 
     273             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     274             : 
     275           0 : void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) {}
     276           0 : sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkBitmap&) { return nullptr; }
     277           0 : sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkImage*) { return nullptr; }
     278           0 : sk_sp<SkSpecialImage> SkBaseDevice::snapSpecial() { return nullptr; }
     279             : 
     280             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     281             : 
     282           0 : bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
     283           0 :     return this->onReadPixels(info, dstP, rowBytes, x, y);
     284             : }
     285             : 
     286           0 : bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
     287             :                                int x, int y) {
     288           0 :     return this->onWritePixels(info, pixels, rowBytes, x, y);
     289             : }
     290             : 
     291           0 : bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, int) {
     292           0 :     return false;
     293             : }
     294             : 
     295           0 : bool SkBaseDevice::onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) {
     296           0 :     return false;
     297             : }
     298             : 
     299         473 : bool SkBaseDevice::accessPixels(SkPixmap* pmap) {
     300         946 :     SkPixmap tempStorage;
     301         473 :     if (nullptr == pmap) {
     302           0 :         pmap = &tempStorage;
     303             :     }
     304         946 :     return this->onAccessPixels(pmap);
     305             : }
     306             : 
     307          40 : bool SkBaseDevice::peekPixels(SkPixmap* pmap) {
     308          80 :     SkPixmap tempStorage;
     309          40 :     if (nullptr == pmap) {
     310           0 :         pmap = &tempStorage;
     311             :     }
     312          80 :     return this->onPeekPixels(pmap);
     313             : }
     314             : 
     315             : //////////////////////////////////////////////////////////////////////////////////////////
     316             : 
     317           0 : static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
     318             :                         SkPathMeasure& meas, const SkMatrix& matrix) {
     319           0 :     SkMatrix::MapXYProc proc = matrix.getMapXYProc();
     320             : 
     321           0 :     for (int i = 0; i < count; i++) {
     322             :         SkPoint pos;
     323             :         SkVector tangent;
     324             : 
     325           0 :         proc(matrix, src[i].fX, src[i].fY, &pos);
     326           0 :         SkScalar sx = pos.fX;
     327           0 :         SkScalar sy = pos.fY;
     328             : 
     329           0 :         if (!meas.getPosTan(sx, &pos, &tangent)) {
     330             :             // set to 0 if the measure failed, so that we just set dst == pos
     331           0 :             tangent.set(0, 0);
     332             :         }
     333             : 
     334             :         /*  This is the old way (that explains our approach but is way too slow
     335             :          SkMatrix    matrix;
     336             :          SkPoint     pt;
     337             : 
     338             :          pt.set(sx, sy);
     339             :          matrix.setSinCos(tangent.fY, tangent.fX);
     340             :          matrix.preTranslate(-sx, 0);
     341             :          matrix.postTranslate(pos.fX, pos.fY);
     342             :          matrix.mapPoints(&dst[i], &pt, 1);
     343             :          */
     344           0 :         dst[i].set(pos.fX - tangent.fY * sy, pos.fY + tangent.fX * sy);
     345             :     }
     346           0 : }
     347             : 
     348             : /*  TODO
     349             : 
     350             :  Need differentially more subdivisions when the follow-path is curvy. Not sure how to
     351             :  determine that, but we need it. I guess a cheap answer is let the caller tell us,
     352             :  but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
     353             :  */
     354           0 : static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
     355             :                       const SkMatrix& matrix) {
     356           0 :     SkPath::Iter    iter(src, false);
     357             :     SkPoint         srcP[4], dstP[3];
     358             :     SkPath::Verb    verb;
     359             : 
     360           0 :     while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
     361           0 :         switch (verb) {
     362             :             case SkPath::kMove_Verb:
     363           0 :                 morphpoints(dstP, srcP, 1, meas, matrix);
     364           0 :                 dst->moveTo(dstP[0]);
     365           0 :                 break;
     366             :             case SkPath::kLine_Verb:
     367             :                 // turn lines into quads to look bendy
     368           0 :                 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
     369           0 :                 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
     370           0 :                 morphpoints(dstP, srcP, 2, meas, matrix);
     371           0 :                 dst->quadTo(dstP[0], dstP[1]);
     372           0 :                 break;
     373             :             case SkPath::kQuad_Verb:
     374           0 :                 morphpoints(dstP, &srcP[1], 2, meas, matrix);
     375           0 :                 dst->quadTo(dstP[0], dstP[1]);
     376           0 :                 break;
     377             :             case SkPath::kCubic_Verb:
     378           0 :                 morphpoints(dstP, &srcP[1], 3, meas, matrix);
     379           0 :                 dst->cubicTo(dstP[0], dstP[1], dstP[2]);
     380           0 :                 break;
     381             :             case SkPath::kClose_Verb:
     382           0 :                 dst->close();
     383           0 :                 break;
     384             :             default:
     385           0 :                 SkDEBUGFAIL("unknown verb");
     386           0 :                 break;
     387             :         }
     388             :     }
     389           0 : }
     390             : 
     391           0 : void SkBaseDevice::drawTextOnPath(const void* text, size_t byteLength,
     392             :                                   const SkPath& follow, const SkMatrix* matrix,
     393             :                                   const SkPaint& paint) {
     394           0 :     SkASSERT(byteLength == 0 || text != nullptr);
     395             : 
     396             :     // nothing to draw
     397           0 :     if (text == nullptr || byteLength == 0) {
     398           0 :         return;
     399             :     }
     400             : 
     401           0 :     SkTextToPathIter    iter((const char*)text, byteLength, paint, true);
     402           0 :     SkPathMeasure       meas(follow, false);
     403           0 :     SkScalar            hOffset = 0;
     404             : 
     405             :     // need to measure first
     406           0 :     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
     407           0 :         SkScalar pathLen = meas.getLength();
     408           0 :         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
     409           0 :             pathLen = SkScalarHalf(pathLen);
     410             :         }
     411           0 :         hOffset += pathLen;
     412             :     }
     413             : 
     414             :     const SkPath*   iterPath;
     415             :     SkScalar        xpos;
     416             :     SkMatrix        scaledMatrix;
     417           0 :     SkScalar        scale = iter.getPathScale();
     418             : 
     419           0 :     scaledMatrix.setScale(scale, scale);
     420             : 
     421           0 :     while (iter.next(&iterPath, &xpos)) {
     422           0 :         if (iterPath) {
     423           0 :             SkPath      tmp;
     424           0 :             SkMatrix    m(scaledMatrix);
     425             : 
     426           0 :             tmp.setIsVolatile(true);
     427           0 :             m.postTranslate(xpos + hOffset, 0);
     428           0 :             if (matrix) {
     429           0 :                 m.postConcat(*matrix);
     430             :             }
     431           0 :             morphpath(&tmp, *iterPath, meas, m);
     432           0 :             this->drawPath(tmp, iter.getPaint(), nullptr, true);
     433             :         }
     434             :     }
     435             : }
     436             : 
     437             : #include "SkUtils.h"
     438             : typedef int (*CountTextProc)(const char* text);
     439           0 : static int count_utf16(const char* text) {
     440           0 :     const uint16_t* prev = (uint16_t*)text;
     441           0 :     (void)SkUTF16_NextUnichar(&prev);
     442           0 :     return SkToInt((const char*)prev - text);
     443             : }
     444           0 : static int return_4(const char* text) { return 4; }
     445           0 : static int return_2(const char* text) { return 2; }
     446             : 
     447           0 : void SkBaseDevice::drawTextRSXform(const void* text, size_t len,
     448             :                                    const SkRSXform xform[], const SkPaint& paint) {
     449           0 :     CountTextProc proc = nullptr;
     450           0 :     switch (paint.getTextEncoding()) {
     451             :         case SkPaint::kUTF8_TextEncoding:
     452           0 :             proc = SkUTF8_CountUTF8Bytes;
     453           0 :             break;
     454             :         case SkPaint::kUTF16_TextEncoding:
     455           0 :             proc = count_utf16;
     456           0 :             break;
     457             :         case SkPaint::kUTF32_TextEncoding:
     458           0 :             proc = return_4;
     459           0 :             break;
     460             :         case SkPaint::kGlyphID_TextEncoding:
     461           0 :             proc = return_2;
     462           0 :             break;
     463             :     }
     464             : 
     465             :     SkMatrix localM, currM;
     466           0 :     const void* stopText = (const char*)text + len;
     467           0 :     while ((const char*)text < (const char*)stopText) {
     468           0 :         localM.setRSXform(*xform++);
     469           0 :         currM.setConcat(this->ctm(), localM);
     470           0 :         SkAutoDeviceCTMRestore adc(this, currM);
     471             : 
     472           0 :         int subLen = proc((const char*)text);
     473           0 :         this->drawText(text, subLen, 0, 0, paint);
     474           0 :         text = (const char*)text + subLen;
     475             :     }
     476           0 : }
     477             : 
     478             : //////////////////////////////////////////////////////////////////////////////////////////
     479             : 
     480          21 : uint32_t SkBaseDevice::filterTextFlags(const SkPaint& paint) const {
     481          21 :     uint32_t flags = paint.getFlags();
     482             : 
     483          21 :     if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
     484           0 :         return flags;
     485             :     }
     486             : 
     487          42 :     if (kUnknown_SkPixelGeometry == fSurfaceProps.pixelGeometry()
     488          21 :         || this->onShouldDisableLCD(paint)) {
     489             : 
     490           0 :         flags &= ~SkPaint::kLCDRenderText_Flag;
     491           0 :         flags |= SkPaint::kGenA8FromLCD_Flag;
     492             :     }
     493             : 
     494          21 :     return flags;
     495             : }
     496             : 
     497           0 : sk_sp<SkSurface> SkBaseDevice::makeSurface(SkImageInfo const&, SkSurfaceProps const&) {
     498           0 :     return nullptr;
     499             : }
     500             : 
     501             : //////////////////////////////////////////////////////////////////////////////////////////
     502             : 
     503         144 : void SkBaseDevice::LogDrawScaleFactor(const SkMatrix& matrix, SkFilterQuality filterQuality) {
     504             : #if SK_HISTOGRAMS_ENABLED
     505             :     enum ScaleFactor {
     506             :         kUpscale_ScaleFactor,
     507             :         kNoScale_ScaleFactor,
     508             :         kDownscale_ScaleFactor,
     509             :         kLargeDownscale_ScaleFactor,
     510             : 
     511             :         kLast_ScaleFactor = kLargeDownscale_ScaleFactor
     512             :     };
     513             : 
     514             :     float rawScaleFactor = matrix.getMinScale();
     515             : 
     516             :     ScaleFactor scaleFactor;
     517             :     if (rawScaleFactor < 0.5f) {
     518             :         scaleFactor = kLargeDownscale_ScaleFactor;
     519             :     } else if (rawScaleFactor < 1.0f) {
     520             :         scaleFactor = kDownscale_ScaleFactor;
     521             :     } else if (rawScaleFactor > 1.0f) {
     522             :         scaleFactor = kUpscale_ScaleFactor;
     523             :     } else {
     524             :         scaleFactor = kNoScale_ScaleFactor;
     525             :     }
     526             : 
     527             :     switch (filterQuality) {
     528             :         case kNone_SkFilterQuality:
     529             :             SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.NoneFilterQuality", scaleFactor,
     530             :                                      kLast_ScaleFactor + 1);
     531             :             break;
     532             :         case kLow_SkFilterQuality:
     533             :             SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.LowFilterQuality", scaleFactor,
     534             :                                      kLast_ScaleFactor + 1);
     535             :             break;
     536             :         case kMedium_SkFilterQuality:
     537             :             SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.MediumFilterQuality", scaleFactor,
     538             :                                      kLast_ScaleFactor + 1);
     539             :             break;
     540             :         case kHigh_SkFilterQuality:
     541             :             SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.HighFilterQuality", scaleFactor,
     542             :                                      kLast_ScaleFactor + 1);
     543             :             break;
     544             :     }
     545             : 
     546             :     // Also log filter quality independent scale factor.
     547             :     SK_HISTOGRAM_ENUMERATION("DrawScaleFactor.AnyFilterQuality", scaleFactor,
     548             :                              kLast_ScaleFactor + 1);
     549             : 
     550             :     // Also log an overall histogram of filter quality.
     551             :     SK_HISTOGRAM_ENUMERATION("FilterQuality", filterQuality, kLast_SkFilterQuality + 1);
     552             : #endif
     553         144 : }
     554             : 

Generated by: LCOV version 1.13