1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* some layout debugging functions that ought to live in nsFrame.cpp */
9 #include "nsAttrValue.h"
11 #include "nsDisplayList.h"
12 #include "nsPrintfCString.h"
16 using namespace mozilla
;
17 using namespace mozilla::layers
;
19 static std::ostream
& operator<<(std::ostream
& os
, const nsPrintfCString
& rhs
) {
24 static void PrintDisplayListTo(nsDisplayListBuilder
* aBuilder
,
25 const nsDisplayList
& aList
,
26 std::stringstream
& aStream
, uint32_t aIndent
,
29 static void PrintDisplayItemTo(nsDisplayListBuilder
* aBuilder
,
30 nsDisplayItem
* aItem
, std::stringstream
& aStream
,
31 uint32_t aIndent
, bool aDumpSublist
,
36 for (uint32_t indent
= 0; indent
< aIndent
; indent
++) {
40 nsAutoString contentData
;
41 nsIFrame
* f
= aItem
->Frame();
42 #ifdef DEBUG_FRAME_DUMP
43 f
->GetFrameName(contentData
);
45 nsIContent
* content
= f
->GetContent();
48 if (content
->GetID()) {
49 content
->GetID()->ToString(tmp
);
50 contentData
.AppendLiteral(" id:");
51 contentData
.Append(tmp
);
53 const nsAttrValue
* classes
=
54 content
->IsElement() ? content
->AsElement()->GetClasses() : nullptr;
56 classes
->ToString(tmp
);
57 contentData
.AppendLiteral(" class:");
58 contentData
.Append(tmp
);
62 nsRect rect
= aBuilder
? aItem
->GetBounds(aBuilder
, &snap
) : nsRect();
64 aBuilder
? aItem
->GetComponentAlphaBounds(aBuilder
) : nsRect();
65 nsDisplayList
* list
= aItem
->GetChildren();
66 const DisplayItemClip
& clip
= aItem
->GetClip();
68 aBuilder
? aItem
->GetOpaqueRegion(aBuilder
, &snap
) : nsRect();
70 #ifdef MOZ_DUMP_PAINTING
71 if (aDumpHtml
&& aItem
->Painted()) {
72 nsCString
string(aItem
->Name());
74 string
.AppendInt((uint64_t)aItem
);
75 aStream
<< nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">",
76 string
.BeginReading());
80 aStream
<< nsPrintfCString(
81 "%s p=0x%p f=0x%p(%s) key=%d %sbounds(%d,%d,%d,%d) "
82 "componentAlpha(%d,%d,%d,%d) clip(%s) asr(%s) clipChain(%s)%s ",
83 aItem
->Name(), aItem
, (void*)f
, NS_ConvertUTF16toUTF8(contentData
).get(),
84 aItem
->GetPerFrameKey(),
85 (aItem
->ZIndex() ? nsPrintfCString("z=%d ", aItem
->ZIndex()).get() : ""),
86 rect
.x
, rect
.y
, rect
.width
, rect
.height
, component
.x
, component
.y
,
87 component
.width
, component
.height
, clip
.ToString().get(),
88 ActiveScrolledRoot::ToString(aItem
->GetActiveScrolledRoot()).get(),
89 DisplayItemClipChain::ToString(aItem
->GetClipChain()).get(),
90 (aBuilder
&& aItem
->IsUniform(aBuilder
)) ? " uniform" : "");
92 for (auto iter
= opaque
.RectIter(); !iter
.Done(); iter
.Next()) {
93 const nsRect
& r
= iter
.Get();
94 aStream
<< nsPrintfCString(" (opaque %d,%d,%d,%d)", r
.x
, r
.y
, r
.width
,
98 const auto& willChange
= aItem
->Frame()->StyleDisplay()->mWillChange
;
99 if (!willChange
.features
.IsEmpty()) {
100 aStream
<< " (will-change=";
101 for (size_t i
= 0; i
< willChange
.features
.Length(); i
++) {
105 nsDependentAtomString
buffer(willChange
.features
.AsSpan()[i
].AsAtom());
106 aStream
<< NS_LossyConvertUTF16toASCII(buffer
).get();
111 if (aItem
->HasHitTestInfo()) {
112 const auto& hitTestInfo
= aItem
->GetHitTestInfo();
113 aStream
<< nsPrintfCString(" hitTestInfo(0x%x)",
114 hitTestInfo
.Info().serialize());
116 nsRect area
= hitTestInfo
.Area();
117 aStream
<< nsPrintfCString(" hitTestArea(%d,%d,%d,%d)", area
.x
, area
.y
,
118 area
.width
, area
.height
);
121 auto ReuseStateToString
= [](nsDisplayItem::ReuseState aState
) {
123 case nsDisplayItem::ReuseState::None
:
125 case nsDisplayItem::ReuseState::Reusable
:
127 case nsDisplayItem::ReuseState::PreProcessed
:
128 return "PreProcessed";
129 case nsDisplayItem::ReuseState::Reused
:
133 MOZ_ASSERT_UNREACHABLE();
137 aStream
<< nsPrintfCString(" reuse-state(%s)",
138 ReuseStateToString(aItem
->GetReuseState()));
140 // Display item specific debug info
141 aItem
->WriteDebugInfo(aStream
);
143 #ifdef MOZ_DUMP_PAINTING
144 if (aDumpHtml
&& aItem
->Painted()) {
148 #ifdef MOZ_DUMP_PAINTING
149 if (aItem
->GetType() == DisplayItemType::TYPE_MASK
) {
151 (static_cast<nsDisplayMasksAndClipPaths
*>(aItem
))->PrintEffects(str
);
152 aStream
<< str
.get();
155 if (aItem
->GetType() == DisplayItemType::TYPE_FILTER
) {
157 (static_cast<nsDisplayFilters
*>(aItem
))->PrintEffects(str
);
158 aStream
<< str
.get();
162 #ifdef MOZ_DUMP_PAINTING
163 if (aDumpHtml
&& aItem
->Painted()) {
164 nsCString
string(aItem
->Name());
166 string
.AppendInt((uint64_t)aItem
);
167 aStream
<< nsPrintfCString("<br><img id=\"%s\">\n", string
.BeginReading());
171 if (aDumpSublist
&& list
) {
172 PrintDisplayListTo(aBuilder
, *list
, aStream
, aIndent
+ 1, aDumpHtml
);
176 static void PrintDisplayListTo(nsDisplayListBuilder
* aBuilder
,
177 const nsDisplayList
& aList
,
178 std::stringstream
& aStream
, uint32_t aIndent
,
184 for (nsDisplayItem
* i
: aList
) {
188 PrintDisplayItemTo(aBuilder
, i
, aStream
, aIndent
, true, aDumpHtml
);
199 void nsIFrame::PrintDisplayList(nsDisplayListBuilder
* aBuilder
,
200 const nsDisplayList
& aList
, bool aDumpHtml
) {
201 std::stringstream ss
;
202 PrintDisplayList(aBuilder
, aList
, ss
, aDumpHtml
);
203 fprintf_stderr(stderr
, "%s", ss
.str().c_str());
206 void nsIFrame::PrintDisplayList(nsDisplayListBuilder
* aBuilder
,
207 const nsDisplayList
& aList
,
208 std::stringstream
& aStream
, bool aDumpHtml
) {
209 PrintDisplayListTo(aBuilder
, aList
, aStream
, 0, aDumpHtml
);
212 void nsIFrame::PrintDisplayItem(nsDisplayListBuilder
* aBuilder
,
213 nsDisplayItem
* aItem
,
214 std::stringstream
& aStream
, uint32_t aIndent
,
215 bool aDumpSublist
, bool aDumpHtml
) {
216 PrintDisplayItemTo(aBuilder
, aItem
, aStream
, aIndent
, aDumpSublist
,
221 * The two functions below are intended to be called from a debugger.
223 void PrintDisplayItemToStdout(nsDisplayListBuilder
* aBuilder
,
224 nsDisplayItem
* aItem
) {
225 std::stringstream stream
;
226 PrintDisplayItemTo(aBuilder
, aItem
, stream
, 0, true, false);
227 puts(stream
.str().c_str());
230 void PrintDisplayListToStdout(nsDisplayListBuilder
* aBuilder
,
231 const nsDisplayList
& aList
) {
232 std::stringstream stream
;
233 PrintDisplayListTo(aBuilder
, aList
, stream
, 0, false);
234 puts(stream
.str().c_str());
237 #ifdef MOZ_DUMP_PAINTING
238 static void PrintDisplayListSetItem(nsDisplayListBuilder
* aBuilder
,
239 const char* aItemName
,
240 const nsDisplayList
& aList
,
241 std::stringstream
& aStream
,
246 aStream
<< aItemName
<< "\n";
247 PrintDisplayListTo(aBuilder
, aList
, aStream
, 0, aDumpHtml
);
253 void nsIFrame::PrintDisplayListSet(nsDisplayListBuilder
* aBuilder
,
254 const nsDisplayListSet
& aSet
,
255 std::stringstream
& aStream
, bool aDumpHtml
) {
259 PrintDisplayListSetItem(aBuilder
, "[BorderBackground]",
260 *(aSet
.BorderBackground()), aStream
, aDumpHtml
);
261 PrintDisplayListSetItem(aBuilder
, "[BlockBorderBackgrounds]",
262 *(aSet
.BlockBorderBackgrounds()), aStream
, aDumpHtml
);
263 PrintDisplayListSetItem(aBuilder
, "[Floats]", *(aSet
.Floats()), aStream
,
265 PrintDisplayListSetItem(aBuilder
, "[PositionedDescendants]",
266 *(aSet
.PositionedDescendants()), aStream
, aDumpHtml
);
267 PrintDisplayListSetItem(aBuilder
, "[Outlines]", *(aSet
.Outlines()), aStream
,
269 PrintDisplayListSetItem(aBuilder
, "[Content]", *(aSet
.Content()), aStream
,