michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * implementation of interface that allows layout-debug extension access michael@0: * to some internals of layout michael@0: */ michael@0: michael@0: #include "nsILayoutDebugger.h" michael@0: #include "nsFrame.h" michael@0: #include "nsDisplayList.h" michael@0: #include "FrameLayerBuilder.h" michael@0: #include "nsPrintfCString.h" michael@0: michael@0: #include michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::layers; michael@0: michael@0: #ifdef DEBUG michael@0: class nsLayoutDebugger : public nsILayoutDebugger { michael@0: public: michael@0: nsLayoutDebugger(); michael@0: virtual ~nsLayoutDebugger(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: NS_IMETHOD SetShowFrameBorders(bool aEnable) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetShowFrameBorders(bool* aResult) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetShowEventTargetFrameBorder(bool aEnable) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetShowEventTargetFrameBorder(bool* aResult) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetContentSize(nsIDocument* aDocument, michael@0: int32_t* aSizeInBytesResult) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetFrameSize(nsIPresShell* aPresentation, michael@0: int32_t* aSizeInBytesResult) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetStyleSize(nsIPresShell* aPresentation, michael@0: int32_t* aSizeInBytesResult) MOZ_OVERRIDE; michael@0: michael@0: }; michael@0: michael@0: nsresult michael@0: NS_NewLayoutDebugger(nsILayoutDebugger** aResult) michael@0: { michael@0: NS_PRECONDITION(aResult, "null OUT ptr"); michael@0: if (!aResult) { michael@0: return NS_ERROR_NULL_POINTER; michael@0: } michael@0: nsLayoutDebugger* it = new nsLayoutDebugger(); michael@0: return it->QueryInterface(NS_GET_IID(nsILayoutDebugger), (void**)aResult); michael@0: } michael@0: michael@0: nsLayoutDebugger::nsLayoutDebugger() michael@0: { michael@0: } michael@0: michael@0: nsLayoutDebugger::~nsLayoutDebugger() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsLayoutDebugger, nsILayoutDebugger) michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::SetShowFrameBorders(bool aEnable) michael@0: { michael@0: nsFrame::ShowFrameBorders(aEnable); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::GetShowFrameBorders(bool* aResult) michael@0: { michael@0: *aResult = nsFrame::GetShowFrameBorders(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::SetShowEventTargetFrameBorder(bool aEnable) michael@0: { michael@0: nsFrame::ShowEventTargetFrameBorder(aEnable); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::GetShowEventTargetFrameBorder(bool* aResult) michael@0: { michael@0: *aResult = nsFrame::GetShowEventTargetFrameBorder(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::GetContentSize(nsIDocument* aDocument, michael@0: int32_t* aSizeInBytesResult) michael@0: { michael@0: *aSizeInBytesResult = 0; michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::GetFrameSize(nsIPresShell* aPresentation, michael@0: int32_t* aSizeInBytesResult) michael@0: { michael@0: *aSizeInBytesResult = 0; michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation, michael@0: int32_t* aSizeInBytesResult) michael@0: { michael@0: *aSizeInBytesResult = 0; michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: #endif michael@0: michael@0: #ifdef MOZ_DUMP_PAINTING michael@0: static void michael@0: PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, michael@0: FILE* aOutput, uint32_t aIndent, bool aDumpHtml); michael@0: michael@0: static void michael@0: PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, michael@0: FILE* aOutput, uint32_t aIndent, bool aDumpSublist, bool aDumpHtml) michael@0: { michael@0: nsCString str; michael@0: if (!aDumpHtml) { michael@0: for (uint32_t indent = 0; indent < aIndent; indent++) { michael@0: str += " "; michael@0: } michael@0: } michael@0: nsIFrame* f = aItem->Frame(); michael@0: nsAutoString fName; michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: f->GetFrameName(fName); michael@0: #endif michael@0: bool snap; michael@0: nsRect rect = aItem->GetBounds(aBuilder, &snap); michael@0: nscolor color; michael@0: nsRect vis = aItem->GetVisibleRect(); michael@0: nsRect component = aItem->GetComponentAlphaBounds(aBuilder); michael@0: nsDisplayList* list = aItem->GetChildren(); michael@0: const DisplayItemClip& clip = aItem->GetClip(); michael@0: nsRegion opaque; michael@0: if (!list || list->DidComputeVisibility()) { michael@0: opaque = aItem->GetOpaqueRegion(aBuilder, &snap); michael@0: } michael@0: if (aDumpHtml && aItem->Painted()) { michael@0: nsCString string(aItem->Name()); michael@0: string.Append("-"); michael@0: string.AppendInt((uint64_t)aItem); michael@0: str += nsPrintfCString("", string.BeginReading()); michael@0: } michael@0: str += nsPrintfCString("%s %p(%s) bounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) %s", michael@0: aItem->Name(), (void*)f, NS_ConvertUTF16toUTF8(fName).get(), michael@0: rect.x, rect.y, rect.width, rect.height, michael@0: vis.x, vis.y, vis.width, vis.height, michael@0: component.x, component.y, component.width, component.height, michael@0: clip.ToString().get(), michael@0: aItem->IsUniform(aBuilder, &color) ? " uniform" : ""); michael@0: nsRegionRectIterator iter(opaque); michael@0: for (const nsRect* r = iter.Next(); r; r = iter.Next()) { michael@0: str += nsPrintfCString(" (opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); michael@0: } michael@0: aItem->WriteDebugInfo(str); michael@0: if (aDumpHtml && aItem->Painted()) { michael@0: str += ""; michael@0: } michael@0: uint32_t key = aItem->GetPerFrameKey(); michael@0: Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key); michael@0: if (layer) { michael@0: if (aDumpHtml) { michael@0: str += nsPrintfCString(" layer=%p", layer, layer); michael@0: } else { michael@0: str += nsPrintfCString(" layer=%p", layer); michael@0: } michael@0: } michael@0: if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) { michael@0: (static_cast(aItem))->PrintEffects(str); michael@0: } michael@0: fprintf_stderr(aOutput, "%s\n", str.get()); michael@0: if (aDumpSublist && list) { michael@0: PrintDisplayListTo(aBuilder, *list, aOutput, aIndent+1, aDumpHtml); michael@0: } michael@0: } michael@0: michael@0: static void michael@0: PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, michael@0: FILE* aOutput, uint32_t aIndent, bool aDumpHtml) michael@0: { michael@0: if (aDumpHtml) { michael@0: fprintf_stderr(aOutput, ""); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsFrame::PrintDisplayItem(nsDisplayListBuilder* aBuilder, michael@0: nsDisplayItem* aItem, michael@0: FILE* aFile, michael@0: bool aDumpSublist, michael@0: bool aDumpHtml) michael@0: { michael@0: PrintDisplayItemTo(aBuilder, aItem, aFile, 0, aDumpSublist, aDumpHtml); michael@0: } michael@0: michael@0: void michael@0: nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsDisplayList& aList, michael@0: FILE* aFile, michael@0: bool aDumpHtml) michael@0: { michael@0: PrintDisplayListTo(aBuilder, aList, aFile, 0, aDumpHtml); michael@0: } michael@0: michael@0: static void michael@0: PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder, michael@0: const char* aItemName, michael@0: const nsDisplayList& aList, michael@0: FILE* aFile, michael@0: bool aDumpHtml) michael@0: { michael@0: if (aDumpHtml) { michael@0: fprintf_stderr(aFile, "
  • "); michael@0: } michael@0: fprintf_stderr(aFile, "%s", aItemName); michael@0: PrintDisplayListTo(aBuilder, aList, aFile, 0, aDumpHtml); michael@0: if (aDumpHtml) { michael@0: fprintf_stderr(aFile, "
  • "); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsFrame::PrintDisplayListSet(nsDisplayListBuilder* aBuilder, michael@0: const nsDisplayListSet& aSet, michael@0: FILE *aFile, michael@0: bool aDumpHtml) michael@0: { michael@0: if (aDumpHtml) { michael@0: fprintf_stderr(aFile, ""); michael@0: } michael@0: } michael@0: michael@0: #endif