From 0b5bbb0f82e022c8acfbcb6312f0ed18e1ab90ce Mon Sep 17 00:00:00 2001 From: "chudy@google.com" Date: Tue, 31 Jul 2012 19:55:32 +0000 Subject: [PATCH] Optimized hit testing feature, refactored into seperate function from canvas draw calls Review URL: https://codereview.appspot.com/6443068 git-svn-id: http://skia.googlecode.com/svn/trunk@4867 2bbb7eff-a529-9590-31e7-b0007b416f81 --- debugger/QT/SkCanvasWidget.cpp | 13 ++----- debugger/QT/SkGLWidget.cpp | 3 +- debugger/QT/SkGLWidget.h | 2 +- debugger/QT/SkRasterWidget.cpp | 10 ++--- debugger/QT/SkRasterWidget.h | 2 +- debugger/SkDebugCanvas.cpp | 85 +++++++++++++++++++++++++----------------- debugger/SkDebugCanvas.h | 30 ++++----------- debugger/SkDrawCommand.h | 9 ++++- debugger/SkHitBox.cpp | 66 -------------------------------- debugger/SkHitBox.h | 81 ---------------------------------------- gyp/debugger.gyp | 2 - 11 files changed, 73 insertions(+), 230 deletions(-) delete mode 100644 debugger/SkHitBox.cpp delete mode 100644 debugger/SkHitBox.h diff --git a/debugger/QT/SkCanvasWidget.cpp b/debugger/QT/SkCanvasWidget.cpp index e4716af..c560aec 100644 --- a/debugger/QT/SkCanvasWidget.cpp +++ b/debugger/QT/SkCanvasWidget.cpp @@ -33,9 +33,7 @@ SkCanvasWidget::SkCanvasWidget() : QWidget() } SkCanvasWidget::~SkCanvasWidget() { - if (fDebugCanvas) { - delete fDebugCanvas; - } + delete fDebugCanvas; } void SkCanvasWidget::drawTo(int index) { @@ -78,13 +76,8 @@ void SkCanvasWidget::mouseMoveEvent(QMouseEvent* event) { void SkCanvasWidget::mousePressEvent(QMouseEvent* event) { fPreviousPoint.set(event->globalX(), event->globalY()); - if (fDebugCanvas) { - fDebugCanvas->getBoxClass()->setHitPoint(event->x(), event->y()); - fDebugCanvas->isCalculatingHits(true); - drawTo(fIndex); - emit hitChanged(fDebugCanvas->getHitBoxPoint()); - fDebugCanvas->isCalculatingHits(false); - } + emit hitChanged(fDebugCanvas->getLayerAtPoint(event->x(), event->y(), + fIndex, fTransform, fScaleFactor)); } void SkCanvasWidget::mouseDoubleClickEvent(QMouseEvent* event) { diff --git a/debugger/QT/SkGLWidget.cpp b/debugger/QT/SkGLWidget.cpp index 74ed48e..e3c4161 100644 --- a/debugger/QT/SkGLWidget.cpp +++ b/debugger/QT/SkGLWidget.cpp @@ -54,8 +54,7 @@ void SkGLWidget::paintGL() { } else if (fScaleFactor > 0) { canvas.scale(fScaleFactor, fScaleFactor); } - // TODO(chudy): Remove bitmap arguement. - fDebugCanvas->drawTo(&canvas, fIndex+1, NULL); + fDebugCanvas->drawTo(&canvas, fIndex); canvas.flush(); } diff --git a/debugger/QT/SkGLWidget.h b/debugger/QT/SkGLWidget.h index 5295f4c..76257be 100644 --- a/debugger/QT/SkGLWidget.h +++ b/debugger/QT/SkGLWidget.h @@ -29,7 +29,7 @@ public: void setDebugCanvas(SkDebugCanvas* debugCanvas) { fDebugCanvas = debugCanvas; - fIndex = debugCanvas->getSize(); + fIndex = debugCanvas->getSize() - 1; this->updateGL(); } diff --git a/debugger/QT/SkRasterWidget.cpp b/debugger/QT/SkRasterWidget.cpp index db89de7..2cf1f34 100644 --- a/debugger/QT/SkRasterWidget.cpp +++ b/debugger/QT/SkRasterWidget.cpp @@ -28,12 +28,8 @@ SkRasterWidget::~SkRasterWidget() { void SkRasterWidget::resizeEvent(QResizeEvent* event) { fBitmap.setConfig(SkBitmap::kARGB_8888_Config, event->size().width(), event->size().height()); fBitmap.allocPixels(); - if (fDevice) { - delete fDevice; - } - fDevice = new SkDevice(fBitmap); - - + delete fDevice; + fDevice = new SkDevice(fBitmap); this->update(); } @@ -50,7 +46,7 @@ void SkRasterWidget::paintEvent(QPaintEvent* event) { fMatrix = canvas.getTotalMatrix(); fClip = canvas.getTotalClip().getBounds(); - fDebugCanvas->drawTo(&canvas, fIndex+1, &fBitmap); + fDebugCanvas->drawTo(&canvas, fIndex); QPainter painter(this); QStyleOption opt; diff --git a/debugger/QT/SkRasterWidget.h b/debugger/QT/SkRasterWidget.h index af65792..1692800 100644 --- a/debugger/QT/SkRasterWidget.h +++ b/debugger/QT/SkRasterWidget.h @@ -31,7 +31,7 @@ public: void setDebugCanvas(SkDebugCanvas* debugCanvas) { fDebugCanvas = debugCanvas; - fIndex = debugCanvas->getSize(); + fIndex = debugCanvas->getSize() - 1; this->update(); } diff --git a/debugger/SkDebugCanvas.cpp b/debugger/SkDebugCanvas.cpp index 12d7127..9819858 100644 --- a/debugger/SkDebugCanvas.cpp +++ b/debugger/SkDebugCanvas.cpp @@ -29,47 +29,62 @@ void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) { void SkDebugCanvas::draw(SkCanvas* canvas) { if(!commandVector.empty()) { for(it = commandVector.begin(); it != commandVector.end(); ++it) { - if ((*it)->getVisibility()) { + if ((*it)->isVisible()) { (*it)->execute(canvas); } } } } -void SkDebugCanvas::drawTo(SkCanvas* canvas, int index, SkBitmap* bitmap) { +int SkDebugCanvas::getCommandAtPoint(int x, int y, int index, + SkIPoint transform, float scale) { + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); + bitmap.allocPixels(); + + SkCanvas canvas(bitmap); + canvas.translate(transform.fX - x, transform.fY - y); + if (scale < 0) { + canvas.scale((1.0 / -scale), (1.0 / -scale)); + } else if (scale > 0) { + canvas.scale(scale, scale); + } + + int layer = 0; + int prev = bitmap.getColor(0,0); + for (int i = 0; i < index; i++) { + if (commandVector[i]->isVisible()) { + commandVector[i]->execute(&canvas); + } + if (prev != bitmap.getColor(0,0)) { + layer = i; + } + prev = bitmap.getColor(0,0); + } + return layer; +} + +void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { int counter = 0; - if(!commandVector.empty()) { - for(it = commandVector.begin(); it != commandVector.end(); ++it) { - if (counter != (index-1)) { - if ((*it)->getVisibility()) { - (*it)->execute(canvas); - } - } else { - if (fFilter) { - SkPaint* p = new SkPaint(); - p->setColor(0xAAFFFFFF); - canvas->save(); - canvas->resetMatrix(); - SkRect dump; - // TODO(chudy): Replace with a call to QtWidget to get dimensions. - dump.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(fWidth), SkIntToScalar(fHeight)); - canvas->clipRect(dump, SkRegion::kReplace_Op, false ); - canvas->drawRectCoords(SkIntToScalar(0),SkIntToScalar(0),SkIntToScalar(fWidth),SkIntToScalar(fHeight), *p); - canvas->restore(); - } - if ((*it)->getVisibility()) { - (*it)->execute(canvas); - } - } - if (fCalculateHits == true && bitmap != NULL) { - fHitBox.updateHitPoint(bitmap, counter); - } + SkASSERT(!commandVector.empty()); + SkASSERT(index < commandVector.size()); + for (int i = 0; i <= index; i++) { + if (i == index && fFilter) { + SkPaint p; + p.setColor(0xAAFFFFFF); + canvas->save(); + canvas->resetMatrix(); + SkRect mask; + mask.set(SkIntToScalar(0), SkIntToScalar(0), + SkIntToScalar(fWidth), SkIntToScalar(fHeight)); + canvas->clipRect(mask, SkRegion::kReplace_Op, false); + canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0), + SkIntToScalar(fWidth), SkIntToScalar(fHeight), p); + canvas->restore(); + } - /* TODO(chudy): Implement a bitmap wide function that will take - * ~50 out of each R,G,B. This will make everything but the last - * command brighter. - */ - if (++counter == index) return; + if (commandVector[i]->isVisible()) { + commandVector[i]->execute(canvas); } } } @@ -86,7 +101,7 @@ std::vector* SkDebugCanvas::getCommandInfoAt(int index) { bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) { SkASSERT(index < commandVector.size()); - return commandVector[index]->getVisibility(); + return commandVector[index]->isVisible(); } std::vector SkDebugCanvas::getDrawCommands() { @@ -252,5 +267,5 @@ bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) { void SkDebugCanvas::toggleCommand(int index, bool toggle) { SkASSERT(index < commandVector.size()); - commandVector[index]->setVisibility(toggle); + commandVector[index]->setVisible(toggle); } diff --git a/debugger/SkDebugCanvas.h b/debugger/SkDebugCanvas.h index fa2d757..c13ea10 100644 --- a/debugger/SkDebugCanvas.h +++ b/debugger/SkDebugCanvas.h @@ -13,7 +13,6 @@ #include "SkCanvas.h" #include "SkDrawCommand.h" #include "SkPicture.h" -#include "SkHitBox.h" #include class SkDebugCanvas : public SkCanvas { @@ -43,7 +42,13 @@ public: @param canvas The canvas being drawn to @param index The index of the final command being executed */ - void drawTo(SkCanvas* canvas, int index, SkBitmap* bitmap); + void drawTo(SkCanvas* canvas, int index); + + /** + Returns the index of the last draw command to write to the pixel at (x,y) + */ + int getCommandAtPoint(int x, int y, int index, + SkIPoint transform, float scale); /** Returns the draw command at the given index. @@ -74,31 +79,12 @@ public: std::vector* getDrawCommandsAsStrings(); /** - Returns the mapping of all pixels to a layer value. - */ - int* getHitBox() { - return fHitBox.getHitBox(); - } - - SkHitBox* getBoxClass() { - return &fHitBox; - } - - int getHitBoxPoint() { - return fHitBox.getPoint(); - } - - /** Returns length of draw command vector. */ int getSize() { return commandVector.size(); } - void isCalculatingHits(bool isEnabled) { - fCalculateHits = isEnabled; - } - /** Toggles the visibility / execution of the draw command at index i with the value of toggle. @@ -194,8 +180,6 @@ private: int fHeight; int fWidth; SkBitmap fBm; - SkHitBox fHitBox; - bool fCalculateHits; bool fFilter; /** diff --git a/debugger/SkDrawCommand.h b/debugger/SkDrawCommand.h index 45d9dd6..f09dae9 100644 --- a/debugger/SkDrawCommand.h +++ b/debugger/SkDrawCommand.h @@ -28,8 +28,13 @@ public: return GetCommandString(fDrawType); } - bool getVisibility() const { return fVisible; } - void setVisibility(bool toggle) {fVisible = toggle; } + bool isVisible() const { + return fVisible; + } + + void setVisible(bool toggle) { + fVisible = toggle; + } std::vector* Info() {return &fInfo; }; virtual void execute(SkCanvas* canvas)=0; diff --git a/debugger/SkHitBox.cpp b/debugger/SkHitBox.cpp deleted file mode 100644 index a65fcc4..0000000 --- a/debugger/SkHitBox.cpp +++ /dev/null @@ -1,66 +0,0 @@ - -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "SkHitBox.h" - -SkHitBox::SkHitBox() { - fHitBox = NULL; - fX = -1; - fY = -1; - fLayer = -1; -} - -SkHitBox::~SkHitBox() {} - -void SkHitBox::alloc(int width, int height) { - free(fHitBox); - int length = width * height; - fHitBox = (int*) malloc(length * sizeof(int)); - for (int i = 0; i < length; i++) { - fHitBox[i] = 0; - } -} - -void SkHitBox::updateHitBox(SkBitmap* newBitmap, int layer) { - int length = fPrev.width() * fPrev.height(); - int* prevBase = (int*)fPrev.getPixels(); - int* currBase = (int*)newBitmap->getPixels(); - - for (int i = 0; i < length; i++) { - if (SkUnPreMultiply::PMColorToColor(prevBase[i]) != - SkUnPreMultiply::PMColorToColor(currBase[i])) { - fHitBox[i] = layer; - } - } - if (fPrev.empty()) { - alloc(newBitmap->width(), newBitmap->height()); - fPrev.setConfig(SkBitmap::kARGB_8888_Config, newBitmap->width(), newBitmap->height()); - fPrev.allocPixels(); - } - newBitmap->deepCopyTo(&fPrev, SkBitmap::kARGB_8888_Config); -} - -void SkHitBox::updateHitPoint(SkBitmap* newBitmap, int layer) { - int* prevBase = (int*)fPrev.getPixels(); - int* currBase = (int*)newBitmap->getPixels(); - int pixel = fY * fPrev.width() + fX; - - if (pointIsSet() && !fPrev.empty()) { - if (SkUnPreMultiply::PMColorToColor(prevBase[pixel]) != - SkUnPreMultiply::PMColorToColor(currBase[pixel])) { - fLayer = layer; - } - } - if (fPrev.empty()) { - alloc(newBitmap->width(), newBitmap->height()); - fPrev.setConfig(SkBitmap::kARGB_8888_Config, newBitmap->width(), newBitmap->height()); - fPrev.allocPixels(); - } - newBitmap->deepCopyTo(&fPrev, SkBitmap::kARGB_8888_Config); -} diff --git a/debugger/SkHitBox.h b/debugger/SkHitBox.h deleted file mode 100644 index 19a65fd..0000000 --- a/debugger/SkHitBox.h +++ /dev/null @@ -1,81 +0,0 @@ - -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#ifndef SKHITBOX_H_ -#define SKHITBOX_H_ - -#include "SkBitmap.h" -#include "SkUnPreMultiply.h" - -/* NOTE(chudy): It's possible that this class can be entirely static similar to - * SkObjectParser. We will have to pass in the fHitBox void * every call. - */ -class SkHitBox { -public: - SkHitBox(); - ~SkHitBox(); - - /** - Allocates enough space in memory for our hitbox pointer to contain - a layer value for every pixel. Initializes every value to 0. - */ - void alloc(int width, int height); - - /** - Compares the new SkBitmap compared to the SkBitmap from the last - call. Updates our hitbox with the draw command number if different. - */ - void updateHitBox(SkBitmap* newBitmap, int layer); - - /** - Compares point x,y in the new bitmap compared to the saved previous - one. Updates hitpoint with the draw command number if different. - */ - void updateHitPoint(SkBitmap* newBitmap, int layer); - - /** - Sets the target hitpoint we are attempting to find the layer of. - */ - void setHitPoint(int x, int y) { - fX = x; - fY = y; - fLayer = 0; - } - - /** - Returns a pointer to the start of the hitbox. - */ - int* getHitBox() { - return fHitBox; - } - - /** - Returns the layer numbr corresponding to the point (fX, fY) in this class. - */ - int getPoint() { - return fLayer; - } - - /** - Checks to see if a mouse click has been passed in. - */ - bool pointIsSet() { - return !(fX == -1 && fY == -1); - } - -private: - SkBitmap fPrev; - int* fHitBox; - int fX; - int fY; - int fLayer; -}; - - -#endif /* SKHITBOX_H_ */ diff --git a/gyp/debugger.gyp b/gyp/debugger.gyp index 5b18c5e..34ff403 100644 --- a/gyp/debugger.gyp +++ b/gyp/debugger.gyp @@ -32,8 +32,6 @@ '../debugger/SkObjectParser.cpp', '../debugger/QT/SkSettingsWidget.h', '../debugger/QT/SkSettingsWidget.cpp', - '../debugger/SkHitBox.h', - '../debugger/SkHitBox.cpp', '../debugger/QT/SkGLWidget.h', '../debugger/QT/SkGLWidget.cpp', '../debugger/QT/SkRasterWidget.h', -- 2.7.4