15092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com/* 25092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com * Copyright 2013 Google Inc. 35092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com * 45092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com * Use of this source code is governed by a BSD-style license that can be 55092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com * found in the LICENSE file. 65092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com */ 75092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 85092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkPdfDiffEncoder.h" 95092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkPdfNativeTokenizer.h" 105092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 115092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#ifdef PDF_TRACE_DIFF_IN_PNG 125092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkBitmap.h" 135092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkBitmapDevice.h" 145092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkCanvas.h" 155092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkClipStack.h" 165092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkColor.h" 175092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkImageEncoder.h" 185092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkPaint.h" 195092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkPath.h" 205092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkRegion.h" 215092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkScalar.h" 225092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#include "SkString.h" 235092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 245092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comextern "C" SkBitmap* gDumpBitmap; 255092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comextern "C" SkCanvas* gDumpCanvas; 265092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comSkBitmap* gDumpBitmap = NULL; 275092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comSkCanvas* gDumpCanvas = NULL; 285092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comstatic int gReadOp; 295092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comstatic int gOpCounter; 305092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comstatic SkString gLastKeyword; 315092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#endif // PDF_TRACE_DIFF_IN_PNG 325092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 335092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.comvoid SkPdfDiffEncoder::WriteToFile(PdfToken* token) { 345092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#ifdef PDF_TRACE_DIFF_IN_PNG 355092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com gReadOp++; 365092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com gOpCounter++; 375092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 385092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // Only attempt to write if the dump bitmap and canvas are non NULL. They are set by 395092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // pdf_viewer_main.cpp 405092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (NULL == gDumpBitmap || NULL == gDumpCanvas) { 415092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com return; 425092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 435092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 445092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // TODO(edisonn): this code is used to make a step by step history of all the draw operations 455092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // so we could find the step where something is wrong. 465092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (!gLastKeyword.isEmpty()) { 475092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com gDumpCanvas->flush(); 485092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 495092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // Copy the existing drawing. Then we will draw the difference caused by this command, 505092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // highlighted with a blue border. 515092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkBitmap bitmap; 525092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (gDumpBitmap->copyTo(&bitmap, SkBitmap::kARGB_8888_Config)) { 535092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 545092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 555092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkCanvas canvas(device); 565092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 575092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // draw context stuff here 585092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkPaint blueBorder; 595092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com blueBorder.setColor(SK_ColorBLUE); 605092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com blueBorder.setStyle(SkPaint::kStroke_Style); 615092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com blueBorder.setTextSize(SkDoubleToScalar(20)); 625092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 635092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkString str; 645092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 655092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com const SkClipStack* clipStack = gDumpCanvas->getClipStack(); 665092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (clipStack) { 675092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); 685092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com const SkClipStack::Element* elem; 695092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com double y = 0; 705092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com int total = 0; 715092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com while ((elem = iter.next()) != NULL) { 725092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com total++; 735092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com y += 30; 745092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 755092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com switch (elem->getType()) { 765092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com case SkClipStack::Element::kRect_Type: 775092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawRect(elem->getRect(), blueBorder); 785092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawText("Rect Clip", strlen("Rect Clip"), 795092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 805092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com break; 815092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com case SkClipStack::Element::kPath_Type: 825092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawPath(elem->getPath(), blueBorder); 835092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawText("Path Clip", strlen("Path Clip"), 845092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 855092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com break; 865092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com case SkClipStack::Element::kEmpty_Type: 875092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawText("Empty Clip!!!", strlen("Empty Clip!!!"), 885092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 895092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com break; 905092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com default: 915092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawText("Unknown Clip!!!", strlen("Unknown Clip!!!"), 925092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 935092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com break; 945092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 955092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 965092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 975092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com y += 30; 985092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com str.printf("Number of clips in stack: %i", total); 995092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawText(str.c_str(), str.size(), 1005092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkDoubleToScalar(10), SkDoubleToScalar(y), blueBorder); 1015092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 1025092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1035092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com const SkRegion& clipRegion = gDumpCanvas->getTotalClip(); 1045092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkPath clipPath; 1055092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (clipRegion.getBoundaryPath(&clipPath)) { 1065092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkPaint redBorder; 1075092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com redBorder.setColor(SK_ColorRED); 1085092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com redBorder.setStyle(SkPaint::kStroke_Style); 1095092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.drawPath(clipPath, redBorder); 1105092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 1115092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1125092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com canvas.flush(); 1135092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1145092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkString out; 1155092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1165092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com // TODO(edisonn): overlay on top of image inf about the clip , grafic state, the stack 1175092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1185092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com out.appendf("/tmp/log_step_by_step/step-%i-%s.png", gOpCounter, gLastKeyword.c_str()); 1195092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1205092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); 1215092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 1225092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 1235092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com 1245092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com if (token->fType == kKeyword_TokenType && token->fKeyword && token->fKeywordLength > 0) { 1255092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com gLastKeyword.set(token->fKeyword, token->fKeywordLength); 1265092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } else { 1275092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com gLastKeyword.reset(); 1285092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com } 1295092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com#endif 1305092adc5461a7c5cb3e1fad01be2174c3f4a0c46scroggo@google.com} 131