9d78b262bfc654b787695cddf15673fdad3d81b8
[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                 #ifdef TRANSFORM_OBJECTS_NOT_VIEW
255                         view->Doc().LoadSVG(currentAction.textargs, Rect(Real(1)/Real(2),Real(1)/Real(2),Real(1)/Real(800),Real(1)/Real(600))); 
256                 #else
257                         const Rect & bounds = view->GetBounds();
258                         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)));
259                 #endif
260                 currentAction.type = AT_WaitFrame;
261                 view->ForceRenderDirty();
262                 view->ForceBufferDirty();
263                 view->ForceBoundsDirty();
264                 currentAction.loops = 1;
265                 break;
266         }
267         case AT_Label:
268                 m_labels[currentAction.textargs] = m_index;
269                 currentAction.type = AT_WaitFrame;
270                 currentAction.loops = 1;
271                 break;
272         case AT_Goto:
273                 m_index = m_labels[currentAction.textargs];
274                 currentAction.loops = 1;
275                 break;
276         case AT_Debug:
277                 Debug("View bounds: %s", view->GetBounds().Str().c_str());
278                 if (currentAction.textargs.size() > 0)
279                         Debug("%s", currentAction.textargs.c_str());
280                 break;
281         case AT_ClearDocument:
282                 view->Doc().ClearObjects();
283                 currentAction.loops = 1;
284                 break;
285         case AT_ClearPerformance:
286                 ClearPerformance(view, scr);
287                 currentAction.loops = 1;
288                 break;
289         case AT_PrintPerformance:
290                 PrintPerformance(view, scr);
291                 currentAction.loops = 1;        
292                 break;
293         case AT_RecordPerformance:
294                 PrintPerformance(view, scr);
295                 break;
296         case AT_DebugFont:
297                 scr->ShowDebugFont(currentAction.textargs == "1" || currentAction.textargs == "on");
298                 currentAction.loops = 1;
299                 break;
300                 
301         case AT_ApproachBoundsZeno:
302         {       
303                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
304                 if (currentAction.z != VReal(1))
305                 {
306                         target.x = view->GetBounds().x + (target.x-view->GetBounds().x)/VReal(currentAction.z);
307                         target.y = view->GetBounds().y + (target.y-view->GetBounds().y)/VReal(currentAction.z);
308                         target.w = view->GetBounds().w + (target.w-view->GetBounds().w)/VReal(currentAction.z);
309                         target.h = view->GetBounds().h + (target.h-view->GetBounds().h)/VReal(currentAction.z);
310                 }
311                 
312
313                 VReal s = target.w/(view->GetBounds().w);
314                 if (Real(s) != 1)
315                 {
316                         VReal x0;
317                         VReal y0;
318                         x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
319                         y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
320                         view->ScaleAroundPoint(x0, y0, s);
321                         currentAction.loops++;
322                 }
323                 else
324                 {
325                         Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
326                         currentAction.type = AT_WaitFrame;
327                 }
328                 break;
329         }
330         case AT_ApproachBoundsLinear:
331         {
332                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
333                 target.x += view->GetBounds().x;
334                 target.y += view->GetBounds().y;
335                 target.w += view->GetBounds().w;
336                 target.h += view->GetBounds().h;
337                 VReal s = target.w/(view->GetBounds().w);
338                 if (Real(s) != 1)
339                 {
340                         VReal x0;
341                         VReal y0;
342                         x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
343                         y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
344                         view->ScaleAroundPoint(x0, y0, s);
345                         currentAction.loops++;
346                 }
347                 else
348                 {
349                         Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
350                         currentAction.type = AT_WaitFrame;
351                 }
352                 break;
353         }
354         case AT_SetBounds:
355         {
356                 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
357                 view->SetBounds(target);
358                 break;
359         }
360         
361         case AT_QueryGPUBounds:
362         {
363                 view->QueryGPUBounds(currentAction.textargs.c_str(), "w");
364                 currentAction.loops = 1;
365                 break;
366         }
367         case AT_ScreenShot:
368         {
369                 view->SaveBMP(currentAction.textargs.c_str());
370                 currentAction.loops = 1;
371                 break;
372         }
373         case AT_PrintFPS:
374         {
375                 // Using a (apparently) Soviet trick to calculate the stddev in one pass
376                 // This was my favourite algorithm in my Physics honours project
377                 // Ah the memories
378                 // The horrible horrible memories
379                 // At least things won't get that bad
380                 // Right?
381                 if (currentAction.loops <= 1)
382                 {
383                         double n = double(currentAction.iz);
384                         m_fps_cpu_mean /= n;
385                         m_fps_gpu_mean /= n;
386                         
387                         m_fps_cpu_stddev = sqrt(m_fps_cpu_stddev / n - m_fps_cpu_mean*m_fps_cpu_mean);
388                         m_fps_gpu_stddev = sqrt(m_fps_gpu_stddev / n - m_fps_gpu_mean*m_fps_gpu_mean);
389                         
390                         
391                         
392                         printf("%d\t%f\t%f\t%f\t%f\n", currentAction.iz,
393                                 m_fps_gpu_mean, m_fps_gpu_stddev,
394                                 m_fps_cpu_mean, m_fps_cpu_stddev);
395                 }
396                 else
397                 {
398                         
399                         double fps_cpu = 1.0/scr->GetLastFrameTimeCPU();
400                         double fps_gpu = 1.0/scr->GetLastFrameTimeGPU();
401                         
402                         m_fps_cpu_mean += fps_cpu;
403                         m_fps_gpu_mean += fps_gpu;
404                         
405                         m_fps_cpu_stddev += fps_cpu*fps_cpu;
406                         m_fps_gpu_stddev += fps_gpu*fps_gpu;
407                 }
408                 break;
409         }
410         case AT_PrintBounds:
411         {
412                 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());
413                 break;
414         }
415         case AT_ProfileDisplay:
416         {
417                 g_profiler.Enable(currentAction.iz);
418                 break;
419         }
420         default:
421                 Fatal("Unknown script command in queue.");
422         }
423         currentAction.loops--;
424         return false;
425 }
426
427 void DebugScript::ClearPerformance(View * view, Screen * scr)
428 {
429         m_perf_start.clock = clock();
430         m_perf_start.object_count = view->Doc().ObjectCount();
431         m_perf_start.view_bounds = view->GetBounds();
432         m_perf_last = m_perf_start;
433 }
434
435 void DebugScript::PrintPerformance(View * view, Screen * scr)
436 {
437         DebugScript::PerformanceData now;
438         now.clock = clock();
439         now.object_count = view->Doc().ObjectCount();
440         now.view_bounds = view->GetBounds();
441
442         // object_count  clock  delta_clock  x  Log10(x)  y  Log10(y)  w  Log10(w)  Size(w)
443         #ifdef QUADTREE_DISABLED
444         printf("%d\t%llu\t%llu\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
445                 now.object_count, (long long unsigned)now.clock,
446                 (long long unsigned)(now.clock - m_perf_last.clock),
447                 Str(now.view_bounds.x).c_str(), Str(Log10(Abs(now.view_bounds.x))).c_str(),
448                 Str(now.view_bounds.y).c_str(), Str(Log10(Abs(now.view_bounds.y))).c_str(),
449                 Str(now.view_bounds.w).c_str(), Str(Log10(now.view_bounds.w)).c_str(),
450                 (unsigned)Size(now.view_bounds.w));
451         #endif
452         m_perf_last = now;
453 }

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