Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 : * implementation of interface that allows layout-debug extension access
8 : * to some internals of layout
9 : */
10 :
11 : #include "nsILayoutDebugger.h"
12 :
13 : #include "nsAttrValue.h"
14 : #include "nsFrame.h"
15 : #include "nsDisplayList.h"
16 : #include "FrameLayerBuilder.h"
17 : #include "nsPrintfCString.h"
18 :
19 : #include <iostream>
20 : #include <stdio.h>
21 :
22 : using namespace mozilla;
23 : using namespace mozilla::layers;
24 :
25 : #ifdef DEBUG
26 : class nsLayoutDebugger : public nsILayoutDebugger {
27 : public:
28 : nsLayoutDebugger();
29 :
30 : NS_DECL_ISUPPORTS
31 :
32 : NS_IMETHOD SetShowFrameBorders(bool aEnable) override;
33 :
34 : NS_IMETHOD GetShowFrameBorders(bool* aResult) override;
35 :
36 : NS_IMETHOD SetShowEventTargetFrameBorder(bool aEnable) override;
37 :
38 : NS_IMETHOD GetShowEventTargetFrameBorder(bool* aResult) override;
39 :
40 : protected:
41 : virtual ~nsLayoutDebugger();
42 : };
43 :
44 : nsresult
45 0 : NS_NewLayoutDebugger(nsILayoutDebugger** aResult)
46 : {
47 0 : NS_PRECONDITION(aResult, "null OUT ptr");
48 0 : if (!aResult) {
49 0 : return NS_ERROR_NULL_POINTER;
50 : }
51 0 : nsLayoutDebugger* it = new nsLayoutDebugger();
52 0 : return it->QueryInterface(NS_GET_IID(nsILayoutDebugger), (void**)aResult);
53 : }
54 :
55 0 : nsLayoutDebugger::nsLayoutDebugger()
56 : {
57 0 : }
58 :
59 0 : nsLayoutDebugger::~nsLayoutDebugger()
60 : {
61 0 : }
62 :
63 0 : NS_IMPL_ISUPPORTS(nsLayoutDebugger, nsILayoutDebugger)
64 :
65 : NS_IMETHODIMP
66 0 : nsLayoutDebugger::SetShowFrameBorders(bool aEnable)
67 : {
68 0 : nsFrame::ShowFrameBorders(aEnable);
69 0 : return NS_OK;
70 : }
71 :
72 : NS_IMETHODIMP
73 0 : nsLayoutDebugger::GetShowFrameBorders(bool* aResult)
74 : {
75 0 : *aResult = nsFrame::GetShowFrameBorders();
76 0 : return NS_OK;
77 : }
78 :
79 : NS_IMETHODIMP
80 0 : nsLayoutDebugger::SetShowEventTargetFrameBorder(bool aEnable)
81 : {
82 0 : nsFrame::ShowEventTargetFrameBorder(aEnable);
83 0 : return NS_OK;
84 : }
85 :
86 : NS_IMETHODIMP
87 0 : nsLayoutDebugger::GetShowEventTargetFrameBorder(bool* aResult)
88 : {
89 0 : *aResult = nsFrame::GetShowEventTargetFrameBorder();
90 0 : return NS_OK;
91 : }
92 :
93 : #endif
94 :
95 0 : std::ostream& operator<<(std::ostream& os, const nsPrintfCString& rhs) {
96 0 : os << rhs.get();
97 0 : return os;
98 : }
99 :
100 : static void
101 : PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
102 : std::stringstream& aStream, uint32_t aIndent, bool aDumpHtml);
103 :
104 : static void
105 0 : PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
106 : std::stringstream& aStream, uint32_t aIndent, bool aDumpSublist, bool aDumpHtml)
107 : {
108 0 : std::stringstream ss;
109 :
110 0 : if (!aDumpHtml) {
111 0 : for (uint32_t indent = 0; indent < aIndent; indent++) {
112 0 : aStream << " ";
113 : }
114 : }
115 0 : nsAutoString contentData;
116 0 : nsIFrame* f = aItem->Frame();
117 : #ifdef DEBUG_FRAME_DUMP
118 0 : f->GetFrameName(contentData);
119 : #endif
120 0 : nsIContent* content = f->GetContent();
121 0 : if (content) {
122 0 : nsString tmp;
123 0 : if (content->GetID()) {
124 0 : content->GetID()->ToString(tmp);
125 0 : contentData.AppendLiteral(" id:");
126 0 : contentData.Append(tmp);
127 : }
128 0 : const nsAttrValue* classes = content->IsElement() ?
129 0 : content->AsElement()->GetClasses() : nullptr;
130 0 : if (classes) {
131 0 : classes->ToString(tmp);
132 0 : contentData.AppendLiteral(" class:");
133 0 : contentData.Append(tmp);
134 : }
135 : }
136 : bool snap;
137 0 : nsRect rect = aItem->GetBounds(aBuilder, &snap);
138 0 : nsRect layerRect = rect - (*aItem->GetAnimatedGeometryRoot())->GetOffsetToCrossDoc(aItem->ReferenceFrame());
139 0 : nsRect vis = aItem->GetVisibleRect();
140 0 : nsRect component = aItem->GetComponentAlphaBounds(aBuilder);
141 0 : nsDisplayList* list = aItem->GetChildren();
142 0 : const DisplayItemClip& clip = aItem->GetClip();
143 0 : nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
144 :
145 : #ifdef MOZ_DUMP_PAINTING
146 0 : if (aDumpHtml && aItem->Painted()) {
147 0 : nsCString string(aItem->Name());
148 0 : string.Append('-');
149 0 : string.AppendInt((uint64_t)aItem);
150 0 : aStream << nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">", string.BeginReading());
151 : }
152 : #endif
153 :
154 0 : aStream << nsPrintfCString("%s p=0x%p f=0x%p(%s) %sbounds(%d,%d,%d,%d) layerBounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) asr(%s) clipChain(%s)%s ref=0x%p agr=0x%p",
155 0 : aItem->Name(), aItem, (void*)f, NS_ConvertUTF16toUTF8(contentData).get(),
156 0 : (aItem->ZIndex() ? nsPrintfCString("z=%d ", aItem->ZIndex()).get() : ""),
157 : rect.x, rect.y, rect.width, rect.height,
158 : layerRect.x, layerRect.y, layerRect.width, layerRect.height,
159 : vis.x, vis.y, vis.width, vis.height,
160 : component.x, component.y, component.width, component.height,
161 0 : clip.ToString().get(),
162 0 : ActiveScrolledRoot::ToString(aItem->GetActiveScrolledRoot()).get(),
163 0 : DisplayItemClipChain::ToString(aItem->GetClipChain()).get(),
164 0 : aItem->IsUniform(aBuilder) ? " uniform" : "",
165 0 : aItem->ReferenceFrame(), aItem->GetAnimatedGeometryRoot()->mFrame);
166 :
167 0 : for (auto iter = opaque.RectIter(); !iter.Done(); iter.Next()) {
168 0 : const nsRect& r = iter.Get();
169 0 : aStream << nsPrintfCString(" (opaque %d,%d,%d,%d)", r.x, r.y, r.width, r.height);
170 : }
171 :
172 0 : const auto& willChange = aItem->Frame()->StyleDisplay()->mWillChange;
173 0 : if (!willChange.IsEmpty()) {
174 0 : aStream << " (will-change=";
175 0 : for (size_t i = 0; i < willChange.Length(); i++) {
176 0 : if (i > 0) {
177 0 : aStream << ",";
178 : }
179 0 : nsDependentAtomString buffer(willChange[i]);
180 0 : aStream << NS_LossyConvertUTF16toASCII(buffer).get();
181 : }
182 0 : aStream << ")";
183 : }
184 :
185 : // Display item specific debug info
186 0 : aItem->WriteDebugInfo(aStream);
187 :
188 : #ifdef MOZ_DUMP_PAINTING
189 0 : if (aDumpHtml && aItem->Painted()) {
190 0 : aStream << "</a>";
191 : }
192 : #endif
193 0 : uint32_t key = aItem->GetPerFrameKey();
194 0 : Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key);
195 0 : if (layer) {
196 0 : if (aDumpHtml) {
197 0 : aStream << nsPrintfCString(" <a href=\"#%p\">layer=%p</a>", layer, layer);
198 : } else {
199 0 : aStream << nsPrintfCString(" layer=0x%p", layer);
200 : }
201 : }
202 : #ifdef MOZ_DUMP_PAINTING
203 0 : if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
204 0 : nsCString str;
205 0 : (static_cast<nsDisplayMask*>(aItem))->PrintEffects(str);
206 0 : aStream << str.get();
207 : }
208 :
209 0 : if (aItem->GetType() == nsDisplayItem::TYPE_FILTER) {
210 0 : nsCString str;
211 0 : (static_cast<nsDisplayFilter*>(aItem))->PrintEffects(str);
212 0 : aStream << str.get();
213 : }
214 : #endif
215 0 : aStream << "\n";
216 : #ifdef MOZ_DUMP_PAINTING
217 0 : if (aDumpHtml && aItem->Painted()) {
218 0 : nsCString string(aItem->Name());
219 0 : string.Append('-');
220 0 : string.AppendInt((uint64_t)aItem);
221 0 : aStream << nsPrintfCString("<br><img id=\"%s\">\n", string.BeginReading());
222 : }
223 : #endif
224 :
225 0 : if (aDumpSublist && list) {
226 0 : PrintDisplayListTo(aBuilder, *list, aStream, aIndent+1, aDumpHtml);
227 : }
228 0 : }
229 :
230 : static void
231 0 : PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
232 : std::stringstream& aStream, uint32_t aIndent, bool aDumpHtml)
233 : {
234 0 : if (aDumpHtml) {
235 0 : aStream << "<ul>";
236 : }
237 :
238 0 : for (nsDisplayItem* i = aList.GetBottom(); i != nullptr; i = i->GetAbove()) {
239 0 : if (aDumpHtml) {
240 0 : aStream << "<li>";
241 : }
242 0 : PrintDisplayItemTo(aBuilder, i, aStream, aIndent, true, aDumpHtml);
243 0 : if (aDumpHtml) {
244 0 : aStream << "</li>";
245 : }
246 : }
247 :
248 0 : if (aDumpHtml) {
249 0 : aStream << "</ul>";
250 : }
251 0 : }
252 :
253 : void
254 0 : nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
255 : const nsDisplayList& aList,
256 : std::stringstream& aStream,
257 : bool aDumpHtml)
258 : {
259 0 : PrintDisplayListTo(aBuilder, aList, aStream, 0, aDumpHtml);
260 0 : }
261 :
262 : /**
263 : * The two functions below are intended to be called from a debugger.
264 : */
265 : void
266 0 : PrintDisplayItemToStdout(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
267 : {
268 0 : std::stringstream stream;
269 0 : PrintDisplayItemTo(aBuilder, aItem, stream, 0, true, false);
270 0 : std::cout << stream.str() << std::endl;
271 0 : }
272 :
273 : void
274 0 : PrintDisplayListToStdout(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList)
275 : {
276 0 : std::stringstream stream;
277 0 : PrintDisplayListTo(aBuilder, aList, stream, 0, false);
278 0 : std::cout << stream.str() << std::endl;
279 0 : }
280 :
281 : #ifdef MOZ_DUMP_PAINTING
282 : static void
283 0 : PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder,
284 : const char* aItemName,
285 : const nsDisplayList& aList,
286 : std::stringstream& aStream,
287 : bool aDumpHtml)
288 : {
289 0 : if (aDumpHtml) {
290 0 : aStream << "<li>";
291 : }
292 0 : aStream << aItemName << "\n";
293 0 : PrintDisplayListTo(aBuilder, aList, aStream, 0, aDumpHtml);
294 0 : if (aDumpHtml) {
295 0 : aStream << "</li>";
296 : }
297 0 : }
298 :
299 : void
300 0 : nsFrame::PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
301 : const nsDisplayListSet& aSet,
302 : std::stringstream& aStream,
303 : bool aDumpHtml)
304 : {
305 0 : if (aDumpHtml) {
306 0 : aStream << "<ul>";
307 : }
308 0 : PrintDisplayListSetItem(aBuilder, "[BorderBackground]", *(aSet.BorderBackground()), aStream, aDumpHtml);
309 0 : PrintDisplayListSetItem(aBuilder, "[BlockBorderBackgrounds]", *(aSet.BlockBorderBackgrounds()), aStream, aDumpHtml);
310 0 : PrintDisplayListSetItem(aBuilder, "[Floats]", *(aSet.Floats()), aStream, aDumpHtml);
311 0 : PrintDisplayListSetItem(aBuilder, "[PositionedDescendants]", *(aSet.PositionedDescendants()), aStream, aDumpHtml);
312 0 : PrintDisplayListSetItem(aBuilder, "[Outlines]", *(aSet.Outlines()), aStream, aDumpHtml);
313 0 : PrintDisplayListSetItem(aBuilder, "[Content]", *(aSet.Content()), aStream, aDumpHtml);
314 0 : if (aDumpHtml) {
315 0 : aStream << "</ul>";
316 : }
317 0 : }
318 :
319 : #endif
|