michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #include "SkView.h" michael@0: #include "SkCanvas.h" michael@0: michael@0: //////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkView::SkView(uint32_t flags) : fFlags(SkToU8(flags)) michael@0: { michael@0: fWidth = fHeight = 0; michael@0: fLoc.set(0, 0); michael@0: fParent = fFirstChild = fNextSibling = fPrevSibling = NULL; michael@0: fMatrix.setIdentity(); michael@0: fContainsFocus = 0; michael@0: } michael@0: michael@0: SkView::~SkView() michael@0: { michael@0: this->detachAllChildren(); michael@0: } michael@0: michael@0: void SkView::setFlags(uint32_t flags) michael@0: { michael@0: SkASSERT((flags & ~kAllFlagMasks) == 0); michael@0: michael@0: uint32_t diff = fFlags ^ flags; michael@0: michael@0: if (diff & kVisible_Mask) michael@0: this->inval(NULL); michael@0: michael@0: fFlags = SkToU8(flags); michael@0: michael@0: if (diff & kVisible_Mask) michael@0: { michael@0: this->inval(NULL); michael@0: } michael@0: } michael@0: michael@0: void SkView::setVisibleP(bool pred) michael@0: { michael@0: this->setFlags(SkSetClearShift(fFlags, pred, kVisible_Shift)); michael@0: } michael@0: michael@0: void SkView::setEnabledP(bool pred) michael@0: { michael@0: this->setFlags(SkSetClearShift(fFlags, pred, kEnabled_Shift)); michael@0: } michael@0: michael@0: void SkView::setFocusableP(bool pred) michael@0: { michael@0: this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift)); michael@0: } michael@0: michael@0: void SkView::setClipToBounds(bool pred) { michael@0: this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift)); michael@0: } michael@0: michael@0: void SkView::setSize(SkScalar width, SkScalar height) michael@0: { michael@0: width = SkMaxScalar(0, width); michael@0: height = SkMaxScalar(0, height); michael@0: michael@0: if (fWidth != width || fHeight != height) michael@0: { michael@0: this->inval(NULL); michael@0: fWidth = width; michael@0: fHeight = height; michael@0: this->inval(NULL); michael@0: this->onSizeChange(); michael@0: this->invokeLayout(); michael@0: } michael@0: } michael@0: michael@0: void SkView::setLoc(SkScalar x, SkScalar y) michael@0: { michael@0: if (fLoc.fX != x || fLoc.fY != y) michael@0: { michael@0: this->inval(NULL); michael@0: fLoc.set(x, y); michael@0: this->inval(NULL); michael@0: } michael@0: } michael@0: michael@0: void SkView::offset(SkScalar dx, SkScalar dy) michael@0: { michael@0: if (dx || dy) michael@0: this->setLoc(fLoc.fX + dx, fLoc.fY + dy); michael@0: } michael@0: michael@0: void SkView::setLocalMatrix(const SkMatrix& matrix) michael@0: { michael@0: this->inval(NULL); michael@0: fMatrix = matrix; michael@0: this->inval(NULL); michael@0: } michael@0: michael@0: void SkView::draw(SkCanvas* canvas) michael@0: { michael@0: if (fWidth && fHeight && this->isVisible()) michael@0: { michael@0: SkRect r; michael@0: r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight); michael@0: if (this->isClipToBounds() && michael@0: canvas->quickReject(r)) { michael@0: return; michael@0: } michael@0: michael@0: SkAutoCanvasRestore as(canvas, true); michael@0: michael@0: if (this->isClipToBounds()) { michael@0: canvas->clipRect(r); michael@0: } michael@0: michael@0: canvas->translate(fLoc.fX, fLoc.fY); michael@0: canvas->concat(fMatrix); michael@0: michael@0: if (fParent) { michael@0: fParent->beforeChild(this, canvas); michael@0: } michael@0: michael@0: int sc = canvas->save(); michael@0: this->onDraw(canvas); michael@0: canvas->restoreToCount(sc); michael@0: michael@0: if (fParent) { michael@0: fParent->afterChild(this, canvas); michael@0: } michael@0: michael@0: B2FIter iter(this); michael@0: SkView* child; michael@0: michael@0: SkCanvas* childCanvas = this->beforeChildren(canvas); michael@0: michael@0: while ((child = iter.next()) != NULL) michael@0: child->draw(childCanvas); michael@0: michael@0: this->afterChildren(canvas); michael@0: } michael@0: } michael@0: michael@0: void SkView::inval(SkRect* rect) { michael@0: SkView* view = this; michael@0: SkRect storage; michael@0: michael@0: for (;;) { michael@0: if (!view->isVisible()) { michael@0: return; michael@0: } michael@0: if (view->isClipToBounds()) { michael@0: SkRect bounds; michael@0: view->getLocalBounds(&bounds); michael@0: if (rect && !bounds.intersect(*rect)) { michael@0: return; michael@0: } michael@0: storage = bounds; michael@0: rect = &storage; michael@0: } michael@0: if (view->handleInval(rect)) { michael@0: return; michael@0: } michael@0: michael@0: SkView* parent = view->fParent; michael@0: if (parent == NULL) { michael@0: return; michael@0: } michael@0: michael@0: if (rect) { michael@0: rect->offset(view->fLoc.fX, view->fLoc.fY); michael@0: } michael@0: view = parent; michael@0: } michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////// michael@0: michael@0: bool SkView::setFocusView(SkView* fv) michael@0: { michael@0: SkView* view = this; michael@0: michael@0: do { michael@0: if (view->onSetFocusView(fv)) michael@0: return true; michael@0: } while ((view = view->fParent) != NULL); michael@0: return false; michael@0: } michael@0: michael@0: SkView* SkView::getFocusView() const michael@0: { michael@0: SkView* focus = NULL; michael@0: const SkView* view = this; michael@0: do { michael@0: if (view->onGetFocusView(&focus)) michael@0: break; michael@0: } while ((view = view->fParent) != NULL); michael@0: return focus; michael@0: } michael@0: michael@0: bool SkView::hasFocus() const michael@0: { michael@0: return this == this->getFocusView(); michael@0: } michael@0: michael@0: bool SkView::acceptFocus() michael@0: { michael@0: return this->isFocusable() && this->setFocusView(this); michael@0: } michael@0: michael@0: /* michael@0: Try to give focus to this view, or its children michael@0: */ michael@0: SkView* SkView::acceptFocus(FocusDirection dir) michael@0: { michael@0: if (dir == kNext_FocusDirection) michael@0: { michael@0: if (this->acceptFocus()) michael@0: return this; michael@0: michael@0: B2FIter iter(this); michael@0: SkView* child, *focus; michael@0: while ((child = iter.next()) != NULL) michael@0: if ((focus = child->acceptFocus(dir)) != NULL) michael@0: return focus; michael@0: } michael@0: else // prev michael@0: { michael@0: F2BIter iter(this); michael@0: SkView* child, *focus; michael@0: while ((child = iter.next()) != NULL) michael@0: if ((focus = child->acceptFocus(dir)) != NULL) michael@0: return focus; michael@0: michael@0: if (this->acceptFocus()) michael@0: return this; michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: michael@0: SkView* SkView::moveFocus(FocusDirection dir) michael@0: { michael@0: SkView* focus = this->getFocusView(); michael@0: michael@0: if (focus == NULL) michael@0: { // start with the root michael@0: focus = this; michael@0: while (focus->fParent) michael@0: focus = focus->fParent; michael@0: } michael@0: michael@0: SkView* child, *parent; michael@0: michael@0: if (dir == kNext_FocusDirection) michael@0: { michael@0: parent = focus; michael@0: child = focus->fFirstChild; michael@0: if (child) michael@0: goto FIRST_CHILD; michael@0: else michael@0: goto NEXT_SIB; michael@0: michael@0: do { michael@0: while (child != parent->fFirstChild) michael@0: { michael@0: FIRST_CHILD: michael@0: if ((focus = child->acceptFocus(dir)) != NULL) michael@0: return focus; michael@0: child = child->fNextSibling; michael@0: } michael@0: NEXT_SIB: michael@0: child = parent->fNextSibling; michael@0: parent = parent->fParent; michael@0: } while (parent != NULL); michael@0: } michael@0: else // prevfocus michael@0: { michael@0: parent = focus->fParent; michael@0: if (parent == NULL) // we're the root michael@0: return focus->acceptFocus(dir); michael@0: else michael@0: { michael@0: child = focus; michael@0: while (parent) michael@0: { michael@0: while (child != parent->fFirstChild) michael@0: { michael@0: child = child->fPrevSibling; michael@0: if ((focus = child->acceptFocus(dir)) != NULL) michael@0: return focus; michael@0: } michael@0: if (parent->acceptFocus()) michael@0: return parent; michael@0: michael@0: child = parent; michael@0: parent = parent->fParent; michael@0: } michael@0: } michael@0: } michael@0: return NULL; michael@0: } michael@0: michael@0: void SkView::onFocusChange(bool gainFocusP) michael@0: { michael@0: this->inval(NULL); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkView::Click::Click(SkView* target) michael@0: { michael@0: SkASSERT(target); michael@0: fTargetID = target->getSinkID(); michael@0: fType = NULL; michael@0: fWeOwnTheType = false; michael@0: fOwner = NULL; michael@0: } michael@0: michael@0: SkView::Click::~Click() michael@0: { michael@0: this->resetType(); michael@0: } michael@0: michael@0: void SkView::Click::resetType() michael@0: { michael@0: if (fWeOwnTheType) michael@0: { michael@0: sk_free(fType); michael@0: fWeOwnTheType = false; michael@0: } michael@0: fType = NULL; michael@0: } michael@0: michael@0: bool SkView::Click::isType(const char type[]) const michael@0: { michael@0: const char* t = fType; michael@0: michael@0: if (type == t) michael@0: return true; michael@0: michael@0: if (type == NULL) michael@0: type = ""; michael@0: if (t == NULL) michael@0: t = ""; michael@0: return !strcmp(t, type); michael@0: } michael@0: michael@0: void SkView::Click::setType(const char type[]) michael@0: { michael@0: this->resetType(); michael@0: fType = (char*)type; michael@0: } michael@0: michael@0: void SkView::Click::copyType(const char type[]) michael@0: { michael@0: if (fType != type) michael@0: { michael@0: this->resetType(); michael@0: if (type) michael@0: { michael@0: size_t len = strlen(type) + 1; michael@0: fType = (char*)sk_malloc_throw(len); michael@0: memcpy(fType, type, len); michael@0: fWeOwnTheType = true; michael@0: } michael@0: } michael@0: } michael@0: michael@0: SkView::Click* SkView::findClickHandler(SkScalar x, SkScalar y, unsigned modi) { michael@0: if (x < 0 || y < 0 || x >= fWidth || y >= fHeight) { michael@0: return NULL; michael@0: } michael@0: michael@0: if (this->onSendClickToChildren(x, y, modi)) { michael@0: F2BIter iter(this); michael@0: SkView* child; michael@0: michael@0: while ((child = iter.next()) != NULL) michael@0: { michael@0: SkPoint p; michael@0: if (!child->globalToLocal(x, y, &p)) { michael@0: continue; michael@0: } michael@0: michael@0: Click* click = child->findClickHandler(p.fX, p.fY, modi); michael@0: michael@0: if (click) { michael@0: return click; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return this->onFindClickHandler(x, y, modi); michael@0: } michael@0: michael@0: void SkView::DoClickDown(Click* click, int x, int y, unsigned modi) michael@0: { michael@0: SkASSERT(click); michael@0: michael@0: SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); michael@0: if (NULL == target) { michael@0: return; michael@0: } michael@0: michael@0: click->fIOrig.set(x, y); michael@0: click->fICurr = click->fIPrev = click->fIOrig; michael@0: michael@0: click->fOrig.iset(x, y); michael@0: if (!target->globalToLocal(&click->fOrig)) { michael@0: // no history to let us recover from this failure michael@0: return; michael@0: } michael@0: click->fPrev = click->fCurr = click->fOrig; michael@0: michael@0: click->fState = Click::kDown_State; michael@0: click->fModifierKeys = modi; michael@0: target->onClick(click); michael@0: } michael@0: michael@0: void SkView::DoClickMoved(Click* click, int x, int y, unsigned modi) michael@0: { michael@0: SkASSERT(click); michael@0: michael@0: SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); michael@0: if (NULL == target) { michael@0: return; michael@0: } michael@0: michael@0: click->fIPrev = click->fICurr; michael@0: click->fICurr.set(x, y); michael@0: michael@0: click->fPrev = click->fCurr; michael@0: click->fCurr.iset(x, y); michael@0: if (!target->globalToLocal(&click->fCurr)) { michael@0: // on failure pretend the mouse didn't move michael@0: click->fCurr = click->fPrev; michael@0: } michael@0: michael@0: click->fState = Click::kMoved_State; michael@0: click->fModifierKeys = modi; michael@0: target->onClick(click); michael@0: } michael@0: michael@0: void SkView::DoClickUp(Click* click, int x, int y, unsigned modi) michael@0: { michael@0: SkASSERT(click); michael@0: michael@0: SkView* target = (SkView*)SkEventSink::FindSink(click->fTargetID); michael@0: if (NULL == target) { michael@0: return; michael@0: } michael@0: michael@0: click->fIPrev = click->fICurr; michael@0: click->fICurr.set(x, y); michael@0: michael@0: click->fPrev = click->fCurr; michael@0: click->fCurr.iset(x, y); michael@0: if (!target->globalToLocal(&click->fCurr)) { michael@0: // on failure pretend the mouse didn't move michael@0: click->fCurr = click->fPrev; michael@0: } michael@0: michael@0: click->fState = Click::kUp_State; michael@0: click->fModifierKeys = modi; michael@0: target->onClick(click); michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////// michael@0: michael@0: void SkView::invokeLayout() { michael@0: SkView::Layout* layout = this->getLayout(); michael@0: michael@0: if (layout) { michael@0: layout->layoutChildren(this); michael@0: } michael@0: } michael@0: michael@0: void SkView::onDraw(SkCanvas* canvas) { michael@0: Artist* artist = this->getArtist(); michael@0: michael@0: if (artist) { michael@0: artist->draw(this, canvas); michael@0: } michael@0: } michael@0: michael@0: void SkView::onSizeChange() {} michael@0: michael@0: bool SkView::onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) { michael@0: return true; michael@0: } michael@0: michael@0: SkView::Click* SkView::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) { michael@0: return NULL; michael@0: } michael@0: michael@0: bool SkView::onClick(Click*) { michael@0: return false; michael@0: } michael@0: michael@0: bool SkView::handleInval(const SkRect*) { michael@0: return false; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////// michael@0: michael@0: void SkView::getLocalBounds(SkRect* bounds) const { michael@0: if (bounds) { michael@0: bounds->set(0, 0, fWidth, fHeight); michael@0: } michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////// michael@0: ////////////////////////////////////////////////////////////////////// michael@0: michael@0: void SkView::detachFromParent_NoLayout() { michael@0: this->validate(); michael@0: if (fParent == NULL) { michael@0: return; michael@0: } michael@0: michael@0: if (fContainsFocus) { michael@0: (void)this->setFocusView(NULL); michael@0: } michael@0: michael@0: this->inval(NULL); michael@0: michael@0: SkView* next = NULL; michael@0: michael@0: if (fNextSibling != this) { // do we have any siblings michael@0: fNextSibling->fPrevSibling = fPrevSibling; michael@0: fPrevSibling->fNextSibling = fNextSibling; michael@0: next = fNextSibling; michael@0: } michael@0: michael@0: if (fParent->fFirstChild == this) { michael@0: fParent->fFirstChild = next; michael@0: } michael@0: michael@0: fParent = fNextSibling = fPrevSibling = NULL; michael@0: michael@0: this->validate(); michael@0: this->unref(); michael@0: } michael@0: michael@0: void SkView::detachFromParent() { michael@0: this->validate(); michael@0: SkView* parent = fParent; michael@0: michael@0: if (parent) { michael@0: this->detachFromParent_NoLayout(); michael@0: parent->invokeLayout(); michael@0: } michael@0: } michael@0: michael@0: SkView* SkView::attachChildToBack(SkView* child) { michael@0: this->validate(); michael@0: SkASSERT(child != this); michael@0: michael@0: if (child == NULL || fFirstChild == child) michael@0: goto DONE; michael@0: michael@0: child->ref(); michael@0: child->detachFromParent_NoLayout(); michael@0: michael@0: if (fFirstChild == NULL) { michael@0: child->fNextSibling = child; michael@0: child->fPrevSibling = child; michael@0: } else { michael@0: child->fNextSibling = fFirstChild; michael@0: child->fPrevSibling = fFirstChild->fPrevSibling; michael@0: fFirstChild->fPrevSibling->fNextSibling = child; michael@0: fFirstChild->fPrevSibling = child; michael@0: } michael@0: michael@0: fFirstChild = child; michael@0: child->fParent = this; michael@0: child->inval(NULL); michael@0: michael@0: this->validate(); michael@0: this->invokeLayout(); michael@0: DONE: michael@0: return child; michael@0: } michael@0: michael@0: SkView* SkView::attachChildToFront(SkView* child) { michael@0: this->validate(); michael@0: SkASSERT(child != this); michael@0: michael@0: if (child == NULL || (fFirstChild && fFirstChild->fPrevSibling == child)) michael@0: goto DONE; michael@0: michael@0: child->ref(); michael@0: child->detachFromParent_NoLayout(); michael@0: michael@0: if (fFirstChild == NULL) { michael@0: fFirstChild = child; michael@0: child->fNextSibling = child; michael@0: child->fPrevSibling = child; michael@0: } else { michael@0: child->fNextSibling = fFirstChild; michael@0: child->fPrevSibling = fFirstChild->fPrevSibling; michael@0: fFirstChild->fPrevSibling->fNextSibling = child; michael@0: fFirstChild->fPrevSibling = child; michael@0: } michael@0: michael@0: child->fParent = this; michael@0: child->inval(NULL); michael@0: michael@0: this->validate(); michael@0: this->invokeLayout(); michael@0: DONE: michael@0: return child; michael@0: } michael@0: michael@0: void SkView::detachAllChildren() { michael@0: this->validate(); michael@0: while (fFirstChild) michael@0: fFirstChild->detachFromParent_NoLayout(); michael@0: } michael@0: michael@0: void SkView::localToGlobal(SkMatrix* matrix) const { michael@0: if (matrix) { michael@0: matrix->reset(); michael@0: const SkView* view = this; michael@0: while (view) michael@0: { michael@0: matrix->preConcat(view->getLocalMatrix()); michael@0: matrix->preTranslate(-view->fLoc.fX, -view->fLoc.fY); michael@0: view = view->fParent; michael@0: } michael@0: } michael@0: } michael@0: bool SkView::globalToLocal(SkScalar x, SkScalar y, SkPoint* local) const michael@0: { michael@0: SkASSERT(this); michael@0: michael@0: if (NULL != local) { michael@0: SkMatrix m; michael@0: this->localToGlobal(&m); michael@0: if (!m.invert(&m)) { michael@0: return false; michael@0: } michael@0: SkPoint p; michael@0: m.mapXY(x, y, &p); michael@0: local->set(p.fX, p.fY); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////// michael@0: michael@0: /* Even if the subclass overrides onInflate, they should always be michael@0: sure to call the inherited method, so that we get called. michael@0: */ michael@0: void SkView::onInflate(const SkDOM& dom, const SkDOM::Node* node) { michael@0: SkScalar x, y; michael@0: michael@0: x = this->locX(); michael@0: y = this->locY(); michael@0: (void)dom.findScalar(node, "x", &x); michael@0: (void)dom.findScalar(node, "y", &y); michael@0: this->setLoc(x, y); michael@0: michael@0: x = this->width(); michael@0: y = this->height(); michael@0: (void)dom.findScalar(node, "width", &x); michael@0: (void)dom.findScalar(node, "height", &y); michael@0: this->setSize(x, y); michael@0: michael@0: // inflate the flags michael@0: michael@0: static const char* gFlagNames[] = { michael@0: "visible", "enabled", "focusable", "flexH", "flexV" michael@0: }; michael@0: SkASSERT(SK_ARRAY_COUNT(gFlagNames) == kFlagShiftCount); michael@0: michael@0: bool b; michael@0: uint32_t flags = this->getFlags(); michael@0: for (unsigned i = 0; i < SK_ARRAY_COUNT(gFlagNames); i++) michael@0: if (dom.findBool(node, gFlagNames[i], &b)) michael@0: flags = SkSetClearShift(flags, b, i); michael@0: this->setFlags(flags); michael@0: } michael@0: michael@0: void SkView::inflate(const SkDOM& dom, const SkDOM::Node* node) { michael@0: this->onInflate(dom, node); michael@0: } michael@0: michael@0: void SkView::onPostInflate(const SkTDict&) { michael@0: // override in subclass as needed michael@0: } michael@0: michael@0: void SkView::postInflate(const SkTDict& dict) { michael@0: this->onPostInflate(dict); michael@0: michael@0: B2FIter iter(this); michael@0: SkView* child; michael@0: while ((child = iter.next()) != NULL) michael@0: child->postInflate(dict); michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////// michael@0: michael@0: SkView* SkView::sendEventToParents(const SkEvent& evt) { michael@0: SkView* parent = fParent; michael@0: michael@0: while (parent) { michael@0: if (parent->doEvent(evt)) { michael@0: return parent; michael@0: } michael@0: parent = parent->fParent; michael@0: } michael@0: return NULL; michael@0: } michael@0: michael@0: SkView* SkView::sendQueryToParents(SkEvent* evt) { michael@0: SkView* parent = fParent; michael@0: michael@0: while (parent) { michael@0: if (parent->doQuery(evt)) { michael@0: return parent; michael@0: } michael@0: parent = parent->fParent; michael@0: } michael@0: return NULL; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////// michael@0: ////////////////////////////////////////////////////////////////// michael@0: michael@0: SkView::F2BIter::F2BIter(const SkView* parent) { michael@0: fFirstChild = parent ? parent->fFirstChild : NULL; michael@0: fChild = fFirstChild ? fFirstChild->fPrevSibling : NULL; michael@0: } michael@0: michael@0: SkView* SkView::F2BIter::next() { michael@0: SkView* curr = fChild; michael@0: michael@0: if (fChild) { michael@0: if (fChild == fFirstChild) { michael@0: fChild = NULL; michael@0: } else { michael@0: fChild = fChild->fPrevSibling; michael@0: } michael@0: } michael@0: return curr; michael@0: } michael@0: michael@0: SkView::B2FIter::B2FIter(const SkView* parent) { michael@0: fFirstChild = parent ? parent->fFirstChild : NULL; michael@0: fChild = fFirstChild; michael@0: } michael@0: michael@0: SkView* SkView::B2FIter::next() { michael@0: SkView* curr = fChild; michael@0: michael@0: if (fChild) { michael@0: SkView* next = fChild->fNextSibling; michael@0: if (next == fFirstChild) michael@0: next = NULL; michael@0: fChild = next; michael@0: } michael@0: return curr; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////// michael@0: ////////////////////////////////////////////////////////////////// michael@0: michael@0: #ifdef SK_DEBUG michael@0: michael@0: void SkView::validate() const { michael@0: // SkASSERT(this->getRefCnt() > 0 && this->getRefCnt() < 100); michael@0: if (fParent) { michael@0: SkASSERT(fNextSibling); michael@0: SkASSERT(fPrevSibling); michael@0: } else { michael@0: bool nextNull = NULL == fNextSibling; michael@0: bool prevNull = NULL == fNextSibling; michael@0: SkASSERT(nextNull == prevNull); michael@0: } michael@0: } michael@0: michael@0: static inline void show_if_nonzero(const char name[], SkScalar value) michael@0: { michael@0: if (value) michael@0: SkDebugf("%s=\"%g\"", name, value/65536.); michael@0: } michael@0: michael@0: static void tab(int level) michael@0: { michael@0: for (int i = 0; i < level; i++) michael@0: SkDebugf(" "); michael@0: } michael@0: michael@0: static void dumpview(const SkView* view, int level, bool recurse) michael@0: { michael@0: tab(level); michael@0: michael@0: SkDebugf("locX()); michael@0: show_if_nonzero(" y", view->locY()); michael@0: show_if_nonzero(" width", view->width()); michael@0: show_if_nonzero(" height", view->height()); michael@0: michael@0: if (recurse) michael@0: { michael@0: SkView::B2FIter iter(view); michael@0: SkView* child; michael@0: bool noChildren = true; michael@0: michael@0: while ((child = iter.next()) != NULL) michael@0: { michael@0: if (noChildren) michael@0: SkDebugf(">\n"); michael@0: noChildren = false; michael@0: dumpview(child, level + 1, true); michael@0: } michael@0: michael@0: if (!noChildren) michael@0: { michael@0: tab(level); michael@0: SkDebugf("\n"); michael@0: } michael@0: else michael@0: goto ONELINER; michael@0: } michael@0: else michael@0: { michael@0: ONELINER: michael@0: SkDebugf(" />\n"); michael@0: } michael@0: } michael@0: michael@0: void SkView::dump(bool recurse) const michael@0: { michael@0: dumpview(this, 0, recurse); michael@0: } michael@0: michael@0: #endif