gfx/skia/trunk/src/utils/debugger/SkDebugCanvas.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.

     2 /*
     3  * Copyright 2012 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
    10 #include "SkColorPriv.h"
    11 #include "SkDebugCanvas.h"
    12 #include "SkDrawCommand.h"
    13 #include "SkDrawFilter.h"
    14 #include "SkDevice.h"
    15 #include "SkXfermode.h"
    17 SkDebugCanvas::SkDebugCanvas(int width, int height)
    18         : INHERITED(width, height)
    19         , fWidth(width)
    20         , fHeight(height)
    21         , fFilter(false)
    22         , fMegaVizMode(false)
    23         , fIndex(0)
    24         , fOverdrawViz(false)
    25         , fOverdrawFilter(NULL)
    26         , fOverrideTexFiltering(false)
    27         , fTexOverrideFilter(NULL)
    28         , fOutstandingSaveCount(0) {
    29     fUserMatrix.reset();
    31     // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
    32     // operations. This can lead to problems in the debugger which expects all
    33     // the operations in the captured skp to appear in the debug canvas. To
    34     // circumvent this we create a wide open clip here (an empty clip rect
    35     // is not sufficient).
    36     // Internally, the SkRect passed to clipRect is converted to an SkIRect and
    37     // rounded out. The following code creates a nearly maximal rect that will
    38     // not get collapsed by the coming conversions (Due to precision loss the
    39     // inset has to be surprisingly large).
    40     SkIRect largeIRect = SkIRect::MakeLargest();
    41     largeIRect.inset(1024, 1024);
    42     SkRect large = SkRect::Make(largeIRect);
    43 #ifdef SK_DEBUG
    44     large.roundOut(&largeIRect);
    45     SkASSERT(!largeIRect.isEmpty());
    46 #endif
    47     // call the base class' version to avoid adding a draw command
    48     this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
    49 }
    51 SkDebugCanvas::~SkDebugCanvas() {
    52     fCommandVector.deleteAll();
    53     SkSafeUnref(fOverdrawFilter);
    54     SkSafeUnref(fTexOverrideFilter);
    55 }
    57 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
    58     fCommandVector.push(command);
    59 }
    61 void SkDebugCanvas::draw(SkCanvas* canvas) {
    62     if (!fCommandVector.isEmpty()) {
    63         drawTo(canvas, fCommandVector.count() - 1);
    64     }
    65 }
    67 void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
    68     canvas->concat(fUserMatrix);
    69 }
    71 int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
    72     SkBitmap bitmap;
    73     bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
    75     SkCanvas canvas(bitmap);
    76     canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
    77     applyUserTransform(&canvas);
    79     int layer = 0;
    80     SkColor prev = bitmap.getColor(0,0);
    81     for (int i = 0; i < index; i++) {
    82         if (fCommandVector[i]->isVisible()) {
    83             fCommandVector[i]->execute(&canvas);
    84         }
    85         if (prev != bitmap.getColor(0,0)) {
    86             layer = i;
    87         }
    88         prev = bitmap.getColor(0,0);
    89     }
    90     return layer;
    91 }
    93 static SkPMColor OverdrawXferModeProc(SkPMColor src, SkPMColor dst) {
    94     // This table encodes the color progression of the overdraw visualization
    95     static const SkPMColor gTable[] = {
    96         SkPackARGB32(0x00, 0x00, 0x00, 0x00),
    97         SkPackARGB32(0xFF, 128, 158, 255),
    98         SkPackARGB32(0xFF, 170, 185, 212),
    99         SkPackARGB32(0xFF, 213, 195, 170),
   100         SkPackARGB32(0xFF, 255, 192, 127),
   101         SkPackARGB32(0xFF, 255, 185, 85),
   102         SkPackARGB32(0xFF, 255, 165, 42),
   103         SkPackARGB32(0xFF, 255, 135, 0),
   104         SkPackARGB32(0xFF, 255,  95, 0),
   105         SkPackARGB32(0xFF, 255,  50, 0),
   106         SkPackARGB32(0xFF, 255,  0, 0)
   107     };
   109     for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
   110         if (gTable[i] == dst) {
   111             return gTable[i+1];
   112         }
   113     }
   115     return gTable[SK_ARRAY_COUNT(gTable)-1];
   116 }
   118 // The OverdrawFilter modifies every paint to use an SkProcXfermode which
   119 // in turn invokes OverdrawXferModeProc
   120 class SkOverdrawFilter : public SkDrawFilter {
   121 public:
   122     SkOverdrawFilter() {
   123         fXferMode = SkProcXfermode::Create(OverdrawXferModeProc);
   124     }
   126     virtual ~SkOverdrawFilter() {
   127         delete fXferMode;
   128     }
   130     virtual bool filter(SkPaint* p, Type) SK_OVERRIDE {
   131         p->setXfermode(fXferMode);
   132         return true;
   133     }
   135 protected:
   136     SkXfermode* fXferMode;
   138 private:
   139     typedef SkDrawFilter INHERITED;
   140 };
   142 // SkTexOverrideFilter modifies every paint to use the specified
   143 // texture filtering mode
   144 class SkTexOverrideFilter : public SkDrawFilter {
   145 public:
   146     SkTexOverrideFilter() : fFilterLevel(SkPaint::kNone_FilterLevel) {
   147     }
   149     void setFilterLevel(SkPaint::FilterLevel filterLevel) {
   150         fFilterLevel = filterLevel;
   151     }
   153     virtual bool filter(SkPaint* p, Type) SK_OVERRIDE {
   154         p->setFilterLevel(fFilterLevel);
   155         return true;
   156     }
   158 protected:
   159     SkPaint::FilterLevel fFilterLevel;
   161 private:
   162     typedef SkDrawFilter INHERITED;
   163 };
   165 class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
   166 public:
   167     SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
   169     virtual void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE {
   170         SkPaint p;
   171         p.setColor(SK_ColorRED);
   172         p.setStyle(SkPaint::kStroke_Style);
   173         p.setAntiAlias(doAA);
   174         fCanvas->drawRect(r, p);
   175     }
   176     virtual void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) SK_OVERRIDE {
   177         SkPaint p;
   178         p.setColor(SK_ColorGREEN);
   179         p.setStyle(SkPaint::kStroke_Style);
   180         p.setAntiAlias(doAA);
   181         fCanvas->drawRRect(rr, p);
   182     }
   183     virtual void clipPath(const SkPath& path, SkRegion::Op, bool doAA) SK_OVERRIDE {
   184         SkPaint p;
   185         p.setColor(SK_ColorBLUE);
   186         p.setStyle(SkPaint::kStroke_Style);
   187         p.setAntiAlias(doAA);
   188         fCanvas->drawPath(path, p);
   189     }
   191 protected:
   192     SkCanvas* fCanvas;
   194 private:
   195     typedef SkCanvas::ClipVisitor INHERITED;
   196 };
   198 // set up the saveLayer commands so that the active ones
   199 // return true in their 'active' method
   200 void SkDebugCanvas::markActiveCommands(int index) {
   201     fActiveLayers.rewind();
   202     fActiveCulls.rewind();
   204     for (int i = 0; i < fCommandVector.count(); ++i) {
   205         fCommandVector[i]->setActive(false);
   206     }
   208     for (int i = 0; i < index; ++i) {
   209         SkDrawCommand::Action result = fCommandVector[i]->action();
   210         if (SkDrawCommand::kPushLayer_Action == result) {
   211             fActiveLayers.push(fCommandVector[i]);
   212         } else if (SkDrawCommand::kPopLayer_Action == result) {
   213             fActiveLayers.pop();
   214         } else if (SkDrawCommand::kPushCull_Action == result) {
   215             fActiveCulls.push(fCommandVector[i]);
   216         } else if (SkDrawCommand::kPopCull_Action == result) {
   217             fActiveCulls.pop();
   218         }
   219     }
   221     for (int i = 0; i < fActiveLayers.count(); ++i) {
   222         fActiveLayers[i]->setActive(true);
   223     }
   225     for (int i = 0; i < fActiveCulls.count(); ++i) {
   226         fActiveCulls[i]->setActive(true);
   227     }
   228 }
   230 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
   231     SkASSERT(!fCommandVector.isEmpty());
   232     SkASSERT(index < fCommandVector.count());
   233     int i = 0;
   235     // This only works assuming the canvas and device are the same ones that
   236     // were previously drawn into because they need to preserve all saves
   237     // and restores.
   238     // The visibility filter also requires a full re-draw - otherwise we can
   239     // end up drawing the filter repeatedly.
   240     if (fIndex < index && !fFilter && !fMegaVizMode) {
   241         i = fIndex + 1;
   242     } else {
   243         for (int j = 0; j < fOutstandingSaveCount; j++) {
   244             canvas->restore();
   245         }
   246         canvas->clear(SK_ColorTRANSPARENT);
   247         canvas->resetMatrix();
   248         SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth),
   249                                      SkIntToScalar(fHeight));
   250         canvas->clipRect(rect, SkRegion::kReplace_Op );
   251         applyUserTransform(canvas);
   252         fOutstandingSaveCount = 0;
   253     }
   255     // The setting of the draw filter has to go here (rather than in
   256     // SkRasterWidget) due to the canvas restores this class performs.
   257     // Since the draw filter is stored in the layer stack if we
   258     // call setDrawFilter on anything but the root layer odd things happen.
   259     if (fOverdrawViz) {
   260         if (NULL == fOverdrawFilter) {
   261             fOverdrawFilter = new SkOverdrawFilter;
   262         }
   264         if (fOverdrawFilter != canvas->getDrawFilter()) {
   265             canvas->setDrawFilter(fOverdrawFilter);
   266         }
   267     } else if (fOverrideTexFiltering) {
   268         if (NULL == fTexOverrideFilter) {
   269             fTexOverrideFilter = new SkTexOverrideFilter;
   270         }
   272         if (fTexOverrideFilter != canvas->getDrawFilter()) {
   273             canvas->setDrawFilter(fTexOverrideFilter);
   274         }
   275     } else {
   276         canvas->setDrawFilter(NULL);
   277     }
   279     if (fMegaVizMode) {
   280         this->markActiveCommands(index);
   281     }
   283     for (; i <= index; i++) {
   284         if (i == index && fFilter) {
   285             SkPaint p;
   286             p.setColor(0xAAFFFFFF);
   287             canvas->save();
   288             canvas->resetMatrix();
   289             SkRect mask;
   290             mask.set(SkIntToScalar(0), SkIntToScalar(0),
   291                     SkIntToScalar(fWidth), SkIntToScalar(fHeight));
   292             canvas->clipRect(mask, SkRegion::kReplace_Op, false);
   293             canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
   294                     SkIntToScalar(fWidth), SkIntToScalar(fHeight), p);
   295             canvas->restore();
   296         }
   298         if (fCommandVector[i]->isVisible()) {
   299             if (fMegaVizMode && fCommandVector[i]->active()) {
   300                 // "active" commands execute their visualization behaviors:
   301                 //     All active saveLayers get replaced with saves so all draws go to the
   302                 //     visible canvas.
   303                 //     All active culls draw their cull box
   304                 fCommandVector[i]->vizExecute(canvas);
   305             } else {
   306                 fCommandVector[i]->execute(canvas);
   307             }
   309             fCommandVector[i]->trackSaveState(&fOutstandingSaveCount);
   310         }
   311     }
   313     if (fMegaVizMode) {
   314         SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight));
   315         r.outset(SK_Scalar1, SK_Scalar1);
   317         canvas->save();
   318         // nuke the CTM
   319         canvas->setMatrix(SkMatrix::I());
   320         // turn off clipping
   321         canvas->clipRect(r, SkRegion::kReplace_Op);
   323         // visualize existing clips
   324         SkDebugClipVisitor visitor(canvas);
   326         canvas->replayClips(&visitor);
   328         canvas->restore();
   329     }
   330     fMatrix = canvas->getTotalMatrix();
   331     if (!canvas->getClipDeviceBounds(&fClip)) {
   332         fClip.setEmpty();
   333     }
   334     fIndex = index;
   335 }
   337 void SkDebugCanvas::deleteDrawCommandAt(int index) {
   338     SkASSERT(index < fCommandVector.count());
   339     delete fCommandVector[index];
   340     fCommandVector.remove(index);
   341 }
   343 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
   344     SkASSERT(index < fCommandVector.count());
   345     return fCommandVector[index];
   346 }
   348 void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) {
   349     SkASSERT(index < fCommandVector.count());
   350     delete fCommandVector[index];
   351     fCommandVector[index] = command;
   352 }
   354 SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) {
   355     SkASSERT(index < fCommandVector.count());
   356     return fCommandVector[index]->Info();
   357 }
   359 bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
   360     SkASSERT(index < fCommandVector.count());
   361     return fCommandVector[index]->isVisible();
   362 }
   364 const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
   365     return fCommandVector;
   366 }
   368 SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() {
   369     return fCommandVector;
   370 }
   372 // TODO(chudy): Free command string memory.
   373 SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const {
   374     SkTArray<SkString>* commandString = new SkTArray<SkString>(fCommandVector.count());
   375     if (!fCommandVector.isEmpty()) {
   376         for (int i = 0; i < fCommandVector.count(); i ++) {
   377             commandString->push_back() = fCommandVector[i]->toString();
   378         }
   379     }
   380     return commandString;
   381 }
   383 void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkPaint::FilterLevel level) {
   384     if (NULL == fTexOverrideFilter) {
   385         fTexOverrideFilter = new SkTexOverrideFilter;
   386     }
   388     fOverrideTexFiltering = overrideTexFiltering;
   389     fTexOverrideFilter->setFilterLevel(level);
   390 }
   392 void SkDebugCanvas::clear(SkColor color) {
   393     addDrawCommand(new SkClearCommand(color));
   394 }
   396 void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   397     this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
   398 }
   400 void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   401     this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
   402 }
   404 void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
   405     this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
   406 }
   408 void SkDebugCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
   409     this->addDrawCommand(new SkClipRegionCommand(region, op));
   410 }
   412 void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
   413     addDrawCommand(new SkConcatCommand(matrix));
   414     this->INHERITED::didConcat(matrix);
   415 }
   417 void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
   418                                SkScalar top, const SkPaint* paint = NULL) {
   419     addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
   420 }
   422 void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
   423                                          const SkRect* src, const SkRect& dst,
   424                                          const SkPaint* paint,
   425                                          SkCanvas::DrawBitmapRectFlags flags) {
   426     addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint, flags));
   427 }
   429 void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
   430                                      const SkMatrix& matrix, const SkPaint* paint) {
   431     addDrawCommand(new SkDrawBitmapMatrixCommand(bitmap, matrix, paint));
   432 }
   434 void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap,
   435         const SkIRect& center, const SkRect& dst, const SkPaint* paint) {
   436     addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
   437 }
   439 void SkDebugCanvas::drawData(const void* data, size_t length) {
   440     addDrawCommand(new SkDrawDataCommand(data, length));
   441 }
   443 void SkDebugCanvas::beginCommentGroup(const char* description) {
   444     addDrawCommand(new SkBeginCommentGroupCommand(description));
   445 }
   447 void SkDebugCanvas::addComment(const char* kywd, const char* value) {
   448     addDrawCommand(new SkCommentCommand(kywd, value));
   449 }
   451 void SkDebugCanvas::endCommentGroup() {
   452     addDrawCommand(new SkEndCommentGroupCommand());
   453 }
   455 void SkDebugCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
   456     addDrawCommand(new SkDrawOvalCommand(oval, paint));
   457 }
   459 void SkDebugCanvas::drawPaint(const SkPaint& paint) {
   460     addDrawCommand(new SkDrawPaintCommand(paint));
   461 }
   463 void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   464     addDrawCommand(new SkDrawPathCommand(path, paint));
   465 }
   467 void SkDebugCanvas::drawPicture(SkPicture& picture) {
   468     addDrawCommand(new SkDrawPictureCommand(picture));
   469 }
   471 void SkDebugCanvas::drawPoints(PointMode mode, size_t count,
   472                                const SkPoint pts[], const SkPaint& paint) {
   473     addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
   474 }
   476 void SkDebugCanvas::drawPosText(const void* text, size_t byteLength,
   477         const SkPoint pos[], const SkPaint& paint) {
   478     addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
   479 }
   481 void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength,
   482         const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
   483     addDrawCommand(
   484         new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
   485 }
   487 void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
   488     // NOTE(chudy): Messing up when renamed to DrawRect... Why?
   489     addDrawCommand(new SkDrawRectCommand(rect, paint));
   490 }
   492 void SkDebugCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   493     addDrawCommand(new SkDrawRRectCommand(rrect, paint));
   494 }
   496 void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
   497                                  const SkPaint& paint) {
   498     this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
   499 }
   501 void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
   502                                const SkPaint* paint = NULL) {
   503     addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint));
   504 }
   506 void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
   507         SkScalar y, const SkPaint& paint) {
   508     addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
   509 }
   511 void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength,
   512         const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
   513     addDrawCommand(
   514         new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
   515 }
   517 void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount,
   518         const SkPoint vertices[], const SkPoint texs[], const SkColor colors[],
   519         SkXfermode*, const uint16_t indices[], int indexCount,
   520         const SkPaint& paint) {
   521     addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
   522                    texs, colors, NULL, indices, indexCount, paint));
   523 }
   525 void SkDebugCanvas::onPushCull(const SkRect& cullRect) {
   526     this->addDrawCommand(new SkPushCullCommand(cullRect));
   527 }
   529 void SkDebugCanvas::onPopCull() {
   530     this->addDrawCommand(new SkPopCullCommand());
   531 }
   533 void SkDebugCanvas::willRestore() {
   534     this->addDrawCommand(new SkRestoreCommand());
   535     this->INHERITED::willRestore();
   536 }
   538 void SkDebugCanvas::didRotate(SkScalar degrees) {
   539     addDrawCommand(new SkRotateCommand(degrees));
   540     this->INHERITED::didRotate(degrees);
   541 }
   543 void SkDebugCanvas::willSave(SaveFlags flags) {
   544     this->addDrawCommand(new SkSaveCommand(flags));
   545     this->INHERITED::willSave(flags);
   546 }
   548 SkCanvas::SaveLayerStrategy SkDebugCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
   549                                                          SaveFlags flags) {
   550     this->addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags));
   551     this->INHERITED::willSaveLayer(bounds, paint, flags);
   552     // No need for a full layer.
   553     return kNoLayer_SaveLayerStrategy;
   554 }
   556 void SkDebugCanvas::didScale(SkScalar sx, SkScalar sy) {
   557     addDrawCommand(new SkScaleCommand(sx, sy));
   558     this->INHERITED::didScale(sx, sy);
   559 }
   561 void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
   562     addDrawCommand(new SkSetMatrixCommand(matrix));
   563     this->INHERITED::didSetMatrix(matrix);
   564 }
   566 void SkDebugCanvas::didSkew(SkScalar sx, SkScalar sy) {
   567     addDrawCommand(new SkSkewCommand(sx, sy));
   568     this->INHERITED::didSkew(sx, sy);
   569 }
   571 void SkDebugCanvas::didTranslate(SkScalar dx, SkScalar dy) {
   572     addDrawCommand(new SkTranslateCommand(dx, dy));
   573     this->INHERITED::didTranslate(dx, dy);
   574 }
   576 void SkDebugCanvas::toggleCommand(int index, bool toggle) {
   577     SkASSERT(index < fCommandVector.count());
   578     fCommandVector[index]->setVisible(toggle);
   579 }

mercurial