filtermain.cpp revision c3410b8cbbf63ac7968262c25c996bdbaab20588
1/* 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 8#include "SkDebugCanvas.h" 9#include "SkDevice.h" 10#include "SkGraphics.h" 11#include "SkImageDecoder.h" 12#include "SkImageEncoder.h" 13#include "SkOSFile.h" 14#include "SkPicture.h" 15#include "SkPicturePlayback.h" 16#include "SkPictureRecord.h" 17#include "SkStream.h" 18#include "picture_utils.h" 19#include "path_utils.h" 20 21static void usage() { 22 SkDebugf("Usage: filter -i inFile [-o outFile] [--input-dir path] [--output-dir path]\n"); 23 SkDebugf(" [-h|--help]\n\n"); 24 SkDebugf(" -i inFile : file to file.\n"); 25 SkDebugf(" -o outFile : result of filtering.\n"); 26 SkDebugf(" --input-dir : process all files in dir with .skp extension.\n"); 27 SkDebugf(" --output-dir : results of filtering the input dir.\n"); 28 SkDebugf(" -h|--help : Show this help message.\n"); 29} 30 31// Is the supplied paint simply a color? 32static bool is_simple(const SkPaint& p) { 33 return NULL == p.getPathEffect() && 34 NULL == p.getShader() && 35 NULL == p.getXfermode() && 36 NULL == p.getMaskFilter() && 37 NULL == p.getColorFilter() && 38 NULL == p.getRasterizer() && 39 NULL == p.getLooper() && 40 NULL == p.getImageFilter(); 41} 42 43// Check for: 44// SAVE_LAYER 45// DRAW_BITMAP_RECT_TO_RECT 46// RESTORE 47// where the saveLayer's color can be moved into the drawBitmapRect 48static bool check_0(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 49 if (SAVE_LAYER != commands[curCommand]->getType() || 50 commands.count() <= curCommand+2 || 51 DRAW_BITMAP_RECT_TO_RECT != commands[curCommand+1]->getType() || 52 RESTORE != commands[curCommand+2]->getType()) 53 return false; 54 55 SaveLayer* saveLayer = (SaveLayer*) commands[curCommand]; 56 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+1]; 57 58 const SkPaint* saveLayerPaint = saveLayer->paint(); 59 SkPaint* dbmrPaint = dbmr->paint(); 60 61 // For this optimization we only fold the saveLayer and drawBitmapRect 62 // together if the saveLayer's draw is simple (i.e., no fancy effects) and 63 // and the only difference in the colors is that the saveLayer's can have 64 // an alpha while the drawBitmapRect's is opaque. 65 // TODO: it should be possible to fold them together even if they both 66 // have different non-255 alphas but this is low priority since we have 67 // never seen that case 68 // If either operation lacks a paint then the collapse is trivial 69 SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque 70 71 return NULL == saveLayerPaint || 72 NULL == dbmrPaint || 73 (is_simple(*saveLayerPaint) && dbmrPaint->getColor() == layerColor); 74} 75 76// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer 77// and restore 78static void apply_0(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 79 SaveLayer* saveLayer = (SaveLayer*) commands[curCommand]; 80 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+1]; 81 Restore* restore = (Restore*) commands[curCommand+2]; 82 83 const SkPaint* saveLayerPaint = saveLayer->paint(); 84 SkPaint* dbmrPaint = dbmr->paint(); 85 86 if (NULL == saveLayerPaint) { 87 saveLayer->setVisible(false); 88 restore->setVisible(false); 89 } else if (NULL == dbmrPaint) { 90 saveLayer->setVisible(false); 91 dbmr->setPaint(*saveLayerPaint); 92 restore->setVisible(false); 93 } else { 94 saveLayer->setVisible(false); 95 SkColor newColor = SkColorSetA(dbmrPaint->getColor(), 96 SkColorGetA(saveLayerPaint->getColor())); 97 dbmrPaint->setColor(newColor); 98 restore->setVisible(false); 99 } 100} 101 102// Check for: 103// SAVE_LAYER 104// SAVE 105// CLIP_RECT 106// DRAW_BITMAP_RECT_TO_RECT 107// RESTORE 108// RESTORE 109// where the saveLayer's color can be moved into the drawBitmapRect 110static bool check_1(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 111 if (SAVE_LAYER != commands[curCommand]->getType() || 112 commands.count() <= curCommand+5 || 113 SAVE != commands[curCommand+1]->getType() || 114 CLIP_RECT != commands[curCommand+2]->getType() || 115 DRAW_BITMAP_RECT_TO_RECT != commands[curCommand+3]->getType() || 116 RESTORE != commands[curCommand+4]->getType() || 117 RESTORE != commands[curCommand+5]->getType()) 118 return false; 119 120 SaveLayer* saveLayer = (SaveLayer*) commands[curCommand]; 121 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+3]; 122 123 const SkPaint* saveLayerPaint = saveLayer->paint(); 124 SkPaint* dbmrPaint = dbmr->paint(); 125 126 // For this optimization we only fold the saveLayer and drawBitmapRect 127 // together if the saveLayer's draw is simple (i.e., no fancy effects) and 128 // and the only difference in the colors is that the saveLayer's can have 129 // an alpha while the drawBitmapRect's is opaque. 130 // TODO: it should be possible to fold them together even if they both 131 // have different non-255 alphas but this is low priority since we have 132 // never seen that case 133 // If either operation lacks a paint then the collapse is trivial 134 SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque 135 136 return NULL == saveLayerPaint || 137 NULL == dbmrPaint || 138 (is_simple(*saveLayerPaint) && dbmrPaint->getColor() == layerColor); 139} 140 141// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer 142// and restore 143static void apply_1(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 144 SaveLayer* saveLayer = (SaveLayer*) commands[curCommand]; 145 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+3]; 146 Restore* restore = (Restore*) commands[curCommand+5]; 147 148 const SkPaint* saveLayerPaint = saveLayer->paint(); 149 SkPaint* dbmrPaint = dbmr->paint(); 150 151 if (NULL == saveLayerPaint) { 152 saveLayer->setVisible(false); 153 restore->setVisible(false); 154 } else if (NULL == dbmrPaint) { 155 saveLayer->setVisible(false); 156 dbmr->setPaint(*saveLayerPaint); 157 restore->setVisible(false); 158 } else { 159 saveLayer->setVisible(false); 160 SkColor newColor = SkColorSetA(dbmrPaint->getColor(), 161 SkColorGetA(saveLayerPaint->getColor())); 162 dbmrPaint->setColor(newColor); 163 restore->setVisible(false); 164 } 165} 166 167// Check for: 168// SAVE 169// CLIP_RECT 170// DRAW_RECT 171// RESTORE 172// where the rect is entirely within the clip and the clip is an intersect 173static bool check_2(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 174 if (SAVE != commands[curCommand]->getType() || 175 commands.count() <= curCommand+4 || 176 CLIP_RECT != commands[curCommand+1]->getType() || 177 DRAW_RECT != commands[curCommand+2]->getType() || 178 RESTORE != commands[curCommand+3]->getType()) 179 return false; 180 181 ClipRect* cr = (ClipRect*) commands[curCommand+1]; 182 DrawRectC* dr = (DrawRectC*) commands[curCommand+2]; 183 184 if (SkRegion::kIntersect_Op != cr->op()) { 185 return false; 186 } 187 188 return cr->rect().contains(dr->rect()); 189} 190 191// Remove everything but the drawRect 192static void apply_2(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 193 Save* save = (Save*) commands[curCommand]; 194 ClipRect* cr = (ClipRect*) commands[curCommand+1]; 195 Restore* restore = (Restore*) commands[curCommand+3]; 196 197 save->setVisible(false); 198 cr->setVisible(false); 199 // leave the drawRect alone 200 restore->setVisible(false); 201} 202 203// Check for: 204// SAVE 205// CLIP_RRECT 206// DRAW_RECT 207// RESTORE 208// where the rect entirely encloses the clip 209static bool check_3(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 210 if (SAVE != commands[curCommand]->getType() || 211 commands.count() <= curCommand+4 || 212 CLIP_RRECT != commands[curCommand+1]->getType() || 213 DRAW_RECT != commands[curCommand+2]->getType() || 214 RESTORE != commands[curCommand+3]->getType()) 215 return false; 216 217 ClipRRect* crr = (ClipRRect*) commands[curCommand+1]; 218 DrawRectC* dr = (DrawRectC*) commands[curCommand+2]; 219 220 if (SkRegion::kIntersect_Op != crr->op()) { 221 return false; 222 } 223 224 return dr->rect().contains(crr->rrect().rect()); 225} 226 227// Replace everything with a drawRRect with the paint from the drawRect 228// and the AA settings from the clipRRect 229static void apply_3(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 230 Save* save = (Save*) commands[curCommand]; 231 ClipRRect* crr = (ClipRRect*) commands[curCommand+1]; 232 DrawRectC* dr = (DrawRectC*) commands[curCommand+2]; 233 Restore* restore = (Restore*) commands[curCommand+3]; 234 235 save->setVisible(false); 236 crr->setVisible(false); 237 dr->setVisible(false); 238 restore->setVisible(false); 239 240 // TODO: could skip paint re-creation if the AA settings already match 241 SkPaint newPaint = dr->paint(); 242 newPaint.setAntiAlias(crr->doAA()); 243 DrawRRect* drr = new DrawRRect(crr->rrect(), newPaint); 244 commands[curCommand+2] = drr; 245} 246 247// Check for: 248// SAVE 249// CLIP_RECT 250// DRAW_BITMAP_RECT_TO_RECT 251// RESTORE 252// where the rect and drawBitmapRect dst exactly match 253static bool check_4(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 254 if (SAVE != commands[curCommand]->getType() || 255 commands.count() <= curCommand+4 || 256 CLIP_RECT != commands[curCommand+1]->getType() || 257 DRAW_BITMAP_RECT_TO_RECT != commands[curCommand+2]->getType() || 258 RESTORE != commands[curCommand+3]->getType()) 259 return false; 260 261 ClipRect* cr = (ClipRect*) commands[curCommand+1]; 262 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+2]; 263 264 if (SkRegion::kIntersect_Op != cr->op()) { 265 return false; 266 } 267 268 return dbmr->dstRect() == cr->rect(); 269} 270 271// Remove everything but the drawBitmapRect 272static void apply_4(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 273 Save* save = (Save*) commands[curCommand]; 274 ClipRect* cr = (ClipRect*) commands[curCommand+1]; 275 Restore* restore = (Restore*) commands[curCommand+3]; 276 277 save->setVisible(false); 278 cr->setVisible(false); 279 // leave drawBitmapRect alone 280 restore->setVisible(false); 281} 282 283// Check for: 284// TRANSLATE 285// where the translate is zero 286static bool check_5(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 287 if (TRANSLATE != commands[curCommand]->getType()) { 288 return false; 289 } 290 291 Translate* t = (Translate*) commands[curCommand]; 292 293 return 0 == t->x() && 0 == t->y(); 294} 295 296// Just remove the translate 297static void apply_5(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 298 Translate* t = (Translate*) commands[curCommand]; 299 300 t->setVisible(false); 301} 302 303// Check for: 304// SCALE 305// where the scale is 1,1 306static bool check_6(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 307 if (SCALE != commands[curCommand]->getType()) { 308 return false; 309 } 310 311 Scale* s = (Scale*) commands[curCommand]; 312 313 return SK_Scalar1 == s->x() && SK_Scalar1 == s->y(); 314} 315 316// Just remove the scale 317static void apply_6(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 318 Scale* s = (Scale*) commands[curCommand]; 319 320 s->setVisible(false); 321} 322 323// Check for: 324// SAVE 325// CLIP_RECT 326// SAVE_LAYER 327// SAVE 328// CLIP_RECT 329// SAVE_LAYER 330// SAVE 331// CLIP_RECT 332// DRAWBITMAPRECTTORECT 333// RESTORE 334// RESTORE 335// RESTORE 336// RESTORE 337// RESTORE 338// where: 339// all the clipRect's are BW, nested, intersections 340// the drawBitmapRectToRect is a 1-1 copy from src to dest 341// the last (smallest) clip rect is a subset of the drawBitmapRectToRect's dest rect 342// all the saveLayer's paints can be rolled into the drawBitmapRectToRect's paint 343// This pattern is used by Google spreadsheet when drawing the toolbar buttons 344static bool check_7(const SkTDArray<SkDrawCommand*>& commands, int curCommand) { 345 if (SAVE != commands[curCommand]->getType() || 346 commands.count() <= curCommand+13 || 347 CLIP_RECT != commands[curCommand+1]->getType() || 348 SAVE_LAYER != commands[curCommand+2]->getType() || 349 SAVE != commands[curCommand+3]->getType() || 350 CLIP_RECT != commands[curCommand+4]->getType() || 351 SAVE_LAYER != commands[curCommand+5]->getType() || 352 SAVE != commands[curCommand+6]->getType() || 353 CLIP_RECT != commands[curCommand+7]->getType() || 354 DRAW_BITMAP_RECT_TO_RECT != commands[curCommand+8]->getType() || 355 RESTORE != commands[curCommand+9]->getType() || 356 RESTORE != commands[curCommand+10]->getType() || 357 RESTORE != commands[curCommand+11]->getType() || 358 RESTORE != commands[curCommand+12]->getType() || 359 RESTORE != commands[curCommand+13]->getType()) 360 return false; 361 362 ClipRect* clip0 = (ClipRect*) commands[curCommand+1]; 363 SaveLayer* saveLayer0 = (SaveLayer*) commands[curCommand+2]; 364 ClipRect* clip1 = (ClipRect*) commands[curCommand+4]; 365 SaveLayer* saveLayer1 = (SaveLayer*) commands[curCommand+5]; 366 ClipRect* clip2 = (ClipRect*) commands[curCommand+7]; 367 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+8]; 368 369 if (clip0->doAA() || clip1->doAA() || clip2->doAA()) { 370 return false; 371 } 372 373 if (SkRegion::kIntersect_Op != clip0->op() || 374 SkRegion::kIntersect_Op != clip1->op() || 375 SkRegion::kIntersect_Op != clip2->op()) { 376 return false; 377 } 378 379 if (!clip0->rect().contains(clip1->rect()) || 380 !clip1->rect().contains(clip2->rect())) { 381 return false; 382 } 383 384 // The src->dest mapping needs to be 1-to-1 385 if (NULL == dbmr->srcRect()) { 386 if (dbmr->bitmap().width() != dbmr->dstRect().width() || 387 dbmr->bitmap().height() != dbmr->dstRect().height()) { 388 return false; 389 } 390 } else { 391 if (dbmr->srcRect()->width() != dbmr->dstRect().width() || 392 dbmr->srcRect()->height() != dbmr->dstRect().height()) { 393 return false; 394 } 395 } 396 397 if (!dbmr->dstRect().contains(clip2->rect())) { 398 return false; 399 } 400 401 const SkPaint* saveLayerPaint0 = saveLayer0->paint(); 402 const SkPaint* saveLayerPaint1 = saveLayer1->paint(); 403 404 if ((NULL != saveLayerPaint0 && !is_simple(*saveLayerPaint0)) || 405 (NULL != saveLayerPaint1 && !is_simple(*saveLayerPaint1))) { 406 return false; 407 } 408 409 SkPaint* dbmrPaint = dbmr->paint(); 410 411 if (NULL == dbmrPaint) { 412 return true; 413 } 414 415 if (NULL != saveLayerPaint0) { 416 SkColor layerColor0 = saveLayerPaint0->getColor() | 0xFF000000; // force opaque 417 if (dbmrPaint->getColor() != layerColor0) { 418 return false; 419 } 420 } 421 422 if (NULL != saveLayerPaint1) { 423 SkColor layerColor1 = saveLayerPaint1->getColor() | 0xFF000000; // force opaque 424 if (dbmrPaint->getColor() != layerColor1) { 425 return false; 426 } 427 } 428 429 return true; 430} 431 432// Reduce to a single drawBitmapRectToRect call by folding the clipRect's into 433// the src and dst Rects and the saveLayer paints into the drawBitmapRectToRect's 434// paint. 435static void apply_7(SkTDArray<SkDrawCommand*>& commands, int curCommand) { 436 Save* save0 = (Save*) commands[curCommand]; 437 ClipRect* clip0 = (ClipRect*) commands[curCommand+1]; 438 SaveLayer* saveLayer0 = (SaveLayer*) commands[curCommand+2]; 439 Save* save1 = (Save*) commands[curCommand+3]; 440 ClipRect* clip1 = (ClipRect*) commands[curCommand+4]; 441 SaveLayer* saveLayer1 = (SaveLayer*) commands[curCommand+5]; 442 Save* save2 = (Save*) commands[curCommand+6]; 443 ClipRect* clip2 = (ClipRect*) commands[curCommand+7]; 444 DrawBitmapRect* dbmr = (DrawBitmapRect*) commands[curCommand+8]; 445 Restore* restore0 = (Restore*) commands[curCommand+9]; 446 Restore* restore1 = (Restore*) commands[curCommand+10]; 447 Restore* restore2 = (Restore*) commands[curCommand+11]; 448 Restore* restore3 = (Restore*) commands[curCommand+12]; 449 Restore* restore4 = (Restore*) commands[curCommand+13]; 450 451 SkScalar newSrcLeft = dbmr->srcRect()->fLeft + clip2->rect().fLeft - dbmr->dstRect().fLeft; 452 SkScalar newSrcTop = dbmr->srcRect()->fTop + clip2->rect().fTop - dbmr->dstRect().fTop; 453 454 SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop, 455 clip2->rect().width(), clip2->rect().height()); 456 457 dbmr->setSrcRect(newSrc); 458 dbmr->setDstRect(clip2->rect()); 459 460 SkColor color = 0xFF000000; 461 int a0, a1; 462 463 const SkPaint* saveLayerPaint0 = saveLayer0->paint(); 464 if (NULL != saveLayerPaint0) { 465 color = saveLayerPaint0->getColor(); 466 a0 = SkColorGetA(color); 467 } else { 468 a0 = 0xFF; 469 } 470 471 const SkPaint* saveLayerPaint1 = saveLayer1->paint(); 472 if (NULL != saveLayerPaint1) { 473 color = saveLayerPaint1->getColor(); 474 a1 = SkColorGetA(color); 475 } else { 476 a1 = 0xFF; 477 } 478 479 int newA = (a0 * a1) / 255; 480 SkASSERT(newA <= 0xFF); 481 482 SkPaint* dbmrPaint = dbmr->paint(); 483 484 if (NULL != dbmrPaint) { 485 SkColor newColor = SkColorSetA(dbmrPaint->getColor(), newA); 486 dbmrPaint->setColor(newColor); 487 } else { 488 SkColor newColor = SkColorSetA(color, newA); 489 490 SkPaint newPaint; 491 newPaint.setColor(newColor); 492 dbmr->setPaint(newPaint); 493 } 494 495 // remove everything except the drawbitmaprect 496 save0->setVisible(false); 497 clip0->setVisible(false); 498 saveLayer0->setVisible(false); 499 save1->setVisible(false); 500 clip1->setVisible(false); 501 saveLayer1->setVisible(false); 502 save2->setVisible(false); 503 clip2->setVisible(false); 504 restore0->setVisible(false); 505 restore1->setVisible(false); 506 restore2->setVisible(false); 507 restore3->setVisible(false); 508 restore4->setVisible(false); 509} 510 511typedef bool (*PFCheck)(const SkTDArray<SkDrawCommand*>& commands, int curCommand); 512typedef void (*PFApply)(SkTDArray<SkDrawCommand*>& commands, int curCommand); 513 514struct OptTableEntry { 515 PFCheck fCheck; 516 PFApply fApply; 517 int fNumTimesApplied; 518} gOptTable[] = { 519 { check_0, apply_0, 0 }, 520 { check_1, apply_1, 0 }, 521 { check_2, apply_2, 0 }, 522 { check_3, apply_3, 0 }, 523 { check_4, apply_4, 0 }, 524 { check_5, apply_5, 0 }, 525 { check_6, apply_6, 0 }, 526 { check_7, apply_7, 0 }, 527}; 528 529static int filter_picture(const SkString& inFile, const SkString& outFile) { 530 SkPicture* inPicture = NULL; 531 532 SkFILEStream inStream(inFile.c_str()); 533 if (inStream.isValid()) { 534 inPicture = SkNEW_ARGS(SkPicture, (&inStream, NULL, &SkImageDecoder::DecodeMemory)); 535 } 536 537 if (NULL == inPicture) { 538 SkDebugf("Could not read file %s\n", inFile.c_str()); 539 return -1; 540 } 541 542 int localCount[SK_ARRAY_COUNT(gOptTable)]; 543 544 memset(localCount, 0, sizeof(localCount)); 545 546 SkDebugCanvas debugCanvas(inPicture->width(), inPicture->height()); 547 debugCanvas.setBounds(inPicture->width(), inPicture->height()); 548 inPicture->draw(&debugCanvas); 549 550 SkTDArray<SkDrawCommand*>& commands = debugCanvas.getDrawCommands(); 551 552 // hide the initial save and restore since replaying the commands will 553 // re-add them 554 if (commands.count() > 0) { 555 commands[0]->setVisible(false); 556 commands[commands.count()-1]->setVisible(false); 557 } 558 559 for (int i = 0; i < commands.count(); ++i) { 560 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { 561 if ((*gOptTable[opt].fCheck)(commands, i)) { 562 (*gOptTable[opt].fApply)(commands, i); 563 ++gOptTable[opt].fNumTimesApplied; 564 ++localCount[opt]; 565 } 566 } 567 } 568 569 if (!outFile.isEmpty()) { 570 SkPicture outPicture; 571 572 SkCanvas* canvas = outPicture.beginRecording(inPicture->width(), inPicture->height()); 573 debugCanvas.draw(canvas); 574 outPicture.endRecording(); 575 576 SkFILEWStream outStream(outFile.c_str()); 577 578 outPicture.serialize(&outStream); 579 } 580 581 bool someOptFired = false; 582 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { 583 if (0 != localCount[opt]) { 584 SkDebugf("%d: %d ", opt, localCount[opt]); 585 someOptFired = true; 586 } 587 } 588 589 if (!someOptFired) { 590 SkDebugf("No opts fired\n"); 591 } else { 592 SkDebugf("\n"); 593 } 594 595 return 0; 596} 597 598// This function is not marked as 'static' so it can be referenced externally 599// in the iOS build. 600int tool_main(int argc, char** argv); // suppress a warning on mac 601 602int tool_main(int argc, char** argv) { 603 SkGraphics::Init(); 604 605 if (argc < 3) { 606 usage(); 607 return -1; 608 } 609 610 SkString inFile, outFile, inDir, outDir; 611 612 char* const* stop = argv + argc; 613 for (++argv; argv < stop; ++argv) { 614 if (strcmp(*argv, "-i") == 0) { 615 argv++; 616 if (argv < stop && **argv) { 617 inFile.set(*argv); 618 } else { 619 SkDebugf("missing arg for -i\n"); 620 usage(); 621 return -1; 622 } 623 } else if (strcmp(*argv, "--input-dir") == 0) { 624 argv++; 625 if (argv < stop && **argv) { 626 inDir.set(*argv); 627 } else { 628 SkDebugf("missing arg for --input-dir\n"); 629 usage(); 630 return -1; 631 } 632 } else if (strcmp(*argv, "--output-dir") == 0) { 633 argv++; 634 if (argv < stop && **argv) { 635 outDir.set(*argv); 636 } else { 637 SkDebugf("missing arg for --output-dir\n"); 638 usage(); 639 return -1; 640 } 641 } else if (strcmp(*argv, "-o") == 0) { 642 argv++; 643 if (argv < stop && **argv) { 644 outFile.set(*argv); 645 } else { 646 SkDebugf("missing arg for -o\n"); 647 usage(); 648 return -1; 649 } 650 } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) { 651 usage(); 652 return 0; 653 } else { 654 SkDebugf("unknown arg %s\n", *argv); 655 usage(); 656 return -1; 657 } 658 } 659 660 SkOSFile::Iter iter(inDir.c_str(), "skp"); 661 662 SkString inputFilename, outputFilename; 663 if (iter.next(&inputFilename)) { 664 665 do { 666 sk_tools::make_filepath(&inFile, inDir, inputFilename); 667 if (!outDir.isEmpty()) { 668 sk_tools::make_filepath(&outFile, outDir, inputFilename); 669 } 670 SkDebugf("Executing %s\n", inputFilename.c_str()); 671 filter_picture(inFile, outFile); 672 } while(iter.next(&inputFilename)); 673 674 } else if (!inFile.isEmpty()) { 675 filter_picture(inFile, outFile); 676 } else { 677 usage(); 678 return -1; 679 } 680 681 for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { 682 SkDebugf("opt %d: %d\n", opt, gOptTable[opt].fNumTimesApplied); 683 } 684 685 SkGraphics::Term(); 686 return 0; 687} 688 689#if !defined SK_BUILD_FOR_IOS 690int main(int argc, char * const argv[]) { 691 return tool_main(argc, (char**) argv); 692} 693#endif 694