blob: 39c484d7243dd763d0466bb2c03758bc9c283db3 [file] [log] [blame]
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +00001/*
2 * Copyright 2012 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
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +00008#include "SkDebugCanvas.h"
robertphillips@google.com801cee12012-10-19 19:06:11 +00009#include "SkDevice.h"
scroggo@google.com7def5e12013-05-31 14:00:10 +000010#include "SkForceLinking.h"
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000011#include "SkGraphics.h"
robertphillips@google.com4e4d75b2012-11-12 18:03:19 +000012#include "SkImageDecoder.h"
robertphillips@google.com801cee12012-10-19 19:06:11 +000013#include "SkImageEncoder.h"
djsollen@google.coma09e8832012-11-13 18:50:33 +000014#include "SkOSFile.h"
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000015#include "SkPicture.h"
robertphillips@google.com801cee12012-10-19 19:06:11 +000016#include "SkPicturePlayback.h"
17#include "SkPictureRecord.h"
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000018#include "SkStream.h"
djsollen@google.coma09e8832012-11-13 18:50:33 +000019#include "picture_utils.h"
robertphillips@google.comd3d377f2012-12-07 20:56:13 +000020#include "path_utils.h"
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000021
scroggo@google.com7def5e12013-05-31 14:00:10 +000022__SK_FORCE_IMAGE_DECODER_LINKING;
23
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000024static void usage() {
robertphillips@google.comd3d377f2012-12-07 20:56:13 +000025 SkDebugf("Usage: filter -i inFile [-o outFile] [--input-dir path] [--output-dir path]\n");
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +000026 SkDebugf(" [-h|--help]\n\n");
robertphillips@google.com2e87ba02013-04-08 15:45:30 +000027 SkDebugf(" -i inFile : file to filter.\n");
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000028 SkDebugf(" -o outFile : result of filtering.\n");
djsollen@google.coma09e8832012-11-13 18:50:33 +000029 SkDebugf(" --input-dir : process all files in dir with .skp extension.\n");
30 SkDebugf(" --output-dir : results of filtering the input dir.\n");
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +000031 SkDebugf(" -h|--help : Show this help message.\n");
32}
33
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +000034// Is the supplied paint simply a color?
35static bool is_simple(const SkPaint& p) {
36 return NULL == p.getPathEffect() &&
37 NULL == p.getShader() &&
38 NULL == p.getXfermode() &&
39 NULL == p.getMaskFilter() &&
40 NULL == p.getColorFilter() &&
41 NULL == p.getRasterizer() &&
42 NULL == p.getLooper() &&
43 NULL == p.getImageFilter();
44}
robertphillips@google.comd3d377f2012-12-07 20:56:13 +000045
robertphillips@google.com50c84da2013-04-01 18:18:49 +000046
robertphillips@google.com73743552013-02-05 20:51:49 +000047// Check for:
48// SAVE_LAYER
49// DRAW_BITMAP_RECT_TO_RECT
50// RESTORE
51// where the saveLayer's color can be moved into the drawBitmapRect
robertphillips@google.com50c84da2013-04-01 18:18:49 +000052static bool check_0(SkDebugCanvas* canvas, int curCommand) {
53 if (SAVE_LAYER != canvas->getDrawCommandAt(curCommand)->getType() ||
54 canvas->getSize() <= curCommand+2 ||
55 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
56 RESTORE != canvas->getDrawCommandAt(curCommand+2)->getType()) {
robertphillips@google.com73743552013-02-05 20:51:49 +000057 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +000058 }
robertphillips@google.com73743552013-02-05 20:51:49 +000059
commit-bot@chromium.org7a115912013-06-18 20:20:55 +000060 SkSaveLayerCommand* saveLayer =
61 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
62 SkDrawBitmapRectCommand* dbmr =
63 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+1);
robertphillips@google.com73743552013-02-05 20:51:49 +000064
65 const SkPaint* saveLayerPaint = saveLayer->paint();
66 SkPaint* dbmrPaint = dbmr->paint();
67
skia.committer@gmail.com3d18d062013-02-14 07:01:34 +000068 // For this optimization we only fold the saveLayer and drawBitmapRect
robertphillips@google.comc5257042013-04-02 15:30:03 +000069 // together if the saveLayer's draw is simple (i.e., no fancy effects)
70 // and the only difference in the colors is their alpha value
robertphillips@google.com1780a3c2013-02-13 13:27:44 +000071 SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
robertphillips@google.comc5257042013-04-02 15:30:03 +000072 SkColor dbmrColor = dbmrPaint->getColor() | 0xFF000000; // force opaque
robertphillips@google.com1780a3c2013-02-13 13:27:44 +000073
robertphillips@google.comc5257042013-04-02 15:30:03 +000074 // If either operation lacks a paint then the collapse is trivial
robertphillips@google.com73743552013-02-05 20:51:49 +000075 return NULL == saveLayerPaint ||
76 NULL == dbmrPaint ||
robertphillips@google.comc5257042013-04-02 15:30:03 +000077 (is_simple(*saveLayerPaint) && dbmrColor == layerColor);
robertphillips@google.com73743552013-02-05 20:51:49 +000078}
79
80// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer
81// and restore
robertphillips@google.com50c84da2013-04-01 18:18:49 +000082static void apply_0(SkDebugCanvas* canvas, int curCommand) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +000083 SkSaveLayerCommand* saveLayer =
84 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
robertphillips@google.com73743552013-02-05 20:51:49 +000085 const SkPaint* saveLayerPaint = saveLayer->paint();
robertphillips@google.com73743552013-02-05 20:51:49 +000086
robertphillips@google.com50c84da2013-04-01 18:18:49 +000087 // if (NULL == saveLayerPaint) the dbmr's paint doesn't need to be changed
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +000088 if (NULL != saveLayerPaint) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +000089 SkDrawBitmapRectCommand* dbmr =
90 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+1);
robertphillips@google.com50c84da2013-04-01 18:18:49 +000091 SkPaint* dbmrPaint = dbmr->paint();
92
93 if (NULL == dbmrPaint) {
94 // if the DBMR doesn't have a paint just use the saveLayer's
95 dbmr->setPaint(*saveLayerPaint);
96 } else if (NULL != saveLayerPaint) {
robertphillips@google.comc5257042013-04-02 15:30:03 +000097 // Both paints are present so their alphas need to be combined
98 SkColor color = saveLayerPaint->getColor();
99 int a0 = SkColorGetA(color);
100
101 color = dbmrPaint->getColor();
102 int a1 = SkColorGetA(color);
103
104 int newA = SkMulDiv255Round(a0, a1);
105 SkASSERT(newA <= 0xFF);
106
107 SkColor newColor = SkColorSetA(color, newA);
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000108 dbmrPaint->setColor(newColor);
109 }
robertphillips@google.com73743552013-02-05 20:51:49 +0000110 }
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000111
112 canvas->deleteDrawCommandAt(curCommand+2); // restore
113 canvas->deleteDrawCommandAt(curCommand); // saveLayer
robertphillips@google.com73743552013-02-05 20:51:49 +0000114}
115
116// Check for:
117// SAVE_LAYER
118// SAVE
119// CLIP_RECT
120// DRAW_BITMAP_RECT_TO_RECT
121// RESTORE
122// RESTORE
123// where the saveLayer's color can be moved into the drawBitmapRect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000124static bool check_1(SkDebugCanvas* canvas, int curCommand) {
125 if (SAVE_LAYER != canvas->getDrawCommandAt(curCommand)->getType() ||
126 canvas->getSize() <= curCommand+5 ||
127 SAVE != canvas->getDrawCommandAt(curCommand+1)->getType() ||
128 CLIP_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
129 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+3)->getType() ||
130 RESTORE != canvas->getDrawCommandAt(curCommand+4)->getType() ||
131 RESTORE != canvas->getDrawCommandAt(curCommand+5)->getType()) {
robertphillips@google.com73743552013-02-05 20:51:49 +0000132 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000133 }
robertphillips@google.com73743552013-02-05 20:51:49 +0000134
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000135 SkSaveLayerCommand* saveLayer =
136 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
137 SkDrawBitmapRectCommand* dbmr =
138 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+3);
robertphillips@google.com73743552013-02-05 20:51:49 +0000139
140 const SkPaint* saveLayerPaint = saveLayer->paint();
141 SkPaint* dbmrPaint = dbmr->paint();
142
skia.committer@gmail.com3d18d062013-02-14 07:01:34 +0000143 // For this optimization we only fold the saveLayer and drawBitmapRect
robertphillips@google.com1780a3c2013-02-13 13:27:44 +0000144 // together if the saveLayer's draw is simple (i.e., no fancy effects) and
145 // and the only difference in the colors is that the saveLayer's can have
146 // an alpha while the drawBitmapRect's is opaque.
147 // TODO: it should be possible to fold them together even if they both
148 // have different non-255 alphas but this is low priority since we have
149 // never seen that case
150 // If either operation lacks a paint then the collapse is trivial
151 SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
152
robertphillips@google.com73743552013-02-05 20:51:49 +0000153 return NULL == saveLayerPaint ||
154 NULL == dbmrPaint ||
robertphillips@google.com1780a3c2013-02-13 13:27:44 +0000155 (is_simple(*saveLayerPaint) && dbmrPaint->getColor() == layerColor);
robertphillips@google.com73743552013-02-05 20:51:49 +0000156}
157
158// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer
159// and restore
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000160static void apply_1(SkDebugCanvas* canvas, int curCommand) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000161 SkSaveLayerCommand* saveLayer =
162 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
robertphillips@google.com73743552013-02-05 20:51:49 +0000163 const SkPaint* saveLayerPaint = saveLayer->paint();
robertphillips@google.com73743552013-02-05 20:51:49 +0000164
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000165 // if (NULL == saveLayerPaint) the dbmr's paint doesn't need to be changed
166 if (NULL != saveLayerPaint) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000167 SkDrawBitmapRectCommand* dbmr =
168 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+3);
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000169 SkPaint* dbmrPaint = dbmr->paint();
170
171 if (NULL == dbmrPaint) {
172 dbmr->setPaint(*saveLayerPaint);
173 } else {
174 SkColor newColor = SkColorSetA(dbmrPaint->getColor(),
175 SkColorGetA(saveLayerPaint->getColor()));
176 dbmrPaint->setColor(newColor);
177 }
robertphillips@google.com73743552013-02-05 20:51:49 +0000178 }
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000179
180 canvas->deleteDrawCommandAt(curCommand+5); // restore
181 canvas->deleteDrawCommandAt(curCommand); // saveLayer
robertphillips@google.com73743552013-02-05 20:51:49 +0000182}
183
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000184// Check for:
185// SAVE
186// CLIP_RECT
187// DRAW_RECT
188// RESTORE
189// where the rect is entirely within the clip and the clip is an intersect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000190static bool check_2(SkDebugCanvas* canvas, int curCommand) {
191 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
192 canvas->getSize() <= curCommand+4 ||
193 CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
194 DRAW_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
195 RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000196 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000197 }
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000198
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000199 SkClipRectCommand* cr =
200 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
201 SkDrawRectCommand* dr =
202 (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000203
204 if (SkRegion::kIntersect_Op != cr->op()) {
205 return false;
206 }
207
208 return cr->rect().contains(dr->rect());
209}
210
211// Remove everything but the drawRect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000212static void apply_2(SkDebugCanvas* canvas, int curCommand) {
213 canvas->deleteDrawCommandAt(curCommand+3); // restore
214 // drawRect
215 canvas->deleteDrawCommandAt(curCommand+1); // clipRect
216 canvas->deleteDrawCommandAt(curCommand); // save
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000217}
218
219// Check for:
220// SAVE
221// CLIP_RRECT
222// DRAW_RECT
223// RESTORE
224// where the rect entirely encloses the clip
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000225static bool check_3(SkDebugCanvas* canvas, int curCommand) {
226 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
227 canvas->getSize() <= curCommand+4 ||
228 CLIP_RRECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
229 DRAW_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
230 RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000231 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000232 }
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000233
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000234 SkClipRRectCommand* crr =
235 (SkClipRRectCommand*) canvas->getDrawCommandAt(curCommand+1);
236 SkDrawRectCommand* dr =
237 (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000238
239 if (SkRegion::kIntersect_Op != crr->op()) {
240 return false;
241 }
242
243 return dr->rect().contains(crr->rrect().rect());
244}
245
246// Replace everything with a drawRRect with the paint from the drawRect
247// and the AA settings from the clipRRect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000248static void apply_3(SkDebugCanvas* canvas, int curCommand) {
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000249
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000250 canvas->deleteDrawCommandAt(curCommand+3); // restore
251
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000252 SkClipRRectCommand* crr =
253 (SkClipRRectCommand*) canvas->getDrawCommandAt(curCommand+1);
254 SkDrawRectCommand* dr =
255 (SkDrawRectCommand*) canvas->getDrawCommandAt(curCommand+2);
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000256
257 // TODO: could skip paint re-creation if the AA settings already match
robertphillips@google.com91217d02013-03-17 18:33:46 +0000258 SkPaint newPaint = dr->paint();
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000259 newPaint.setAntiAlias(crr->doAA());
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000260 SkDrawRRectCommand* drr = new SkDrawRRectCommand(crr->rrect(), newPaint);
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000261 canvas->setDrawCommandAt(curCommand+2, drr);
262
263 canvas->deleteDrawCommandAt(curCommand+1); // clipRRect
264 canvas->deleteDrawCommandAt(curCommand); // save
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000265}
266
267// Check for:
268// SAVE
269// CLIP_RECT
270// DRAW_BITMAP_RECT_TO_RECT
271// RESTORE
272// where the rect and drawBitmapRect dst exactly match
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000273static bool check_4(SkDebugCanvas* canvas, int curCommand) {
274 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
275 canvas->getSize() <= curCommand+4 ||
276 CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
277 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
278 RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000279 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000280 }
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000281
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000282 SkClipRectCommand* cr =
283 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
284 SkDrawBitmapRectCommand* dbmr =
285 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000286
287 if (SkRegion::kIntersect_Op != cr->op()) {
288 return false;
289 }
290
291 return dbmr->dstRect() == cr->rect();
292}
293
294// Remove everything but the drawBitmapRect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000295static void apply_4(SkDebugCanvas* canvas, int curCommand) {
296 canvas->deleteDrawCommandAt(curCommand+3); // restore
297 // drawBitmapRectToRect
298 canvas->deleteDrawCommandAt(curCommand+1); // clipRect
299 canvas->deleteDrawCommandAt(curCommand); // save
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000300}
301
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000302// Check for:
303// TRANSLATE
304// where the translate is zero
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000305static bool check_5(SkDebugCanvas* canvas, int curCommand) {
306 if (TRANSLATE != canvas->getDrawCommandAt(curCommand)->getType()) {
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000307 return false;
308 }
309
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000310 SkTranslateCommand* t =
311 (SkTranslateCommand*) canvas->getDrawCommandAt(curCommand);
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000312
313 return 0 == t->x() && 0 == t->y();
314}
315
316// Just remove the translate
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000317static void apply_5(SkDebugCanvas* canvas, int curCommand) {
318 canvas->deleteDrawCommandAt(curCommand); // translate
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000319}
320
321// Check for:
322// SCALE
323// where the scale is 1,1
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000324static bool check_6(SkDebugCanvas* canvas, int curCommand) {
325 if (SCALE != canvas->getDrawCommandAt(curCommand)->getType()) {
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000326 return false;
327 }
328
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000329 SkScaleCommand* s = (SkScaleCommand*) canvas->getDrawCommandAt(curCommand);
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000330
331 return SK_Scalar1 == s->x() && SK_Scalar1 == s->y();
332}
333
334// Just remove the scale
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000335static void apply_6(SkDebugCanvas* canvas, int curCommand) {
336 canvas->deleteDrawCommandAt(curCommand); // scale
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000337}
338
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000339// Check for:
340// SAVE
341// CLIP_RECT
342// SAVE_LAYER
343// SAVE
344// CLIP_RECT
345// SAVE_LAYER
346// SAVE
347// CLIP_RECT
348// DRAWBITMAPRECTTORECT
349// RESTORE
350// RESTORE
351// RESTORE
352// RESTORE
353// RESTORE
354// where:
355// all the clipRect's are BW, nested, intersections
356// the drawBitmapRectToRect is a 1-1 copy from src to dest
357// the last (smallest) clip rect is a subset of the drawBitmapRectToRect's dest rect
358// all the saveLayer's paints can be rolled into the drawBitmapRectToRect's paint
359// This pattern is used by Google spreadsheet when drawing the toolbar buttons
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000360static bool check_7(SkDebugCanvas* canvas, int curCommand) {
361 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
362 canvas->getSize() <= curCommand+13 ||
363 CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
364 SAVE_LAYER != canvas->getDrawCommandAt(curCommand+2)->getType() ||
365 SAVE != canvas->getDrawCommandAt(curCommand+3)->getType() ||
366 CLIP_RECT != canvas->getDrawCommandAt(curCommand+4)->getType() ||
367 SAVE_LAYER != canvas->getDrawCommandAt(curCommand+5)->getType() ||
368 SAVE != canvas->getDrawCommandAt(curCommand+6)->getType() ||
369 CLIP_RECT != canvas->getDrawCommandAt(curCommand+7)->getType() ||
370 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+8)->getType() ||
371 RESTORE != canvas->getDrawCommandAt(curCommand+9)->getType() ||
372 RESTORE != canvas->getDrawCommandAt(curCommand+10)->getType() ||
373 RESTORE != canvas->getDrawCommandAt(curCommand+11)->getType() ||
374 RESTORE != canvas->getDrawCommandAt(curCommand+12)->getType() ||
375 RESTORE != canvas->getDrawCommandAt(curCommand+13)->getType()) {
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000376 return false;
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000377 }
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000378
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000379 SkClipRectCommand* clip0 =
380 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
381 SkSaveLayerCommand* saveLayer0 =
382 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2);
383 SkClipRectCommand* clip1 =
384 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+4);
385 SkSaveLayerCommand* saveLayer1 =
386 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5);
387 SkClipRectCommand* clip2 =
388 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7);
389 SkDrawBitmapRectCommand* dbmr =
390 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+8);
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000391
392 if (clip0->doAA() || clip1->doAA() || clip2->doAA()) {
393 return false;
394 }
395
396 if (SkRegion::kIntersect_Op != clip0->op() ||
397 SkRegion::kIntersect_Op != clip1->op() ||
398 SkRegion::kIntersect_Op != clip2->op()) {
399 return false;
400 }
401
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000402 if (!clip0->rect().contains(clip1->rect()) ||
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000403 !clip1->rect().contains(clip2->rect())) {
404 return false;
405 }
406
407 // The src->dest mapping needs to be 1-to-1
408 if (NULL == dbmr->srcRect()) {
409 if (dbmr->bitmap().width() != dbmr->dstRect().width() ||
410 dbmr->bitmap().height() != dbmr->dstRect().height()) {
411 return false;
412 }
413 } else {
414 if (dbmr->srcRect()->width() != dbmr->dstRect().width() ||
415 dbmr->srcRect()->height() != dbmr->dstRect().height()) {
416 return false;
417 }
418 }
419
420 if (!dbmr->dstRect().contains(clip2->rect())) {
421 return false;
422 }
423
424 const SkPaint* saveLayerPaint0 = saveLayer0->paint();
425 const SkPaint* saveLayerPaint1 = saveLayer1->paint();
426
427 if ((NULL != saveLayerPaint0 && !is_simple(*saveLayerPaint0)) ||
428 (NULL != saveLayerPaint1 && !is_simple(*saveLayerPaint1))) {
429 return false;
430 }
431
432 SkPaint* dbmrPaint = dbmr->paint();
433
434 if (NULL == dbmrPaint) {
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000435 return true;
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000436 }
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000437
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000438 if (NULL != saveLayerPaint0) {
439 SkColor layerColor0 = saveLayerPaint0->getColor() | 0xFF000000; // force opaque
440 if (dbmrPaint->getColor() != layerColor0) {
441 return false;
442 }
443 }
444
445 if (NULL != saveLayerPaint1) {
446 SkColor layerColor1 = saveLayerPaint1->getColor() | 0xFF000000; // force opaque
447 if (dbmrPaint->getColor() != layerColor1) {
448 return false;
449 }
450 }
451
452 return true;
453}
454
455// Reduce to a single drawBitmapRectToRect call by folding the clipRect's into
456// the src and dst Rects and the saveLayer paints into the drawBitmapRectToRect's
457// paint.
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000458static void apply_7(SkDebugCanvas* canvas, int curCommand) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000459 SkSaveLayerCommand* saveLayer0 =
460 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2);
461 SkSaveLayerCommand* saveLayer1 =
462 (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5);
463 SkClipRectCommand* clip2 =
464 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7);
465 SkDrawBitmapRectCommand* dbmr =
466 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+8);
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000467
468 SkScalar newSrcLeft = dbmr->srcRect()->fLeft + clip2->rect().fLeft - dbmr->dstRect().fLeft;
469 SkScalar newSrcTop = dbmr->srcRect()->fTop + clip2->rect().fTop - dbmr->dstRect().fTop;
470
skia.committer@gmail.com6acd09e2013-03-29 07:01:22 +0000471 SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop,
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000472 clip2->rect().width(), clip2->rect().height());
473
474 dbmr->setSrcRect(newSrc);
475 dbmr->setDstRect(clip2->rect());
476
477 SkColor color = 0xFF000000;
478 int a0, a1;
479
480 const SkPaint* saveLayerPaint0 = saveLayer0->paint();
481 if (NULL != saveLayerPaint0) {
482 color = saveLayerPaint0->getColor();
483 a0 = SkColorGetA(color);
484 } else {
485 a0 = 0xFF;
486 }
487
488 const SkPaint* saveLayerPaint1 = saveLayer1->paint();
489 if (NULL != saveLayerPaint1) {
490 color = saveLayerPaint1->getColor();
491 a1 = SkColorGetA(color);
492 } else {
493 a1 = 0xFF;
494 }
495
robertphillips@google.comc5257042013-04-02 15:30:03 +0000496 int newA = SkMulDiv255Round(a0, a1);
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000497 SkASSERT(newA <= 0xFF);
498
499 SkPaint* dbmrPaint = dbmr->paint();
500
501 if (NULL != dbmrPaint) {
502 SkColor newColor = SkColorSetA(dbmrPaint->getColor(), newA);
503 dbmrPaint->setColor(newColor);
504 } else {
505 SkColor newColor = SkColorSetA(color, newA);
506
507 SkPaint newPaint;
508 newPaint.setColor(newColor);
509 dbmr->setPaint(newPaint);
510 }
511
512 // remove everything except the drawbitmaprect
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000513 canvas->deleteDrawCommandAt(curCommand+13); // restore
514 canvas->deleteDrawCommandAt(curCommand+12); // restore
515 canvas->deleteDrawCommandAt(curCommand+11); // restore
516 canvas->deleteDrawCommandAt(curCommand+10); // restore
517 canvas->deleteDrawCommandAt(curCommand+9); // restore
518 canvas->deleteDrawCommandAt(curCommand+7); // clipRect
519 canvas->deleteDrawCommandAt(curCommand+6); // save
520 canvas->deleteDrawCommandAt(curCommand+5); // saveLayer
521 canvas->deleteDrawCommandAt(curCommand+4); // clipRect
522 canvas->deleteDrawCommandAt(curCommand+3); // save
523 canvas->deleteDrawCommandAt(curCommand+2); // saveLayer
524 canvas->deleteDrawCommandAt(curCommand+1); // clipRect
525 canvas->deleteDrawCommandAt(curCommand); // save
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000526}
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000527
commit-bot@chromium.org3bdf1642013-04-01 21:00:27 +0000528// Check for:
529// SAVE
530// CLIP_RECT
531// DRAWBITMAPRECTTORECT
532// RESTORE
533// where:
534// the drawBitmapRectToRect is a 1-1 copy from src to dest
535// the clip rect is BW and a subset of the drawBitmapRectToRect's dest rect
536static bool check_8(SkDebugCanvas* canvas, int curCommand) {
537 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
538 canvas->getSize() <= curCommand+4 ||
539 CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
540 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
541 RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
542 return false;
543 }
544
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000545 SkClipRectCommand* clip =
546 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
547 SkDrawBitmapRectCommand* dbmr =
548 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);
commit-bot@chromium.org3bdf1642013-04-01 21:00:27 +0000549
550 if (clip->doAA() || SkRegion::kIntersect_Op != clip->op()) {
551 return false;
552 }
553
554 // The src->dest mapping needs to be 1-to-1
555 if (NULL == dbmr->srcRect()) {
556 if (dbmr->bitmap().width() != dbmr->dstRect().width() ||
557 dbmr->bitmap().height() != dbmr->dstRect().height()) {
558 return false;
559 }
560 } else {
561 if (dbmr->srcRect()->width() != dbmr->dstRect().width() ||
562 dbmr->srcRect()->height() != dbmr->dstRect().height()) {
563 return false;
564 }
565 }
566
567 if (!dbmr->dstRect().contains(clip->rect())) {
568 return false;
569 }
570
571 return true;
572}
573
574// Fold the clipRect into the drawBitmapRectToRect's src and dest rects
575static void apply_8(SkDebugCanvas* canvas, int curCommand) {
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000576 SkClipRectCommand* clip =
577 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
578 SkDrawBitmapRectCommand* dbmr =
579 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);
commit-bot@chromium.org3bdf1642013-04-01 21:00:27 +0000580
581 SkScalar newSrcLeft, newSrcTop;
582
583 if (NULL != dbmr->srcRect()) {
584 newSrcLeft = dbmr->srcRect()->fLeft + clip->rect().fLeft - dbmr->dstRect().fLeft;
585 newSrcTop = dbmr->srcRect()->fTop + clip->rect().fTop - dbmr->dstRect().fTop;
586 } else {
587 newSrcLeft = clip->rect().fLeft - dbmr->dstRect().fLeft;
588 newSrcTop = clip->rect().fTop - dbmr->dstRect().fTop;
589 }
590
591 SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop,
592 clip->rect().width(), clip->rect().height());
593
594 dbmr->setSrcRect(newSrc);
595 dbmr->setDstRect(clip->rect());
596
597 // remove everything except the drawbitmaprect
598 canvas->deleteDrawCommandAt(curCommand+3);
599 canvas->deleteDrawCommandAt(curCommand+1);
600 canvas->deleteDrawCommandAt(curCommand);
601}
602
603// Check for:
604// SAVE
605// CLIP_RECT
606// DRAWBITMAPRECTTORECT
607// RESTORE
608// where:
609// clipRect is BW and encloses the DBMR2R's dest rect
610static bool check_9(SkDebugCanvas* canvas, int curCommand) {
611 if (SAVE != canvas->getDrawCommandAt(curCommand)->getType() ||
612 canvas->getSize() <= curCommand+4 ||
613 CLIP_RECT != canvas->getDrawCommandAt(curCommand+1)->getType() ||
614 DRAW_BITMAP_RECT_TO_RECT != canvas->getDrawCommandAt(curCommand+2)->getType() ||
615 RESTORE != canvas->getDrawCommandAt(curCommand+3)->getType()) {
616 return false;
617 }
618
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000619 SkClipRectCommand* clip =
620 (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+1);
621 SkDrawBitmapRectCommand* dbmr =
622 (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+2);
commit-bot@chromium.org3bdf1642013-04-01 21:00:27 +0000623
624 if (clip->doAA() || SkRegion::kIntersect_Op != clip->op()) {
625 return false;
626 }
627
628 if (!clip->rect().contains(dbmr->dstRect())) {
629 return false;
630 }
631
632 return true;
633}
634
635// remove everything except the drawbitmaprect
636static void apply_9(SkDebugCanvas* canvas, int curCommand) {
637 canvas->deleteDrawCommandAt(curCommand+3); // restore
638 // drawBitmapRectToRect
639 canvas->deleteDrawCommandAt(curCommand+1); // clipRect
640 canvas->deleteDrawCommandAt(curCommand); // save
641}
642
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000643typedef bool (*PFCheck)(SkDebugCanvas* canvas, int curCommand);
644typedef void (*PFApply)(SkDebugCanvas* canvas, int curCommand);
robertphillips@google.com73743552013-02-05 20:51:49 +0000645
646struct OptTableEntry {
647 PFCheck fCheck;
648 PFApply fApply;
649 int fNumTimesApplied;
650} gOptTable[] = {
651 { check_0, apply_0, 0 },
652 { check_1, apply_1, 0 },
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000653 { check_2, apply_2, 0 },
654 { check_3, apply_3, 0 },
655 { check_4, apply_4, 0 },
robertphillips@google.com9105ad02013-03-17 18:46:16 +0000656 { check_5, apply_5, 0 },
657 { check_6, apply_6, 0 },
robertphillips@google.comc3410b82013-03-28 12:25:25 +0000658 { check_7, apply_7, 0 },
commit-bot@chromium.org3bdf1642013-04-01 21:00:27 +0000659 { check_8, apply_8, 0 },
660 { check_9, apply_9, 0 },
robertphillips@google.com73743552013-02-05 20:51:49 +0000661};
662
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000663
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000664static int filter_picture(const SkString& inFile, const SkString& outFile) {
robertphillips@google.com4d98b742013-05-10 14:51:54 +0000665 SkAutoTDelete<SkPicture> inPicture;
djsollen@google.coma09e8832012-11-13 18:50:33 +0000666
667 SkFILEStream inStream(inFile.c_str());
668 if (inStream.isValid()) {
scroggo@google.comf1754ec2013-06-28 21:32:00 +0000669 inPicture.reset(SkPicture::CreateFromStream(&inStream));
djsollen@google.coma09e8832012-11-13 18:50:33 +0000670 }
671
robertphillips@google.com4d98b742013-05-10 14:51:54 +0000672 if (NULL == inPicture.get()) {
djsollen@google.coma09e8832012-11-13 18:50:33 +0000673 SkDebugf("Could not read file %s\n", inFile.c_str());
674 return -1;
675 }
676
robertphillips@google.com73743552013-02-05 20:51:49 +0000677 int localCount[SK_ARRAY_COUNT(gOptTable)];
678
679 memset(localCount, 0, sizeof(localCount));
680
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000681 SkDebugCanvas debugCanvas(inPicture->width(), inPicture->height());
682 debugCanvas.setBounds(inPicture->width(), inPicture->height());
683 inPicture->draw(&debugCanvas);
djsollen@google.coma09e8832012-11-13 18:50:33 +0000684
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000685 // delete the initial save and restore since replaying the commands will
robertphillips@google.com73743552013-02-05 20:51:49 +0000686 // re-add them
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000687 if (debugCanvas.getSize() > 1) {
688 debugCanvas.deleteDrawCommandAt(0);
689 debugCanvas.deleteDrawCommandAt(debugCanvas.getSize()-1);
robertphillips@google.com73743552013-02-05 20:51:49 +0000690 }
691
robertphillips@google.comd9c18532013-04-01 19:10:21 +0000692 bool changed = true;
robertphillips@google.com2e87ba02013-04-08 15:45:30 +0000693 int numBefore = debugCanvas.getSize();
robertphillips@google.comd9c18532013-04-01 19:10:21 +0000694
695 while (changed) {
696 changed = false;
697 for (int i = 0; i < debugCanvas.getSize(); ++i) {
698 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
699 if ((*gOptTable[opt].fCheck)(&debugCanvas, i)) {
700 (*gOptTable[opt].fApply)(&debugCanvas, i);
701
702 ++gOptTable[opt].fNumTimesApplied;
703 ++localCount[opt];
704
705 if (debugCanvas.getSize() == i) {
706 // the optimization removed all the remaining operations
707 break;
708 }
709
710 opt = 0; // try all the opts all over again
711 changed = true;
712 }
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000713 }
714 }
715 }
djsollen@google.coma09e8832012-11-13 18:50:33 +0000716
robertphillips@google.com2e87ba02013-04-08 15:45:30 +0000717 int numAfter = debugCanvas.getSize();
718
djsollen@google.coma09e8832012-11-13 18:50:33 +0000719 if (!outFile.isEmpty()) {
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000720 SkPicture outPicture;
721
722 SkCanvas* canvas = outPicture.beginRecording(inPicture->width(), inPicture->height());
723 debugCanvas.draw(canvas);
724 outPicture.endRecording();
725
djsollen@google.coma09e8832012-11-13 18:50:33 +0000726 SkFILEWStream outStream(outFile.c_str());
727
728 outPicture.serialize(&outStream);
729 }
730
robertphillips@google.com73743552013-02-05 20:51:49 +0000731 bool someOptFired = false;
732 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
733 if (0 != localCount[opt]) {
734 SkDebugf("%d: %d ", opt, localCount[opt]);
735 someOptFired = true;
736 }
737 }
738
739 if (!someOptFired) {
740 SkDebugf("No opts fired\n");
741 } else {
skia.committer@gmail.com32840172013-04-09 07:01:27 +0000742 SkDebugf("\t before: %d after: %d delta: %d\n",
robertphillips@google.com2e87ba02013-04-08 15:45:30 +0000743 numBefore, numAfter, numBefore-numAfter);
robertphillips@google.com73743552013-02-05 20:51:49 +0000744 }
745
djsollen@google.coma09e8832012-11-13 18:50:33 +0000746 return 0;
747}
748
tfarina@chromium.orga5b7cc02012-10-08 14:41:10 +0000749// This function is not marked as 'static' so it can be referenced externally
750// in the iOS build.
humper@google.com05af1af2013-01-07 16:47:43 +0000751int tool_main(int argc, char** argv); // suppress a warning on mac
752
caryclark@google.com9598f422012-10-09 12:32:37 +0000753int tool_main(int argc, char** argv) {
robertphillips@google.com4d98b742013-05-10 14:51:54 +0000754#if SK_ENABLE_INST_COUNT
755 gPrintInstCount = true;
756#endif
757
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000758 SkGraphics::Init();
759
robertphillips@google.com801cee12012-10-19 19:06:11 +0000760 if (argc < 3) {
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000761 usage();
762 return -1;
763 }
764
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000765 SkString inFile, outFile, inDir, outDir;
robertphillips@google.com801cee12012-10-19 19:06:11 +0000766
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000767 char* const* stop = argv + argc;
768 for (++argv; argv < stop; ++argv) {
769 if (strcmp(*argv, "-i") == 0) {
770 argv++;
771 if (argv < stop && **argv) {
772 inFile.set(*argv);
773 } else {
robertphillips@google.com801cee12012-10-19 19:06:11 +0000774 SkDebugf("missing arg for -i\n");
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000775 usage();
776 return -1;
777 }
djsollen@google.coma09e8832012-11-13 18:50:33 +0000778 } else if (strcmp(*argv, "--input-dir") == 0) {
779 argv++;
780 if (argv < stop && **argv) {
781 inDir.set(*argv);
782 } else {
783 SkDebugf("missing arg for --input-dir\n");
784 usage();
785 return -1;
786 }
787 } else if (strcmp(*argv, "--output-dir") == 0) {
788 argv++;
789 if (argv < stop && **argv) {
790 outDir.set(*argv);
791 } else {
792 SkDebugf("missing arg for --output-dir\n");
793 usage();
794 return -1;
795 }
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000796 } else if (strcmp(*argv, "-o") == 0) {
797 argv++;
798 if (argv < stop && **argv) {
799 outFile.set(*argv);
800 } else {
robertphillips@google.com801cee12012-10-19 19:06:11 +0000801 SkDebugf("missing arg for -o\n");
802 usage();
803 return -1;
804 }
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000805 } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) {
806 usage();
807 return 0;
808 } else {
809 SkDebugf("unknown arg %s\n", *argv);
810 usage();
811 return -1;
812 }
813 }
814
djsollen@google.coma09e8832012-11-13 18:50:33 +0000815 SkOSFile::Iter iter(inDir.c_str(), "skp");
humper@google.com05af1af2013-01-07 16:47:43 +0000816
djsollen@google.coma09e8832012-11-13 18:50:33 +0000817 SkString inputFilename, outputFilename;
818 if (iter.next(&inputFilename)) {
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000819
djsollen@google.coma09e8832012-11-13 18:50:33 +0000820 do {
821 sk_tools::make_filepath(&inFile, inDir, inputFilename);
822 if (!outDir.isEmpty()) {
823 sk_tools::make_filepath(&outFile, outDir, inputFilename);
824 }
825 SkDebugf("Executing %s\n", inputFilename.c_str());
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000826 filter_picture(inFile, outFile);
djsollen@google.coma09e8832012-11-13 18:50:33 +0000827 } while(iter.next(&inputFilename));
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000828
djsollen@google.coma09e8832012-11-13 18:50:33 +0000829 } else if (!inFile.isEmpty()) {
robertphillips@google.com3b0a9fe2013-01-31 15:56:22 +0000830 filter_picture(inFile, outFile);
djsollen@google.coma09e8832012-11-13 18:50:33 +0000831 } else {
832 usage();
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000833 return -1;
834 }
835
robertphillips@google.com73743552013-02-05 20:51:49 +0000836 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) {
837 SkDebugf("opt %d: %d\n", opt, gOptTable[opt].fNumTimesApplied);
838 }
839
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000840 SkGraphics::Term();
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000841 return 0;
842}
843
844#if !defined SK_BUILD_FOR_IOS
845int main(int argc, char * const argv[]) {
caryclark@google.com9598f422012-10-09 12:32:37 +0000846 return tool_main(argc, (char**) argv);
robertphillips@google.comc7e4a5a2012-10-04 13:00:33 +0000847}
848#endif