My eyes, they burn! Also runs faster, slightly less buggy.
[ipdf/code.git] / src / debugscript.cpp
1 #include "debugscript.h"
2 #include "profiler.h"
3
4 #include <string>
5
6 using namespace IPDF;
7 using namespace std;
8
9 void DebugScript::ParseAction(View * view, Screen * scr)
10 {
11         *m_input >> std::ws;
12         if (m_input == NULL || !m_input->good())
13                 return;
14         istream & inp = *m_input;
15         Debug("Get action type...");
16         std::string actionType;
17         inp >> actionType;
18         Debug("Action type: %s", actionType.c_str());
19         // Skip comments
20         while (actionType[0] == '#')
21         {
22                 std::string tmp;
23                 std::getline(inp, tmp);
24                 inp >> std::ws >> actionType;
25         }
26         if (actionType == "loop")
27         {
28                 inp >> currentAction.loops >> actionType;
29         }
30         else
31         {
32                 currentAction.loops = 1;
33         }
34
35         if (actionType == "wait")
36         {
37                 currentAction.type = AT_WaitFrame;
38                 return;
39         }
40         else if (actionType == "translate")
41         {
42                 std::string _x, _y;
43                 inp >> _x >> _y;
44                 currentAction.type = AT_Translate;
45                 currentAction.x = RealFromStr(_x.c_str());
46                 currentAction.y = RealFromStr(_y.c_str());
47                 return;
48         }
49         else if (actionType == "zoom")
50         {
51                 std::string _x, _y, _z;
52                 inp >> _x >> _y >> _z;
53                 currentAction.type = AT_Zoom;
54                 currentAction.x = RealFromStr(_x.c_str());
55                 currentAction.y = RealFromStr(_y.c_str());
56                 currentAction.z = RealFromStr(_z.c_str());
57         }
58         else if (actionType == "pxtranslate")
59         {
60                 inp >> currentAction.ix >> currentAction.iy;
61                 currentAction.type = AT_TranslatePx;
62         }
63         else if (actionType == "pxzoom")
64         {
65                 inp >> currentAction.ix >> currentAction.iy >> currentAction.iz;
66                 currentAction.type = AT_ZoomPx;
67         }
68         else if (actionType == "gpu")
69         {
70                 currentAction.type = AT_SetGPURendering;
71         }
72         else if (actionType == "cpu")
73         {
74                 currentAction.type = AT_SetCPURendering;
75         }
76         else if (actionType == "lazy")
77         {
78                 currentAction.type = AT_EnableLazyRendering;
79         }
80         else if (actionType == "nolazy")
81         {
82                 currentAction.type = AT_DisableLazyRendering;
83         }
84         else if (actionType == "quit")
85         {
86                 currentAction.type = AT_Quit;
87         }
88         else if (actionType == "loadsvg")
89         {
90                 currentAction.type = AT_LoadSVG;
91                 inp >> currentAction.textargs;
92         }
93         else if (actionType == "label")
94         {
95                 currentAction.type = AT_Label;
96                 inp >> currentAction.textargs;
97         }
98         else if (actionType == "goto")
99         {
100                 currentAction.type = AT_Goto;
101                 inp >> currentAction.textargs;
102         }
103         else if (actionType == "debug")
104         {
105                 currentAction.type = AT_Debug;
106                 getline(inp,currentAction.textargs);
107         }
108         else if (actionType == "clear")
109         {
110                 currentAction.type = AT_ClearDocument;
111         }
112         else if (actionType == "clearperf")
113         {
114                 currentAction.type = AT_ClearPerformance;
115         }
116         else if (actionType == "printperf")
117         {
118                 currentAction.type = AT_PrintPerformance;
119         }
120         else if (actionType == "recordperf")
121         {
122                 currentAction.type = AT_RecordPerformance;
123         }
124         else if (actionType == "debugfont")
125         {
126                 currentAction.type = AT_DebugFont;
127                 inp >> currentAction.textargs;
128         }
129         else if (actionType == "approachz") // approach zenoistically
130         {
131                 currentAction.type = AT_ApproachBoundsZeno;
132                 std::string _x, _y, _w, _h, _z;
133                 inp >> _x >> _y >> _w >> _h >> _z;
134                 currentAction.x = RealFromStr(_x.c_str());
135                 currentAction.y = RealFromStr(_y.c_str());
136                 currentAction.w = RealFromStr(_w.c_str());
137                 currentAction.h = RealFromStr(_h.c_str());
138                 currentAction.z = RealFromStr(_z.c_str());
139         }
140         else if (actionType == "approachl") // approach linearly
141         {
142                 currentAction.type = AT_ApproachBoundsLinear;
143                 std::string _x, _y, _w, _h, _z;
144                 inp >> _x >> _y >> _w >> _h >> _z;
145                 currentAction.x = RealFromStr(_x.c_str());
146                 currentAction.y = RealFromStr(_y.c_str());
147                 currentAction.w = RealFromStr(_w.c_str());
148                 currentAction.h = RealFromStr(_h.c_str());
149                 currentAction.z = RealFromStr(_z.c_str());
150                 currentAction.x = (currentAction.x - view->GetBounds().x)/currentAction.z;
151                 currentAction.y = (currentAction.y - view->GetBounds().y)/currentAction.z;
152                 currentAction.w = (currentAction.w - view->GetBounds().w)/currentAction.z;
153                 currentAction.h = (currentAction.h - view->GetBounds().h)/currentAction.z;
154         }
155         else if (actionType == "setbounds")
156         {
157                 currentAction.type = AT_SetBounds;
158                 std::string _x, _y, _w, _h;
159                 inp >> _x >> _y >> _w >> _h;
160                 currentAction.x = RealFromStr(_x.c_str());
161                 currentAction.y = RealFromStr(_y.c_str());
162                 currentAction.w = RealFromStr(_w.c_str());
163                 currentAction.h = RealFromStr(_h.c_str());
164         }
165         else if (actionType == "querygpubounds")
166         {
167                 currentAction.type = AT_QueryGPUBounds;
168                 inp >> currentAction.textargs;
169                 currentAction.loops = 1;
170         }
171         else if (actionType == "screenshot")
172         {
173                 currentAction.type = AT_ScreenShot;
174                 inp >> currentAction.textargs;  
175         }
176         else if (actionType == "printfps")
177         {
178                 currentAction.type = AT_PrintFPS;
179                 currentAction.iz = currentAction.loops;
180                 m_fps_cpu_mean = 0;
181                 m_fps_gpu_mean = 0;
182                 m_fps_cpu_stddev = 0;
183                 m_fps_gpu_stddev = 0;
184         }
185         else if (actionType == "printbounds")
186         {
187                 currentAction.type = AT_PrintBounds;
188         }
189         else if (actionType == "profileon")
190         {
191                 currentAction.type = AT_ProfileDisplay;
192                 currentAction.iz = 1;
193         }
194         else if (actionType == "profileoff")
195         {
196                 currentAction.type = AT_ProfileDisplay;
197                 currentAction.iz = 0;
198         }
199         else
200                 Fatal("Unknown action %s", actionType.c_str());
201
202 }
203
204 bool DebugScript::Execute(View *view, Screen *scr)
205 {
206         if (currentAction.loops <= 0)
207         {
208                 if (m_index >= m_actions.size())
209                 {
210                         ParseAction(view, scr);
211                         if (m_labels.size() > 0)
212                         {
213                                 m_actions.push_back(currentAction);
214                                 m_index++;
215                         }
216                                 
217                 }
218                 else
219                         currentAction = m_actions[m_index++];
220         }
221
222         switch(currentAction.type)
223         {
224         case AT_Quit:
225                 return true;
226         case AT_WaitFrame:
227                 break;
228         case AT_Translate:
229                 view->Translate(currentAction.x, currentAction.y);
230                 break;
231         case AT_TranslatePx:
232                 view->Translate(Real(currentAction.ix)/Real(scr->ViewportWidth()), Real(currentAction.iy)/Real(scr->ViewportHeight()));
233                 break;
234         case AT_Zoom:
235                 view->ScaleAroundPoint(currentAction.x, currentAction.y, currentAction.z);
236                 break;
237         case AT_ZoomPx:
238                 view->ScaleAroundPoint(Real(currentAction.ix)/Real(scr->ViewportWidth()),Real(currentAction.iy)/Real(scr->ViewportHeight()), Real(expf(-currentAction.iz/20.f)));
239                 break;
240         case AT_SetGPURendering:
241                 view->SetGPURendering(true);
242                 break;
243         case AT_SetCPURendering:
244                 view->SetGPURendering(false);
245                 break;
246         case AT_EnableLazyRendering:
247                 view->SetLazyRendering(true);
248                 break;
249         case AT_DisableLazyRendering:
250                 view->SetLazyRendering(false);
251                 break;
252         case AT_LoadSVG:
253         {
254 #ifndef QUADTREE_DISABLED
255                 view->Doc().SetQuadtreeInsertNode(view->GetCurrentQuadtreeNode());
256 #endif
257                 #ifdef TRANSFORM_OBJECTS_NOT_VIEW
258                         view->Doc().LoadSVG(currentAction.textargs, Rect(Real(1)/Real(2),Real(1)/Real(2),Real(1)/Real(800),Real(1)/Real(600))); 
259                 #else
260                         const Rect & bounds = view->GetBounds();
261                         view->Doc().LoadSVG(currentAction.textargs, Rect(bounds.x+bounds.w/Real(2),bounds.y+bounds.h/Real(2),bounds.w/Real(800),bounds.h/Real(600)));
262                 #endif
263 #ifndef QUADTREE_DISABLED
264                 view->Doc().PropagateQuadChanges(view->GetCurrentQuadtreeNode());
265                 view->Doc().PropagateQuadChanges(view->Doc().GetQuadTree().GetNeighbour(view->GetCurrentQuadtreeNode(), 0, 1, 0));
266                 view->Doc().PropagateQuadChanges(view->Doc().GetQuadTree().GetNeighbour(view->GetCurrentQuadtreeNode(), 1, 0, 0));
267                 view->Doc().PropagateQuadChanges(view->Doc().GetQuadTree().GetNeighbour(view->GetCurrentQuadtreeNode(), 1, 1, 0));
268 #endif
269                 currentAction.type = AT_WaitFrame;
270                 view->ForceRenderDirty();
271                 view->ForceBufferDirty();
272                 view->ForceBoundsDirty();
273                 currentAction.loops = 1;
274                 break;
275         }
276         case AT_Label:
277                 m_labels[currentAction.textargs] = m_index;
278                 currentAction.type = AT_WaitFrame;
279                 currentAction.loops = 1;
280                 break;
281         case AT_Goto:
282                 m_index = m_labels[currentAction.textargs];
283                 currentAction.loops = 1;
284                 break;
285         case AT_Debug:
286                 Debug("View bounds: %s", view->GetBounds().Str().c_str());
287                 if (currentAction.textargs.size() > 0)
288                         Debug("%s", currentAction.textargs.c_str());
289                 break;
290         case AT_ClearDocument:
291                 view->Doc().ClearObjects();
292                 currentAction.loops = 1;
293                 break;
294         case AT_ClearPerformance:
295                 ClearPerformance(view, scr);
296                 currentAction.loops = 1;
297                 break;
298         case AT_PrintPerformance:
299                 PrintPerformance(view, scr);
300                 currentAction.loops = 1;        
301                 break;
302         case AT_RecordPerformance:
303                 PrintPerformance(view, scr);
304                 break;
305         case AT_DebugFont:
306                 scr->ShowDebugFont(currentAction.textargs == "1" || currentAction.textargs == "on");
307                 currentAction.loops = 1;
308                 break;
309                 
310         case AT_ApproachBoundsZeno:
311         {       
312                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
313                 if (currentAction.z != VReal(1))
314                 {
315                         target.x = view->GetBounds().x + (target.x-view->GetBounds().x)/VReal(currentAction.z);
316                         target.y = view->GetBounds().y + (target.y-view->GetBounds().y)/VReal(currentAction.z);
317                         target.w = view->GetBounds().w + (target.w-view->GetBounds().w)/VReal(currentAction.z);
318                         target.h = view->GetBounds().h + (target.h-view->GetBounds().h)/VReal(currentAction.z);
319                 }
320                 
321
322                 VReal s = target.w/(view->GetBounds().w);
323                 if (Real(s) != 1)
324                 {
325                         VReal x0;
326                         VReal y0;
327                         x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
328                         y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
329                         view->ScaleAroundPoint(x0, y0, s);
330                         currentAction.loops++;
331                 }
332                 else
333                 {
334                         Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
335                         currentAction.type = AT_WaitFrame;
336                 }
337                 break;
338         }
339         case AT_ApproachBoundsLinear:
340         {
341                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
342                 target.x += view->GetBounds().x;
343                 target.y += view->GetBounds().y;
344                 target.w += view->GetBounds().w;
345                 target.h += view->GetBounds().h;
346                 VReal s = target.w/(view->GetBounds().w);
347                 if (Real(s) != 1)
348                 {
349                         VReal x0;
350                         VReal y0;
351                         x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
352                         y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
353                         view->ScaleAroundPoint(x0, y0, s);
354                         currentAction.loops++;
355                 }
356                 else
357                 {
358                         Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
359                         currentAction.type = AT_WaitFrame;
360                 }
361                 break;
362         }
363         case AT_SetBounds:
364         {
365                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
366                 view->SetBounds(target);
367                 break;
368         }
369         
370         case AT_QueryGPUBounds:
371         {
372                 view->QueryGPUBounds(currentAction.textargs.c_str(), "w");
373                 currentAction.loops = 1;
374                 break;
375         }
376         case AT_ScreenShot:
377         {
378                 view->SaveBMP(currentAction.textargs.c_str());
379                 currentAction.loops = 1;
380                 break;
381         }
382         case AT_PrintFPS:
383         {
384                 // Using a (apparently) Soviet trick to calculate the stddev in one pass
385                 // This was my favourite algorithm in my Physics honours project
386                 // Ah the memories
387                 // The horrible horrible memories
388                 // At least things won't get that bad
389                 // Right?
390                 if (currentAction.loops <= 1)
391                 {
392                         double n = double(currentAction.iz);
393                         m_fps_cpu_mean /= n;
394                         m_fps_gpu_mean /= n;
395                         
396                         m_fps_cpu_stddev = sqrt(m_fps_cpu_stddev / n - m_fps_cpu_mean*m_fps_cpu_mean);
397                         m_fps_gpu_stddev = sqrt(m_fps_gpu_stddev / n - m_fps_gpu_mean*m_fps_gpu_mean);
398                         
399                         
400                         
401                         printf("%d\t%f\t%f\t%f\t%f\n", currentAction.iz,
402                                 m_fps_gpu_mean, m_fps_gpu_stddev,
403                                 m_fps_cpu_mean, m_fps_cpu_stddev);
404                 }
405                 else
406                 {
407                         
408                         double fps_cpu = 1.0/scr->GetLastFrameTimeCPU();
409                         double fps_gpu = 1.0/scr->GetLastFrameTimeGPU();
410                         
411                         m_fps_cpu_mean += fps_cpu;
412                         m_fps_gpu_mean += fps_gpu;
413                         
414                         m_fps_cpu_stddev += fps_cpu*fps_cpu;
415                         m_fps_gpu_stddev += fps_gpu*fps_gpu;
416                 }
417                 break;
418         }
419         case AT_PrintBounds:
420         {
421                 printf("%s\t%s\t%s\t%s\n", Str(view->GetBounds().x).c_str(), Str(view->GetBounds().y).c_str(), Str(view->GetBounds().w).c_str(), Str(view->GetBounds().h).c_str());
422                 break;
423         }
424         case AT_ProfileDisplay:
425         {
426                 g_profiler.Enable(currentAction.iz);
427                 break;
428         }
429         default:
430                 Fatal("Unknown script command in queue.");
431         }
432         currentAction.loops--;
433         return false;
434 }
435
436 void DebugScript::ClearPerformance(View * view, Screen * scr)
437 {
438         m_perf_start.clock = clock();
439         m_perf_start.object_count = view->Doc().ObjectCount();
440         m_perf_start.view_bounds = view->GetBounds();
441         m_perf_last = m_perf_start;
442 }
443
444 void DebugScript::PrintPerformance(View * view, Screen * scr)
445 {
446         DebugScript::PerformanceData now;
447         now.clock = clock();
448         now.object_count = view->Doc().ObjectCount();
449         now.view_bounds = view->GetBounds();
450
451         // object_count  clock  delta_clock  x  Log10(x)  y  Log10(y)  w  Log10(w)  Size(w)
452         #ifdef QUADTREE_DISABLED
453         printf("%d\t%llu\t%llu\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
454                 now.object_count, (long long unsigned)now.clock,
455                 (long long unsigned)(now.clock - m_perf_last.clock),
456                 Str(now.view_bounds.x).c_str(), Str(Log10(Abs(now.view_bounds.x))).c_str(),
457                 Str(now.view_bounds.y).c_str(), Str(Log10(Abs(now.view_bounds.y))).c_str(),
458                 Str(now.view_bounds.w).c_str(), Str(Log10(now.view_bounds.w)).c_str(),
459                 (unsigned)Size(now.view_bounds.w));
460         #endif
461         m_perf_last = now;
462 }

UCC git Repository :: git.ucc.asn.au