1 /* 2 * Copyright 2013 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 "SkPdfDiffEncoder.h" 9 #include "SkPdfNativeTokenizer.h" 10 11 #ifdef PDF_TRACE_DIFF_IN_PNG 12 #include "SkBitmap.h" 13 #include "SkBitmapDevice.h" 14 #include "SkCanvas.h" 15 #include "SkClipStack.h" 16 #include "SkColor.h" 17 #include "SkImageEncoder.h" 18 #include "SkPaint.h" 19 #include "SkPath.h" 20 #include "SkRegion.h" 21 #include "SkScalar.h" 22 #include "SkString.h" 23 24 extern "C" SkBitmap* gDumpBitmap; 25 extern "C" SkCanvas* gDumpCanvas; 26 SkBitmap* gDumpBitmap = NULL; 27 SkCanvas* gDumpCanvas = NULL; 28 static int gReadOp; 29 static int gOpCounter; 30 static SkString gLastKeyword; 31 #endif // PDF_TRACE_DIFF_IN_PNG 32 33 void SkPdfDiffEncoder::WriteToFile(PdfToken* token) { 34 #ifdef PDF_TRACE_DIFF_IN_PNG 35 gReadOp++; 36 gOpCounter++; 37 38 // Only attempt to write if the dump bitmap and canvas are non NULL. They are set by 39 // pdf_viewer_main.cpp 40 if (NULL == gDumpBitmap || NULL == gDumpCanvas) { 41 return; 42 } 43 44 // TODO(edisonn): this code is used to make a step by step history of all the draw operations 45 // so we could find the step where something is wrong. 46 if (!gLastKeyword.isEmpty()) { 47 gDumpCanvas->flush(); 48 49 // Copy the existing drawing. Then we will draw the difference caused by this command, 50 // highlighted with a blue border. 51 SkBitmap bitmap; 52 if (gDumpBitmap->copyTo(&bitmap, SkBitmap::kARGB_8888_Config)) { 53 54 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 55 SkCanvas canvas(device); 56 57 // draw context stuff here 58 SkPaint blueBorder; 59 blueBorder.setColor(SK_ColorBLUE); 60 blueBorder.setStyle(SkPaint::kStroke_Style); 61 blueBorder.setTextSize(SkDoubleToScalar(20)); 62 63 SkString str; 64 65 const SkClipStack* clipStack = gDumpCanvas->getClipStack(); 66 if (clipStack) { 67 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 68 const SkClipStack::Element* elem; 69 double y = 0; 70 int total = 0; 71 while ((elem = iter.next()) != NULL) { 72 total++; 73 y += 30; 74 75 switch (elem->getType()) { 76 case SkClipStack::Element::kRect_Type: 77 canvas.drawRect(elem->getRect(), blueBorder); 78 canvas.drawText("Rect Clip", strlen("Rect Clip"), 79 SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 80 break; 81 case SkClipStack::Element::kPath_Type: 82 canvas.drawPath(elem->getPath(), blueBorder); 83 canvas.drawText("Path Clip", strlen("Path Clip"), 84 SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 85 break; 86 case SkClipStack::Element::kEmpty_Type: 87 canvas.drawText("Empty Clip!!!", strlen("Empty Clip!!!"), 88 SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 89 break; 90 default: 91 canvas.drawText("Unknown Clip!!!", strlen("Unknown Clip!!!"), 92 SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 93 break; 94 } 95 } 96 97 y += 30; 98 str.printf("Number of clips in stack: %i", total); 99 canvas.drawText(str.c_str(), str.size(), 100 SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 101 } 102 103 const SkRegion& clipRegion = gDumpCanvas->getTotalClip(); 104 SkPath clipPath; 105 if (clipRegion.getBoundaryPath(&clipPath)) { 106 SkPaint redBorder; 107 redBorder.setColor(SK_ColorRED); 108 redBorder.setStyle(SkPaint::kStroke_Style); 109 canvas.drawPath(clipPath, redBorder); 110 } 111 112 canvas.flush(); 113 114 SkString out; 115 116 // TODO(edisonn): overlay on top of image inf about the clip , grafic state, the stack 117 118 out.appendf("/tmp/log_step_by_step/step-%i-%s.png", gOpCounter, gLastKeyword.c_str()); 119 120 SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); 121 } 122 } 123 124 if (token->fType == kKeyword_TokenType && token->fKeyword && token->fKeywordLength > 0) { 125 gLastKeyword.set(token->fKeyword, token->fKeywordLength); 126 } else { 127 gLastKeyword.reset(); 128 } 129 #endif 130 } 131