|
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 #include "nsFrame.h" |
|
13 #include "nsDisplayList.h" |
|
14 #include "FrameLayerBuilder.h" |
|
15 #include "nsPrintfCString.h" |
|
16 |
|
17 #include <stdio.h> |
|
18 |
|
19 using namespace mozilla; |
|
20 using namespace mozilla::layers; |
|
21 |
|
22 #ifdef DEBUG |
|
23 class nsLayoutDebugger : public nsILayoutDebugger { |
|
24 public: |
|
25 nsLayoutDebugger(); |
|
26 virtual ~nsLayoutDebugger(); |
|
27 |
|
28 NS_DECL_ISUPPORTS |
|
29 |
|
30 NS_IMETHOD SetShowFrameBorders(bool aEnable) MOZ_OVERRIDE; |
|
31 |
|
32 NS_IMETHOD GetShowFrameBorders(bool* aResult) MOZ_OVERRIDE; |
|
33 |
|
34 NS_IMETHOD SetShowEventTargetFrameBorder(bool aEnable) MOZ_OVERRIDE; |
|
35 |
|
36 NS_IMETHOD GetShowEventTargetFrameBorder(bool* aResult) MOZ_OVERRIDE; |
|
37 |
|
38 NS_IMETHOD GetContentSize(nsIDocument* aDocument, |
|
39 int32_t* aSizeInBytesResult) MOZ_OVERRIDE; |
|
40 |
|
41 NS_IMETHOD GetFrameSize(nsIPresShell* aPresentation, |
|
42 int32_t* aSizeInBytesResult) MOZ_OVERRIDE; |
|
43 |
|
44 NS_IMETHOD GetStyleSize(nsIPresShell* aPresentation, |
|
45 int32_t* aSizeInBytesResult) MOZ_OVERRIDE; |
|
46 |
|
47 }; |
|
48 |
|
49 nsresult |
|
50 NS_NewLayoutDebugger(nsILayoutDebugger** aResult) |
|
51 { |
|
52 NS_PRECONDITION(aResult, "null OUT ptr"); |
|
53 if (!aResult) { |
|
54 return NS_ERROR_NULL_POINTER; |
|
55 } |
|
56 nsLayoutDebugger* it = new nsLayoutDebugger(); |
|
57 return it->QueryInterface(NS_GET_IID(nsILayoutDebugger), (void**)aResult); |
|
58 } |
|
59 |
|
60 nsLayoutDebugger::nsLayoutDebugger() |
|
61 { |
|
62 } |
|
63 |
|
64 nsLayoutDebugger::~nsLayoutDebugger() |
|
65 { |
|
66 } |
|
67 |
|
68 NS_IMPL_ISUPPORTS(nsLayoutDebugger, nsILayoutDebugger) |
|
69 |
|
70 NS_IMETHODIMP |
|
71 nsLayoutDebugger::SetShowFrameBorders(bool aEnable) |
|
72 { |
|
73 nsFrame::ShowFrameBorders(aEnable); |
|
74 return NS_OK; |
|
75 } |
|
76 |
|
77 NS_IMETHODIMP |
|
78 nsLayoutDebugger::GetShowFrameBorders(bool* aResult) |
|
79 { |
|
80 *aResult = nsFrame::GetShowFrameBorders(); |
|
81 return NS_OK; |
|
82 } |
|
83 |
|
84 NS_IMETHODIMP |
|
85 nsLayoutDebugger::SetShowEventTargetFrameBorder(bool aEnable) |
|
86 { |
|
87 nsFrame::ShowEventTargetFrameBorder(aEnable); |
|
88 return NS_OK; |
|
89 } |
|
90 |
|
91 NS_IMETHODIMP |
|
92 nsLayoutDebugger::GetShowEventTargetFrameBorder(bool* aResult) |
|
93 { |
|
94 *aResult = nsFrame::GetShowEventTargetFrameBorder(); |
|
95 return NS_OK; |
|
96 } |
|
97 |
|
98 NS_IMETHODIMP |
|
99 nsLayoutDebugger::GetContentSize(nsIDocument* aDocument, |
|
100 int32_t* aSizeInBytesResult) |
|
101 { |
|
102 *aSizeInBytesResult = 0; |
|
103 return NS_ERROR_FAILURE; |
|
104 } |
|
105 |
|
106 NS_IMETHODIMP |
|
107 nsLayoutDebugger::GetFrameSize(nsIPresShell* aPresentation, |
|
108 int32_t* aSizeInBytesResult) |
|
109 { |
|
110 *aSizeInBytesResult = 0; |
|
111 return NS_ERROR_FAILURE; |
|
112 } |
|
113 |
|
114 NS_IMETHODIMP |
|
115 nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation, |
|
116 int32_t* aSizeInBytesResult) |
|
117 { |
|
118 *aSizeInBytesResult = 0; |
|
119 return NS_ERROR_FAILURE; |
|
120 } |
|
121 #endif |
|
122 |
|
123 #ifdef MOZ_DUMP_PAINTING |
|
124 static void |
|
125 PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, |
|
126 FILE* aOutput, uint32_t aIndent, bool aDumpHtml); |
|
127 |
|
128 static void |
|
129 PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, |
|
130 FILE* aOutput, uint32_t aIndent, bool aDumpSublist, bool aDumpHtml) |
|
131 { |
|
132 nsCString str; |
|
133 if (!aDumpHtml) { |
|
134 for (uint32_t indent = 0; indent < aIndent; indent++) { |
|
135 str += " "; |
|
136 } |
|
137 } |
|
138 nsIFrame* f = aItem->Frame(); |
|
139 nsAutoString fName; |
|
140 #ifdef DEBUG_FRAME_DUMP |
|
141 f->GetFrameName(fName); |
|
142 #endif |
|
143 bool snap; |
|
144 nsRect rect = aItem->GetBounds(aBuilder, &snap); |
|
145 nscolor color; |
|
146 nsRect vis = aItem->GetVisibleRect(); |
|
147 nsRect component = aItem->GetComponentAlphaBounds(aBuilder); |
|
148 nsDisplayList* list = aItem->GetChildren(); |
|
149 const DisplayItemClip& clip = aItem->GetClip(); |
|
150 nsRegion opaque; |
|
151 if (!list || list->DidComputeVisibility()) { |
|
152 opaque = aItem->GetOpaqueRegion(aBuilder, &snap); |
|
153 } |
|
154 if (aDumpHtml && aItem->Painted()) { |
|
155 nsCString string(aItem->Name()); |
|
156 string.Append("-"); |
|
157 string.AppendInt((uint64_t)aItem); |
|
158 str += nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">", string.BeginReading()); |
|
159 } |
|
160 str += nsPrintfCString("%s %p(%s) bounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) %s", |
|
161 aItem->Name(), (void*)f, NS_ConvertUTF16toUTF8(fName).get(), |
|
162 rect.x, rect.y, rect.width, rect.height, |
|
163 vis.x, vis.y, vis.width, vis.height, |
|
164 component.x, component.y, component.width, component.height, |
|
165 clip.ToString().get(), |
|
166 aItem->IsUniform(aBuilder, &color) ? " uniform" : ""); |
|
167 nsRegionRectIterator iter(opaque); |
|
168 for (const nsRect* r = iter.Next(); r; r = iter.Next()) { |
|
169 str += nsPrintfCString(" (opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); |
|
170 } |
|
171 aItem->WriteDebugInfo(str); |
|
172 if (aDumpHtml && aItem->Painted()) { |
|
173 str += "</a>"; |
|
174 } |
|
175 uint32_t key = aItem->GetPerFrameKey(); |
|
176 Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key); |
|
177 if (layer) { |
|
178 if (aDumpHtml) { |
|
179 str += nsPrintfCString(" <a href=\"#%p\">layer=%p</a>", layer, layer); |
|
180 } else { |
|
181 str += nsPrintfCString(" layer=%p", layer); |
|
182 } |
|
183 } |
|
184 if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) { |
|
185 (static_cast<nsDisplaySVGEffects*>(aItem))->PrintEffects(str); |
|
186 } |
|
187 fprintf_stderr(aOutput, "%s\n", str.get()); |
|
188 if (aDumpSublist && list) { |
|
189 PrintDisplayListTo(aBuilder, *list, aOutput, aIndent+1, aDumpHtml); |
|
190 } |
|
191 } |
|
192 |
|
193 static void |
|
194 PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, |
|
195 FILE* aOutput, uint32_t aIndent, bool aDumpHtml) |
|
196 { |
|
197 if (aDumpHtml) { |
|
198 fprintf_stderr(aOutput, "<ul>"); |
|
199 } |
|
200 |
|
201 for (nsDisplayItem* i = aList.GetBottom(); i != nullptr; i = i->GetAbove()) { |
|
202 if (aDumpHtml) { |
|
203 fprintf_stderr(aOutput, "<li>"); |
|
204 } |
|
205 PrintDisplayItemTo(aBuilder, i, aOutput, aIndent, true, aDumpHtml); |
|
206 if (aDumpHtml) { |
|
207 fprintf_stderr(aOutput, "</li>"); |
|
208 } |
|
209 } |
|
210 |
|
211 if (aDumpHtml) { |
|
212 fprintf_stderr(aOutput, "</ul>"); |
|
213 } |
|
214 } |
|
215 |
|
216 void |
|
217 nsFrame::PrintDisplayItem(nsDisplayListBuilder* aBuilder, |
|
218 nsDisplayItem* aItem, |
|
219 FILE* aFile, |
|
220 bool aDumpSublist, |
|
221 bool aDumpHtml) |
|
222 { |
|
223 PrintDisplayItemTo(aBuilder, aItem, aFile, 0, aDumpSublist, aDumpHtml); |
|
224 } |
|
225 |
|
226 void |
|
227 nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder, |
|
228 const nsDisplayList& aList, |
|
229 FILE* aFile, |
|
230 bool aDumpHtml) |
|
231 { |
|
232 PrintDisplayListTo(aBuilder, aList, aFile, 0, aDumpHtml); |
|
233 } |
|
234 |
|
235 static void |
|
236 PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder, |
|
237 const char* aItemName, |
|
238 const nsDisplayList& aList, |
|
239 FILE* aFile, |
|
240 bool aDumpHtml) |
|
241 { |
|
242 if (aDumpHtml) { |
|
243 fprintf_stderr(aFile, "<li>"); |
|
244 } |
|
245 fprintf_stderr(aFile, "%s", aItemName); |
|
246 PrintDisplayListTo(aBuilder, aList, aFile, 0, aDumpHtml); |
|
247 if (aDumpHtml) { |
|
248 fprintf_stderr(aFile, "</li>"); |
|
249 } |
|
250 } |
|
251 |
|
252 void |
|
253 nsFrame::PrintDisplayListSet(nsDisplayListBuilder* aBuilder, |
|
254 const nsDisplayListSet& aSet, |
|
255 FILE *aFile, |
|
256 bool aDumpHtml) |
|
257 { |
|
258 if (aDumpHtml) { |
|
259 fprintf_stderr(aFile, "<ul>"); |
|
260 } |
|
261 PrintDisplayListSetItem(aBuilder, "[BorderBackground]", *(aSet.BorderBackground()), aFile, aDumpHtml); |
|
262 PrintDisplayListSetItem(aBuilder, "[BlockBorderBackgrounds]", *(aSet.BlockBorderBackgrounds()), aFile, aDumpHtml); |
|
263 PrintDisplayListSetItem(aBuilder, "[Floats]", *(aSet.Floats()), aFile, aDumpHtml); |
|
264 PrintDisplayListSetItem(aBuilder, "[PositionedDescendants]", *(aSet.PositionedDescendants()), aFile, aDumpHtml); |
|
265 PrintDisplayListSetItem(aBuilder, "[Outlines]", *(aSet.Outlines()), aFile, aDumpHtml); |
|
266 PrintDisplayListSetItem(aBuilder, "[Content]", *(aSet.Content()), aFile, aDumpHtml); |
|
267 if (aDumpHtml) { |
|
268 fprintf_stderr(aFile, "</ul>"); |
|
269 } |
|
270 } |
|
271 |
|
272 #endif |