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

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